[Bf-blender-cvs] [b64f0fab068] master: Cycles: internal support for Alembic procedurals

Kevin Dietrich noreply at git.blender.org
Mon Jan 25 15:52:19 CET 2021


Commit: b64f0fab068169a7c379be728aae8994eb893b18
Author: Kevin Dietrich
Date:   Mon Jan 25 15:12:00 2021 +0100
Branches: master
https://developer.blender.org/rBb64f0fab068169a7c379be728aae8994eb893b18

Cycles: internal support for Alembic procedurals

The implementation is currently optimized to load animation sequences once
and then quickly scrubbing through them. Later on an option should be added
to optimize for memory usage and only load the current frame into memory.

Currently mesh and curve objects are supported, including support for UV and
vertex color attributes. Missing still is support for arbitrary attributes and
motion blur, as well as better handling of changing topology. Shader assignments
are made using FaceSets found in the Alembic archive.

The animation (and constant) data of the objects inside the Alembic archive is
loaded at once at the beginning of the render and kept inside a cache. At each
frame change we simply update the right socket of the corresponding Cycles node
if the data is animated. This allows for fast playback in the viewport
(depending on the scene size and compute power).

Note this is not yet exposed in the Blender UI, it's a feature that is still under
development and not ready for general use.

Ref T79174, D3089

===================================================================

M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/render/CMakeLists.txt
A	intern/cycles/render/alembic.cpp
A	intern/cycles/render/alembic.h
M	intern/cycles/render/scene.cpp
M	intern/cycles/render/scene.h
M	intern/cycles/render/shader.cpp

===================================================================

diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index aae2c35da4b..a8319960b96 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -59,7 +59,6 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
       b_scene(b_scene),
       shader_map(scene),
       object_map(scene),
