Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2021-03-12 03:57:41 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2021-03-12 03:57:41 +0300
commit8922d177c1019cc846928a3d5344991e000eeaa4 (patch)
tree2f52c520623cbfd48a3390b3ee4e0ad032289479
parentd72fc36ec5c632cafa2f9e2c8897ce81fc83a372 (diff)
Alembic procedural: specific result type for cache lookups
This type, CacheLookupResult, holds the data for the current time, or an explanation as to why no data is available (already loaded, or simply nothing available). This is useful to document the behavior of the code but also, in future changes, to respond appropriately for missing data.
-rw-r--r--intern/cycles/render/alembic.cpp29
-rw-r--r--intern/cycles/render/alembic.h92
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);
}
};