From f517b3a29568fd43b722973c7c46d3c358ba0dda Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 18 May 2022 16:42:49 +0200 Subject: Fix T98157: improve animation fps with better check in depsgraph Previously, the depsgraph assumed that every node tree might contain a reference to a video. This resulted noticeable overhead when there was no video. Checking whether a node tree contained a video was relatively expensive to do in the depsgraph. It is cheaper now due to the structure of the new node tree updater. This also adds an additional run-time field to `bNodeTree` (there are quite a few already). We should move those to a separate run-time struct, but not as part of a bug fix. Differential Revision: https://developer.blender.org/D14957 --- source/blender/blenkernel/intern/node.cc | 1 + .../blender/blenkernel/intern/node_tree_update.cc | 31 ++++++++++++++++++++++ .../depsgraph/intern/builder/deg_builder_nodes.cc | 19 +++++++------ .../intern/builder/deg_builder_relations.cc | 11 +++++--- source/blender/makesdna/DNA_node_types.h | 13 ++++++++- 5 files changed, 63 insertions(+), 12 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 200eefb73ec..e9c8b438284 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -670,6 +670,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) ntree->progress = nullptr; ntree->execdata = nullptr; + ntree->runtime_flag = 0; ntree->field_inferencing_interface = nullptr; BKE_ntree_update_tag_missing_runtime_data(ntree); diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index baf3a0c8d22..8afe7ce7520 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -12,6 +12,7 @@ #include "DNA_node_types.h" #include "BKE_anim_data.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_node_tree_update.h" @@ -984,6 +985,7 @@ class NodeTreeMainUpdater { this->remove_unused_previews_when_necessary(ntree); this->ensure_tree_ref(ntree, tree_ref); + this->update_has_image_animation(*tree_ref); if (ntree.type == NTREE_GEOMETRY) { if (node_field_inferencing::update_field_inferencing(*tree_ref)) { result.interface_changed = true; @@ -1254,6 +1256,35 @@ class NodeTreeMainUpdater { BKE_node_preview_remove_unused(&ntree); } + void update_has_image_animation(const NodeTreeRef &tree_ref) + { + bNodeTree &ntree = *tree_ref.btree(); + ntree.runtime_flag &= ~NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION; + if (ntree.type != NTREE_SHADER) { + return; + } + + /* Check if a used node group has an animated image. */ + for (const NodeRef *group_node : tree_ref.nodes_by_type("NodeGroup")) { + const bNodeTree *group = reinterpret_cast(group_node->bnode()->id); + if (group != nullptr) { + if (group->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) { + ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION; + return; + } + } + } + /* Check if the tree itself has an animated image. */ + for (const StringRefNull idname : {"ShaderNodeTexImage", "ShaderNodeTexEnvironment"}) + for (const NodeRef *node : tree_ref.nodes_by_type(idname)) { + Image *image = reinterpret_cast(node->bnode()->id); + if (image != nullptr && BKE_image_is_animated(image)) { + ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION; + return; + } + } + } + void update_node_levels(bNodeTree &ntree) { ntreeUpdateNodeLevels(&ntree); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 4782f1c4a5d..c6fc3cd5d0b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1078,14 +1078,17 @@ void DepsgraphNodeBuilder::build_animdata_nlastrip_targets(ListBase *strips) void DepsgraphNodeBuilder::build_animation_images(ID *id) { - /* GPU materials might use an animated image. However, these materials have no been built yet. We - * could scan the entire node tree recursively to check if any texture node has a video. That is - * quite expensive. For now just always add this operation node, because it is very fast. */ - /* TODO: Add a more precise check when it is cheaper to iterate over all image nodes in a node - * tree. */ - const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO); - - if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) { + /* GPU materials might use an animated image. However, these materials have no been built yet so + * we have to check if they might be created during evaluation. */ + bool has_image_animation = false; + if (ELEM(GS(id->name), ID_MA, ID_WO)) { + bNodeTree *ntree = *BKE_ntree_ptr_from_id(id); + if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) { + has_image_animation = true; + } + } + + if (has_image_animation || BKE_image_user_id_has_animation(id)) { ID *id_cow = get_cow_id(id); add_operation_node( id, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 5eccb5a4eb2..3eeab23823c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1446,10 +1446,15 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id) void DepsgraphRelationBuilder::build_animation_images(ID *id) { /* See #DepsgraphNodeBuilder::build_animation_images. */ - const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO); + bool has_image_animation = false; + if (ELEM(GS(id->name), ID_MA, ID_WO)) { + bNodeTree *ntree = *BKE_ntree_ptr_from_id(id); + if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) { + has_image_animation = true; + } + } - /* TODO: can we check for existence of node for performance? */ - if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) { + if (has_image_animation || BKE_image_user_id_has_animation(id)) { OperationKey image_animation_key( id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION); TimeSourceKey time_src_key; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index d18fe1b81dd..b66fe31c00e 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -499,7 +499,13 @@ typedef struct bNodeTree { int type; - char _pad1[4]; + /** + * Used to cache run-time information of the node tree. + * #eNodeTreeRuntimeFlag. + */ + uint8_t runtime_flag; + + char _pad1[3]; /** * Sockets in groups have unique identifiers, adding new sockets always @@ -601,6 +607,11 @@ typedef enum eNodeTreeExecutionMode { NTREE_EXECUTION_MODE_FULL_FRAME = 1, } eNodeTreeExecutionMode; +typedef enum eNodeTreeRuntimeFlag { + /** There is a node that references an image with animation. */ + NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION = 1 << 0, +} eNodeTreeRuntimeFlag; + /* socket value structs for input buttons * DEPRECATED now using ID properties */ -- cgit v1.2.3 From 342e12d6d92198bba8355562600a2f97bb45fed5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 14 Jan 2021 16:33:52 +0100 Subject: Subdiv: support interpolating orco coordinates in subdivision surfaces This makes changes to the opensubdiv module to support additional vertex data besides the vertex position, that is smootly interpolated the same way. This is different than varying data which is interpolated linearly. Fixes T96596: wrong generated texture coordinates with GPU subdivision. In that bug lazy subdivision would not interpolate orcos. Later on, this implementation can also be used to remove the modifier stack mechanism where modifiers are evaluated a second time for orcos, which is messy and inefficient. But that's a more risky change, this is just the part to fix the bug in 3.2. Differential Revision: https://developer.blender.org/D14973 --- source/blender/blenkernel/BKE_subdiv_eval.h | 11 ++++- source/blender/blenkernel/intern/DerivedMesh.cc | 4 ++ .../blenkernel/intern/multires_reshape_smooth.c | 4 +- source/blender/blenkernel/intern/subdiv_eval.c | 54 ++++++++++++++++++++-- source/blender/blenkernel/intern/subdiv_mesh.c | 39 ++++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h index a33140b721d..7673f18317a 100644 --- a/source/blender/blenkernel/BKE_subdiv_eval.h +++ b/source/blender/blenkernel/BKE_subdiv_eval.h @@ -15,6 +15,7 @@ extern "C" { struct Mesh; struct OpenSubdiv_EvaluatorCache; +struct OpenSubdiv_EvaluatorSettings; struct Subdiv; typedef enum eSubdivEvaluatorType { @@ -25,7 +26,8 @@ typedef enum eSubdivEvaluatorType { /* Returns true if evaluator is ready for use. */ bool BKE_subdiv_eval_begin(struct Subdiv *subdiv, eSubdivEvaluatorType evaluator_type, - struct OpenSubdiv_EvaluatorCache *evaluator_cache); + struct OpenSubdiv_EvaluatorCache *evaluator_cache, + const struct OpenSubdiv_EvaluatorSettings *settings); /* coarse_vertex_cos is an optional argument which allows to override coordinates of the coarse * mesh. */ @@ -60,6 +62,13 @@ void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv, void BKE_subdiv_eval_limit_point_and_normal( struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3]); +/* Evaluate smoothly interpolated vertex data (such as orco). */ +void BKE_subdiv_eval_vertex_data(struct Subdiv *subdiv, + const int ptex_face_index, + const float u, + const float v, + float r_vertex_data[]); + /* Evaluate face-varying layer (such as UV). */ void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv, int face_varying_channel, diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 7ca76e72839..6b43fe57e93 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -1180,6 +1180,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_id_free(nullptr, mesh_orco_cloth); } + /* Remove temporary data layer only needed for modifier evaluation. + * Save some memory, and ensure GPU subdivision does not need to deal with this. */ + CustomData_free_layers(&mesh_final->vdata, CD_CLOTH_ORCO, mesh_final->totvert); + /* Compute normals. */ if (is_own_mesh) { mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index b76e2b3aec6..8246de12ebf 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -1073,7 +1073,9 @@ static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_c converter_init(reshape_smooth_context, &converter); Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter); - BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL); + + OpenSubdiv_EvaluatorSettings evaluator_settings = {0}; + BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL, &evaluator_settings); reshape_smooth_context->reshape_subdiv = reshape_subdiv; diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c index 9edd9815400..d03c0f89948 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.c +++ b/source/blender/blenkernel/intern/subdiv_eval.c @@ -44,7 +44,8 @@ static eOpenSubdivEvaluator opensubdiv_evalutor_from_subdiv_evaluator_type( bool BKE_subdiv_eval_begin(Subdiv *subdiv, eSubdivEvaluatorType evaluator_type, - OpenSubdiv_EvaluatorCache *evaluator_cache) + OpenSubdiv_EvaluatorCache *evaluator_cache, + const OpenSubdiv_EvaluatorSettings *settings) { BKE_subdiv_stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE); if (subdiv->topology_refiner == NULL) { @@ -57,7 +58,7 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv, opensubdiv_evalutor_from_subdiv_evaluator_type(evaluator_type); BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE); subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner( - subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache); + subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache, settings); BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE); if (subdiv->evaluator == NULL) { return false; @@ -179,13 +180,52 @@ static void set_face_varying_data_from_uv(Subdiv *subdiv, MEM_freeN(buffer); } +static void set_vertex_data_from_orco(Subdiv *subdiv, const Mesh *mesh) +{ + const float(*orco)[3] = CustomData_get_layer(&mesh->vdata, CD_ORCO); + const float(*cloth_orco)[3] = CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO); + + if (orco || cloth_orco) { + OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; + const int num_verts = topology_refiner->getNumVertices(topology_refiner); + + if (orco && cloth_orco) { + /* Set one by one if have both. */ + for (int i = 0; i < num_verts; i++) { + float data[6]; + copy_v3_v3(data, orco[i]); + copy_v3_v3(data + 3, cloth_orco[i]); + evaluator->setVertexData(evaluator, data, i, 1); + } + } + else { + /* Faster single call if we have either. */ + if (orco) { + evaluator->setVertexData(evaluator, orco[0], 0, num_verts); + } + else if (cloth_orco) { + evaluator->setVertexData(evaluator, cloth_orco[0], 0, num_verts); + } + } + } +} + +static void get_mesh_evaluator_settings(OpenSubdiv_EvaluatorSettings *settings, const Mesh *mesh) +{ + settings->num_vertex_data = (CustomData_has_layer(&mesh->vdata, CD_ORCO) ? 3 : 0) + + (CustomData_has_layer(&mesh->vdata, CD_CLOTH_ORCO) ? 3 : 0); +} + bool BKE_subdiv_eval_begin_from_mesh(Subdiv *subdiv, const Mesh *mesh, const float (*coarse_vertex_cos)[3], eSubdivEvaluatorType evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache) { - if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache)) { + OpenSubdiv_EvaluatorSettings settings = {0}; + get_mesh_evaluator_settings(&settings, mesh); + if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache, &settings)) { return false; } return BKE_subdiv_eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos); @@ -208,6 +248,8 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv, const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index); set_face_varying_data_from_uv(subdiv, mesh, mloopuv, layer_index); } + /* Set vertex data to orco. */ + set_vertex_data_from_orco(subdiv, mesh); /* Update evaluator to the new coarse geometry. */ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE); subdiv->evaluator->refine(subdiv->evaluator); @@ -281,6 +323,12 @@ void BKE_subdiv_eval_limit_point_and_normal(Subdiv *subdiv, normalize_v3(r_N); } +void BKE_subdiv_eval_vertex_data( + Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_vertex_data[]) +{ + subdiv->evaluator->evaluateVertexData(subdiv->evaluator, ptex_face_index, u, v, r_vertex_data); +} + void BKE_subdiv_eval_face_varying(Subdiv *subdiv, const int face_varying_channel, const int ptex_face_index, diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 83427adcb43..e846dc2d807 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -44,6 +44,9 @@ typedef struct SubdivMeshContext { /* UV layers interpolation. */ int num_uv_layers; MLoopUV *uv_layers[MAX_MTFACE]; + /* Orco interpolation. */ + float (*orco)[3]; + float (*cloth_orco)[3]; /* Per-subdivided vertex counter of averaged values. */ int *accumulated_counters; bool have_displacement; @@ -69,6 +72,9 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx) ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX); /* UV layers interpolation. */ subdiv_mesh_ctx_cache_uv_layers(ctx); + /* Orco interpolation. */ + ctx->orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_ORCO); + ctx->cloth_orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_CLOTH_ORCO); } static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices) @@ -416,6 +422,34 @@ static void subdiv_mesh_tls_free(void *tls_v) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Evaluation helper functions + * \{ */ + +static void subdiv_vertex_orco_evaluate(const SubdivMeshContext *ctx, + const int ptex_face_index, + const float u, + const float v, + const int subdiv_vertex_index) +{ + if (ctx->orco || ctx->cloth_orco) { + float vertex_data[6]; + BKE_subdiv_eval_vertex_data(ctx->subdiv, ptex_face_index, u, v, vertex_data); + + if (ctx->orco) { + copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data); + if (ctx->cloth_orco) { + copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data + 3); + } + } + else if (ctx->cloth_orco) { + copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data); + } + } +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Accumulation helpers * \{ */ @@ -530,6 +564,8 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co); /* Apply displacement. */ add_v3_v3(subdiv_vert->co, D); + /* Evaluate undeformed texture coordinate. */ + subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index); /* Remove facedot flag. This can happen if there is more than one subsurf modifier. */ BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index); } @@ -556,6 +592,8 @@ static void evaluate_vertex_and_apply_displacement_interpolate( BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co); /* Apply displacement. */ add_v3_v3(subdiv_vert->co, D); + /* Evaluate undeformed texture coordinate. */ + subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index); } static void subdiv_mesh_vertex_displacement_every_corner_or_edge( @@ -723,6 +761,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v); BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co); subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh); + subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index); } /** \} */ -- cgit v1.2.3 From 2e70af5cd527e2c1f40e6f3af22adc3337714744 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 18 May 2022 17:00:19 +0200 Subject: Fix T97761: incorrect mixing of integers Sometimes integers are mixed using float weights. In those cases the mixed result has to be converted from into float again. Previously, this was done using a simple cast, which was unexpected because e.g. 14.999 would be cast to 14 instead of 15. Now, the values are rounded properly. This can affect existing files unfortunately without a good option for versioning. Gladly, very few files seem to depend on the details of the old behavior. Differential Revision: https://developer.blender.org/D14892 --- source/blender/blenkernel/BKE_attribute_math.hh | 12 ++++++------ source/blender/blenlib/BLI_math_base.hh | 12 ++++++++++-- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh index 4482e13e1cf..3d194ba77dc 100644 --- a/source/blender/blenkernel/BKE_attribute_math.hh +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -56,7 +56,7 @@ template T mix3(const float3 &weights, const T &v0, const T &v1, con template<> inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2) { - return static_cast(weights.x * v0 + weights.y * v1 + weights.z * v2); + return static_cast(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2)); } template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2) @@ -66,7 +66,7 @@ template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2) { - return static_cast(weights.x * v0 + weights.y * v1 + weights.z * v2); + return static_cast(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2)); } template<> @@ -131,12 +131,12 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b) template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b) { - return static_cast((1.0f - factor) * a + factor * b); + return static_cast(std::round((1.0f - factor) * a + factor * b)); } template<> inline int mix2(const float factor, const int &a, const int &b) { - return static_cast((1.0f - factor) * a + factor * b); + return static_cast(std::round((1.0f - factor) * a + factor * b)); } template<> inline float mix2(const float factor, const float &a, const float &b) @@ -356,7 +356,7 @@ template<> struct DefaultMixerStruct { template<> struct DefaultMixerStruct { static int double_to_int(const double &value) { - return static_cast(value); + return static_cast(std::round(value)); } /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It * uses double instead of float so that it is accurate for all 32 bit integers. */ @@ -375,7 +375,7 @@ template<> struct DefaultMixerStruct { template<> struct DefaultMixerStruct { static int8_t float_to_int8_t(const float &value) { - return static_cast(value); + return static_cast(std::round(value)); } /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */ using type = SimpleMixerWithAccumulationType; diff --git a/source/blender/blenlib/BLI_math_base.hh b/source/blender/blenlib/BLI_math_base.hh index 81f5343056e..034c6968c94 100644 --- a/source/blender/blenlib/BLI_math_base.hh +++ b/source/blender/blenlib/BLI_math_base.hh @@ -108,12 +108,20 @@ template))> inline T interpolate(const T &a, const T &b, const FactorT &t) { - return a * (1 - t) + b * t; + auto result = a * (1 - t) + b * t; + if constexpr (std::is_integral_v && std::is_floating_point_v) { + result = std::round(result); + } + return result; } template inline T midpoint(const T &a, const T &b) { - return (a + b) * T(0.5); + auto result = (a + b) * T(0.5); + if constexpr (std::is_integral_v) { + result = std::round(result); + } + return result; } } // namespace blender::math -- cgit v1.2.3 From c56103356f642041f76c0be84772a40f1caad9df Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 18 May 2022 17:02:09 +0200 Subject: Fix incorrect track search area election color It was following the pattern area selection color instead of its own. --- source/blender/editors/space_clip/clip_draw.c | 62 ++++++++++++++++----------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'source') diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 99524184323..7800ce797aa 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -676,6 +676,40 @@ static void track_colors(MovieTrackingTrack *track, int act, float col[3], float } } +static void set_draw_marker_area_color(const MovieTrackingTrack *track, + const MovieTrackingMarker *marker, + const bool is_track_active, + const bool is_area_selected, + const float color[3], + const float selected_color[3]) +{ + if (track->flag & TRACK_LOCKED) { + if (is_track_active) { + immUniformThemeColor(TH_ACT_MARKER); + } + else if (is_area_selected) { + immUniformThemeColorShade(TH_LOCK_MARKER, 64); + } + else { + immUniformThemeColor(TH_LOCK_MARKER); + } + } + else if (marker->flag & MARKER_DISABLED) { + if (is_track_active) { + immUniformThemeColor(TH_ACT_MARKER); + } + else if (is_area_selected) { + immUniformThemeColorShade(TH_DIS_MARKER, 128); + } + else { + immUniformThemeColor(TH_DIS_MARKER); + } + } + else { + immUniformColor3fv(is_area_selected ? selected_color : color); + } +} + static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, @@ -785,31 +819,7 @@ static void draw_marker_areas(SpaceClip *sc, GPU_matrix_push(); GPU_matrix_translate_2fv(marker_pos); - if (track->flag & TRACK_LOCKED) { - if (act) { - immUniformThemeColor(TH_ACT_MARKER); - } - else if (track->pat_flag & SELECT) { - immUniformThemeColorShade(TH_LOCK_MARKER, 64); - } - else { - immUniformThemeColor(TH_LOCK_MARKER); - } - } - else if (marker->flag & MARKER_DISABLED) { - if (act) { - immUniformThemeColor(TH_ACT_MARKER); - } - else if (track->pat_flag & SELECT) { - immUniformThemeColorShade(TH_DIS_MARKER, 128); - } - else { - immUniformThemeColor(TH_DIS_MARKER); - } - } - else { - immUniformColor3fv((track->pat_flag & SELECT) ? scol : col); - } + set_draw_marker_area_color(track, marker, act, track->pat_flag & SELECT, col, scol); if (tiny) { immUniform1f("dash_width", 6.0f); @@ -834,6 +844,8 @@ static void draw_marker_areas(SpaceClip *sc, 0; if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) { + set_draw_marker_area_color(track, marker, act, track->search_flag & SELECT, col, scol); + imm_draw_box_wire_2d(shdr_pos, marker->search_min[0], marker->search_min[1], -- cgit v1.2.3