Merge branch 'master' into blender2.8
[blender.git] / source / blender / modifiers / intern / MOD_weightvgproximity.c
index 584c68756c1837978fcc86874942a7c1fd5cd9cd..6b31ca677cc0c59a622739605f1ef96fe55e97cb 100644 (file)
 #include "DNA_object_types.h"
 
 #include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
 #include "BKE_deform.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
+#include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_texture.h"          /* Texture masking. */
 
-#include "depsgraph_private.h"
 #include "DEG_depsgraph_build.h"
 
 #include "MEM_guardedalloc.h"
 
 #include "MOD_weightvg_util.h"
 #include "MOD_modifiertypes.h"
+#include "MOD_util.h"
 
 //#define USE_TIMEIT
 
@@ -139,7 +142,7 @@ static void vert2geom_task_cb_ex(
 static void get_vert2geom_distance(
         int numVerts, float (*v_cos)[3],
         float *dist_v, float *dist_e, float *dist_f,
-        DerivedMesh *target, const SpaceTransform *loc2trgt)
+        Mesh *target, const SpaceTransform *loc2trgt)
 {
        Vert2GeomData data = {0};
        Vert2GeomDataChunk data_chunk = {{{0}}};
@@ -150,7 +153,7 @@ static void get_vert2geom_distance(
 
        if (dist_v) {
                /* Create a bvh-tree of the given target's verts. */
-               bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2);
+               BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2);
                if (treeData_v.tree == NULL) {
                        OUT_OF_MEMORY();
                        return;
@@ -158,7 +161,7 @@ static void get_vert2geom_distance(
        }
        if (dist_e) {
                /* Create a bvh-tree of the given target's edges. */
-               bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2);
+               BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2);
                if (treeData_e.tree == NULL) {
                        OUT_OF_MEMORY();
                        return;
@@ -166,7 +169,7 @@ static void get_vert2geom_distance(
        }
        if (dist_f) {
                /* Create a bvh-tree of the given target's faces. */
-               bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2);
+               BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2);
                if (treeData_f.tree == NULL) {
                        OUT_OF_MEMORY();
                        return;
@@ -260,13 +263,15 @@ static void do_map(Object *ob, float *weights, const int nidx, const float min_d
        if (!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) {
                RNG *rng = NULL;
 
-               if (mode == MOD_WVG_MAPPING_RANDOM)
+               if (mode == MOD_WVG_MAPPING_RANDOM) {
                        rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));
+               }
 
                weightvg_do_map(nidx, weights, mode, NULL, rng);
 
-               if (rng)
+               if (rng) {
                        BLI_rng_free(rng);
+               }
        }
 }
 
@@ -335,29 +340,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
        walk(userData, ob, md, "mask_texture");
 }
 
-static void updateDepgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
-{
-       WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
-       DagNode *curNode;
-
-       if (wmd->proximity_ob_target) {
-               curNode = dag_get_node(ctx->forest, wmd->proximity_ob_target);
-               dag_add_relation(ctx->forest, curNode, ctx->obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
-                                "WeightVGProximity Modifier");
-       }
-
-       if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
-               curNode = dag_get_node(ctx->forest, wmd->mask_tex_map_obj);
-
-               dag_add_relation(ctx->forest, curNode, ctx->obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
-                                "WeightVGProximity Modifier");
-       }
-
-       if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
-               dag_add_relation(ctx->forest, ctx->obNode, ctx->obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
-                                "WeightVGProximity Modifier");
-}
-
 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
 {
        WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
@@ -384,16 +366,15 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
        return (wmd->proximity_ob_target == NULL);
 }
 
