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:
-rw-r--r--intern/cycles/test/CMakeLists.txt1
-rw-r--r--intern/cycles/test/util_transform_test.cpp53
-rw-r--r--intern/cycles/util/util_math_float4.h18
-rw-r--r--intern/cycles/util/util_transform.cpp28
-rw-r--r--intern/cycles/util/util_transform.h11
-rw-r--r--source/blender/blenkernel/BKE_action.h5
-rw-r--r--source/blender/blenkernel/intern/action.c49
-rw-r--r--source/blender/blenkernel/intern/armature.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c4
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc8
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc21
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h5
-rw-r--r--source/blender/editors/armature/armature_relations.c1
-rw-r--r--source/blender/makesdna/DNA_action_types.h3
14 files changed, 190 insertions, 19 deletions
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_math_float4.h b/intern/cycles/util/util_math_float4.h
index cd4b3e3b74c..ec5328adb31 100644
--- a/intern/cycles/util/util_math_float4.h
+++ b/intern/cycles/util/util_math_float4.h
@@ -477,6 +477,24 @@ ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b)
return (b != 0.0f) ? a / b : make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
+ccl_device_inline bool isfinite4_safe(float4 v)
+{
+ return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z) && isfinite_safe(v.w);
+}
+
+ccl_device_inline float4 ensure_finite4(float4 v)
+{
+ if (!isfinite_safe(v.x))
+ v.x = 0.0f;
+ if (!isfinite_safe(v.y))
+ v.y = 0.0f;
+ if (!isfinite_safe(v.z))
+ v.z = 0.0f;
+ if (!isfinite_safe(v.w))
+ v.w = 0.0f;
+ return v;
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_FLOAT4_H__ */
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)
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index d0a6264d5cf..d8bbd389aa6 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -466,6 +466,17 @@ ccl_device void transform_motion_array_interpolate(Transform *tfm,
transform_compose(tfm, &decomp);
}
+ccl_device_inline bool transform_isfinite_safe(Transform *tfm)
+{
+ return isfinite4_safe(tfm->x) && isfinite4_safe(tfm->y) && isfinite4_safe(tfm->z);
+}
+
+ccl_device_inline bool transform_decomposed_isfinite_safe(DecomposedTransform *decomp)
+{
+ return isfinite4_safe(decomp->x) && isfinite4_safe(decomp->y) && isfinite4_safe(decomp->z) &&
+ isfinite4_safe(decomp->w);
+}
+
#ifndef __KERNEL_GPU__
class BoundBox2D;
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index b7904ce1879..c3cfd4b33ea 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -129,6 +129,8 @@ void BKE_pose_channel_free(struct bPoseChannel *pchan);
void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime);
+void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime);
+
void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime);
void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime);
@@ -153,12 +155,15 @@ void BKE_pose_copy_data_ex(struct bPose **dst,
const bool copy_constraints);
void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints);
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
+void BKE_pose_channel_session_uuid_generate(struct bPoseChannel *pchan);
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
+void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose);
+
#ifndef NDEBUG
bool BKE_pose_channels_is_valid(const struct bPose *pose);
#endif
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index fa7eee83a68..85ac2c693cb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -37,6 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "BLI_session_uuid.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
@@ -482,6 +483,11 @@ void action_groups_clear_tempflags(bAction *act)
/* *************** Pose channels *************** */
+void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan)
+{
+ pchan->runtime.session_uuid = BLI_session_uuid_generate();
+}
+
/**
* Return a pointer to the pose channel of the given name
* from this pose.
@@ -524,6 +530,8 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
/* If not, create it and add it */
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
+ BKE_pose_channel_session_uuid_generate(chan);
+
BLI_strncpy(chan->name, name, sizeof(chan->name));
chan->custom_scale = 1.0f;
@@ -698,6 +706,10 @@ void BKE_pose_copy_data_ex(bPose **dst,
id_us_plus((ID *)pchan->custom);
}
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ BKE_pose_channel_session_uuid_generate(pchan);
+ }
+
/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
if (pchan->custom_tx) {
pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
@@ -726,7 +738,7 @@ void BKE_pose_copy_data_ex(bPose **dst,
pchan->draw_data = NULL; /* Drawing cache, no need to copy. */
/* Runtime data, no need to copy. */
- memset(&pchan->runtime, 0, sizeof(pchan->runtime));
+ BKE_pose_channel_runtime_reset_on_copy(&pchan->runtime);
}
/* for now, duplicate Bone Groups too when doing this */
@@ -956,6 +968,14 @@ void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
memset(runtime, 0, sizeof(*runtime));
}
+/* Reset all non-persistent fields. */
+void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime)
+{
+ const SessionUUID uuid = runtime->session_uuid;
+ memset(runtime, 0, sizeof(*runtime));
+ runtime->session_uuid = uuid;
+}
+
/** Deallocates runtime cache of a pose channel */
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime)
{
@@ -1692,3 +1712,30 @@ void what_does_obaction(Object *ob,
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
}
}
+
+void BKE_pose_check_uuids_unique_and_report(const bPose *pose)
+{
+ if (pose == NULL) {
+ return;
+ }
+
+ struct GSet *used_uuids = BLI_gset_new(
+ BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids");
+
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
+ const SessionUUID *session_uuid = &pchan->runtime.session_uuid;
+ if (!BLI_session_uuid_is_generated(session_uuid)) {
+ printf("Pose channel %s does not have UUID generated.\n", pchan->name);
+ continue;
+ }
+
+ if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) {
+ printf("Pose channel %s has duplicate UUID generated.\n", pchan->name);
+ continue;
+ }
+
+ BLI_gset_insert(used_uuids, (void *)session_uuid);
+ }
+
+ BLI_gset_free(used_uuids, NULL);
+}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index c977ebe4ae2..631ce4edd20 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2205,7 +2205,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
pchan->mpath = NULL;
/* Reset runtime data, we don't want to share that with the proxy. */
- BKE_pose_channel_runtime_reset(&pchanw.runtime);
+ BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime);
/* this is freed so copy a copy, else undo crashes */
if (pchanw.prop) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 398598a3fb6..6d220d1fd1d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5145,6 +5145,9 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose)
pose->chan_array = NULL;
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ BKE_pose_channel_runtime_reset(&pchan->runtime);
+ BKE_pose_channel_session_uuid_generate(pchan);
+
pchan->bone = NULL;
BLO_read_data_address(reader, &pchan->parent);
BLO_read_data_address(reader, &pchan->child);
@@ -5170,7 +5173,6 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose)
CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
pchan->draw_data = NULL;
- BKE_pose_channel_runtime_reset(&pchan->runtime);
}
pose->ikdata = NULL;
if (pose->ikparam != NULL) {
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 9956391a2d7..89df41944e5 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -288,6 +288,14 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid)
{
const ID *id_for_copy = id;
+ if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
+ const ID_Type id_type = GS(id_for_copy->name);
+ if (id_type == ID_OB) {
+ const Object *object = reinterpret_cast<const Object *>(id_for_copy);
+ BKE_pose_check_uuids_unique_and_report(object->pose);
+ }
+ }
+
#ifdef NESTED_ID_NASTY_WORKAROUND
NestedIDHackTempStorage id_hack_storage;
id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
index e0957a10cb1..88334e41192 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
@@ -85,11 +85,11 @@ void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object)
{
if (object->pose != nullptr) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- /* This is nullptr in Edit mode. */
- if (pchan->orig_pchan != nullptr) {
- pose_channel_runtime_data.add(pchan->orig_pchan, pchan->runtime);
- BKE_pose_channel_runtime_reset(&pchan->runtime);
- }
+ const SessionUUID &session_uuid = pchan->runtime.session_uuid;
+ BLI_assert(BLI_session_uuid_is_generated(&session_uuid));
+
+ pose_channel_runtime_data.add(session_uuid, pchan->runtime);
+ BKE_pose_channel_runtime_reset(&pchan->runtime);
}
}
}
@@ -171,13 +171,10 @@ void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
{
if (object->pose != nullptr) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- /* This is nullptr in Edit mode. */
- if (pchan->orig_pchan != nullptr) {
- optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(
- pchan->orig_pchan);
- if (runtime.has_value()) {
- pchan->runtime = *runtime;
- }
+ const SessionUUID &session_uuid = pchan->runtime.session_uuid;
+ optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uuid);
+ if (runtime.has_value()) {
+ pchan->runtime = *runtime;
}
}
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h
index 04d7fb1bc22..a10f15634ce 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h
@@ -24,6 +24,9 @@
#pragma once
#include "DNA_object_types.h"
+#include "DNA_session_uuid_types.h"
+
+#include "BLI_session_uuid.h"
#include "intern/eval/deg_eval_runtime_backup_modifier.h"
#include "intern/eval/deg_eval_runtime_backup_pose.h"
@@ -54,7 +57,7 @@ class ObjectRuntimeBackup {
short base_flag;
unsigned short base_local_view_bits;
ModifierRuntimeDataBackup modifier_runtime_data;
- Map<bPoseChannel *, bPoseChannel_Runtime> pose_channel_runtime_data;
+ Map<SessionUUID, bPoseChannel_Runtime> pose_channel_runtime_data;
};
} // namespace deg
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 0dd35fb9fdc..a737916e9a2 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -384,6 +384,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
BLI_remlink(curarm->edbo, curbone);
BLI_addtail(arm->edbo, curbone);
+ /* Pose channel is moved from one storage to another, its UUID is still unique. */
BLI_remlink(&opose->chanbase, pchan);
BLI_addtail(&pose->chanbase, pchan);
BKE_pose_channels_hash_free(opose);
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 98e858dbf41..74293e25c5c 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -30,6 +30,7 @@
#include "DNA_ID.h"
#include "DNA_listBase.h"
+#include "DNA_session_uuid_types.h"
#include "DNA_userdef_types.h" /* ThemeWireColor */
#include "DNA_vec_types.h"
#include "DNA_view2d_types.h"
@@ -188,6 +189,8 @@ struct DualQuat;
struct Mat4;
typedef struct bPoseChannel_Runtime {
+ SessionUUID session_uuid;
+
/* Cached dual quaternion for deformation. */
struct DualQuat deform_dual_quat;