-      procedural_map(scene),
       geometry_map(scene),
       light_map(scene),
       particle_system_map(scene),
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 9fcec4df5c2..389f913b145 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC_SYS
 )
 
 set(SRC
+  alembic.cpp
   attribute.cpp
   background.cpp
   bake.cpp
@@ -65,6 +66,7 @@ set(SRC
 )
 
 set(SRC_HEADERS
+  alembic.h
   attribute.h
   bake.h
   background.h
@@ -146,6 +148,16 @@ if(WITH_OPENVDB)
   )
 endif()
 
+if(WITH_ALEMBIC)
+  add_definitions(-DWITH_ALEMBIC)
+  list(APPEND INC_SYS
+    ${ALEMBIC_INCLUDE_DIRS}
+  )
+  list(APPEND LIB
+    ${ALEMBIC_LIBRARIES}
+  )
+endif()
+
 if(WITH_NANOVDB)
   list(APPEND INC_SYS
     ${NANOVDB_INCLUDE_DIRS}
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp
new file mode 100644
index 00000000000..34e547fe529
--- /dev/null
+++ b/intern/cycles/render/alembic.cpp
@@ -0,0 +1,1869 @@
+/*
+ * Copyright 2011-2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/alembic.h"
+
+#include "render/camera.h"
+#include "render/curves.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/shader.h"
+
+#include "util/util_foreach.h"
+#include "util/util_progress.h"
+#include "util/util_transform.h"
+#include "util/util_vector.h"
+
+#ifdef WITH_ALEMBIC
+
+using namespace Alembic::AbcGeom;
+
+CCL_NAMESPACE_BEGIN
+
+/* TODO(@kevindietrich): motion blur support */
+
+void CachedData::clear()
+{
+  attributes.clear();
+  curve_first_key.clear();
+  curve_keys.clear();
+  curve_radius.clear();
+  curve_shader.clear();
+  num_ngons.clear();
+  shader.clear();
+  subd_creases_edge.clear();
+  subd_creases_weight.clear();
+  subd_face_corners.clear();
+  subd_num_corners.clear();
+  subd_ptex_offset.clear();
+  subd_smooth.clear();
+  subd_start_corner.clear();
+  transforms.clear();
+  triangles.clear();
+  triangles_loops.clear();
+  vertices.clear();
+
+  for (CachedAttribute &attr : attributes) {
+    attr.data.clear();
+  }
+
+  attributes.clear();
+}
+
+CachedData::CachedAttribute &CachedData::add_attribute(const ustring &name,
+                                                       const TimeSampling &time_sampling)
+{
+  for (auto &attr : attributes) {
+    if (attr.name == name) {
+      return attr;
+    }
+  }
+
+  CachedAttribute &attr = attributes.emplace_back();
+  attr.name = name;
+  attr.data.set_time_sampling(time_sampling);
+  return attr;
+}
+
+bool CachedData::is_constant() const
+{
+#  define CHECK_IF_CONSTANT(data) \
+    if (!data.is_constant()) { \
+      return false; \
+    }
+
+  CHECK_IF_CONSTANT(curve_first_key)
+  CHECK_IF_CONSTANT(curve_keys)
+  CHECK_IF_CONSTANT(curve_radius)
+  CHECK_IF_CONSTANT(curve_shader)
+  CHECK_IF_CONSTANT(num_ngons)
+  CHECK_IF_CONSTANT(shader)
+  CHECK_IF_CONSTANT(subd_creases_edge)
+  CHECK_IF_CONSTANT(subd_creases_weight)
+  CHECK_IF_CONSTANT(subd_face_corners)
+  CHECK_IF_CONSTANT(subd_num_corners)
+  CHECK_IF_CONSTANT(subd_ptex_offset)
+  CHECK_IF_CONSTANT(subd_smooth)
+  CHECK_IF_CONSTANT(subd_start_corner)
+  CHECK_IF_CONSTANT(transforms)
+  CHECK_IF_CONSTANT(triangles)
+  CHECK_IF_CONSTANT(triangles_loops)
+  CHECK_IF_CONSTANT(vertices)
+
+  for (const CachedAttribute &attr : attributes) {
+    if (!attr.data.is_constant()) {
+      return false;
+    }
+  }
+
+  return true;
+
+#  undef CHECK_IF_CONSTANT
+}
+
+void CachedData::invalidate_last_loaded_time(bool attributes_only)
+{
+  if (attributes_only) {
+    for (CachedAttribute &attr : attributes) {
+      attr.data.invalidate_last_loaded_time();
+    }
+
+    return;
+  }
+
+  curve_first_key.invalidate_last_loaded_time();
+  curve_keys.invalidate_last_loaded_time();
+  curve_radius.invalidate_last_loaded_time();
+  curve_shader.invalidate_last_loaded_time();
+  num_ngons.invalidate_last_loaded_time();
+  shader.invalidate_last_loaded_time();
+  subd_creases_edge.invalidate_last_loaded_time();
+  subd_creases_weight.invalidate_last_loaded_time();
+  subd_face_corners.invalidate_last_loaded_time();
+  subd_num_corners.invalidate_last_loaded_time();
+  subd_ptex_offset.invalidate_last_loaded_time();
+  subd_smooth.invalidate_last_loaded_time();
+  subd_start_corner.invalidate_last_loaded_time();
+  transforms.invalidate_last_loaded_time();
+  triangles.invalidate_last_loaded_time();
+  triangles_loops.invalidate_last_loaded_time();
+  vertices.invalidate_last_loaded_time();
+}
+
+void CachedData::set_time_sampling(TimeSampling time_sampling)
+{
+  curve_first_key.set_time_sampling(time_sampling);
+  curve_keys.set_time_sampling(time_sampling);
+  curve_radius.set_time_sampling(time_sampling);
+  curve_shader.set_time_sampling(time_sampling);
+  num_ngons.set_time_sampling(time_sampling);
+  shader.set_time_sampling(time_sampling);
+  subd_creases_edge.set_time_sampling(time_sampling);
+  subd_creases_weight.set_time_sampling(time_sampling);
+  subd_face_corners.set_time_sampling(time_sampling);
+  subd_num_corners.set_time_sampling(time_sampling);
+  subd_ptex_offset.set_time_sampling(time_sampling);
+  subd_smooth.set_time_sampling(time_sampling);
+  subd_start_corner.set_time_sampling(time_sampling);
+  transforms.set_time_sampling(time_sampling);
+  triangles.set_time_sampling(time_sampling);
+  triangles_loops.set_time_sampling(time_sampling);
+  vertices.set_time_sampling(time_sampling);
+
+  for (CachedAttribute &attr : attributes) {
+    attr.data.set_time_sampling(time_sampling);
+  }
+}
+
+/* get the sample times to load data for the given the start and end frame of the procedural */
+static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
+                                               const TimeSampling &time_sampling,
+                                               size_t num_samples)
+{
+  set<chrono_t> result;
+
+  if (num_samples < 2) {
+    result.insert(0.0);
+    return result;
+  }
+
+  double start_frame = (double)(proc->get_start_frame() / proc->get_frame_rate());
+  double end_frame = (double)((proc->get_end_frame() + 1) / proc->get_frame_rate());
+
+  size_t start_index = time_sampling.getFloorIndex(start_frame, num_samples).first;
+  size_t end_index = time_sampling.getCeilIndex(end_frame, num_samples).first;
+
+  for (size_t i = start_index; i < end_index; ++i) {
+    result.insert(time_sampling.getSampleTime(i));
+  }
+
+  return result;
+}
+
+static float3 make_float3_from_yup(const V3f &v)
+{
+  return make_float3(v.x, -v.z, v.y);
+}
+
+static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
+{
+  V3d scale, shear, rotation, translation;
+  extractSHRT(mtx,
+              scale,
+              shear,
+              rotation,
+              translation,
+              true,
+              IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY);
+
+  M44d rot_mat, scale_mat, trans_mat;
+  rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y));
+  scale_mat.setScale(V3d(scale.x, scale.z, scale.y));
+  trans_mat.setTranslation(V3d(translation.x, -translation.z, translation.y));
+
+  M44d temp_mat = scale_mat * rot_mat * trans_mat;
+
+  scale_mat.setScale(static_cast<double>(scale_mult));
+
+  return temp_mat * scale_mat;
+}
+
+static void transform_decompose(
+    const M44d &mat, V3d &scale, V3d &shear, Quatd &rotation, V3d &translation)
+{
+  M44d mat_remainder(mat);
+
+  /* extract scale and shear */
+  Imath::extractAndRemoveScalingAndShear(mat_remainder, scale, shear);
+
+  /* extract translation */
+  translation.x = mat_remainder[3][0];
+  translation.y = mat_remainder[3][1];
+  translation.z = mat_remainder[3][2];
+
+  /* extract rotation */
+  rotation = extractQuat(mat_remainder);
+}
+
+static M44d transform_compose(const V3d &scale,
+                              const V3d &shear,
+                              const Quatd &rotation,
+                              const V3d &translation)
+{
+  M44d scale_mat, shear_mat, rot_mat, trans_mat;
+
+  scale_mat.setScale(scale);
+  shear_mat.setShear(shear);
+  rot_mat = rotation.toMatrix44();
+  trans_mat.setTranslation(translation);
+
+  return scale_mat * shear_mat * rot_mat * trans_mat;
+}
+
+/* get the matrix for the specified time, or return the identity matrix if there is no exact match
+ */
+static M44d get_matrix_for_time(const MatrixSampleMap &samples, chrono_t time)
+{
+  MatrixSampleMap::const_iterator iter = samples.find(time);
+  if (iter != samples.end()) {
+    return iter->second;
+  }
+
+  return M44d();
+}
+
+/* get the matrix for the specified time, or interpolate between samples if there is no exact match
+ */
+static M44d get_interpolated_matrix_for_time(const MatrixSampleMap &samples, chrono_t time)
+{
+  if (samples.empty()) {
+    return M44d();
+  }
+
+  /* see if exact match */
+  MatrixSampleMap::const_iterator iter = samples.find(time);
+  if (iter != samples.end()) {
+    return iter->second;
+  }
+
+  if (samples.size() == 1) {
+    return samples.begin()->second;
+  }
+
+  if (time <= samples.begin()->first) {
+    return samples.begin()->second;
+  }
+
+  if (time >= samples.rbegin()->first) {
+    return samples.rbegin()->second;
+  }
+
+  /* find previous and next time sample to interpolate */
+  chrono_t prev_time = sam

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list