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
path: root/intern
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2021-05-03 08:34:26 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2021-05-03 17:20:06 +0300
commit9f1e20e74f0ff0635cc58eab6a09f9a7f3d017ad (patch)
treef4064f40d9b1d26bb63f019b177982d6770587ed /intern
parente2c671e34cd7d35477a8c2cde07e3b2af0d67a2a (diff)
Alembic Procedural: precompute vertex normals
This precomputes vertex normals in the procedural and caches them in case none are found in the archive. This only applies to polygon meshes, as subdivision meshes are yet to be subdivided, so it is useless to do this computation. The goal here is to speed up data updates between frames, as computing normals shows up in profiles even for large objects. This saves around 16% of update time for a production file.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/render/alembic_read.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/intern/cycles/render/alembic_read.cpp b/intern/cycles/render/alembic_read.cpp
index 0a80e34b23e..4806eb26638 100644
--- a/intern/cycles/render/alembic_read.cpp
+++ b/intern/cycles/render/alembic_read.cpp
@@ -86,6 +86,55 @@ static void read_data_loop(AlembicProcedural *proc,
/* Polygon Mesh Geometries. */
+/* Compute the vertex normals in case none are present in the IPolyMeshSchema, this is mostly used
+ * to avoid computing them in the GeometryManager in order to speed up data updates. */
+static void compute_vertex_normals(CachedData &cache, double current_time)
+{
+ if (cache.vertices.size() == 0) {
+ return;
+ }
+
+ CachedData::CachedAttribute &attr_normal = cache.add_attribute(
+ ustring("N"), cache.vertices.get_time_sampling());
+ attr_normal.std = ATTR_STD_VERTEX_NORMAL;
+ attr_normal.element = ATTR_ELEMENT_VERTEX;
+ attr_normal.type_desc = TypeNormal;
+
+ const array<float3> *vertices =
+ cache.vertices.data_for_time_no_check(current_time).get_data_or_null();
+ const array<int3> *triangles =
+ cache.triangles.data_for_time_no_check(current_time).get_data_or_null();
+
+ if (!vertices || !triangles) {
+ attr_normal.data.add_no_data(current_time);
+ return;
+ }
+
+ array<char> attr_data(vertices->size() * sizeof(float3));
+ float3 *attr_ptr = reinterpret_cast<float3 *>(attr_data.data());
+ memset(attr_ptr, 0, vertices->size() * sizeof(float3));
+
+ for (size_t t = 0; t < triangles->size(); ++t) {
+ const int3 tri_int3 = triangles->data()[t];
+ Mesh::Triangle tri{};
+ tri.v[0] = tri_int3[0];
+ tri.v[1] = tri_int3[1];
+ tri.v[2] = tri_int3[2];
+
+ const float3 tri_N = tri.compute_normal(vertices->data());
+
+ for (int v = 0; v < 3; ++v) {
+ attr_ptr[tri_int3[v]] += tri_N;
+ }
+ }
+
+ for (size_t v = 0; v < vertices->size(); ++v) {
+ attr_ptr[v] = normalize(attr_ptr[v]);
+ }
+
+ attr_normal.data.add_data(attr_data, current_time);
+}
+
static void add_normals(const Int32ArraySamplePtr face_indices,
const IN3fGeomParam &normals,
double time,
@@ -327,6 +376,9 @@ static void read_poly_mesh_geometry(CachedData &cached_data,
if (data.normals.valid()) {
add_normals(face_indices, data.normals, time, cached_data);
}
+ else {
+ compute_vertex_normals(cached_data, time);
+ }
}
void read_geometry_data(AlembicProcedural *proc,