diff options
-rw-r--r-- | intern/cycles/render/alembic.cpp | 29 | ||||
-rw-r--r-- | intern/cycles/render/alembic.h | 92 |
2 files changed, 100 insertions, 21 deletions
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp index 59454eac8a5..0841a3c09cd 100644 --- a/intern/cycles/render/alembic.cpp +++ b/intern/cycles/render/alembic.cpp @@ -408,8 +408,10 @@ static void add_uvs(AlembicProcedural *proc, continue; } - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); - const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); + const array<int3> *triangles_loops = + cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null(); if (!triangles || !triangles_loops) { continue; @@ -456,7 +458,8 @@ static void add_normals(const Int32ArraySamplePtr face_indices, *normals.getTimeSampling()); attr.std = ATTR_STD_VERTEX_NORMAL; - const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + const array<float3> *vertices = + cached_data.vertices.data_for_time_no_check(time).get_data_or_null(); if (!vertices) { return; @@ -491,7 +494,8 @@ static void add_normals(const Int32ArraySamplePtr face_indices, *normals.getTimeSampling()); attr.std = ATTR_STD_VERTEX_NORMAL; - const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + const array<float3> *vertices = + cached_data.vertices.data_for_time_no_check(time).get_data_or_null(); if (!vertices) { return; @@ -1109,9 +1113,10 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER; attribute.type_desc = TypeFloat2; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); - const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check( - time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); + const array<int3> *triangles_loops = + cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null(); if (!triangles || !triangles_loops) { return; @@ -1164,7 +1169,8 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER_BYTE; attribute.type_desc = TypeRGBA; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); if (!triangles) { return; @@ -1220,7 +1226,8 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER_BYTE; attribute.type_desc = TypeRGBA; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); if (!triangles) { return; @@ -1259,7 +1266,7 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data, set<Attribute *> cached_attributes; for (CachedData::CachedAttribute &attribute : cached_data.attributes) { - const array<char> *attr_data = attribute.data.data_for_time(frame_time); + const array<char> *attr_data = attribute.data.data_for_time(frame_time).get_data_or_null(); Attribute *attr = nullptr; if (attribute.std != ATTR_STD_NONE) { @@ -1558,7 +1565,7 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket()); - array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time); + array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time).get_data_or_null(); if (triangle_data) { array<int> triangles; array<bool> smooth; diff --git a/intern/cycles/render/alembic.h b/intern/cycles/render/alembic.h index 6552336e6ab..0fc02f1da23 100644 --- a/intern/cycles/render/alembic.h +++ b/intern/cycles/render/alembic.h @@ -50,6 +50,78 @@ template<typename> struct is_array : public std::false_type { template<typename T> struct is_array<array<T>> : public std::true_type { }; +/* Holds the data for a cache lookup at a given time, as well as informations to + * help disambiguate successes or failures to get data from the cache. */ +template<typename T> class CacheLookupResult { + enum class State { + NEW_DATA, + ALREADY_LOADED, + NO_DATA_FOR_TIME, + }; + + T *data; + State state; + + protected: + /* Prevent default construction outside of the class: for a valid result, we + * should use the static functions below. */ + CacheLookupResult() = default; + + public: + static CacheLookupResult new_data(T *data_) + { + CacheLookupResult result; + result.data = data_; + result.state = State::NEW_DATA; + return result; + } + + static CacheLookupResult no_data_found_for_time() + { + CacheLookupResult result; + result.data = nullptr; + result.state = State::NO_DATA_FOR_TIME; + return result; + } + + static CacheLookupResult already_loaded() + { + CacheLookupResult result; + result.data = nullptr; + result.state = State::ALREADY_LOADED; + return result; + } + + /* This should only be call if new data is available. */ + const T &get_data() const + { + assert(state == State::NEW_DATA); + assert(data != nullptr); + return *data; + } + + T *get_data_or_null() const + { + // data_ should already be null if there is no new data so no need to check + return data; + } + + bool has_new_data() const + { + return state == State::NEW_DATA; + } + + bool has_already_loaded() const + { + return state == State::ALREADY_LOADED; + } + + bool has_no_data_for_time() const + { + return state == State::NO_DATA_FOR_TIME; + } +}; + /* Store the data set for an animation at every time points, or at the beginning of the animation * for constant data. * @@ -79,10 +151,10 @@ template<typename T> class DataStore { /* Get the data for the specified time. * Return nullptr if there is no data or if the data for this time was already loaded. */ - T *data_for_time(double time) + CacheLookupResult<T> data_for_time(double time) { if (size() == 0) { - return nullptr; + return CacheLookupResult<T>::no_data_found_for_time(); } std::pair<size_t, Alembic::Abc::chrono_t> index_pair; @@ -90,26 +162,26 @@ template<typename T> class DataStore { DataTimePair &data_pair = data[index_pair.first]; if (last_loaded_time == data_pair.time) { - return nullptr; + return CacheLookupResult<T>::already_loaded(); } last_loaded_time = data_pair.time; - return &data_pair.data; + return CacheLookupResult<T>::new_data(&data_pair.data); } /* get the data for the specified time, but do not check if the data was already loaded for this * time return nullptr if there is no data */ - T *data_for_time_no_check(double time) + CacheLookupResult<T> data_for_time_no_check(double time) { if (size() == 0) { - return nullptr; + return CacheLookupResult<T>::no_data_found_for_time(); } std::pair<size_t, Alembic::Abc::chrono_t> index_pair; index_pair = time_sampling.getNearIndex(time, data.size()); DataTimePair &data_pair = data[index_pair.first]; - return &data_pair.data; + return CacheLookupResult<T>::new_data(&data_pair.data); } void add_data(T &data_, double time) @@ -149,15 +221,15 @@ template<typename T> class DataStore { * data for this time or it was already loaded, do nothing. */ void copy_to_socket(double time, Node *node, const SocketType *socket) { - T *data_ = data_for_time(time); + CacheLookupResult<T> result = data_for_time(time); - if (data_ == nullptr) { + if (!result.has_new_data()) { return; } /* TODO(kevindietrich): arrays are emptied when passed to the sockets, so for now we copy the * arrays to avoid reloading the data */ - T value = *data_; + T value = result.get_data(); node->set(*socket, value); } }; |