diff options
author | Sybren A. Stüvel <sybren@stuvel.eu> | 2018-05-09 12:33:32 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@stuvel.eu> | 2018-05-09 13:17:24 +0300 |
commit | 632755a3b1988e7553b381c2d737cb956e26780b (patch) | |
tree | 7f290e47a189470810dbdeb77afd4bcfb12a956e | |
parent | 5e915baec4ad657ac9655a9921425bfaec98ea66 (diff) |
Modifiers: ported Surface Deform to Mesh
The modifier performed the 'bind' operation not in the bind operator,
but delayed in the mesh evaluation. This saved the result in a CoW copy
instead of in the actual modifier data. The binding operator now follows
the same approach as Mesh Deform: it forces the modifiers to run on the
real (non-CoW) data, making it possible for the modifier to store the
binding data.
This commit also ports the usage of DerivedMesh to Mesh.
-rw-r--r-- | source/blender/editors/object/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 26 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 2 | ||||
-rw-r--r-- | source/blender/modifiers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/modifiers/MOD_modifier_helpers.h | 39 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_surfacedeform.c | 92 |
6 files changed, 126 insertions, 35 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index e25b04668bc..305e3287029 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../../imbuf ../../makesdna ../../makesrna + ../../modifiers ../../python ../../render/extern/include ../../windowmanager diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index dd04a730542..2e922e7f963 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -90,6 +90,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "MOD_modifier_helpers.h" + #include "object_intern.h" static void modifier_skin_customdata_delete(struct Object *ob); @@ -2331,17 +2333,41 @@ static int surfacedeform_bind_poll(bContext *C) static int surfacedeform_bind_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform); if (!smd) return OPERATOR_CANCELLED; if (smd->flags & MOD_SDEF_BIND) { + /* Un-binding happens inside the modifier when it's evaluated. */ smd->flags &= ~MOD_SDEF_BIND; } else if (smd->target) { + DerivedMesh *dm; + int mode = smd->modifier.mode; + + /* Force modifier to run, it will call binding routine. */ + smd->modifier.mode |= eModifierMode_Realtime; smd->flags |= MOD_SDEF_BIND; + + if (ob->type == OB_MESH) { + dm = mesh_create_derived_view(depsgraph, scene, ob, 0); + dm->release(dm); + } + else if (ob->type == OB_LATTICE) { + BKE_lattice_modifiers_calc(depsgraph, scene, ob); + } + else if (ob->type == OB_MBALL) { + BKE_displist_make_mball(depsgraph, scene, ob); + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + BKE_displist_make_curveTypes(depsgraph, scene, ob, 0); + } + + smd->modifier.mode = mode; } DEG_id_tag_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 148ffed7c7f..31900b98564 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1624,7 +1624,9 @@ typedef struct SurfaceDeformModifierData { /* Surface Deform modifier flags */ enum { + /* This indicates "do bind on next modifier evaluation" as well as "is bound". */ MOD_SDEF_BIND = (1 << 0), + MOD_SDEF_USES_LOOPTRI = (1 << 1), MOD_SDEF_HAS_CONCAVE = (1 << 2), }; diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 397a3263e22..3707819f1fe 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -106,6 +106,7 @@ set(SRC intern/MOD_weightvgproximity.c intern/MOD_wireframe.c + MOD_modifier_helpers MOD_modifiertypes.h intern/MOD_fluidsim_util.h intern/MOD_meshcache_util.h diff --git a/source/blender/modifiers/MOD_modifier_helpers.h b/source/blender/modifiers/MOD_modifier_helpers.h new file mode 100644 index 00000000000..0356bf74d43 --- /dev/null +++ b/source/blender/modifiers/MOD_modifier_helpers.h @@ -0,0 +1,39 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file MOD_modifier_helpers.h + * \ingroup modifiers + * + * Modifier-specific functions that should be accessible from outside the modifiers module. + */ + +#ifndef __MOD_MODIFIER_HELPERS_H__ +#define __MOD_MODIFIER_HELPERS_H__ + +struct Object; +struct SurfaceDeformModifierData; + +/* Defined in MOD_surfacedeform.c */ +bool MOD_surfacedeform_bind(struct Object *ob, struct SurfaceDeformModifierData *smd); + + +#endif /* __MOD_MODIFIER_HELPERS_H__ */ diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index ae011986c47..ea12d8995b6 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1,3 +1,5 @@ +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -6,15 +8,19 @@ #include "BLI_math_geom.h" #include "BLI_task.h" -#include "BKE_cdderivedmesh.h" +#include "BKE_bvhutils.h" +#include "BKE_mesh.h" #include "BKE_editmesh.h" +#include "BKE_library.h" #include "BKE_library_query.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "DEG_depsgraph.h" #include "MEM_guardedalloc.h" +#include "MOD_modifier_helpers.h" #include "MOD_util.h" typedef struct SDefAdjacency { @@ -905,14 +911,14 @@ static void bindVert( } static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)[3], - unsigned int numverts, unsigned int tnumpoly, unsigned int tnumverts, DerivedMesh *tdm) + unsigned int numverts, unsigned int tnumpoly, unsigned int tnumverts, Mesh *target) { BVHTreeFromMesh treeData = {NULL}; - const MVert *mvert = tdm->getVertArray(tdm); - const MPoly *mpoly = tdm->getPolyArray(tdm); - const MEdge *medge = tdm->getEdgeArray(tdm); - const MLoop *mloop = tdm->getLoopArray(tdm); - unsigned int tnumedges = tdm->getNumEdges(tdm); + const MVert *mvert = target->mvert; + const MPoly *mpoly = target->mpoly; + const MEdge *medge = target->medge; + const MLoop *mloop = target->mloop; + unsigned int tnumedges = target->totedge; int adj_result; SDefAdjacencyArray *vert_edges; SDefAdjacency *adj_array; @@ -946,7 +952,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) return false; } - bvhtree_from_mesh_get(&treeData, tdm, BVHTREE_FROM_LOOPTRI, 2); + BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData.tree == NULL) { modifier_setError((ModifierData *)smd, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); @@ -975,7 +981,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) .mpoly = mpoly, .medge = medge, .mloop = mloop, - .looptri = tdm->getLoopTriArray(tdm), + .looptri = BKE_mesh_runtime_looptri_ensure(target), .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetBindVertArray"), .bind_verts = smd->verts, .vertexCos = vertexCos, @@ -1035,6 +1041,30 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) return data.success == 1; } +static Mesh *surfacedeform_get_mesh(SurfaceDeformModifierData *smd, bool *r_needsfree) +{ + Mesh *mesh; + + /* Handle target mesh both in and out of edit mode */ + if (smd->target->mode & OB_MODE_EDIT) { + BMEditMesh *em = BKE_editmesh_from_object(smd->target); + mesh = BKE_bmesh_to_mesh_nomain(em->bm, &(struct BMeshToMeshParams){0}); + *r_needsfree = true; + } + else { + mesh = get_mesh_eval_for_modifier(smd->target, + smd->modifier.mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0); + *r_needsfree = false; + } + + if (!mesh) { + mesh = get_mesh(smd->target, NULL, NULL, NULL, false, false); + *r_needsfree = true; + } + + return mesh; +} + static void deformVert( void *__restrict userdata, const int index, @@ -1097,7 +1127,8 @@ static void surfacedeformModifier_do( float (*vertexCos)[3], unsigned int numverts, Object *ob) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - DerivedMesh *tdm; + bool free_target; + Mesh *target; unsigned int tnumverts, tnumpoly; /* Exit function if bind flag is not set (free bind data if any) */ @@ -1106,22 +1137,14 @@ static void surfacedeformModifier_do( return; } - /* Handle target mesh both in and out of edit mode */ - if (smd->target->mode & OB_MODE_EDIT) { - BMEditMesh *em = BKE_editmesh_from_object(smd->target); - tdm = em->derivedFinal; - } - else { - tdm = smd->target->derivedFinal; - } - - if (!tdm) { + target = surfacedeform_get_mesh(smd, &free_target); + if (!target) { modifier_setError(md, "No valid target mesh"); return; } - tnumverts = tdm->getNumVerts(tdm); - tnumpoly = tdm->getNumPolys(tdm); + tnumverts = target->totvert; + tnumpoly = target->totpoly; /* If not bound, execute bind */ if (!(smd->verts)) { @@ -1130,7 +1153,7 @@ static void surfacedeformModifier_do( invert_m4_m4(tmp_mat, ob->obmat); mul_m4_m4m4(smd->mat, tmp_mat, smd->target->obmat); - if (!surfacedeformBind(smd, vertexCos, numverts, tnumpoly, tnumverts, tdm)) { + if (!surfacedeformBind(smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { smd->flags &= ~MOD_SDEF_BIND; return; } @@ -1139,10 +1162,12 @@ static void surfacedeformModifier_do( /* Poly count checks */ if (smd->numverts != numverts) { modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts); + if (free_target) BKE_id_free(NULL, target); return; } else if (smd->numpoly != tnumpoly) { modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + if (free_target) BKE_id_free(NULL, target); return; } @@ -1154,8 +1179,7 @@ static void surfacedeformModifier_do( }; if (data.targetCos != NULL) { - bool tdm_vert_alloc; - const MVert * const mvert = DM_get_vert_array(tdm, &tdm_vert_alloc); + const MVert * const mvert = target->mvert; for (int i = 0; i < tnumverts; i++) { mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co); @@ -1169,17 +1193,15 @@ static void surfacedeformModifier_do( deformVert, &settings); - if (tdm_vert_alloc) { - MEM_freeN((void *)mvert); - } - MEM_freeN(data.targetCos); } + + if (free_target) BKE_id_free(NULL, target); } static void deformVerts( ModifierData *md, const ModifierEvalContext *ctx, - DerivedMesh *UNUSED(derivedData), + Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); @@ -1188,7 +1210,7 @@ static void deformVerts( static void deformVertsEM( ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *UNUSED(editData), - DerivedMesh *UNUSED(derivedData), + Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); @@ -1211,16 +1233,16 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* copyData */ copyData, - /* deformVerts_DM */ deformVerts, + /* deformVerts_DM */ NULL, /* deformMatrices_DM */ NULL, - /* deformVertsEM_DM */ deformVertsEM, + /* deformVertsEM_DM */ NULL, /* deformMatricesEM_DM*/NULL, /* applyModifier_DM */ NULL, /* applyModifierEM_DM */NULL, - /* deformVerts */ NULL, + /* deformVerts */ deformVerts, /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, + /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* applyModifierEM */ NULL, |