From 95e60b4ffd6c325d2658f318d05ab52d712ca953 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 22 Jul 2022 12:33:08 +0200 Subject: Cleanup: move crazyspace.c to c++ Doing this in preparation for D15407. --- source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/intern/crazyspace.c | 584 ------------------------ source/blender/blenkernel/intern/crazyspace.cc | 588 +++++++++++++++++++++++++ 3 files changed, 589 insertions(+), 585 deletions(-) delete mode 100644 source/blender/blenkernel/intern/crazyspace.c create mode 100644 source/blender/blenkernel/intern/crazyspace.cc (limited to 'source') diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 45a9e85874d..df4b70d4fe6 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -101,7 +101,7 @@ set(SRC intern/colortools.c intern/constraint.c intern/context.c - intern/crazyspace.c + intern/crazyspace.cc intern/cryptomatte.cc intern/curve.cc intern/curve_bevel.c diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c deleted file mode 100644 index 14e862c2377..00000000000 --- a/source/blender/blenkernel/intern/crazyspace.c +++ /dev/null @@ -1,584 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2005 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup bke - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BLI_bitmap.h" -#include "BLI_linklist.h" -#include "BLI_utildefines.h" - -#include "BKE_DerivedMesh.h" -#include "BKE_crazyspace.h" -#include "BKE_editmesh.h" -#include "BKE_lib_id.h" -#include "BKE_mesh.h" -#include "BKE_mesh_wrapper.h" -#include "BKE_modifier.h" -#include "BKE_multires.h" -#include "BKE_report.h" - -#include "DEG_depsgraph_query.h" - -BLI_INLINE void tan_calc_quat_v3(float r_quat[4], - const float co_1[3], - const float co_2[3], - const float co_3[3]) -{ - float vec_u[3], vec_v[3]; - float nor[3]; - - sub_v3_v3v3(vec_u, co_1, co_2); - sub_v3_v3v3(vec_v, co_1, co_3); - - cross_v3_v3v3(nor, vec_u, vec_v); - - if (normalize_v3(nor) > FLT_EPSILON) { - const float zero_vec[3] = {0.0f}; - tri_to_quat_ex(r_quat, zero_vec, vec_u, vec_v, nor); - } - else { - unit_qt(r_quat); - } -} - -static void set_crazy_vertex_quat(float r_quat[4], - const float co_1[3], - const float co_2[3], - const float co_3[3], - const float vd_1[3], - const float vd_2[3], - const float vd_3[3]) -{ - float q1[4], q2[4]; - - tan_calc_quat_v3(q1, co_1, co_2, co_3); - tan_calc_quat_v3(q2, vd_1, vd_2, vd_3); - - sub_qt_qtqt(r_quat, q2, q1); -} - -static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob) -{ - bool disabled = false; - int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); - - ModifierData *md = ob->modifiers.first; - for (int i = 0; md && i <= cageIndex; i++, md = md->next) { - if (md->type == eModifierType_Subsurf) { - md->mode ^= eModifierMode_DisableTemporary; - disabled = true; - } - } - - return disabled; -} - -float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object *obedit))[3] -{ - Scene *scene = DEG_get_input_scene(depsgraph); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - Mesh *mesh_eval = obedit_eval->data; - BMEditMesh *editmesh_eval = mesh_eval->edit_mesh; - - /* disable subsurf temporal, get mapped cos, and enable it */ - if (modifiers_disable_subsurf_temporary(scene_eval, obedit_eval)) { - /* need to make new derivemesh */ - makeDerivedMesh(depsgraph, scene_eval, obedit_eval, &CD_MASK_BAREMESH); - } - - /* now get the cage */ - Mesh *mesh_eval_cage = editbmesh_get_eval_cage_from_orig( - depsgraph, scene, obedit, &CD_MASK_BAREMESH); - - const int nverts = editmesh_eval->bm->totvert; - float(*vertexcos)[3] = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - mesh_get_mapped_verts_coords(mesh_eval_cage, vertexcos, nverts); - - /* set back the flag, no new cage needs to be built, transform does it */ - modifiers_disable_subsurf_temporary(scene_eval, obedit_eval); - - return vertexcos; -} - -void BKE_crazyspace_set_quats_editmesh(BMEditMesh *em, - float (*origcos)[3], - float (*mappedcos)[3], - float (*quats)[4], - const bool use_select) -{ - BMFace *f; - BMIter iter; - int index; - - { - BMVert *v; - BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, index) { - BM_elem_flag_disable(v, BM_ELEM_TAG); - BM_elem_index_set(v, index); /* set_inline */ - } - em->bm->elem_index_dirty &= ~BM_VERT; - } - - BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN) || - BM_elem_flag_test(l_iter->v, BM_ELEM_TAG) || - (use_select && !BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT))) { - continue; - } - - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) { - const float *co_prev, *co_curr, *co_next; /* orig */ - const float *vd_prev, *vd_curr, *vd_next; /* deform */ - - const int i_prev = BM_elem_index_get(l_iter->prev->v); - const int i_curr = BM_elem_index_get(l_iter->v); - const int i_next = BM_elem_index_get(l_iter->next->v); - - /* retrieve mapped coordinates */ - vd_prev = mappedcos[i_prev]; - vd_curr = mappedcos[i_curr]; - vd_next = mappedcos[i_next]; - - if (origcos) { - co_prev = origcos[i_prev]; - co_curr = origcos[i_curr]; - co_next = origcos[i_next]; - } - else { - co_prev = l_iter->prev->v->co; - co_curr = l_iter->v->co; - co_next = l_iter->next->v->co; - } - - set_crazy_vertex_quat(quats[i_curr], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); - - BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); - } - } while ((l_iter = l_iter->next) != l_first); - } -} - -void BKE_crazyspace_set_quats_mesh(Mesh *me, - float (*origcos)[3], - float (*mappedcos)[3], - float (*quats)[4]) -{ - BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); - - /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ - MVert *mvert = me->mvert; - MPoly *mp = me->mpoly; - MLoop *mloop = me->mloop; - - for (int i = 0; i < me->totpoly; i++, mp++) { - MLoop *ml_next = &mloop[mp->loopstart]; - MLoop *ml_curr = &ml_next[mp->totloop - 1]; - MLoop *ml_prev = &ml_next[mp->totloop - 2]; - - for (int j = 0; j < mp->totloop; j++) { - if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) { - const float *co_prev, *co_curr, *co_next; /* orig */ - const float *vd_prev, *vd_curr, *vd_next; /* deform */ - - /* retrieve mapped coordinates */ - vd_prev = mappedcos[ml_prev->v]; - vd_curr = mappedcos[ml_curr->v]; - vd_next = mappedcos[ml_next->v]; - - if (origcos) { - co_prev = origcos[ml_prev->v]; - co_curr = origcos[ml_curr->v]; - co_next = origcos[ml_next->v]; - } - else { - co_prev = mvert[ml_prev->v].co; - co_curr = mvert[ml_curr->v].co; - co_next = mvert[ml_next->v].co; - } - - set_crazy_vertex_quat( - quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); - - BLI_BITMAP_ENABLE(vert_tag, ml_curr->v); - } - - ml_prev = ml_curr; - ml_curr = ml_next; - ml_next++; - } - } - - MEM_freeN(vert_tag); -} - -int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - BMEditMesh *em, - float (**deformmats)[3][3], - float (**deformcos)[3]) -{ - ModifierData *md; - Mesh *me_input = ob->data; - Mesh *me = NULL; - int i, a, modifiers_left_num = 0, verts_num = 0; - int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); - float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; - VirtualModifierData virtualModifierData; - ModifierEvalContext mectx = {depsgraph, ob, 0}; - - BKE_modifiers_clear_errors(ob); - - md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); - - /* compute the deformation matrices and coordinates for the first - * modifiers with on cage editing that are enabled and support computing - * deform matrices */ - for (i = 0; md && i <= cageIndex; i++, md = md->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - - if (!editbmesh_modifier_is_enabled(scene, ob, md, me != NULL)) { - continue; - } - - if (mti->type == eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { - if (!defmats) { - const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - CustomData_MeshMasks cd_mask_extra = CD_MASK_BAREMESH; - CDMaskLink *datamasks = BKE_modifier_calc_data_masks( - scene, ob, md, &cd_mask_extra, required_mode, NULL, NULL); - cd_mask_extra = datamasks->mask; - BLI_linklist_free((LinkNode *)datamasks, NULL); - - me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input); - deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num); - defmats = MEM_mallocN(sizeof(*defmats) * verts_num, "defmats"); - - for (a = 0; a < verts_num; a++) { - unit_m3(defmats[a]); - } - } - mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, verts_num); - } - else { - break; - } - } - - for (; md && i <= cageIndex; md = md->next, i++) { - if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) && - BKE_modifier_is_correctable_deformed(md)) { - modifiers_left_num++; - } - } - - if (me) { - BKE_id_free(NULL, me); - } - - *deformmats = defmats; - *deformcos = deformedVerts; - - return modifiers_left_num; -} - -/** - * Crazy-space evaluation needs to have an object which has all the fields - * evaluated, but the mesh data being at undeformed state. This way it can - * re-apply modifiers and also have proper pointers to key data blocks. - * - * Similar to #BKE_object_eval_reset(), but does not modify the actual evaluated object. - */ -static void crazyspace_init_object_for_eval(struct Depsgraph *depsgraph, - Object *object, - Object *object_crazy) -{ - Object *object_eval = DEG_get_evaluated_object(depsgraph, object); - *object_crazy = *object_eval; - if (object_crazy->runtime.data_orig != NULL) { - object_crazy->data = object_crazy->runtime.data_orig; - } -} - -static void crazyspace_init_verts_and_matrices(const Mesh *mesh, - float (**deformmats)[3][3], - float (**deformcos)[3]) -{ - int verts_num; - *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); - *deformmats = MEM_callocN(sizeof(**deformmats) * verts_num, "defmats"); - for (int a = 0; a < verts_num; a++) { - unit_m3((*deformmats)[a]); - } - BLI_assert(verts_num == mesh->totvert); -} - -static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md) -{ - if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) { - return true; - } - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - return (mti->type == eModifierTypeType_OnlyDeform); -} - -static bool crazyspace_modifier_supports_deform(ModifierData *md) -{ - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - return (mti->type == eModifierTypeType_OnlyDeform); -} - -int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, - Scene *scene, - Object *object, - float (**deformmats)[3][3], - float (**deformcos)[3]) -{ - ModifierData *md; - Mesh *me_eval = NULL; - float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; - int modifiers_left_num = 0; - VirtualModifierData virtualModifierData; - Object object_eval; - crazyspace_init_object_for_eval(depsgraph, object, &object_eval); - MultiresModifierData *mmd = get_multires_modifier(scene, &object_eval, 0); - const bool is_sculpt_mode = (object->mode & OB_MODE_SCULPT) != 0; - const bool has_multires = mmd != NULL && mmd->sculptlvl > 0; - const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; - - if (is_sculpt_mode && has_multires) { - *deformmats = NULL; - *deformcos = NULL; - return modifiers_left_num; - } - - md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); - - for (; md; md = md->next) { - if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { - continue; - } - - if (crazyspace_modifier_supports_deform_matrices(md)) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (defmats == NULL) { - /* NOTE: Evaluated object is re-set to its original un-deformed state. */ - Mesh *me = object_eval.data; - me_eval = BKE_mesh_copy_for_eval(me, true); - crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts); - } - - if (mti->deformMatrices) { - mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, me_eval->totvert); - } - else { - /* More complex handling will continue in BKE_crazyspace_build_sculpt. - * Exiting the loop on a non-deform modifier causes issues - T71213. */ - BLI_assert(crazyspace_modifier_supports_deform(md)); - break; - } - } - } - - for (; md; md = md->next) { - if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { - continue; - } - - if (crazyspace_modifier_supports_deform(md)) { - modifiers_left_num++; - } - } - - if (me_eval != NULL) { - BKE_id_free(NULL, me_eval); - } - - *deformmats = defmats; - *deformcos = deformedVerts; - - return modifiers_left_num; -} - -void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, - Scene *scene, - Object *object, - float (**deformmats)[3][3], - float (**deformcos)[3]) -{ - int totleft = BKE_sculpt_get_first_deform_matrices( - depsgraph, scene, object, deformmats, deformcos); - - if (totleft) { - /* There are deformation modifier which doesn't support deformation matrices calculation. - * Need additional crazy-space correction. */ - - Mesh *mesh = (Mesh *)object->data; - Mesh *mesh_eval = NULL; - - if (*deformcos == NULL) { - crazyspace_init_verts_and_matrices(mesh, deformmats, deformcos); - } - - float(*deformedVerts)[3] = *deformcos; - float(*origVerts)[3] = MEM_dupallocN(deformedVerts); - float(*quats)[4]; - int i, deformed = 0; - VirtualModifierData virtualModifierData; - Object object_eval; - crazyspace_init_object_for_eval(depsgraph, object, &object_eval); - ModifierData *md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); - const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; - - for (; md; md = md->next) { - if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { - continue; - } - - if (crazyspace_modifier_supports_deform(md)) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - - /* skip leading modifiers which have been already - * handled in sculpt_get_first_deform_matrices */ - if (mti->deformMatrices && !deformed) { - continue; - } - - if (mesh_eval == NULL) { - mesh_eval = BKE_mesh_copy_for_eval(mesh, true); - } - - mti->deformVerts(md, &mectx, mesh_eval, deformedVerts, mesh_eval->totvert); - deformed = 1; - } - } - - quats = MEM_mallocN(mesh->totvert * sizeof(*quats), "crazy quats"); - - BKE_crazyspace_set_quats_mesh(mesh, origVerts, deformedVerts, quats); - - for (i = 0; i < mesh->totvert; i++) { - float qmat[3][3], tmat[3][3]; - - quat_to_mat3(qmat, quats[i]); - mul_m3_m3m3(tmat, qmat, (*deformmats)[i]); - copy_m3_m3((*deformmats)[i], tmat); - } - - MEM_freeN(origVerts); - MEM_freeN(quats); - - if (mesh_eval != NULL) { - BKE_id_free(NULL, mesh_eval); - } - } - - if (*deformmats == NULL) { - int a, verts_num; - Mesh *mesh = (Mesh *)object->data; - - *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); - *deformmats = MEM_callocN(sizeof(*(*deformmats)) * verts_num, "defmats"); - - for (a = 0; a < verts_num; a++) { - unit_m3((*deformmats)[a]); - } - } -} - -/* -------------------------------------------------------------------- */ -/** \name Crazyspace API - * \{ */ - -void BKE_crazyspace_api_eval(Depsgraph *depsgraph, - Scene *scene, - Object *object, - struct ReportList *reports) -{ - if (object->runtime.crazyspace_deform_imats != NULL || - object->runtime.crazyspace_deform_cos != NULL) { - return; - } - - if (object->type != OB_MESH) { - BKE_report(reports, - RPT_ERROR, - "Crazyspace transformation is only available for Mesh type of objects"); - return; - } - - const Mesh *mesh = (const Mesh *)object->data; - object->runtime.crazyspace_verts_num = mesh->totvert; - BKE_crazyspace_build_sculpt(depsgraph, - scene, - object, - &object->runtime.crazyspace_deform_imats, - &object->runtime.crazyspace_deform_cos); -} - -void BKE_crazyspace_api_displacement_to_deformed(struct Object *object, - struct ReportList *reports, - int vertex_index, - float displacement[3], - float r_displacement_deformed[3]) -{ - if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { - BKE_reportf(reports, - RPT_ERROR, - "Invalid vertex index %d (expected to be within 0 to %d range)", - vertex_index, - object->runtime.crazyspace_verts_num); - return; - } - - mul_v3_m3v3(r_displacement_deformed, - object->runtime.crazyspace_deform_imats[vertex_index], - displacement); -} - -void BKE_crazyspace_api_displacement_to_original(struct Object *object, - struct ReportList *reports, - int vertex_index, - float displacement_deformed[3], - float r_displacement[3]) -{ - if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { - BKE_reportf(reports, - RPT_ERROR, - "Invalid vertex index %d (expected to be within 0 to %d range))", - vertex_index, - object->runtime.crazyspace_verts_num); - return; - } - - float mat[3][3]; - if (!invert_m3_m3(mat, object->runtime.crazyspace_deform_imats[vertex_index])) { - copy_v3_v3(r_displacement, displacement_deformed); - return; - } - - mul_v3_m3v3(r_displacement, mat, displacement_deformed); -} - -void BKE_crazyspace_api_eval_clear(Object *object) -{ - MEM_SAFE_FREE(object->runtime.crazyspace_deform_imats); - MEM_SAFE_FREE(object->runtime.crazyspace_deform_cos); -} - -/** \} */ diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc new file mode 100644 index 00000000000..c3db3095343 --- /dev/null +++ b/source/blender/blenkernel/intern/crazyspace.cc @@ -0,0 +1,588 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2005 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BLI_bitmap.h" +#include "BLI_linklist.h" +#include "BLI_utildefines.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_crazyspace.h" +#include "BKE_editmesh.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_wrapper.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_report.h" + +#include "DEG_depsgraph_query.h" + +BLI_INLINE void tan_calc_quat_v3(float r_quat[4], + const float co_1[3], + const float co_2[3], + const float co_3[3]) +{ + float vec_u[3], vec_v[3]; + float nor[3]; + + sub_v3_v3v3(vec_u, co_1, co_2); + sub_v3_v3v3(vec_v, co_1, co_3); + + cross_v3_v3v3(nor, vec_u, vec_v); + + if (normalize_v3(nor) > FLT_EPSILON) { + const float zero_vec[3] = {0.0f}; + tri_to_quat_ex(r_quat, zero_vec, vec_u, vec_v, nor); + } + else { + unit_qt(r_quat); + } +} + +static void set_crazy_vertex_quat(float r_quat[4], + const float co_1[3], + const float co_2[3], + const float co_3[3], + const float vd_1[3], + const float vd_2[3], + const float vd_3[3]) +{ + float q1[4], q2[4]; + + tan_calc_quat_v3(q1, co_1, co_2, co_3); + tan_calc_quat_v3(q2, vd_1, vd_2, vd_3); + + sub_qt_qtqt(r_quat, q2, q1); +} + +static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob) +{ + bool disabled = false; + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, 1); + + ModifierData *md = static_cast(ob->modifiers.first); + for (int i = 0; md && i <= cageIndex; i++, md = md->next) { + if (md->type == eModifierType_Subsurf) { + md->mode ^= eModifierMode_DisableTemporary; + disabled = true; + } + } + + return disabled; +} + +float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object *obedit))[3] +{ + Scene *scene = DEG_get_input_scene(depsgraph); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); + Mesh *mesh_eval = static_cast(obedit_eval->data); + BMEditMesh *editmesh_eval = mesh_eval->edit_mesh; + + /* disable subsurf temporal, get mapped cos, and enable it */ + if (modifiers_disable_subsurf_temporary(scene_eval, obedit_eval)) { + /* need to make new derivemesh */ + makeDerivedMesh(depsgraph, scene_eval, obedit_eval, &CD_MASK_BAREMESH); + } + + /* now get the cage */ + Mesh *mesh_eval_cage = editbmesh_get_eval_cage_from_orig( + depsgraph, scene, obedit, &CD_MASK_BAREMESH); + + const int nverts = editmesh_eval->bm->totvert; + float(*vertexcos)[3] = static_cast( + MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map")); + mesh_get_mapped_verts_coords(mesh_eval_cage, vertexcos, nverts); + + /* set back the flag, no new cage needs to be built, transform does it */ + modifiers_disable_subsurf_temporary(scene_eval, obedit_eval); + + return vertexcos; +} + +void BKE_crazyspace_set_quats_editmesh(BMEditMesh *em, + float (*origcos)[3], + float (*mappedcos)[3], + float (*quats)[4], + const bool use_select) +{ + BMFace *f; + BMIter iter; + int index; + + { + BMVert *v; + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, index) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + BM_elem_index_set(v, index); /* set_inline */ + } + em->bm->elem_index_dirty &= ~BM_VERT; + } + + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN) || + BM_elem_flag_test(l_iter->v, BM_ELEM_TAG) || + (use_select && !BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT))) { + continue; + } + + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) { + const float *co_prev, *co_curr, *co_next; /* orig */ + const float *vd_prev, *vd_curr, *vd_next; /* deform */ + + const int i_prev = BM_elem_index_get(l_iter->prev->v); + const int i_curr = BM_elem_index_get(l_iter->v); + const int i_next = BM_elem_index_get(l_iter->next->v); + + /* retrieve mapped coordinates */ + vd_prev = mappedcos[i_prev]; + vd_curr = mappedcos[i_curr]; + vd_next = mappedcos[i_next]; + + if (origcos) { + co_prev = origcos[i_prev]; + co_curr = origcos[i_curr]; + co_next = origcos[i_next]; + } + else { + co_prev = l_iter->prev->v->co; + co_curr = l_iter->v->co; + co_next = l_iter->next->v->co; + } + + set_crazy_vertex_quat(quats[i_curr], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); + + BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); + } + } while ((l_iter = l_iter->next) != l_first); + } +} + +void BKE_crazyspace_set_quats_mesh(Mesh *me, + float (*origcos)[3], + float (*mappedcos)[3], + float (*quats)[4]) +{ + BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); + + /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ + MVert *mvert = me->mvert; + MPoly *mp = me->mpoly; + MLoop *mloop = me->mloop; + + for (int i = 0; i < me->totpoly; i++, mp++) { + MLoop *ml_next = &mloop[mp->loopstart]; + MLoop *ml_curr = &ml_next[mp->totloop - 1]; + MLoop *ml_prev = &ml_next[mp->totloop - 2]; + + for (int j = 0; j < mp->totloop; j++) { + if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) { + const float *co_prev, *co_curr, *co_next; /* orig */ + const float *vd_prev, *vd_curr, *vd_next; /* deform */ + + /* retrieve mapped coordinates */ + vd_prev = mappedcos[ml_prev->v]; + vd_curr = mappedcos[ml_curr->v]; + vd_next = mappedcos[ml_next->v]; + + if (origcos) { + co_prev = origcos[ml_prev->v]; + co_curr = origcos[ml_curr->v]; + co_next = origcos[ml_next->v]; + } + else { + co_prev = mvert[ml_prev->v].co; + co_curr = mvert[ml_curr->v].co; + co_next = mvert[ml_next->v].co; + } + + set_crazy_vertex_quat( + quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); + + BLI_BITMAP_ENABLE(vert_tag, ml_curr->v); + } + + ml_prev = ml_curr; + ml_curr = ml_next; + ml_next++; + } + } + + MEM_freeN(vert_tag); +} + +int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + BMEditMesh *em, + float (**deformmats)[3][3], + float (**deformcos)[3]) +{ + ModifierData *md; + Mesh *me_input = static_cast(ob->data); + Mesh *me = nullptr; + int i, a, modifiers_left_num = 0, verts_num = 0; + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, 1); + float(*defmats)[3][3] = nullptr, (*deformedVerts)[3] = nullptr; + VirtualModifierData virtualModifierData; + ModifierEvalContext mectx = {depsgraph, ob, ModifierApplyFlag(0)}; + + BKE_modifiers_clear_errors(ob); + + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); + + /* compute the deformation matrices and coordinates for the first + * modifiers with on cage editing that are enabled and support computing + * deform matrices */ + for (i = 0; md && i <= cageIndex; i++, md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast(md->type)); + + if (!editbmesh_modifier_is_enabled(scene, ob, md, me != nullptr)) { + continue; + } + + if (mti->type == eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { + if (!defmats) { + const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; + CustomData_MeshMasks cd_mask_extra = CD_MASK_BAREMESH; + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( + scene, ob, md, &cd_mask_extra, required_mode, nullptr, nullptr); + cd_mask_extra = datamasks->mask; + BLI_linklist_free((LinkNode *)datamasks, nullptr); + + me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, nullptr, me_input); + deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num); + defmats = static_cast( + MEM_mallocN(sizeof(*defmats) * verts_num, "defmats")); + + for (a = 0; a < verts_num; a++) { + unit_m3(defmats[a]); + } + } + mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, verts_num); + } + else { + break; + } + } + + for (; md && i <= cageIndex; md = md->next, i++) { + if (editbmesh_modifier_is_enabled(scene, ob, md, me != nullptr) && + BKE_modifier_is_correctable_deformed(md)) { + modifiers_left_num++; + } + } + + if (me) { + BKE_id_free(nullptr, me); + } + + *deformmats = defmats; + *deformcos = deformedVerts; + + return modifiers_left_num; +} + +/** + * Crazy-space evaluation needs to have an object which has all the fields + * evaluated, but the mesh data being at undeformed state. This way it can + * re-apply modifiers and also have proper pointers to key data blocks. + * + * Similar to #BKE_object_eval_reset(), but does not modify the actual evaluated object. + */ +static void crazyspace_init_object_for_eval(struct Depsgraph *depsgraph, + Object *object, + Object *object_crazy) +{ + Object *object_eval = DEG_get_evaluated_object(depsgraph, object); + *object_crazy = blender::dna::shallow_copy(*object_eval); + if (object_crazy->runtime.data_orig != nullptr) { + object_crazy->data = object_crazy->runtime.data_orig; + } +} + +static void crazyspace_init_verts_and_matrices(const Mesh *mesh, + float (**deformmats)[3][3], + float (**deformcos)[3]) +{ + int verts_num; + *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); + *deformmats = static_cast( + MEM_callocN(sizeof(**deformmats) * verts_num, "defmats")); + for (int a = 0; a < verts_num; a++) { + unit_m3((*deformmats)[a]); + } + BLI_assert(verts_num == mesh->totvert); +} + +static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md) +{ + if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) { + return true; + } + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast(md->type)); + return (mti->type == eModifierTypeType_OnlyDeform); +} + +static bool crazyspace_modifier_supports_deform(ModifierData *md) +{ + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast(md->type)); + return (mti->type == eModifierTypeType_OnlyDeform); +} + +int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, + Scene *scene, + Object *object, + float (**deformmats)[3][3], + float (**deformcos)[3]) +{ + ModifierData *md; + Mesh *me_eval = nullptr; + float(*defmats)[3][3] = nullptr, (*deformedVerts)[3] = nullptr; + int modifiers_left_num = 0; + VirtualModifierData virtualModifierData; + Object object_eval; + crazyspace_init_object_for_eval(depsgraph, object, &object_eval); + MultiresModifierData *mmd = get_multires_modifier(scene, &object_eval, 0); + const bool is_sculpt_mode = (object->mode & OB_MODE_SCULPT) != 0; + const bool has_multires = mmd != nullptr && mmd->sculptlvl > 0; + const ModifierEvalContext mectx = {depsgraph, &object_eval, ModifierApplyFlag(0)}; + + if (is_sculpt_mode && has_multires) { + *deformmats = nullptr; + *deformcos = nullptr; + return modifiers_left_num; + } + + md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); + + for (; md; md = md->next) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { + continue; + } + + if (crazyspace_modifier_supports_deform_matrices(md)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast(md->type)); + if (defmats == nullptr) { + /* NOTE: Evaluated object is re-set to its original un-deformed state. */ + Mesh *me = static_cast(object_eval.data); + me_eval = BKE_mesh_copy_for_eval(me, true); + crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts); + } + + if (mti->deformMatrices) { + mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, me_eval->totvert); + } + else { + /* More complex handling will continue in BKE_crazyspace_build_sculpt. + * Exiting the loop on a non-deform modifier causes issues - T71213. */ + BLI_assert(crazyspace_modifier_supports_deform(md)); + break; + } + } + } + + for (; md; md = md->next) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { + continue; + } + + if (crazyspace_modifier_supports_deform(md)) { + modifiers_left_num++; + } + } + + if (me_eval != nullptr) { + BKE_id_free(nullptr, me_eval); + } + + *deformmats = defmats; + *deformcos = deformedVerts; + + return modifiers_left_num; +} + +void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, + Scene *scene, + Object *object, + float (**deformmats)[3][3], + float (**deformcos)[3]) +{ + int totleft = BKE_sculpt_get_first_deform_matrices( + depsgraph, scene, object, deformmats, deformcos); + + if (totleft) { + /* There are deformation modifier which doesn't support deformation matrices calculation. + * Need additional crazy-space correction. */ + + Mesh *mesh = (Mesh *)object->data; + Mesh *mesh_eval = nullptr; + + if (*deformcos == nullptr) { + crazyspace_init_verts_and_matrices(mesh, deformmats, deformcos); + } + + float(*deformedVerts)[3] = *deformcos; + float(*origVerts)[3] = static_cast(MEM_dupallocN(deformedVerts)); + float(*quats)[4]; + int i, deformed = 0; + VirtualModifierData virtualModifierData; + Object object_eval; + crazyspace_init_object_for_eval(depsgraph, object, &object_eval); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); + const ModifierEvalContext mectx = {depsgraph, &object_eval, ModifierApplyFlag(0)}; + + for (; md; md = md->next) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { + continue; + } + + if (crazyspace_modifier_supports_deform(md)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast(md->type)); + + /* skip leading modifiers which have been already + * handled in sculpt_get_first_deform_matrices */ + if (mti->deformMatrices && !deformed) { + continue; + } + + if (mesh_eval == nullptr) { + mesh_eval = BKE_mesh_copy_for_eval(mesh, true); + } + + mti->deformVerts(md, &mectx, mesh_eval, deformedVerts, mesh_eval->totvert); + deformed = 1; + } + } + + quats = static_cast(MEM_mallocN(mesh->totvert * sizeof(*quats), "crazy quats")); + + BKE_crazyspace_set_quats_mesh(mesh, origVerts, deformedVerts, quats); + + for (i = 0; i < mesh->totvert; i++) { + float qmat[3][3], tmat[3][3]; + + quat_to_mat3(qmat, quats[i]); + mul_m3_m3m3(tmat, qmat, (*deformmats)[i]); + copy_m3_m3((*deformmats)[i], tmat); + } + + MEM_freeN(origVerts); + MEM_freeN(quats); + + if (mesh_eval != nullptr) { + BKE_id_free(nullptr, mesh_eval); + } + } + + if (*deformmats == nullptr) { + int a, verts_num; + Mesh *mesh = (Mesh *)object->data; + + *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); + *deformmats = static_cast( + MEM_callocN(sizeof(*(*deformmats)) * verts_num, "defmats")); + + for (a = 0; a < verts_num; a++) { + unit_m3((*deformmats)[a]); + } + } +} + +/* -------------------------------------------------------------------- */ +/** \name Crazyspace API + * \{ */ + +void BKE_crazyspace_api_eval(Depsgraph *depsgraph, + Scene *scene, + Object *object, + struct ReportList *reports) +{ + if (object->runtime.crazyspace_deform_imats != nullptr || + object->runtime.crazyspace_deform_cos != nullptr) { + return; + } + + if (object->type != OB_MESH) { + BKE_report(reports, + RPT_ERROR, + "Crazyspace transformation is only available for Mesh type of objects"); + return; + } + + const Mesh *mesh = (const Mesh *)object->data; + object->runtime.crazyspace_verts_num = mesh->totvert; + BKE_crazyspace_build_sculpt(depsgraph, + scene, + object, + &object->runtime.crazyspace_deform_imats, + &object->runtime.crazyspace_deform_cos); +} + +void BKE_crazyspace_api_displacement_to_deformed(struct Object *object, + struct ReportList *reports, + int vertex_index, + float displacement[3], + float r_displacement_deformed[3]) +{ + if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { + BKE_reportf(reports, + RPT_ERROR, + "Invalid vertex index %d (expected to be within 0 to %d range)", + vertex_index, + object->runtime.crazyspace_verts_num); + return; + } + + mul_v3_m3v3(r_displacement_deformed, + object->runtime.crazyspace_deform_imats[vertex_index], + displacement); +} + +void BKE_crazyspace_api_displacement_to_original(struct Object *object, + struct ReportList *reports, + int vertex_index, + float displacement_deformed[3], + float r_displacement[3]) +{ + if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { + BKE_reportf(reports, + RPT_ERROR, + "Invalid vertex index %d (expected to be within 0 to %d range))", + vertex_index, + object->runtime.crazyspace_verts_num); + return; + } + + float mat[3][3]; + if (!invert_m3_m3(mat, object->runtime.crazyspace_deform_imats[vertex_index])) { + copy_v3_v3(r_displacement, displacement_deformed); + return; + } + + mul_v3_m3v3(r_displacement, mat, displacement_deformed); +} + +void BKE_crazyspace_api_eval_clear(Object *object) +{ + MEM_SAFE_FREE(object->runtime.crazyspace_deform_imats); + MEM_SAFE_FREE(object->runtime.crazyspace_deform_cos); +} + +/** \} */ -- cgit v1.2.3