16# include <Alembic/AbcCoreFactory/All.h>
17# include <Alembic/AbcGeom/All.h>
21class AlembicProcedural;
27using MatrixSampleMap = std::map<Alembic::Abc::chrono_t, Alembic::Abc::M44d>;
29struct MatrixSamplesData {
30 MatrixSampleMap *samples =
nullptr;
31 Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling;
35template<
typename>
struct is_array :
public std::false_type {};
37template<
typename T>
struct is_array<
array<T>> :
public std::true_type {};
41template<
typename T>
class CacheLookupResult {
54 CacheLookupResult() =
default;
57 static CacheLookupResult new_data(T *data_)
61 result.state = State::NEW_DATA;
65 static CacheLookupResult no_data_found_for_time()
68 result.data =
nullptr;
69 result.state = State::NO_DATA_FOR_TIME;
73 static CacheLookupResult already_loaded()
76 result.data =
nullptr;
77 result.state = State::ALREADY_LOADED;
82 const T &get_data()
const
84 assert(
state == State::NEW_DATA);
85 assert(data !=
nullptr);
89 T *get_data_or_null()
const
95 bool has_new_data()
const
97 return state == State::NEW_DATA;
100 bool has_already_loaded()
const
102 return state == State::ALREADY_LOADED;
105 bool has_no_data_for_time()
const
107 return state == State::NO_DATA_FOR_TIME;
116template<
typename T>
class DataStore {
118 struct TimeIndexPair {
122 double source_time = 0;
136 Alembic::AbcCoreAbstract::TimeSampling time_sampling{};
138 double last_loaded_time = std::numeric_limits<double>::max();
142 Alembic::AbcCoreAbstract::ArraySample::Key key1;
143 Alembic::AbcCoreAbstract::ArraySample::Key key2;
145 void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_)
147 time_sampling = time_sampling_;
150 Alembic::AbcCoreAbstract::TimeSampling get_time_sampling()
const
152 return time_sampling;
157 CacheLookupResult<T> data_for_time(
double time)
160 return CacheLookupResult<T>::no_data_found_for_time();
163 const TimeIndexPair &index = get_index_for_time(time);
165 if (index.index == -1ul) {
166 return CacheLookupResult<T>::no_data_found_for_time();
169 if (last_loaded_time == index.time || last_loaded_time == index.source_time) {
170 return CacheLookupResult<T>::already_loaded();
173 last_loaded_time = index.source_time;
175 assert(index.index < data.size());
177 return CacheLookupResult<T>::new_data(&data[index.index]);
182 CacheLookupResult<T> data_for_time_no_check(
double time)
185 return CacheLookupResult<T>::no_data_found_for_time();
188 const TimeIndexPair &index = get_index_for_time(time);
190 if (index.index == -1ul) {
191 return CacheLookupResult<T>::no_data_found_for_time();
194 assert(index.index < data.size());
196 return CacheLookupResult<T>::new_data(&data[index.index]);
199 void add_data(T &data_,
double time)
201 index_data_map.push_back({
time,
time, data.size()});
203 if constexpr (is_array<T>::value) {
205 data.back().steal_data(data_);
209 data.push_back(data_);
212 void reuse_data_for_last_time(
double time)
214 const TimeIndexPair &data_index = index_data_map.back();
215 index_data_map.push_back({
time, data_index.source_time, data_index.index});
218 void add_no_data(
double time)
220 index_data_map.push_back({
time,
time, -1ul});
223 bool is_constant()
const
225 return data.size() <= 1;
235 invalidate_last_loaded_time();
237 index_data_map.clear();
240 void invalidate_last_loaded_time()
242 last_loaded_time = std::numeric_limits<double>::max();
247 void copy_to_socket(
double time,
Node *node,
const SocketType *socket)
249 CacheLookupResult<T> result = data_for_time(time);
251 if (!result.has_new_data()) {
257 T value = result.get_data();
258 node->set(*socket, value);
261 size_t memory_used()
const
263 if constexpr (is_array<T>::value) {
266 for (
const T &
array : data) {
273 return data.size() *
sizeof(
T);
277 const TimeIndexPair &get_index_for_time(
double time)
const
279 std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
280 index_pair = time_sampling.getNearIndex(time, index_data_map.size());
281 return index_data_map[index_pair.first];
290 DataStore<Transform> transforms{};
293 DataStore<array<float3>> vertices;
294 DataStore<array<int3>> triangles{};
297 DataStore<array<int>> uv_loops{};
298 DataStore<array<int>> shader{};
301 DataStore<array<int>> subd_start_corner;
302 DataStore<array<int>> subd_num_corners;
303 DataStore<array<bool>> subd_smooth;
304 DataStore<array<int>> subd_ptex_offset;
305 DataStore<array<int>> subd_face_corners;
306 DataStore<int> num_ngons;
307 DataStore<array<int>> subd_creases_edge;
308 DataStore<array<float>> subd_creases_weight;
309 DataStore<array<int>> subd_vertex_crease_indices;
310 DataStore<array<float>> subd_vertex_crease_weights;
313 DataStore<array<float3>> curve_keys;
314 DataStore<array<float>> curve_radius;
315 DataStore<array<int>> curve_first_key;
316 DataStore<array<int>> curve_shader;
319 DataStore<array<float3>> points;
320 DataStore<array<float>> radiuses;
321 DataStore<array<int>> points_shader;
323 struct CachedAttribute {
328 DataStore<array<char>> data{};
335 CachedAttribute &add_attribute(
const ustring &name,
336 const Alembic::Abc::TimeSampling &time_sampling);
338 bool is_constant()
const;
340 void invalidate_last_loaded_time(
bool attributes_only =
false);
342 void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling);
344 size_t memory_used()
const;
356class AlembicObject :
public Node {
383 friend class AlembicProcedural;
385 void set_object(
Object *
object);
388 void load_data_in_cache(CachedData &cached_data,
389 AlembicProcedural *proc,
390 Alembic::AbcGeom::IPolyMeshSchema &schema,
392 void load_data_in_cache(CachedData &cached_data,
393 AlembicProcedural *proc,
394 Alembic::AbcGeom::ISubDSchema &schema,
396 void load_data_in_cache(CachedData &cached_data,
397 AlembicProcedural *proc,
398 const Alembic::AbcGeom::ICurvesSchema &schema,
400 void load_data_in_cache(CachedData &cached_data,
401 AlembicProcedural *proc,
402 const Alembic::AbcGeom::IPointsSchema &schema,
405 bool has_data_loaded()
const;
417 bool need_shader_update =
true;
419 AlembicObject *instance_of =
nullptr;
421 Alembic::AbcCoreAbstract::TimeSamplingPtr xform_time_sampling;
422 MatrixSampleMap xform_samples;
423 Alembic::AbcGeom::IObject iobject;
426 AbcSchemaType schema_type;
428 CachedData &get_cached_data()
433 bool is_constant()
const
435 return cached_data_.is_constant();
440 cached_data_.clear();
445 bool data_loaded =
false;
447 CachedData cached_data_;
449 void setup_transform_cache(CachedData &cached_data,
float scale);
464 Alembic::AbcGeom::IArchive archive;
512 ~AlembicProcedural();
519 void tag_update(
Scene *scene);
529 AlembicObject *get_or_create_object(
const ustring &path);
533 void add_object(AlembicObject *
object);
536 void load_objects(
Progress &progress);
541 void walk_hierarchy(Alembic::AbcGeom::IObject parent,
542 const Alembic::AbcGeom::ObjectHeader &ohead,
543 MatrixSamplesData matrix_samples_data,
544 const unordered_map<string, AlembicObject *> &object_map,
549 void read_mesh(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
553 void read_curves(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
557 void read_points(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
561 void read_subd(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
563 void build_caches(
Progress &progress);
565 size_t get_prefetch_cache_size_in_bytes()
const
568 return static_cast<size_t>(prefetch_cache_size) * 1024 * 1024;
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 NODE_SOCKET_API_ARRAY(type_, name)
#define NODE_SOCKET_API(type_, name)
static void clear(Message &msg)