-static DerivedMesh *applyModifier(
-        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-        ModifierApplyFlag UNUSED(flag))
+static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
 {
+       BLI_assert(mesh != NULL);
+
        WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
-       DerivedMesh *dm = derivedData;
        MDeformVert *dvert = NULL;
        MDeformWeight **dw, **tdw;
-       int numVerts;
        float (*v_cos)[3] = NULL; /* The vertices coordinates. */
+       Object *ob = ctx->object;
        Object *obr = NULL; /* Our target object. */
        int defgrp_index;
        float *tw = NULL;
@@ -412,32 +393,57 @@ static DerivedMesh *applyModifier(
 #endif
 
        /* Get number of verts. */
-       numVerts = dm->getNumVerts(dm);
+       const int numVerts = mesh->totvert;
 
        /* Check if we can just return the original mesh.
         * Must have verts and therefore verts assigned to vgroups to do anything useful!
         */
-       if ((numVerts == 0) || BLI_listbase_is_empty(&ob->defbase))
-               return dm;
+       if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) {
+               return mesh;
+       }
 
        /* Get our target object. */
        obr = wmd->proximity_ob_target;
-       if (obr == NULL)
-               return dm;
+       if (obr == NULL) {
+               return mesh;
+       }
 
        /* Get vgroup idx from its name. */
        defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
-       if (defgrp_index == -1)
-               return dm;
+       if (defgrp_index == -1) {
+               return mesh;
+       }
 
-       dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts);
-       /* If no vertices were ever added to an object's vgroup, dvert might be NULL.
-        * As this modifier never add vertices to vgroup, just return. */
-       if (!dvert)
-               return dm;
+       const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT);
+       /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
+       /* As this modifier never add vertices to vgroup, just return. */
+       if (!has_mdef) {
+               return mesh;
+       }
 
