15# include <Alembic/AbcCoreFactory/All.h>
16# include <Alembic/AbcGeom/All.h>
20class AlembicProcedural;
26using MatrixSampleMap = std::map<Alembic::Abc::chrono_t, Alembic::Abc::M44d>;
28struct MatrixSamplesData {
29 MatrixSampleMap *samples =
nullptr;
30 Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling;
34template<
typename>
struct is_array :
public std::false_type {};
36template<
typename T>
struct is_array<
array<
T>> :
public std::true_type {};
40template<
typename T>
class CacheLookupResult {
53 CacheLookupResult() =
default;
56 static CacheLookupResult new_data(
T *data_)
60 result.state = State::NEW_DATA;
64 static CacheLookupResult no_data_found_for_time()
68 result.state = State::NO_DATA_FOR_TIME;
72 static CacheLookupResult already_loaded()
76 result.state = State::ALREADY_LOADED;
81 const T &get_data()
const
88 T *get_data_or_null()
const
94 bool has_new_data()
const
96 return state == State::NEW_DATA;
99 bool has_already_loaded()
const
101 return state == State::ALREADY_LOADED;
104 bool has_no_data_for_time()
const
106 return state == State::NO_DATA_FOR_TIME;
115template<
typename T>
class DataStore {
117 struct TimeIndexPair {
121 double source_time = 0;
133 vector<TimeIndexPair> index_data_map{};
135 Alembic::AbcCoreAbstract::TimeSampling time_sampling{};
137 double last_loaded_time = std::numeric_limits<double>::max();
141 Alembic::AbcCoreAbstract::ArraySample::Key key1;
142 Alembic::AbcCoreAbstract::ArraySample::Key key2;
144 void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_)
146 time_sampling = time_sampling_;
149 Alembic::AbcCoreAbstract::TimeSampling get_time_sampling()
const
151 return time_sampling;
156 CacheLookupResult<T> data_for_time(
const double time)
159 return CacheLookupResult<T>::no_data_found_for_time();
162 const TimeIndexPair &index = get_index_for_time(time);
164 if (index.index == -1ul) {
165 return CacheLookupResult<T>::no_data_found_for_time();
168 if (last_loaded_time == index.time || last_loaded_time == index.source_time) {
169 return CacheLookupResult<T>::already_loaded();
172 last_loaded_time = index.source_time;
176 return CacheLookupResult<T>::new_data(&
data[index.index]);
181 CacheLookupResult<T> data_for_time_no_check(
const double time)
184 return CacheLookupResult<T>::no_data_found_for_time();
187 const TimeIndexPair &index = get_index_for_time(time);
189 if (index.index == -1ul) {
190 return CacheLookupResult<T>::no_data_found_for_time();
195 return CacheLookupResult<T>::new_data(&
data[index.index]);
198 void add_data(
T &data_,
double time)
200 index_data_map.push_back({time, time,
data.size()});
202 if constexpr (is_array<T>::value) {
204 data.back().steal_data(data_);
208 data.push_back(data_);
211 void reuse_data_for_last_time(
const double time)
213 const TimeIndexPair &data_index = index_data_map.back();
214 index_data_map.push_back({time, data_index.source_time, data_index.index});
217 void add_no_data(
const double time)
219 index_data_map.push_back({time, time, -1ul});
222 bool is_constant()
const
224 return data.size() <= 1;
234 invalidate_last_loaded_time();
236 index_data_map.clear();
239 void invalidate_last_loaded_time()
241 last_loaded_time = std::numeric_limits<double>::max();
246 void copy_to_socket(
const double time, Node *node,
const SocketType *socket)
248 CacheLookupResult<T>
result = data_for_time(time);
250 if (!
result.has_new_data()) {
257 node->
set(*socket, value);
260 size_t memory_used()
const
262 if constexpr (is_array<T>::value) {
265 for (
const T &array :
data) {
266 mem_used += array.size() *
sizeof(array[0]);
272 return data.size() *
sizeof(
T);
276 const TimeIndexPair &get_index_for_time(
const double time)
const
278 std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
279 index_pair = time_sampling.getNearIndex(time, index_data_map.size());
280 return index_data_map[index_pair.first];
289 DataStore<Transform> transforms{};
292 DataStore<array<float3>> vertices;
293 DataStore<array<int3>> triangles{};
296 DataStore<array<int>> uv_loops{};
297 DataStore<array<int>> shader{};
300 DataStore<array<int>> subd_start_corner;
301 DataStore<array<int>> subd_num_corners;
302 DataStore<array<bool>> subd_smooth;
303 DataStore<array<int>> subd_ptex_offset;
304 DataStore<array<int>> subd_face_corners;
305 DataStore<array<int>> subd_creases_edge;
306 DataStore<array<float>> subd_creases_weight;
307 DataStore<array<int>> subd_vertex_crease_indices;
308 DataStore<array<float>> subd_vertex_crease_weights;
311 DataStore<array<float3>> curve_keys;
312 DataStore<array<float>> curve_radius;
313 DataStore<array<int>> curve_first_key;
314 DataStore<array<int>> curve_shader;
317 DataStore<array<float3>> points;
318 DataStore<array<float>> radiuses;
319 DataStore<array<int>> points_shader;
321 struct CachedAttribute {
326 DataStore<array<char>>
data{};
329 vector<CachedAttribute> attributes{};
333 CachedAttribute &add_attribute(
const ustring &name,
334 const Alembic::Abc::TimeSampling &time_sampling);
336 bool is_constant()
const;
338 void invalidate_last_loaded_time(
bool attributes_only =
false);
340 void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling);
342 size_t memory_used()
const;
354class AlembicObject :
public Node {
378 ~AlembicObject()
override;
381 friend class AlembicProcedural;
383 void set_object(
Object *
object);
386 void load_data_in_cache(CachedData &cached_data,
387 AlembicProcedural *proc,
388 Alembic::AbcGeom::IPolyMeshSchema &schema,
390 void load_data_in_cache(CachedData &cached_data,
391 AlembicProcedural *proc,
392 Alembic::AbcGeom::ISubDSchema &schema,
394 void load_data_in_cache(CachedData &cached_data,
395 AlembicProcedural *proc,
396 const Alembic::AbcGeom::ICurvesSchema &schema,
398 void load_data_in_cache(CachedData &cached_data,
399 AlembicProcedural *proc,
400 const Alembic::AbcGeom::IPointsSchema &schema,
403 bool has_data_loaded()
const;
415 bool need_shader_update =
true;
417 AlembicObject *instance_of =
nullptr;
419 Alembic::AbcCoreAbstract::TimeSamplingPtr xform_time_sampling;
420 MatrixSampleMap xform_samples;
421 Alembic::AbcGeom::IObject iobject;
424 AbcSchemaType schema_type;
426 CachedData &get_cached_data()
431 bool is_constant()
const
433 return cached_data_.is_constant();
438 cached_data_.clear();
443 bool data_loaded =
false;
445 CachedData cached_data_;
447 void setup_transform_cache(CachedData &cached_data,
const float scale);
449 AttributeRequestSet get_requested_attributes();
462 Alembic::AbcGeom::IArchive archive;
463 bool objects_loaded =
false;
464 bool objects_modified =
false;
465 Scene *scene_ =
nullptr;
508 ~AlembicProcedural()
override;
515 void tag_update(
Scene *scene);
525 AlembicObject *get_or_create_object(
const ustring &path);
529 void load_objects(Progress &
progress);
534 void walk_hierarchy(Alembic::AbcGeom::IObject parent,
535 const Alembic::AbcGeom::ObjectHeader &header,
536 MatrixSamplesData matrix_samples_data,
537 const unordered_map<string, AlembicObject *> &object_map,
542 void read_mesh(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
546 void read_curves(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
550 void read_points(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
554 void read_subd(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
556 void build_caches(Progress &
progress);
558 size_t get_prefetch_cache_size_in_bytes()
const
561 return static_cast<size_t>(prefetch_cache_size) * 1024 * 1024;
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const void * element
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
virtual void generate(Scene *scene, Progress &progress)=0
#define CCL_NAMESPACE_END
#define assert(assertion)
#define NODE_SOCKET_API_ARRAY(type_, name)
#define NODE_SOCKET_API(type_, name)
static void clear(Message &msg)
void set(const SocketType &input, bool value)