diff options
Diffstat (limited to 'intern/cycles/render/alembic.h')
-rw-r--r-- | intern/cycles/render/alembic.h | 92 |
1 files changed, 82 insertions, 10 deletions
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); } }; |