-       /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight.
-        */
+       Mesh *result;
+       BKE_id_copy_ex(
+               NULL, &mesh->id, (ID **)&result,
+               LIB_ID_CREATE_NO_MAIN |
+               LIB_ID_CREATE_NO_USER_REFCOUNT |
+               LIB_ID_CREATE_NO_DEG_TAG |
+               LIB_ID_COPY_NO_PREVIEW,
+               false);
+
+       if (has_mdef) {
+               dvert = CustomData_get_layer(&result->vdata, CD_MDEFORMVERT);
+       }
+       else {
+               /* Add a valid data layer! */
+               dvert = CustomData_add_layer(&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
+       }
+       /* Ultimate security check. */
+       if (!dvert) {
+               BKE_id_free(NULL, result);
+               return mesh;
+       }
+
+       /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */
        tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGProximity Modifier, tidx");
        tw = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGProximity Modifier, tw");
        tdw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw");
@@ -454,7 +460,8 @@ static DerivedMesh *applyModifier(
                MEM_freeN(tidx);
                MEM_freeN(tw);
                MEM_freeN(tdw);
-               return dm;
+               BKE_id_free(NULL, result);
+               return mesh;
        }
        if (numIdx != numVerts) {
                indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGProximity Modifier, indices");
@@ -474,25 +481,24 @@ static DerivedMesh *applyModifier(
        MEM_freeN(tidx);
 
        /* Get our vertex coordinates. */
-       v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
        if (numIdx != numVerts) {
-               /* XXX In some situations, this code can be up to about 50 times more performant
-                *     than simply using getVertCo for each affected vertex...
-                */
-               float (*tv_cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "WeightVGProximity Modifier, tv_cos");
-               dm->getVertCos(dm, tv_cos);
-               for (i = 0; i < numIdx; i++)
+               float (*tv_cos)[3] = BKE_mesh_vertexCos_get(result, NULL);
+               v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
+               for (i = 0; i < numIdx; i++) {
                        copy_v3_v3(v_cos[i], tv_cos[indices[i]]);
+               }
                MEM_freeN(tv_cos);
        }
-       else
-               dm->getVertCos(dm, v_cos);
+       else {
+               v_cos = BKE_mesh_vertexCos_get(result, NULL);
+       }
 
        /* Compute wanted distances. */
        if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) {
                const float dist = get_ob2ob_distance(ob, obr);
-               for (i = 0; i < numIdx; i++)
+               for (i = 0; i < numIdx; i++) {
                        new_w[i] = dist;
+               }
        }
        else if (wmd->proximity_mode == MOD_WVG_PROXIMITY_GEOMETRY) {
                const bool use_trgt_verts = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_VERTS) != 0;
@@ -500,23 +506,10 @@ static DerivedMesh *applyModifier(
                const bool use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES) != 0;
 
                if (use_trgt_verts || use_trgt_edges || use_trgt_faces) {
-                       DerivedMesh *target_dm = obr->derivedFinal;
-                       bool free_target_dm = false;
-                       if (!target_dm) {
-                               if (ELEM(obr->type, OB_CURVE, OB_SURF, OB_FONT))
-                                       target_dm = CDDM_from_curve(obr);
-                               else if (obr->type == OB_MESH) {
-                                       Mesh *me = (Mesh *)obr->data;
-                                       if (me->edit_btmesh)
-                                               target_dm = CDDM_from_editbmesh(me->edit_btmesh, false, false);
-                                       else
-                                               target_dm = CDDM_from_mesh(me);
-                               }
-                               free_target_dm = true;
-                       }
+                       Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_object(obr, ctx->flag);
 
-                       /* We must check that we do have a valid target_dm! */
-                       if (target_dm) {
+                       /* We must check that we do have a valid target_mesh! */
+                       if (target_mesh != NULL) {
                                SpaceTransform loc2trgt;
                                float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_v") : NULL;
                                float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_e") : NULL;
@@ -524,7 +517,7 @@ static DerivedMesh *applyModifier(
 
                                BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
                                get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f,
-                                                      target_dm, &loc2trgt);
+                                                      target_mesh, &loc2trgt);
                                for (i = 0; i < numIdx; i++) {
                                        new_w[i] = dists_v ? dists_v[i] : FLT_MAX;
                                        if (dists_e)
@@ -532,10 +525,10 @@ static DerivedMesh *applyModifier(
                                        if (dists_f)
                                                new_w[i] = min_ff(dists_f[i], new_w[i]);
                                }
-                               if (free_target_dm) target_dm->release(target_dm);
-                               if (dists_v) MEM_freeN(dists_v);
-                               if (dists_e) MEM_freeN(dists_e);
-                               if (dists_f) MEM_freeN(dists_f);
+
+                               MEM_SAFE_FREE(dists_v);
+                               MEM_SAFE_FREE(dists_e);
+                               MEM_SAFE_FREE(dists_f);
                        }
                        /* Else, fall back to default obj2vert behavior. */
                        else {
@@ -551,7 +544,7 @@ static DerivedMesh *applyModifier(
        do_map(ob, new_w, numIdx, wmd->min_dist, wmd->max_dist, wmd->falloff_type);
 
        /* Do masking. */
-       weightvg_do_mask(numIdx, indices, org_w, new_w, ob, dm, wmd->mask_constant,
+       weightvg_do_mask(numIdx, indices, org_w, new_w, ob, result, wmd->mask_constant,
                         wmd->mask_defgrp_name, wmd->modifier.scene, wmd->mask_texture,
                         wmd->mask_tex_use_channel, wmd->mask_tex_mapping,
                         wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
@@ -569,16 +562,15 @@ static DerivedMesh *applyModifier(
        MEM_freeN(org_w);
        MEM_freeN(new_w);
        MEM_freeN(dw);
-       if (indices)
-               MEM_freeN(indices);
        MEM_freeN(v_cos);
+       MEM_SAFE_FREE(indices);
 
 #ifdef USE_TIMEIT
        TIMEIT_END(perf);
 #endif
 
        /* Return the vgroup-modified mesh. */
-       return dm;
+       return result;
 }
 
 
@@ -593,17 +585,25 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
                                eModifierTypeFlag_UsesPreview,
 
        /* copyData */          modifier_copyData_generic,
+
+       /* deformVerts_DM */    NULL,
+       /* deformMatrices_DM */ NULL,
+       /* deformVertsEM_DM */  NULL,
+       /* deformMatricesEM_DM*/NULL,
+       /* applyModifier_DM */  NULL,
+       /* applyModifierEM_DM */NULL,
+
        /* deformVerts */       NULL,
        /* deformMatrices */    NULL,
        /* deformVertsEM */     NULL,
        /* deformMatricesEM */  NULL,
        /* applyModifier */     applyModifier,
        /* applyModifierEM */   NULL,
+
        /* initData */          initData,
        /* requiredDataMask */  requiredDataMask,
        /* freeData */          NULL,
        /* isDisabled */        isDisabled,
-       /* updateDepgraph */    updateDepgraph,
        /* updateDepsgraph */   updateDepsgraph,
        /* dependsOnTime */     dependsOnTime,
        /* dependsOnNormals */  NULL,