[Bf-blender-cvs] [51af20b8561] blender-v2.90-release: Cycles: Fix nan in decomposed transform for degenerated input

Sergey Sharybin noreply at git.blender.org
Tue Aug 4 12:07:55 CEST 2020


Commit: 51af20b8561b39d41ecd91abbeae7348dc1d4cdf
Author: Sergey Sharybin
Date:   Mon Aug 3 11:04:51 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rB51af20b8561b39d41ecd91abbeae7348dc1d4cdf

Cycles: Fix nan in decomposed transform for degenerated input

The decomposed transform would have consists of nan values if the input
transform had zero scale.

Now the decomposition will check for zero scale, and if it is detected
then the result will be ensured to be finite. Additionally, rotation
value will be copied from previous/next time step to help avoiding
obscure interpolation.

The latter step can become more comprehensive than the current simple
implementation.

Differential Revision: https://developer.blender.org/D8450

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

M	intern/cycles/test/CMakeLists.txt
A	intern/cycles/test/util_transform_test.cpp
M	intern/cycles/util/util_transform.cpp

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

diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt
index 6dcc7f7b3dd..07b345baff8 100644
--- a/intern/cycles/test/CMakeLists.txt
+++ b/intern/cycles/test/CMakeLists.txt
@@ -112,3 +112,4 @@ set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${C
 CYCLES_TEST(util_avxf_avx "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
 set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
 CYCLES_TEST(util_avxf_avx2 "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+CYCLES_TEST(util_transform "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
diff --git a/intern/cycles/test/util_transform_test.cpp b/intern/cycles/test/util_transform_test.cpp
new file mode 100644
index 00000000000..58ce0fdfee4
--- /dev/null
+++ b/intern/cycles/test/util_transform_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011-2020 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 "testing/testing.h"
+
+#include "util/util_transform.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+TEST(transform_motion_decompose, Degenerated)
+{
+  // Simple case: single degenerated matrix.
+  {
+    vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f)};
+    vector<DecomposedTransform> decomp(motion.size());
+    transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+    EXPECT_TRUE(transform_decomposed_isfinite_safe(&decomp[0]));
+  }
+
+  // Copy from previous to current.
+  {
+    vector<Transform> motion = {transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f)),
+                                transform_scale(0.0f, 0.0f, 0.0f)};
+    vector<DecomposedTransform> decomp(motion.size());
+    transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+    EXPECT_NEAR(len(decomp[1].x - decomp[0].x), 0.0f, 1e-6f);
+  }
+
+  // Copy from next to current.
+  {
+    vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f),
+                                transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f))};
+    vector<DecomposedTransform> decomp(motion.size());
+    transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+    EXPECT_NEAR(len(decomp[0].x - decomp[1].x), 0.0f, 1e-6f);
+  }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 101122740d7..6417752f704 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -269,17 +269,17 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf
   /* extract scale and shear first */
   float3 scale, shear;
   scale.x = len(colx);
-  colx /= scale.x;
+  colx = safe_divide_float3_float(colx, scale.x);
   shear.z = dot(colx, coly);
   coly -= shear.z * colx;
   scale.y = len(coly);
-  coly /= scale.y;
+  coly = safe_divide_float3_float(coly, scale.y);
   shear.y = dot(colx, colz);
   colz -= shear.y * colx;
   shear.x = dot(coly, colz);
   colz -= shear.x * coly;
   scale.z = len(colz);
-  colz /= scale.z;
+  colz = safe_divide_float3_float(colz, scale.z);
 
   transform_set_column(&M, 0, colx);
   transform_set_column(&M, 1, coly);
@@ -300,6 +300,7 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf
 
 void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
 {
+  /* Decompose and correct rotation. */
   for (size_t i = 0; i < size; i++) {
     transform_decompose(decomp + i, motion + i);
 
@@ -310,6 +311,27 @@ void transform_motion_decompose(DecomposedTransform *decomp, const Transform *mo
         decomp[i].x = -decomp[i].x;
     }
   }
+
+  /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
+   * rotation interpolation when the scale goes to 0 for a time step.
+   *
+   * Note that this is very simple and naive implementation, which only deals with degenerated
+   * scale happening only on one frame. It is possible to improve it further by interpolating
+   * rotation into s degenerated range using rotation from timesteps from adjacent non-degenerated
+   * time steps. */
+  for (size_t i = 0; i < size; i++) {
+    const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w);
+    if (!is_zero(scale)) {
+      continue;
+    }
+
+    if (i > 0) {
+      decomp[i].x = decomp[i - 1].x;
+    }
+    else if (i < size - 1) {
+      decomp[i].x = decomp[i + 1].x;
+    }
+  }
 }
 
 Transform transform_from_viewplane(BoundBox2D &viewplane)



More information about the Bf-blender-cvs mailing list