diff options
Diffstat (limited to 'source/blender/blenkernel/intern/modifier.c')
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 4001 |
1 files changed, 2763 insertions, 1238 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9b9e94774bc..eebd5e6d056 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -40,9 +40,11 @@ #include "stdarg.h" #include "math.h" #include "float.h" +#include "ctype.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_kdopbvh.h" #include "BLI_kdtree.h" #include "BLI_linklist.h" #include "BLI_rand.h" @@ -52,7 +54,11 @@ #include "MEM_guardedalloc.h" +#include "DNA_action_types.h" #include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_cloth_types.h" +#include "DNA_curve_types.h" #include "DNA_effect_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" @@ -63,8 +69,6 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" -#include "DNA_curve_types.h" -#include "DNA_camera_types.h" #include "BLI_editVert.h" @@ -73,25 +77,34 @@ #include "BKE_main.h" #include "BKE_anim.h" +#include "BKE_bmesh.h" +#include "BKE_booleanops.h" +#include "BKE_cloth.h" +#include "BKE_collision.h" +#include "BKE_cdderivedmesh.h" #include "BKE_curve.h" #include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_cdderivedmesh.h" #include "BKE_DerivedMesh.h" -#include "BKE_booleanops.h" #include "BKE_displist.h" -#include "BKE_modifier.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" #include "BKE_lattice.h" #include "BKE_library.h" -#include "BKE_subsurf.h" -#include "BKE_object.h" -#include "BKE_mesh.h" -#include "BKE_softbody.h" #include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" +#include "BKE_softbody.h" +#include "BKE_subsurf.h" +#include "BKE_texture.h" #include "BKE_utildefines.h" + #include "depsgraph_private.h" +#include "BKE_deform.h" +#include "BKE_shrinkwrap.h" +#include "BKE_simple_deform.h" //XXX #include "LOD_DependKludge.h" #include "LOD_decimation.h" @@ -147,9 +160,9 @@ static int curveModifier_isDisabled(ModifierData *md) } static void curveModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { CurveModifierData *cmd = (CurveModifierData*) md; @@ -157,8 +170,8 @@ static void curveModifier_foreachObjectLink( } static void curveModifier_updateDepgraph( - ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) { CurveModifierData *cmd = (CurveModifierData*) md; @@ -166,23 +179,23 @@ static void curveModifier_updateDepgraph( DagNode *curNode = dag_get_node(forest, cmd->object); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier"); } } static void curveModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { CurveModifierData *cmd = (CurveModifierData*) md; curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts, - cmd->name, cmd->defaxis); + cmd->name, cmd->defaxis); } static void curveModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; @@ -223,9 +236,9 @@ static int latticeModifier_isDisabled(ModifierData *md) } static void latticeModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -233,7 +246,7 @@ static void latticeModifier_foreachObjectLink( } static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Object *ob, DagNode *obNode) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -241,7 +254,7 @@ static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, DagNode *latNode = dag_get_node(forest, lmd->object); dag_add_relation(forest, latNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier"); } } @@ -260,8 +273,8 @@ static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3]) static void latticeModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -269,12 +282,12 @@ static void latticeModifier_deformVerts( modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ lattice_deform_verts(lmd->object, ob, derivedData, - vertexCos, numVerts, lmd->name); + vertexCos, numVerts, lmd->name); } static void latticeModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; @@ -320,28 +333,28 @@ static void subsurfModifier_freeData(ModifierData *md) } static DerivedMesh *subsurfModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { SubsurfModifierData *smd = (SubsurfModifierData*) md; DerivedMesh *result; result = subsurf_make_derived_from_derived(derivedData, smd, - useRenderParams, NULL, - isFinalCalc, 0); + useRenderParams, NULL, + isFinalCalc, 0); return result; } static DerivedMesh *subsurfModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { SubsurfModifierData *smd = (SubsurfModifierData*) md; DerivedMesh *result; result = subsurf_make_derived_from_derived(derivedData, smd, 0, - NULL, 0, 1); + NULL, 0, 1); return result; } @@ -373,8 +386,8 @@ static int buildModifier_dependsOnTime(ModifierData *md) } static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, - DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *dm = derivedData; DerivedMesh *result; @@ -387,29 +400,29 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, GHashIterator *hashIter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash, - BLI_ghashutil_intcmp); + BLI_ghashutil_intcmp); /* maps edge indices in new mesh to indices in old mesh */ GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash, - BLI_ghashutil_intcmp); + BLI_ghashutil_intcmp); maxVerts = dm->getNumVerts(dm); vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts, - "build modifier vertMap"); + "build modifier vertMap"); for(i = 0; i < maxVerts; ++i) vertMap[i] = i; maxEdges = dm->getNumEdges(dm); edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges, - "build modifier edgeMap"); + "build modifier edgeMap"); for(i = 0; i < maxEdges; ++i) edgeMap[i] = i; maxFaces = dm->getNumFaces(dm); faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces, - "build modifier faceMap"); + "build modifier faceMap"); for(i = 0; i < maxFaces; ++i) faceMap[i] = i; if (ob) { frac = bsystem_time(ob, (float)G.scene->r.cfra, - bmd->start - 1.0f) / bmd->length; + bmd->start - 1.0f) / bmd->length; } else { frac = G.scene->r.cfra - bmd->start / bmd->length; } @@ -424,156 +437,511 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, if(bmd->randomize) BLI_array_randomize(faceMap, sizeof(*faceMap), - maxFaces, bmd->seed); + maxFaces, bmd->seed); /* get the set of all vert indices that will be in the final mesh, - * mapped to the new indices - */ + * mapped to the new indices + */ for(i = 0; i < numFaces; ++i) { MFace mf; dm->getFace(dm, faceMap[i], &mf); - if(!BLI_ghash_haskey(vertHash, (void *)mf.v1)) - BLI_ghash_insert(vertHash, (void *)mf.v1, - (void *)BLI_ghash_size(vertHash)); - if(!BLI_ghash_haskey(vertHash, (void *)mf.v2)) - BLI_ghash_insert(vertHash, (void *)mf.v2, - (void *)BLI_ghash_size(vertHash)); - if(!BLI_ghash_haskey(vertHash, (void *)mf.v3)) - BLI_ghash_insert(vertHash, (void *)mf.v3, - (void *)BLI_ghash_size(vertHash)); - if(mf.v4 && !BLI_ghash_haskey(vertHash, (void *)mf.v4)) - BLI_ghash_insert(vertHash, (void *)mf.v4, - (void *)BLI_ghash_size(vertHash)); + if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } /* get the set of edges that will be in the new mesh (i.e. all edges - * that have both verts in the new mesh) - */ + * that have both verts in the new mesh) + */ maxEdges = dm->getNumEdges(dm); for(i = 0; i < maxEdges; ++i) { MEdge me; dm->getEdge(dm, i, &me); - if(BLI_ghash_haskey(vertHash, (void *)me.v1) - && BLI_ghash_haskey(vertHash, (void *)me.v2)) + if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) + && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) BLI_ghash_insert(edgeHash, - (void *)BLI_ghash_size(edgeHash), (void *)i); + SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i)); } } else if(numEdges) { if(bmd->randomize) BLI_array_randomize(edgeMap, sizeof(*edgeMap), - maxEdges, bmd->seed); + maxEdges, bmd->seed); /* get the set of all vert indices that will be in the final mesh, - * mapped to the new indices - */ + * mapped to the new indices + */ for(i = 0; i < numEdges; ++i) { MEdge me; dm->getEdge(dm, edgeMap[i], &me); - if(!BLI_ghash_haskey(vertHash, (void *)me.v1)) - BLI_ghash_insert(vertHash, (void *)me.v1, - (void *)BLI_ghash_size(vertHash)); - if(!BLI_ghash_haskey(vertHash, (void *)me.v2)) - BLI_ghash_insert(vertHash, (void *)me.v2, - (void *)BLI_ghash_size(vertHash)); + if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2), + SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } /* get the set of edges that will be in the new mesh - */ + */ for(i = 0; i < numEdges; ++i) { MEdge me; dm->getEdge(dm, edgeMap[i], &me); - BLI_ghash_insert(edgeHash, (void *)BLI_ghash_size(edgeHash), - (void *)edgeMap[i]); + BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), + SET_INT_IN_POINTER(edgeMap[i])); } } else { int numVerts = dm->getNumVerts(dm) * frac; if(bmd->randomize) BLI_array_randomize(vertMap, sizeof(*vertMap), - maxVerts, bmd->seed); + maxVerts, bmd->seed); /* get the set of all vert indices that will be in the final mesh, - * mapped to the new indices - */ + * mapped to the new indices + */ for(i = 0; i < numVerts; ++i) - BLI_ghash_insert(vertHash, (void *)vertMap[i], (void *)i); + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i)); } /* now we know the number of verts, edges and faces, we can create - * the mesh - */ + * the mesh + */ result = CDDM_from_template(dm, BLI_ghash_size(vertHash), - BLI_ghash_size(edgeHash), numFaces); + BLI_ghash_size(edgeHash), numFaces); /* copy the vertices across */ for(hashIter = BLI_ghashIterator_new(vertHash); - !BLI_ghashIterator_isDone(hashIter); - BLI_ghashIterator_step(hashIter)) { + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter)) { + MVert source; + MVert *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + + dm->getVert(dm, oldIndex, &source); + dest = CDDM_get_vert(result, newIndex); + + DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + } + BLI_ghashIterator_free(hashIter); + + /* copy the edges across, remapping indices */ + for(i = 0; i < BLI_ghash_size(edgeHash); ++i) { + MEdge source; + MEdge *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i))); + + dm->getEdge(dm, oldIndex, &source); + dest = CDDM_get_edge(result, i); + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + + DM_copy_edge_data(dm, result, oldIndex, i, 1); + *dest = source; + } + + /* copy the faces across, remapping indices */ + for(i = 0; i < numFaces; ++i) { + MFace source; + MFace *dest; + int orig_v4; + + dm->getFace(dm, faceMap[i], &source); + dest = CDDM_get_face(result, i); + + orig_v4 = source.v4; + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); + if(source.v4) + source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); + + DM_copy_face_data(dm, result, faceMap[i], i, 1); + *dest = source; + + test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3)); + } + + CDDM_calc_normals(result); + + BLI_ghash_free(vertHash, NULL, NULL); + BLI_ghash_free(edgeHash, NULL, NULL); + + MEM_freeN(vertMap); + MEM_freeN(edgeMap); + MEM_freeN(faceMap); + + return result; +} + +/* Mask */ + +static void maskModifier_copyData(ModifierData *md, ModifierData *target) +{ + MaskModifierData *mmd = (MaskModifierData*) md; + MaskModifierData *tmmd = (MaskModifierData*) target; + + strcpy(tmmd->vgroup, mmd->vgroup); +} + +static CustomDataMask maskModifier_requiredDataMask(ModifierData *md) +{ + return (1 << CD_MDEFORMVERT); +} + +static void maskModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + walk(userData, ob, &mmd->ob_arm); +} + +static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + + if (mmd->ob_arm) + { + DagNode *armNode = dag_get_node(forest, mmd->ob_arm); + + dag_add_relation(forest, armNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier"); + } +} + +static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + MaskModifierData *mmd= (MaskModifierData *)md; + DerivedMesh *dm= derivedData, *result= NULL; + GHash *vertHash=NULL, *edgeHash, *faceHash; + GHashIterator *hashIter; + MDeformVert *dvert= NULL; + int numFaces=0, numEdges=0, numVerts=0; + int maxVerts, maxEdges, maxFaces; + int i; + + /* Overview of Method: + * 1. Get the vertices that are in the vertexgroup of interest + * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices + * 3. Make a new mesh containing only the mapping data + */ + + /* get original number of verts, edges, and faces */ + maxVerts= dm->getNumVerts(dm); + maxEdges= dm->getNumEdges(dm); + maxFaces= dm->getNumFaces(dm); + + /* check if we can just return the original mesh + * - must have verts and therefore verts assigned to vgroups to do anything useful + */ + if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || + (maxVerts == 0) || (ob->defbase.first == NULL) ) + { + return derivedData; + } + + /* if mode is to use selected armature bones, aggregate the bone groups */ + if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ + { + GHash *vgroupHash, *boneHash; + Object *oba= mmd->ob_arm; + bPoseChannel *pchan; + bDeformGroup *def; + + /* check that there is armature object with bones to use, otherwise return original mesh */ + if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose)) + return derivedData; + + /* hashes for finding mapping of: + * - vgroups to indicies -> vgroupHash (string, int) + * - bones to vgroup indices -> boneHash (index of vgroup, dummy) + */ + vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* build mapping of names of vertex groups to indices */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); + + /* get selected-posechannel <-> vertexgroup index mapping */ + for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next) + { + /* check if bone is selected */ + // TODO: include checks for visibility too? + // FIXME: the depsgraph needs extensions to make this work in realtime... + if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) ) + { + /* check if hash has group for this bone */ + if (BLI_ghash_haskey(vgroupHash, pchan->name)) + { + int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name)); + + /* add index to hash (store under key only) */ + BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan); + } + } + } + + /* if no bones selected, free hashes and return original mesh */ + if (BLI_ghash_size(boneHash) == 0) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* repeat the previous check, but for dverts */ + dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); + if (dvert == NULL) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroups into vertHash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr))) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + + /* free temp hashes */ + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + } + else /* --- Using Nominated VertexGroup only --- */ + { + int defgrp_index = -1; + + /* get index of vertex group */ + if (mmd->vgroup[0]) + { + bDeformGroup *def; + + /* find index by comparing names - SLOW... */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + { + if (!strcmp(def->name, mmd->vgroup)) + { + defgrp_index = i; + break; + } + } + } + + /* get dverts */ + if (defgrp_index >= 0) + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + /* if no vgroup (i.e. dverts) found, return the initial mesh */ + if ((defgrp_index < 0) || (dvert == NULL)) + return dm; + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroup into ghash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (dvert[i].dw[j].def_nr == defgrp_index) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* loop over edges and faces, and do the same thing to + * ensure that they only reference existing verts + */ + for (i = 0; i < maxEdges; i++) + { + MEdge me; + dm->getEdge(dm, i, &me); + + /* only add if both verts will be in new mesh */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) ) + { + BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); + numEdges++; + } + } + for (i = 0; i < maxFaces; i++) + { + MFace mf; + dm->getFace(dm, i, &mf); + + /* all verts must be available */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) && + (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) ) + { + BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces)); + numFaces++; + } + } + + + /* now we know the number of verts, edges and faces, + * we can create the new (reduced) mesh + */ + result = CDDM_from_template(dm, numVerts, numEdges, numFaces); + + + /* using ghash-iterators, map data into new mesh */ + /* vertices */ + for ( hashIter = BLI_ghashIterator_new(vertHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { MVert source; MVert *dest; - int oldIndex = (int)BLI_ghashIterator_getKey(hashIter); - int newIndex = (int)BLI_ghashIterator_getValue(hashIter); - + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + dm->getVert(dm, oldIndex, &source); dest = CDDM_get_vert(result, newIndex); - + DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); - - /* copy the edges across, remapping indices */ - for(i = 0; i < BLI_ghash_size(edgeHash); ++i) { + + /* edges */ + for ( hashIter = BLI_ghashIterator_new(edgeHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { MEdge source; MEdge *dest; - int oldIndex = (int)BLI_ghash_lookup(edgeHash, (void *)i); - + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + dm->getEdge(dm, oldIndex, &source); - dest = CDDM_get_edge(result, i); - - source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1); - source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2); - - DM_copy_edge_data(dm, result, oldIndex, i, 1); + dest = CDDM_get_edge(result, newIndex); + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + + DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); *dest = source; } - - /* copy the faces across, remapping indices */ - for(i = 0; i < numFaces; ++i) { + BLI_ghashIterator_free(hashIter); + + /* faces */ + for ( hashIter = BLI_ghashIterator_new(faceHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { MFace source; MFace *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); int orig_v4; - - dm->getFace(dm, faceMap[i], &source); - dest = CDDM_get_face(result, i); - + + dm->getFace(dm, oldIndex, &source); + dest = CDDM_get_face(result, newIndex); + orig_v4 = source.v4; - - source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1); - source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2); - source.v3 = (int)BLI_ghash_lookup(vertHash, (void *)source.v3); - if(source.v4) - source.v4 = (int)BLI_ghash_lookup(vertHash, (void *)source.v4); - - DM_copy_face_data(dm, result, faceMap[i], i, 1); + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); + if (source.v4) + source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); + + DM_copy_face_data(dm, result, oldIndex, newIndex, 1); *dest = source; - - test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3)); + + test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3)); } - + BLI_ghashIterator_free(hashIter); + + /* recalculate normals */ CDDM_calc_normals(result); - + + /* free hashes */ BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); - - MEM_freeN(vertMap); - MEM_freeN(edgeMap); - MEM_freeN(faceMap); - + BLI_ghash_free(faceHash, NULL, NULL); + + /* return the new mesh */ return result; } @@ -586,7 +954,7 @@ static void arrayModifier_initData(ModifierData *md) ArrayModifierData *amd = (ArrayModifierData*) md; /* default to 2 duplicates distributed along the x-axis by an - offset of 1 object-width + offset of 1 object-width */ amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL; amd->count = 2; @@ -620,9 +988,9 @@ static void arrayModifier_copyData(ModifierData *md, ModifierData *target) } static void arrayModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { ArrayModifierData *amd = (ArrayModifierData*) md; @@ -633,7 +1001,7 @@ static void arrayModifier_foreachObjectLink( } static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Object *ob, DagNode *obNode) { ArrayModifierData *amd = (ArrayModifierData*) md; @@ -641,25 +1009,25 @@ static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, DagNode *curNode = dag_get_node(forest, amd->start_cap); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); } if (amd->end_cap) { DagNode *curNode = dag_get_node(forest, amd->end_cap); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); } if (amd->curve_ob) { DagNode *curNode = dag_get_node(forest, amd->curve_ob); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); } if (amd->offset_ob) { DagNode *curNode = dag_get_node(forest, amd->offset_ob); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); } } @@ -686,12 +1054,12 @@ typedef struct IndexMapEntry { /* the new vert index that this old vert index maps to */ int new; /* -1 if this vert isn't merged, otherwise the old vert index it - * should be replaced with - */ + * should be replaced with + */ int merge; /* 1 if this vert's first copy is merged with the last copy of its - * merge target, otherwise 0 - */ + * merge target, otherwise 0 + */ short merge_final; } IndexMapEntry; @@ -710,19 +1078,19 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum) } else { /* vert was merged with another vert */ /* follow the chain of merges to the end, or until we've passed - * a number of vertices equal to the copy number - */ + * a number of vertices equal to the copy number + */ if(copyNum <= 0) return indexMap[oldIndex].new; else return calc_mapping(indexMap, indexMap[oldIndex].merge, - copyNum - 1); + copyNum - 1); } } static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, - Object *ob, DerivedMesh *dm, - int initFlags) + Object *ob, DerivedMesh *dm, + int initFlags) { int i, j; /* offset matrix */ @@ -752,7 +1120,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, MTC_Mat4One(offset); indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm), - "indexmap"); + "indexmap"); src_mvert = dm->getVertArray(dm); @@ -763,7 +1131,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->offset_type & MOD_ARR_OFF_RELATIVE) { for(j = 0; j < 3; j++) offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, - maxVerts, j); + maxVerts, j); } if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { @@ -776,472 +1144,509 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, MTC_Mat4One(obinv); MTC_Mat4MulSerie(result_mat, offset, - obinv, amd->offset_ob->obmat, - NULL, NULL, NULL, NULL, NULL); + obinv, amd->offset_ob->obmat, + NULL, NULL, NULL, NULL, NULL); MTC_Mat4CpyMat4(offset, result_mat); } if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { Curve *cu = amd->curve_ob->data; if(cu) { + float tmp_mat[3][3]; + float scale; + + object_to_mat3(amd->curve_ob, tmp_mat); + scale = Mat3ToScalef(tmp_mat); + if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist makeDispListCurveTypes(amd->curve_ob, 0); } if(cu->path) - length = cu->path->totdist; + length = scale*cu->path->totdist; } } /* calculate the maximum number of copies which will fit within the - prescribed length */ + prescribed length */ if(amd->fit_type == MOD_ARR_FITLENGTH - || amd->fit_type == MOD_ARR_FITCURVE) { + || amd->fit_type == MOD_ARR_FITCURVE) { float dist = sqrt(MTC_dot3Float(offset[3], offset[3])); - if(dist > FLT_EPSILON) + if(dist > 1e-6f) /* this gives length = first copy start to last copy end - add a tiny offset for floating point rounding errors */ - count = (length + FLT_EPSILON) / dist; + add a tiny offset for floating point rounding errors */ + count = (length + 1e-6f) / dist; else /* if the offset has no translation, just make one copy */ count = 1; - } + } - if(count < 1) - count = 1; + if(count < 1) + count = 1; /* allocate memory for count duplicates (including original) plus - * start and end caps - */ - finalVerts = dm->getNumVerts(dm) * count; - finalEdges = dm->getNumEdges(dm) * count; - finalFaces = dm->getNumFaces(dm) * count; - if(start_cap) { - finalVerts += start_cap->getNumVerts(start_cap); - finalEdges += start_cap->getNumEdges(start_cap); - finalFaces += start_cap->getNumFaces(start_cap); - } - if(end_cap) { - finalVerts += end_cap->getNumVerts(end_cap); - finalEdges += end_cap->getNumEdges(end_cap); - finalFaces += end_cap->getNumFaces(end_cap); - } - result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces); - - /* calculate the offset matrix of the final copy (for merging) */ - MTC_Mat4One(final_offset); - - for(j=0; j < count - 1; j++) { - MTC_Mat4MulMat4(tmp_mat, final_offset, offset); - MTC_Mat4CpyMat4(final_offset, tmp_mat); - } - - numVerts = numEdges = numFaces = 0; - mvert = CDDM_get_verts(result); - - for (i = 0; i < maxVerts; i++) { - MVert *inMV; - MVert *mv = &mvert[numVerts]; - MVert *mv2; - float co[3]; - - inMV = &src_mvert[i]; - - DM_copy_vert_data(dm, result, i, numVerts, 1); - *mv = *inMV; - numVerts++; - - indexMap[i].new = numVerts - 1; - indexMap[i].merge = -1; /* default to no merge */ - indexMap[i].merge_final = 0; /* default to no merge */ - - VECCOPY(co, mv->co); + * start and end caps + */ + finalVerts = dm->getNumVerts(dm) * count; + finalEdges = dm->getNumEdges(dm) * count; + finalFaces = dm->getNumFaces(dm) * count; + if(start_cap) { + finalVerts += start_cap->getNumVerts(start_cap); + finalEdges += start_cap->getNumEdges(start_cap); + finalFaces += start_cap->getNumFaces(start_cap); + } + if(end_cap) { + finalVerts += end_cap->getNumVerts(end_cap); + finalEdges += end_cap->getNumEdges(end_cap); + finalFaces += end_cap->getNumFaces(end_cap); + } + result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces); + + /* calculate the offset matrix of the final copy (for merging) */ + MTC_Mat4One(final_offset); + + for(j=0; j < count - 1; j++) { + MTC_Mat4MulMat4(tmp_mat, final_offset, offset); + MTC_Mat4CpyMat4(final_offset, tmp_mat); + } + + numVerts = numEdges = numFaces = 0; + mvert = CDDM_get_verts(result); + + for (i = 0; i < maxVerts; i++) { + indexMap[i].merge = -1; /* default to no merge */ + indexMap[i].merge_final = 0; /* default to no merge */ + } + + for (i = 0; i < maxVerts; i++) { + MVert *inMV; + MVert *mv = &mvert[numVerts]; + MVert *mv2; + float co[3]; + + inMV = &src_mvert[i]; + + DM_copy_vert_data(dm, result, i, numVerts, 1); + *mv = *inMV; + numVerts++; + + indexMap[i].new = numVerts - 1; + + VECCOPY(co, mv->co); /* Attempts to merge verts from one duplicate with verts from the - * next duplicate which are closer than amd->merge_dist. - * Only the first such vert pair is merged. - * If verts are merged in the first duplicate pair, they are merged - * in all pairs. - */ - if((count > 1) && (amd->flags & MOD_ARR_MERGE)) { - float tmp_co[3]; - VECCOPY(tmp_co, mv->co); - MTC_Mat4MulVecfl(offset, tmp_co); - - for(j = 0; j < maxVerts; j++) { - inMV = &src_mvert[j]; - /* if this vert is within merge limit, merge */ - if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) { - indexMap[i].merge = j; - - /* test for merging with final copy of merge target */ - if(amd->flags & MOD_ARR_MERGEFINAL) { - VECCOPY(tmp_co, inMV->co); - inMV = &src_mvert[i]; - MTC_Mat4MulVecfl(final_offset, tmp_co); - if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) - indexMap[i].merge_final = 1; - } - break; - } - } - } - - /* if no merging, generate copies of this vert */ - if(indexMap[i].merge < 0) { - for(j=0; j < count - 1; j++) { - mv2 = &mvert[numVerts]; - - DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1); - *mv2 = *mv; - numVerts++; - - MTC_Mat4MulVecfl(offset, co); - VECCOPY(mv2->co, co); - } - } else if(indexMap[i].merge != i && indexMap[i].merge_final) { + * next duplicate which are closer than amd->merge_dist. + * Only the first such vert pair is merged. + * If verts are merged in the first duplicate pair, they are merged + * in all pairs. + */ + if((count > 1) && (amd->flags & MOD_ARR_MERGE)) { + float tmp_co[3]; + VECCOPY(tmp_co, mv->co); + MTC_Mat4MulVecfl(offset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + /* if vertex already merged, don't use it */ + if( indexMap[j].merge != -1 ) continue; + + inMV = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) { + indexMap[i].merge = j; + + /* test for merging with final copy of merge target */ + if(amd->flags & MOD_ARR_MERGEFINAL) { + VECCOPY(tmp_co, inMV->co); + inMV = &src_mvert[i]; + MTC_Mat4MulVecfl(final_offset, tmp_co); + if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) + indexMap[i].merge_final = 1; + } + break; + } + } + } + + /* if no merging, generate copies of this vert */ + if(indexMap[i].merge < 0) { + for(j=0; j < count - 1; j++) { + mv2 = &mvert[numVerts]; + + DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1); + *mv2 = *mv; + numVerts++; + + MTC_Mat4MulVecfl(offset, co); + VECCOPY(mv2->co, co); + } + } else if(indexMap[i].merge != i && indexMap[i].merge_final) { /* if this vert is not merging with itself, and it is merging - * with the final copy of its merge target, remove the first copy - */ - numVerts--; - DM_free_vert_data(result, numVerts, 1); - } - } - - /* make a hashtable so we can avoid duplicate edges from merging */ - edges = BLI_edgehash_new(); - - maxEdges = dm->getNumEdges(dm); - medge = CDDM_get_edges(result); - for(i = 0; i < maxEdges; i++) { - MEdge inMED; - MEdge med; - MEdge *med2; - int vert1, vert2; - - dm->getEdge(dm, i, &inMED); - - med = inMED; - med.v1 = indexMap[inMED.v1].new; - med.v2 = indexMap[inMED.v2].new; + * with the final copy of its merge target, remove the first copy + */ + numVerts--; + DM_free_vert_data(result, numVerts, 1); + } + } + + /* make a hashtable so we can avoid duplicate edges from merging */ + edges = BLI_edgehash_new(); + + maxEdges = dm->getNumEdges(dm); + medge = CDDM_get_edges(result); + for(i = 0; i < maxEdges; i++) { + MEdge inMED; + MEdge med; + MEdge *med2; + int vert1, vert2; + + dm->getEdge(dm, i, &inMED); + + med = inMED; + med.v1 = indexMap[inMED.v1].new; + med.v2 = indexMap[inMED.v2].new; /* if vertices are to be merged with the final copies of their - * merge targets, calculate that final copy - */ - if(indexMap[inMED.v1].merge_final) { - med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge, - count - 1); - } - if(indexMap[inMED.v2].merge_final) { - med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge, - count - 1); - } - - if (initFlags) { - med.flag |= ME_EDGEDRAW | ME_EDGERENDER; - } - - if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) { - DM_copy_edge_data(dm, result, i, numEdges, 1); - medge[numEdges] = med; - numEdges++; - - BLI_edgehash_insert(edges, med.v1, med.v2, NULL); - } - - for(j = 1; j < count; j++) - { - vert1 = calc_mapping(indexMap, inMED.v1, j); - vert2 = calc_mapping(indexMap, inMED.v2, j); - /* avoid duplicate edges */ - if(!BLI_edgehash_haskey(edges, vert1, vert2)) { - med2 = &medge[numEdges]; - - DM_copy_edge_data(dm, result, i, numEdges, 1); - *med2 = med; - numEdges++; - - med2->v1 = vert1; - med2->v2 = vert2; - - BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL); - } - } - } - - maxFaces = dm->getNumFaces(dm); - mface = CDDM_get_faces(result); - for (i=0; i < maxFaces; i++) { - MFace inMF; - MFace *mf = &mface[numFaces]; - - dm->getFace(dm, i, &inMF); - - DM_copy_face_data(dm, result, i, numFaces, 1); - *mf = inMF; - - mf->v1 = indexMap[inMF.v1].new; - mf->v2 = indexMap[inMF.v2].new; - mf->v3 = indexMap[inMF.v3].new; - if(inMF.v4) - mf->v4 = indexMap[inMF.v4].new; + * merge targets, calculate that final copy + */ + if(indexMap[inMED.v1].merge_final) { + med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge, + count - 1); + } + if(indexMap[inMED.v2].merge_final) { + med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge, + count - 1); + } + + if(med.v1 == med.v2) continue; + + if (initFlags) { + med.flag |= ME_EDGEDRAW | ME_EDGERENDER; + } + + if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) { + DM_copy_edge_data(dm, result, i, numEdges, 1); + medge[numEdges] = med; + numEdges++; + + BLI_edgehash_insert(edges, med.v1, med.v2, NULL); + } + + for(j = 1; j < count; j++) + { + vert1 = calc_mapping(indexMap, inMED.v1, j); + vert2 = calc_mapping(indexMap, inMED.v2, j); + /* avoid duplicate edges */ + if(!BLI_edgehash_haskey(edges, vert1, vert2)) { + med2 = &medge[numEdges]; + + DM_copy_edge_data(dm, result, i, numEdges, 1); + *med2 = med; + numEdges++; + + med2->v1 = vert1; + med2->v2 = vert2; + + BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL); + } + } + } + + maxFaces = dm->getNumFaces(dm); + mface = CDDM_get_faces(result); + for (i=0; i < maxFaces; i++) { + MFace inMF; + MFace *mf = &mface[numFaces]; + + dm->getFace(dm, i, &inMF); + + DM_copy_face_data(dm, result, i, numFaces, 1); + *mf = inMF; + + mf->v1 = indexMap[inMF.v1].new; + mf->v2 = indexMap[inMF.v2].new; + mf->v3 = indexMap[inMF.v3].new; + if(inMF.v4) + mf->v4 = indexMap[inMF.v4].new; /* if vertices are to be merged with the final copies of their - * merge targets, calculate that final copy - */ - if(indexMap[inMF.v1].merge_final) - mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1); - if(indexMap[inMF.v2].merge_final) - mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1); - if(indexMap[inMF.v3].merge_final) - mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1); - if(inMF.v4 && indexMap[inMF.v4].merge_final) - mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1); - - test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3); - numFaces++; - - /* if the face has fewer than 3 vertices, don't create it */ - if(mf->v3 == 0) { - numFaces--; - DM_free_face_data(result, numFaces, 1); - } - - for(j = 1; j < count; j++) - { - MFace *mf2 = &mface[numFaces]; - - DM_copy_face_data(dm, result, i, numFaces, 1); - *mf2 = *mf; - - mf2->v1 = calc_mapping(indexMap, inMF.v1, j); - mf2->v2 = calc_mapping(indexMap, inMF.v2, j); - mf2->v3 = calc_mapping(indexMap, inMF.v3, j); - if (inMF.v4) - mf2->v4 = calc_mapping(indexMap, inMF.v4, j); - - test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); - numFaces++; - - /* if the face has fewer than 3 vertices, don't create it */ - if(mf2->v3 == 0) { - numFaces--; - DM_free_face_data(result, numFaces, 1); - } - } - } - - /* add start and end caps */ - if(start_cap) { - float startoffset[4][4]; - MVert *cap_mvert; - MEdge *cap_medge; - MFace *cap_mface; - int *origindex; - int *vert_map; - int capVerts, capEdges, capFaces; - - capVerts = start_cap->getNumVerts(start_cap); - capEdges = start_cap->getNumEdges(start_cap); - capFaces = start_cap->getNumFaces(start_cap); - cap_mvert = start_cap->getVertArray(start_cap); - cap_medge = start_cap->getEdgeArray(start_cap); - cap_mface = start_cap->getFaceArray(start_cap); - - Mat4Invert(startoffset, offset); - - vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, - "arrayModifier_doArray vert_map"); - - origindex = result->getVertDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capVerts; i++) { - MVert *mv = &cap_mvert[i]; - short merged = 0; - - if(amd->flags & MOD_ARR_MERGE) { - float tmp_co[3]; - MVert *in_mv; - int j; - - VECCOPY(tmp_co, mv->co); - Mat4MulVecfl(startoffset, tmp_co); - - for(j = 0; j < maxVerts; j++) { - in_mv = &src_mvert[j]; - /* if this vert is within merge limit, merge */ - if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) { - vert_map[i] = calc_mapping(indexMap, j, 0); - merged = 1; - break; - } - } - } - - if(!merged) { - DM_copy_vert_data(start_cap, result, i, numVerts, 1); - mvert[numVerts] = *mv; - Mat4MulVecfl(startoffset, mvert[numVerts].co); - origindex[numVerts] = ORIGINDEX_NONE; - - vert_map[i] = numVerts; - - numVerts++; - } - } - origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capEdges; i++) { - int v1, v2; - - v1 = vert_map[cap_medge[i].v1]; - v2 = vert_map[cap_medge[i].v2]; - - if(!BLI_edgehash_haskey(edges, v1, v2)) { - DM_copy_edge_data(start_cap, result, i, numEdges, 1); - medge[numEdges] = cap_medge[i]; - medge[numEdges].v1 = v1; - medge[numEdges].v2 = v2; - origindex[numEdges] = ORIGINDEX_NONE; - - numEdges++; - } - } - origindex = result->getFaceDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capFaces; i++) { - DM_copy_face_data(start_cap, result, i, numFaces, 1); - mface[numFaces] = cap_mface[i]; - mface[numFaces].v1 = vert_map[mface[numFaces].v1]; - mface[numFaces].v2 = vert_map[mface[numFaces].v2]; - mface[numFaces].v3 = vert_map[mface[numFaces].v3]; - if(mface[numFaces].v4) - mface[numFaces].v4 = vert_map[mface[numFaces].v4]; - origindex[numFaces] = ORIGINDEX_NONE; - - numFaces++; - } - - MEM_freeN(vert_map); - start_cap->release(start_cap); - } - - if(end_cap) { - float endoffset[4][4]; - MVert *cap_mvert; - MEdge *cap_medge; - MFace *cap_mface; - int *origindex; - int *vert_map; - int capVerts, capEdges, capFaces; - - capVerts = end_cap->getNumVerts(end_cap); - capEdges = end_cap->getNumEdges(end_cap); - capFaces = end_cap->getNumFaces(end_cap); - cap_mvert = end_cap->getVertArray(end_cap); - cap_medge = end_cap->getEdgeArray(end_cap); - cap_mface = end_cap->getFaceArray(end_cap); - - Mat4MulMat4(endoffset, final_offset, offset); - - vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, - "arrayModifier_doArray vert_map"); - - origindex = result->getVertDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capVerts; i++) { - MVert *mv = &cap_mvert[i]; - short merged = 0; - - if(amd->flags & MOD_ARR_MERGE) { - float tmp_co[3]; - MVert *in_mv; - int j; - - VECCOPY(tmp_co, mv->co); - Mat4MulVecfl(offset, tmp_co); - - for(j = 0; j < maxVerts; j++) { - in_mv = &src_mvert[j]; - /* if this vert is within merge limit, merge */ - if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) { - vert_map[i] = calc_mapping(indexMap, j, count - 1); - merged = 1; - break; - } - } - } - - if(!merged) { - DM_copy_vert_data(end_cap, result, i, numVerts, 1); - mvert[numVerts] = *mv; - Mat4MulVecfl(endoffset, mvert[numVerts].co); - origindex[numVerts] = ORIGINDEX_NONE; - - vert_map[i] = numVerts; - - numVerts++; - } - } - origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capEdges; i++) { - int v1, v2; - - v1 = vert_map[cap_medge[i].v1]; - v2 = vert_map[cap_medge[i].v2]; - - if(!BLI_edgehash_haskey(edges, v1, v2)) { - DM_copy_edge_data(end_cap, result, i, numEdges, 1); - medge[numEdges] = cap_medge[i]; - medge[numEdges].v1 = v1; - medge[numEdges].v2 = v2; - origindex[numEdges] = ORIGINDEX_NONE; - - numEdges++; - } - } - origindex = result->getFaceDataArray(result, CD_ORIGINDEX); - for(i = 0; i < capFaces; i++) { - DM_copy_face_data(end_cap, result, i, numFaces, 1); - mface[numFaces] = cap_mface[i]; - mface[numFaces].v1 = vert_map[mface[numFaces].v1]; - mface[numFaces].v2 = vert_map[mface[numFaces].v2]; - mface[numFaces].v3 = vert_map[mface[numFaces].v3]; - if(mface[numFaces].v4) - mface[numFaces].v4 = vert_map[mface[numFaces].v4]; - origindex[numFaces] = ORIGINDEX_NONE; - - numFaces++; - } - - MEM_freeN(vert_map); - end_cap->release(end_cap); - } - - BLI_edgehash_free(edges, NULL); - MEM_freeN(indexMap); - - CDDM_lower_num_verts(result, numVerts); - CDDM_lower_num_edges(result, numEdges); - CDDM_lower_num_faces(result, numFaces); - - return result; + * merge targets, calculate that final copy + */ + if(indexMap[inMF.v1].merge_final) + mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1); + if(indexMap[inMF.v2].merge_final) + mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1); + if(indexMap[inMF.v3].merge_final) + mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1); + if(inMF.v4 && indexMap[inMF.v4].merge_final) + mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1); + + if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3) + continue; + + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + + for(j = 1; j < count; j++) + { + MFace *mf2 = &mface[numFaces]; + + DM_copy_face_data(dm, result, i, numFaces, 1); + *mf2 = *mf; + + mf2->v1 = calc_mapping(indexMap, inMF.v1, j); + mf2->v2 = calc_mapping(indexMap, inMF.v2, j); + mf2->v3 = calc_mapping(indexMap, inMF.v3, j); + if (inMF.v4) + mf2->v4 = calc_mapping(indexMap, inMF.v4, j); + + test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 == + mf2->v4))) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + } + } + + /* add start and end caps */ + if(start_cap) { + float startoffset[4][4]; + MVert *cap_mvert; + MEdge *cap_medge; + MFace *cap_mface; + int *origindex; + int *vert_map; + int capVerts, capEdges, capFaces; + + capVerts = start_cap->getNumVerts(start_cap); + capEdges = start_cap->getNumEdges(start_cap); + capFaces = start_cap->getNumFaces(start_cap); + cap_mvert = start_cap->getVertArray(start_cap); + cap_medge = start_cap->getEdgeArray(start_cap); + cap_mface = start_cap->getFaceArray(start_cap); + + Mat4Invert(startoffset, offset); + + vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, + "arrayModifier_doArray vert_map"); + + origindex = result->getVertDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capVerts; i++) { + MVert *mv = &cap_mvert[i]; + short merged = 0; + + if(amd->flags & MOD_ARR_MERGE) { + float tmp_co[3]; + MVert *in_mv; + int j; + + VECCOPY(tmp_co, mv->co); + Mat4MulVecfl(startoffset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + in_mv = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) { + vert_map[i] = calc_mapping(indexMap, j, 0); + merged = 1; + break; + } + } + } + + if(!merged) { + DM_copy_vert_data(start_cap, result, i, numVerts, 1); + mvert[numVerts] = *mv; + Mat4MulVecfl(startoffset, mvert[numVerts].co); + origindex[numVerts] = ORIGINDEX_NONE; + + vert_map[i] = numVerts; + + numVerts++; + } + } + origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capEdges; i++) { + int v1, v2; + + v1 = vert_map[cap_medge[i].v1]; + v2 = vert_map[cap_medge[i].v2]; + + if(!BLI_edgehash_haskey(edges, v1, v2)) { + DM_copy_edge_data(start_cap, result, i, numEdges, 1); + medge[numEdges] = cap_medge[i]; + medge[numEdges].v1 = v1; + medge[numEdges].v2 = v2; + origindex[numEdges] = ORIGINDEX_NONE; + + numEdges++; + } + } + origindex = result->getFaceDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capFaces; i++) { + DM_copy_face_data(start_cap, result, i, numFaces, 1); + mface[numFaces] = cap_mface[i]; + mface[numFaces].v1 = vert_map[mface[numFaces].v1]; + mface[numFaces].v2 = vert_map[mface[numFaces].v2]; + mface[numFaces].v3 = vert_map[mface[numFaces].v3]; + if(mface[numFaces].v4) { + mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } + + origindex[numFaces] = ORIGINDEX_NONE; + + numFaces++; + } + + MEM_freeN(vert_map); + start_cap->release(start_cap); + } + + if(end_cap) { + float endoffset[4][4]; + MVert *cap_mvert; + MEdge *cap_medge; + MFace *cap_mface; + int *origindex; + int *vert_map; + int capVerts, capEdges, capFaces; + + capVerts = end_cap->getNumVerts(end_cap); + capEdges = end_cap->getNumEdges(end_cap); + capFaces = end_cap->getNumFaces(end_cap); + cap_mvert = end_cap->getVertArray(end_cap); + cap_medge = end_cap->getEdgeArray(end_cap); + cap_mface = end_cap->getFaceArray(end_cap); + + Mat4MulMat4(endoffset, final_offset, offset); + + vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, + "arrayModifier_doArray vert_map"); + + origindex = result->getVertDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capVerts; i++) { + MVert *mv = &cap_mvert[i]; + short merged = 0; + + if(amd->flags & MOD_ARR_MERGE) { + float tmp_co[3]; + MVert *in_mv; + int j; + + VECCOPY(tmp_co, mv->co); + Mat4MulVecfl(offset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + in_mv = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) { + vert_map[i] = calc_mapping(indexMap, j, count - 1); + merged = 1; + break; + } + } + } + + if(!merged) { + DM_copy_vert_data(end_cap, result, i, numVerts, 1); + mvert[numVerts] = *mv; + Mat4MulVecfl(endoffset, mvert[numVerts].co); + origindex[numVerts] = ORIGINDEX_NONE; + + vert_map[i] = numVerts; + + numVerts++; + } + } + origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capEdges; i++) { + int v1, v2; + + v1 = vert_map[cap_medge[i].v1]; + v2 = vert_map[cap_medge[i].v2]; + + if(!BLI_edgehash_haskey(edges, v1, v2)) { + DM_copy_edge_data(end_cap, result, i, numEdges, 1); + medge[numEdges] = cap_medge[i]; + medge[numEdges].v1 = v1; + medge[numEdges].v2 = v2; + origindex[numEdges] = ORIGINDEX_NONE; + + numEdges++; + } + } + origindex = result->getFaceDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capFaces; i++) { + DM_copy_face_data(end_cap, result, i, numFaces, 1); + mface[numFaces] = cap_mface[i]; + mface[numFaces].v1 = vert_map[mface[numFaces].v1]; + mface[numFaces].v2 = vert_map[mface[numFaces].v2]; + mface[numFaces].v3 = vert_map[mface[numFaces].v3]; + if(mface[numFaces].v4) { + mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } + origindex[numFaces] = ORIGINDEX_NONE; + + numFaces++; + } + + MEM_freeN(vert_map); + end_cap->release(end_cap); + } + + BLI_edgehash_free(edges, NULL); + MEM_freeN(indexMap); + + CDDM_lower_num_verts(result, numVerts); + CDDM_lower_num_edges(result, numEdges); + CDDM_lower_num_faces(result, numFaces); + + return result; } static DerivedMesh *arrayModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *result; ArrayModifierData *amd = (ArrayModifierData*) md; result = arrayModifier_doArray(amd, ob, derivedData, 0); - CDDM_calc_normals(result); + if(result != derivedData) + CDDM_calc_normals(result); return result; } static DerivedMesh *arrayModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { return arrayModifier_applyModifier(md, ob, derivedData, 0, 1); } @@ -1252,7 +1657,7 @@ static void mirrorModifier_initData(ModifierData *md) { MirrorModifierData *mmd = (MirrorModifierData*) md; - mmd->flag |= MOD_MIR_AXIS_X; + mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP); mmd->tolerance = 0.001; mmd->mirror_ob = NULL; } @@ -1269,9 +1674,9 @@ static void mirrorModifier_copyData(ModifierData *md, ModifierData *target) } static void mirrorModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { MirrorModifierData *mmd = (MirrorModifierData*) md; @@ -1279,7 +1684,7 @@ static void mirrorModifier_foreachObjectLink( } static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Object *ob, DagNode *obNode) { MirrorModifierData *mmd = (MirrorModifierData*) md; @@ -1287,15 +1692,127 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, DagNode *latNode = dag_get_node(forest, mmd->mirror_ob); dag_add_relation(forest, latNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier"); } } +/* finds the best possible flipped name. For renaming; check for unique names afterwards */ +/* if strip_number: removes number extensions */ +void vertgroup_flip_name (char *name, int strip_number) +{ + int len; + char prefix[128]={""}; /* The part before the facing */ + char suffix[128]={""}; /* The part after the facing */ + char replace[128]={""}; /* The replacement string */ + char number[128]={""}; /* The number extension string */ + char *index=NULL; + + len= strlen(name); + if(len<3) return; // we don't do names like .R or .L + + /* We first check the case with a .### extension, let's find the last period */ + if(isdigit(name[len-1])) { + index= strrchr(name, '.'); // last occurrance + if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever! + if(strip_number==0) + strcpy(number, index); + *index= 0; + len= strlen(name); + } + } + + strcpy (prefix, name); + +#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_') + + /* first case; separator . - _ with extensions r R l L */ + if( IS_SEPARATOR(name[len-2]) ) { + switch(name[len-1]) { + case 'l': + prefix[len-1]= 0; + strcpy(replace, "r"); + break; + case 'r': + prefix[len-1]= 0; + strcpy(replace, "l"); + break; + case 'L': + prefix[len-1]= 0; + strcpy(replace, "R"); + break; + case 'R': + prefix[len-1]= 0; + strcpy(replace, "L"); + break; + } + } + /* case; beginning with r R l L , with separator after it */ + else if( IS_SEPARATOR(name[1]) ) { + switch(name[0]) { + case 'l': + strcpy(replace, "r"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'r': + strcpy(replace, "l"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'L': + strcpy(replace, "R"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'R': + strcpy(replace, "L"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + } + } + else if(len > 5) { + /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ + index = BLI_strcasestr(prefix, "right"); + if (index==prefix || index==prefix+len-5) { + if(index[0]=='r') + strcpy (replace, "left"); + else { + if(index[1]=='I') + strcpy (replace, "LEFT"); + else + strcpy (replace, "Left"); + } + *index= 0; + strcpy (suffix, index+5); + } + else { + index = BLI_strcasestr(prefix, "left"); + if (index==prefix || index==prefix+len-4) { + if(index[0]=='l') + strcpy (replace, "right"); + else { + if(index[1]=='E') + strcpy (replace, "RIGHT"); + else + strcpy (replace, "Right"); + } + *index= 0; + strcpy (suffix, index+4); + } + } + } + +#undef IS_SEPARATOR + + sprintf (name, "%s%s%s%s", prefix, replace, suffix, number); +} + static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, - Object *ob, - DerivedMesh *dm, - int initFlags, - int axis) + Object *ob, + DerivedMesh *dm, + int initFlags, + int axis) { int i; float tolerance = mmd->tolerance; @@ -1304,6 +1821,9 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int maxVerts = dm->getNumVerts(dm); int maxEdges = dm->getNumEdges(dm); int maxFaces = dm->getNumFaces(dm); + int vector_size=0, j, a, b; + bDeformGroup *def, *defb; + bDeformGroup **vector_def = NULL; int (*indexMap)[2]; float mtx[4][4], imtx[4][4]; @@ -1313,9 +1833,24 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2); + + if (mmd->flag & MOD_MIR_VGROUP) { + /* calculate the number of deformedGroups */ + for(vector_size = 0, def = ob->defbase.first; def; + def = def->next, vector_size++); + + /* load the deformedGroups for fast access */ + vector_def = + (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size, + "group_index"); + for(a = 0, def = ob->defbase.first; def; def = def->next, a++) { + vector_def[a] = def; + } + } + if (mmd->mirror_ob) { float obinv[4][4]; - + Mat4Invert(obinv, mmd->mirror_ob->obmat); Mat4MulMat4(mtx, ob->obmat, obinv); Mat4Invert(imtx, mtx); @@ -1326,27 +1861,27 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, MVert *mv = CDDM_get_vert(result, numVerts); int isShared; float co[3]; - + dm->getVert(dm, i, &inMV); - + VecCopyf(co, inMV.co); - + if (mmd->mirror_ob) { VecMat4MulVecfl(co, mtx, co); } isShared = ABS(co[axis])<=tolerance; - + /* Because the topology result (# of vertices) must be the same if - * the mesh data is overridden by vertex cos, have to calc sharedness - * based on original coordinates. This is why we test before copy. - */ + * the mesh data is overridden by vertex cos, have to calc sharedness + * based on original coordinates. This is why we test before copy. + */ DM_copy_vert_data(dm, result, i, numVerts, 1); *mv = inMV; numVerts++; - + indexMap[i][0] = numVerts - 1; indexMap[i][1] = !isShared; - + if(isShared) { co[axis] = 0; if (mmd->mirror_ob) { @@ -1357,41 +1892,73 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, mv->flag |= ME_VERT_MERGED; } else { MVert *mv2 = CDDM_get_vert(result, numVerts); - + MDeformVert *dvert = NULL; + DM_copy_vert_data(dm, result, i, numVerts, 1); *mv2 = *mv; - numVerts++; - + co[axis] = -co[axis]; if (mmd->mirror_ob) { VecMat4MulVecfl(co, imtx, co); } VecCopyf(mv2->co, co); + + if (mmd->flag & MOD_MIR_VGROUP){ + dvert = DM_get_vert_data(result, numVerts, CD_MDEFORMVERT); + + if (dvert) + { + for(j = 0; j < dvert[0].totweight; ++j) + { + char tmpname[32]; + + if(dvert->dw[j].def_nr < 0 || + dvert->dw[j].def_nr >= vector_size) + continue; + + def = vector_def[dvert->dw[j].def_nr]; + strcpy(tmpname, def->name); + vertgroup_flip_name(tmpname,0); + + for(b = 0, defb = ob->defbase.first; defb; + defb = defb->next, b++) + { + if(!strcmp(defb->name, tmpname)) + { + dvert->dw[j].def_nr = b; + break; + } + } + } + } + } + + numVerts++; } } for(i = 0; i < maxEdges; i++) { MEdge inMED; MEdge *med = CDDM_get_edge(result, numEdges); - + dm->getEdge(dm, i, &inMED); - + DM_copy_edge_data(dm, result, i, numEdges, 1); *med = inMED; numEdges++; - + med->v1 = indexMap[inMED.v1][0]; med->v2 = indexMap[inMED.v2][0]; if(initFlags) med->flag |= ME_EDGEDRAW | ME_EDGERENDER; - + if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) { MEdge *med2 = CDDM_get_edge(result, numEdges); - + DM_copy_edge_data(dm, result, i, numEdges, 1); *med2 = *med; numEdges++; - + med2->v1 += indexMap[inMED.v1][1]; med2->v2 += indexMap[inMED.v2][1]; } @@ -1400,33 +1967,33 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, for(i = 0; i < maxFaces; i++) { MFace inMF; MFace *mf = CDDM_get_face(result, numFaces); - + dm->getFace(dm, i, &inMF); - + DM_copy_face_data(dm, result, i, numFaces, 1); *mf = inMF; numFaces++; - + mf->v1 = indexMap[inMF.v1][0]; mf->v2 = indexMap[inMF.v2][0]; mf->v3 = indexMap[inMF.v3][0]; mf->v4 = indexMap[inMF.v4][0]; if(indexMap[inMF.v1][1] - || indexMap[inMF.v2][1] - || indexMap[inMF.v3][1] - || (mf->v4 && indexMap[inMF.v4][1])) { + || indexMap[inMF.v2][1] + || indexMap[inMF.v3][1] + || (mf->v4 && indexMap[inMF.v4][1])) { MFace *mf2 = CDDM_get_face(result, numFaces); static int corner_indices[4] = {2, 1, 0, 3}; - + DM_copy_face_data(dm, result, i, numFaces, 1); *mf2 = *mf; - + mf2->v1 += indexMap[inMF.v1][1]; mf2->v2 += indexMap[inMF.v2][1]; mf2->v3 += indexMap[inMF.v3][1]; if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1]; - + /* mirror UVs if enabled */ if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) { MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE); @@ -1440,16 +2007,18 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } } } - + /* Flip face normal */ SWAP(int, mf2->v1, mf2->v3); DM_swap_face_data(result, numFaces, corner_indices); - + test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); numFaces++; } } + if (vector_def) MEM_freeN(vector_def); + MEM_freeN(indexMap); CDDM_lower_num_verts(result, numVerts); @@ -1460,8 +2029,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, - Object *ob, DerivedMesh *dm, - int initFlags) + Object *ob, DerivedMesh *dm, + int initFlags) { DerivedMesh *result = dm; @@ -1484,22 +2053,23 @@ static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, } static DerivedMesh *mirrorModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *result; MirrorModifierData *mmd = (MirrorModifierData*) md; result = mirrorModifier__doMirror(mmd, ob, derivedData, 0); - CDDM_calc_normals(result); + if(result != derivedData) + CDDM_calc_normals(result); return result; } static DerivedMesh *mirrorModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1); } @@ -1570,6 +2140,8 @@ typedef struct SmoothMesh { DerivedMesh *dm; float threshold; /* the cosine of the smoothing angle */ int flags; + MemArena *arena; + ListBase propagatestack, reusestack; } SmoothMesh; static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh) @@ -1622,15 +2194,15 @@ static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert) } static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces, - int max_verts, int max_edges, int max_faces) + int max_verts, int max_edges, int max_faces) { SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh"); mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts, - "SmoothMesh.verts"); + "SmoothMesh.verts"); mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges, - "SmoothMesh.edges"); + "SmoothMesh.edges"); mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces, - "SmoothMesh.faces"); + "SmoothMesh.faces"); mesh->num_verts = num_verts; mesh->num_edges = num_edges; @@ -1652,6 +2224,9 @@ static void smoothmesh_free(SmoothMesh *mesh) for(i = 0; i < mesh->num_edges; ++i) BLI_linklist_free(mesh->edges[i].faces, NULL); + + if(mesh->arena) + BLI_memarena_free(mesh->arena); MEM_freeN(mesh->verts); MEM_freeN(mesh->edges); @@ -1729,7 +2304,7 @@ static void smoothmesh_print(SmoothMesh *mesh) printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}", i, vert->oldIndex, vert->newIndex, - mv.co[0], mv.co[1], mv.co[2]); + mv.co[0], mv.co[1], mv.co[2]); printf(", faces={"); for(node = vert->faces; node != NULL; node = node->next) { printf(" %d", ((SmoothFace *)node->link)->newIndex); @@ -1744,8 +2319,8 @@ static void smoothmesh_print(SmoothMesh *mesh) printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}", i, - edge->oldIndex, edge->newIndex, - edge->verts[0]->newIndex, edge->verts[1]->newIndex); + edge->oldIndex, edge->newIndex, + edge->verts[0]->newIndex, edge->verts[1]->newIndex); if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX"); printf(", faces={"); for(node = edge->faces; node != NULL; node = node->next) { @@ -1787,7 +2362,7 @@ static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm) totface = dm->getNumFaces(dm); mesh = smoothmesh_new(totvert, totedge, totface, - totvert, totedge, totface); + totvert, totedge, totface); mesh->dm = dm; @@ -1857,9 +2432,9 @@ static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm) static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh) { DerivedMesh *result = CDDM_from_template(mesh->dm, - mesh->num_verts, - mesh->num_edges, - mesh->num_faces); + mesh->num_verts, + mesh->num_edges, + mesh->num_faces); MVert *new_verts = CDDM_get_verts(result); MEdge *new_edges = CDDM_get_edges(result); MFace *new_faces = CDDM_get_faces(result); @@ -1870,7 +2445,7 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh) MVert *newMV = &new_verts[vert->newIndex]; DM_copy_vert_data(mesh->dm, result, - vert->oldIndex, vert->newIndex, 1); + vert->oldIndex, vert->newIndex, 1); mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV); } @@ -1879,7 +2454,7 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh) MEdge *newME = &new_edges[edge->newIndex]; DM_copy_edge_data(mesh->dm, result, - edge->oldIndex, edge->newIndex, 1); + edge->oldIndex, edge->newIndex, 1); mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME); newME->v1 = edge->verts[0]->newIndex; newME->v2 = edge->verts[1]->newIndex; @@ -1890,7 +2465,7 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh) MFace *newMF = &new_faces[face->newIndex]; DM_copy_face_data(mesh->dm, result, - face->oldIndex, face->newIndex, 1); + face->oldIndex, face->newIndex, 1); mesh->dm->getFace(mesh->dm, face->oldIndex, newMF); newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex; @@ -1920,7 +2495,7 @@ static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert) * (this should never happen) */ static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert, - SmoothEdge *edge) + SmoothEdge *edge) { int i,j; for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) { @@ -1932,8 +2507,8 @@ static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert, } /* if we get to here, something's wrong (there should always be 2 edges - * which use the same vert in a face) - */ + * which use the same vert in a face) + */ return NULL; } @@ -1962,18 +2537,18 @@ static void linklist_copy(LinkNode **target, LinkNode *source) for(; source; source = source->next) { if(node) { node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy"); - node = node->next; - } else { - node = *target = MEM_mallocN(sizeof(**target), "nlink_copy"); - } - node->link = source->link; - node->next = NULL; - } + node = node->next; +} else { + node = *target = MEM_mallocN(sizeof(**target), "nlink_copy"); +} + node->link = source->link; + node->next = NULL; +} } #endif -/* appends source to target if it's not already in target */ -static void linklist_append_unique(LinkNode **target, void *source) + /* appends source to target if it's not already in target */ + static void linklist_append_unique(LinkNode **target, void *source) { LinkNode *node; LinkNode *prev = NULL; @@ -2007,7 +2582,7 @@ static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend) node->next = *list; *list = prepend; - } +} } #endif @@ -2050,7 +2625,7 @@ static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc) * frees the pointer with freefunc if freefunc is not NULL */ static void linklist_remove_first(LinkNode **list, void *value, - LinkNodeFreeFP freefunc) + LinkNodeFreeFP freefunc) { LinkNode *node = *list; LinkNode *prev = NULL; @@ -2075,7 +2650,7 @@ static void linklist_remove_first(LinkNode **list, void *value, /* removes all elements in source from target */ static void linklist_remove_list(LinkNode **target, LinkNode *source, - LinkNodeFreeFP freefunc) + LinkNodeFreeFP freefunc) { for(; source; source = source->next) linklist_remove_first(target, source->link, freefunc); @@ -2150,15 +2725,15 @@ static void face_replace_edge(void *ptr, void *userdata) #ifdef EDGESPLIT_DEBUG_3 printf("replacing edge %4d with %4d in face %4d", - find->newIndex, replace->newIndex, face->newIndex); + find->newIndex, replace->newIndex, face->newIndex); if(face->edges[3]) printf(": {%2d %2d %2d %2d}", face->edges[0]->newIndex, face->edges[1]->newIndex, - face->edges[2]->newIndex, face->edges[3]->newIndex); + face->edges[2]->newIndex, face->edges[3]->newIndex); else printf(": {%2d %2d %2d}", face->edges[0]->newIndex, face->edges[1]->newIndex, - face->edges[2]->newIndex); + face->edges[2]->newIndex); #endif for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) { @@ -2173,11 +2748,11 @@ static void face_replace_edge(void *ptr, void *userdata) if(face->edges[3]) printf(" -> {%2d %2d %2d %2d}\n", face->edges[0]->newIndex, face->edges[1]->newIndex, - face->edges[2]->newIndex, face->edges[3]->newIndex); + face->edges[2]->newIndex, face->edges[3]->newIndex); else printf(" -> {%2d %2d %2d}\n", face->edges[0]->newIndex, face->edges[1]->newIndex, - face->edges[2]->newIndex); + face->edges[2]->newIndex); #endif } @@ -2187,7 +2762,7 @@ static int edge_is_loose(SmoothEdge *edge) } static int edge_is_sharp(SmoothEdge *edge, int flags, - float threshold) + float threshold) { #ifdef EDGESPLIT_DEBUG_1 printf("edge %d: ", edge->newIndex); @@ -2218,7 +2793,7 @@ static int edge_is_sharp(SmoothEdge *edge, int flags, * - returns to the start edge (NULL is returned) */ static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, - LinkNode **visited_faces, float threshold, int flags) + LinkNode **visited_faces, float threshold, int flags) { SmoothFace *face = NULL; SmoothEdge *edge2 = NULL; @@ -2244,10 +2819,10 @@ static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, BLI_linklist_prepend(visited_faces, face); /* search until we hit a loose edge or a sharp edge or an edge we've - * seen before - */ + * seen before + */ while(face && !edge_is_sharp(edge2, flags, threshold) - && !linklist_contains(visited_edges, edge2)) { + && !linklist_contains(visited_edges, edge2)) { #ifdef EDGESPLIT_DEBUG_3 printf("current face %4d; current edge %4d\n", face->newIndex, edge2->newIndex); @@ -2273,25 +2848,25 @@ static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, printf("loose edge: %4d\n", edge2->newIndex); #endif } - } + } - /* either we came back to the start edge or we found a sharp/loose edge */ - if(linklist_contains(visited_edges, edge2)) - /* we came back to the start edge */ - edge2 = NULL; + /* either we came back to the start edge or we found a sharp/loose edge */ + if(linklist_contains(visited_edges, edge2)) + /* we came back to the start edge */ + edge2 = NULL; - BLI_linklist_free(visited_edges, NULL); + BLI_linklist_free(visited_edges, NULL); #ifdef EDGESPLIT_DEBUG_1 - printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), " - "returning edge %d\n", - edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1); + printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), " + "returning edge %d\n", + edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1); #endif - return edge2; + return edge2; } static void split_single_vert(SmoothVert *vert, SmoothFace *face, - SmoothMesh *mesh) + SmoothMesh *mesh) { SmoothVert *copy_vert; ReplaceData repdata; @@ -2303,10 +2878,53 @@ static void split_single_vert(SmoothVert *vert, SmoothFace *face, face_replace_vert(face, &repdata); } +typedef struct PropagateEdge { + struct PropagateEdge *next, *prev; + SmoothEdge *edge; + SmoothVert *vert; +} PropagateEdge; + +static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) +{ + PropagateEdge *pedge = mesh->reusestack.first; + + if(pedge) { + BLI_remlink(&mesh->reusestack, pedge); + } + else { + if(!mesh->arena) { + mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_calloc(mesh->arena); + } + + pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge)); + } + + pedge->edge = edge; + pedge->vert = vert; + BLI_addhead(&mesh->propagatestack, pedge); +} + +static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh) +{ + PropagateEdge *pedge = mesh->propagatestack.first; + + if(pedge) { + *edge = pedge->edge; + *vert = pedge->vert; + BLI_remlink(&mesh->propagatestack, pedge); + BLI_addhead(&mesh->reusestack, pedge); + } + else { + *edge = NULL; + *vert = NULL; + } +} + static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh); static void propagate_split(SmoothEdge *edge, SmoothVert *vert, - SmoothMesh *mesh) + SmoothMesh *mesh) { SmoothEdge *edge2; LinkNode *visited_faces = NULL; @@ -2316,7 +2934,7 @@ static void propagate_split(SmoothEdge *edge, SmoothVert *vert, #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces, - mesh->threshold, mesh->flags); + mesh->threshold, mesh->flags); if(!edge2) { /* didn't find a sharp or loose edge, so we've hit a dead end */ @@ -2375,12 +2993,12 @@ static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces, - mesh->threshold, mesh->flags); + mesh->threshold, mesh->flags); if(!edge2) { /* didn't find a sharp or loose edge, so try the other vert */ vert2 = other_vert(edge, vert); - propagate_split(edge, vert2, mesh); + push_propagate_stack(edge, vert2, mesh); } else if(!edge_is_loose(edge2)) { /* edge2 is not loose, so it must be sharp */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); @@ -2400,20 +3018,20 @@ static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) vert2 = smoothvert_copy(vert, mesh); /* replace vert with its copy in visited_faces (must be done after - * edge replacement so edges have correct vertices) - */ + * edge replacement so edges have correct vertices) + */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); /* all copying and replacing is done; the mesh should be consistent. - * now propagate the split to the vertices at either end - */ - propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh); - propagate_split(copy_edge2, other_vert(copy_edge2, vert2), mesh); + * now propagate the split to the vertices at either end + */ + push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); + push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh); if(smoothedge_has_vert(edge, vert)) - propagate_split(edge, vert, mesh); + push_propagate_stack(edge, vert, mesh); } else { /* edge2 is loose */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); @@ -2427,19 +3045,19 @@ static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) vert2 = smoothvert_copy(vert, mesh); /* replace vert with its copy in visited_faces (must be done after - * edge replacement so edges have correct vertices) - */ + * edge replacement so edges have correct vertices) + */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); /* copying and replacing is done; the mesh should be consistent. - * now propagate the split to the vertex at the other end - */ - propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh); + * now propagate the split to the vertex at the other end + */ + push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); if(smoothedge_has_vert(edge, vert)) - propagate_split(edge, vert, mesh); + push_propagate_stack(edge, vert, mesh); } BLI_linklist_free(visited_faces, NULL); @@ -2450,7 +3068,7 @@ static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) } static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle, - int flags, int *extra_edges) + int flags, int *extra_edges) { /* if normal1 dot normal2 < threshold, angle is greater, so split */ /* FIXME not sure if this always works */ @@ -2477,40 +3095,41 @@ static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle, for(node = edge->faces->next->next->next; node; node = node->next) (*extra_edges)++; } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)) - && !edge_is_loose(edge)) { + && !edge_is_loose(edge)) { /* (the edge can only be sharp if we're checking angle or flag, - * and it has at least 2 faces) */ + * and it has at least 2 faces) */ - /* if we're checking the sharp flag and it's set, good */ - if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) { - /* this edge is sharp */ - sharp = 1; + /* if we're checking the sharp flag and it's set, good */ + if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) { + /* this edge is sharp */ + sharp = 1; - (*extra_edges)++; - } else if(flags & MOD_EDGESPLIT_FROMANGLE) { - /* we know the edge has 2 faces, so check the angle */ - SmoothFace *face1 = edge->faces->link; - SmoothFace *face2 = edge->faces->next->link; - float edge_angle_cos = MTC_dot3Float(face1->normal, - face2->normal); - - if(edge_angle_cos < threshold) { - /* this edge is sharp */ - sharp = 1; - - (*extra_edges)++; - } - } - } + (*extra_edges)++; + } else if(flags & MOD_EDGESPLIT_FROMANGLE) { + /* we know the edge has 2 faces, so check the angle */ + SmoothFace *face1 = edge->faces->link; + SmoothFace *face2 = edge->faces->next->link; + float edge_angle_cos = MTC_dot3Float(face1->normal, + face2->normal); + + if(edge_angle_cos < threshold) { + /* this edge is sharp */ + sharp = 1; - /* set/clear sharp flag appropriately */ - if(sharp) edge->flag |= ME_SHARP; - else edge->flag &= ~ME_SHARP; + (*extra_edges)++; + } + } + } + + /* set/clear sharp flag appropriately */ + if(sharp) edge->flag |= ME_SHARP; + else edge->flag &= ~ME_SHARP; } } static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags) { + SmoothVert *vert; int i; /* if normal1 dot normal2 < threshold, angle is greater, so split */ /* FIXME not sure if this always works */ @@ -2523,10 +3142,16 @@ static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags) for(i = 0; i < mesh->num_edges; i++) { SmoothEdge *edge = &mesh->edges[i]; - if(edge_is_sharp(edge, flags, mesh->threshold)) + if(edge_is_sharp(edge, flags, mesh->threshold)) { split_edge(edge, edge->verts[0], mesh); - } + do { + pop_propagate_stack(&edge, &vert, mesh); + if(edge && smoothedge_has_vert(edge, vert)) + propagate_split(edge, vert, mesh); + } while(edge); + } + } } static int count_bridge_verts(SmoothMesh *mesh) @@ -2548,19 +3173,19 @@ static int count_bridge_verts(SmoothMesh *mesh) next_edge = face->edges[next]; /* if there are other faces sharing this vertex but not - * these edges, the vertex will be split, so count it - */ + * these edges, the vertex will be split, so count it + */ /* vert has to have at least one face (this one), so faces != 0 */ if(!edge->faces->next && !next_edge->faces->next - && vert->faces->next) { + && vert->faces->next) { count++; - } + } } } /* each bridge vert will be counted once per face that uses it, - * so count is too high, but it's ok for now - */ + * so count is too high, but it's ok for now + */ return count; } @@ -2583,21 +3208,21 @@ static void split_bridge_verts(SmoothMesh *mesh) next_edge = face->edges[next]; /* if there are other faces sharing this vertex but not - * these edges, split the vertex - */ + * these edges, split the vertex + */ /* vert has to have at least one face (this one), so faces != 0 */ if(!edge->faces->next && !next_edge->faces->next - && vert->faces->next) + && vert->faces->next) /* FIXME this needs to find all faces that share edges with - * this one and split off together - */ + * this one and split off together + */ split_single_vert(vert, face, mesh); } } } static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, - Object *ob, DerivedMesh *dm) + Object *ob, DerivedMesh *dm) { SmoothMesh *mesh; DerivedMesh *result; @@ -2640,8 +3265,8 @@ static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, #ifdef EDGESPLIT_DEBUG_0 printf("Edgesplit: Estimated %d verts & %d edges, " - "found %d verts & %d edges\n", max_verts, max_edges, - mesh->num_verts, mesh->num_edges); + "found %d verts & %d edges\n", max_verts, max_edges, + mesh->num_verts, mesh->num_edges); #endif result = CDDM_from_smoothmesh(mesh); @@ -2651,26 +3276,111 @@ static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, } static DerivedMesh *edgesplitModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *result; EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md; result = edgesplitModifier_do(emd, ob, derivedData); - CDDM_calc_normals(result); + if(result != derivedData) + CDDM_calc_normals(result); return result; } static DerivedMesh *edgesplitModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1); } +/* Bevel */ + +static void bevelModifier_initData(ModifierData *md) +{ + BevelModifierData *bmd = (BevelModifierData*) md; + + bmd->value = 0.1f; + bmd->res = 1; + bmd->flags = 0; + bmd->val_flags = 0; + bmd->lim_flags = 0; + bmd->e_flags = 0; + bmd->bevel_angle = 30; + bmd->defgrp_name[0] = '\0'; +} + +static void bevelModifier_copyData(ModifierData *md, ModifierData *target) +{ + BevelModifierData *bmd = (BevelModifierData*) md; + BevelModifierData *tbmd = (BevelModifierData*) target; + + tbmd->value = bmd->value; + tbmd->res = bmd->res; + tbmd->flags = bmd->flags; + tbmd->val_flags = bmd->val_flags; + tbmd->lim_flags = bmd->lim_flags; + tbmd->e_flags = bmd->e_flags; + tbmd->bevel_angle = bmd->bevel_angle; + strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32); +} + +CustomDataMask bevelModifier_requiredDataMask(ModifierData *md) +{ + BevelModifierData *bmd = (BevelModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if(bmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + +static DerivedMesh *bevelModifier_applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *result; + BME_Mesh *bm; + + /*bDeformGroup *def;*/ + int /*i,*/ options, defgrp_index = -1; + BevelModifierData *bmd = (BevelModifierData*) md; + + options = bmd->flags|bmd->val_flags|bmd->lim_flags|bmd->e_flags; + + //~ if ((options & BME_BEVEL_VWEIGHT) && bmd->defgrp_name[0]) { + //~ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { + //~ if (!strcmp(def->name, bmd->defgrp_name)) { + //~ defgrp_index = i; + //~ break; + //~ } + //~ } + //~ if (defgrp_index < 0) { + //~ options &= ~BME_BEVEL_VWEIGHT; + //~ } + //~ } + + bm = BME_derivedmesh_to_bmesh(derivedData); + BME_bevel(bm,bmd->value,bmd->res,options,defgrp_index,bmd->bevel_angle,NULL); + result = BME_bmesh_to_derivedmesh(bm,derivedData); + BME_free_mesh(bm); + + CDDM_calc_normals(result); + + return result; +} + +static DerivedMesh *bevelModifier_applyModifierEM( + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) +{ + return bevelModifier_applyModifier(md, ob, derivedData, 0, 1); +} + /* Displace */ static void displaceModifier_initData(ModifierData *md) @@ -2712,8 +3422,22 @@ CustomDataMask displaceModifier_requiredDataMask(ModifierData *md) return dataMask; } +static int displaceModifier_dependsOnTime(ModifierData *md) +{ + DisplaceModifierData *dmd = (DisplaceModifierData *)md; + + if(dmd->texture) + { + return BKE_texture_dependsOnTime(dmd->texture); + } + else + { + return 0; + } +} + static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob, - ObjectWalkFunc walk, void *userData) + ObjectWalkFunc walk, void *userData) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; @@ -2721,13 +3445,13 @@ static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob, } static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, - IDWalkFunc walk, void *userData) + IDWalkFunc walk, void *userData) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; walk(userData, ob, (ID **)&dmd->texture); - displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData); + displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } static int displaceModifier_isDisabled(ModifierData *md) @@ -2738,8 +3462,8 @@ static int displaceModifier_isDisabled(ModifierData *md) } static void displaceModifier_updateDepgraph( - ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; @@ -2747,7 +3471,7 @@ static void displaceModifier_updateDepgraph( DagNode *curNode = dag_get_node(forest, dmd->map_object); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier"); } } @@ -2761,17 +3485,17 @@ static void validate_layer_name(const CustomData *data, int type, char *name) if(index < 0) { /* either no layer was specified, or the layer we want has been - * deleted, so assign the active layer to name - */ + * deleted, so assign the active layer to name + */ index = CustomData_get_active_layer_index(data, CD_MTFACE); strcpy(name, data->layers[index].name); } } static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, - DerivedMesh *dm, - float (*co)[3], float (*texco)[3], - int numVerts) + DerivedMesh *dm, + float (*co)[3], float (*texco)[3], + int numVerts) { int i; int texmapping = dmd->texmapping; @@ -2789,14 +3513,14 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, MFace *mface = dm->getFaceArray(dm); MFace *mf; char *done = MEM_callocN(sizeof(*done) * numVerts, - "get_texture_coords done"); + "get_texture_coords done"); int numFaces = dm->getNumFaces(dm); MTFace *tf; validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name); tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, - dmd->uvlayer_name); + dmd->uvlayer_name); /* verts are given the UV from the first face that uses them */ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { @@ -2840,18 +3564,18 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, for(i = 0; i < numVerts; ++i, ++co, ++texco) { switch(texmapping) { - case MOD_DISP_MAP_LOCAL: - VECCOPY(*texco, *co); - break; - case MOD_DISP_MAP_GLOBAL: - VECCOPY(*texco, *co); - Mat4MulVecfl(ob->obmat, *texco); - break; - case MOD_DISP_MAP_OBJECT: - VECCOPY(*texco, *co); - Mat4MulVecfl(ob->obmat, *texco); - Mat4MulVecfl(dmd->map_object->imat, *texco); - break; + case MOD_DISP_MAP_LOCAL: + VECCOPY(*texco, *co); + break; + case MOD_DISP_MAP_GLOBAL: + VECCOPY(*texco, *co); + Mat4MulVecfl(ob->obmat, *texco); + break; + case MOD_DISP_MAP_OBJECT: + VECCOPY(*texco, *co); + Mat4MulVecfl(ob->obmat, *texco); + Mat4MulVecfl(dmd->map_object->imat, *texco); + break; } } } @@ -2861,23 +3585,23 @@ static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres) int result_type; result_type = multitex_ext(texture, tex_co, NULL, - NULL, 1, texres); + NULL, 1, texres); /* if the texture gave an RGB value, we assume it didn't give a valid - * intensity, so calculate one (formula from do_material_tex). - * if the texture didn't give an RGB value, copy the intensity across - */ + * intensity, so calculate one (formula from do_material_tex). + * if the texture didn't give an RGB value, copy the intensity across + */ if(result_type & TEX_RGB) texres->tin = (0.35 * texres->tr + 0.45 * texres->tg - + 0.2 * texres->tb); + + 0.2 * texres->tb); else texres->tr = texres->tg = texres->tb = texres->tin; } /* dm must be a CDDerivedMesh */ static void displaceModifier_do( - DisplaceModifierData *dmd, Object *ob, - DerivedMesh *dm, float (*vertexCos)[3], int numVerts) + DisplaceModifierData *dmd, Object *ob, + DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { int i; MVert *mvert; @@ -2904,7 +3628,7 @@ static void displaceModifier_do( dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); tex_co = MEM_callocN(sizeof(*tex_co) * numVerts, - "displaceModifier_do tex_co"); + "displaceModifier_do tex_co"); get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts); for(i = 0; i < numVerts; ++i) { @@ -2933,25 +3657,25 @@ static void displaceModifier_do( delta *= strength; switch(dmd->direction) { - case MOD_DISP_DIR_X: - vertexCos[i][0] += delta; - break; - case MOD_DISP_DIR_Y: - vertexCos[i][1] += delta; - break; - case MOD_DISP_DIR_Z: - vertexCos[i][2] += delta; - break; - case MOD_DISP_DIR_RGB_XYZ: - vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength; - vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength; - vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength; - break; - case MOD_DISP_DIR_NOR: - vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f; - vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f; - vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f; - break; + case MOD_DISP_DIR_X: + vertexCos[i][0] += delta; + break; + case MOD_DISP_DIR_Y: + vertexCos[i][1] += delta; + break; + case MOD_DISP_DIR_Z: + vertexCos[i][2] += delta; + break; + case MOD_DISP_DIR_RGB_XYZ: + vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength; + vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength; + vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength; + break; + case MOD_DISP_DIR_NOR: + vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f; + vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f; + vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f; + break; } } @@ -2959,8 +3683,8 @@ static void displaceModifier_do( } static void displaceModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -2972,14 +3696,14 @@ static void displaceModifier_deformVerts( CDDM_calc_normals(dm); displaceModifier_do((DisplaceModifierData *)md, ob, dm, - vertexCos, numVerts); + vertexCos, numVerts); dm->release(dm); } static void displaceModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -2990,7 +3714,7 @@ static void displaceModifier_deformVertsEM( CDDM_calc_normals(dm); displaceModifier_do((DisplaceModifierData *)md, ob, dm, - vertexCos, numVerts); + vertexCos, numVerts); dm->release(dm); } @@ -3038,7 +3762,7 @@ CustomDataMask uvprojectModifier_requiredDataMask(ModifierData *md) } static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob, - ObjectWalkFunc walk, void *userData) + ObjectWalkFunc walk, void *userData) { UVProjectModifierData *umd = (UVProjectModifierData*) md; int i; @@ -3048,18 +3772,18 @@ static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob, } static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob, - IDWalkFunc walk, void *userData) + IDWalkFunc walk, void *userData) { UVProjectModifierData *umd = (UVProjectModifierData*) md; walk(userData, ob, (ID **)&umd->image); uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, - userData); + userData); } static void uvprojectModifier_updateDepgraph(ModifierData *md, - DagForest *forest, Object *ob, DagNode *obNode) + DagForest *forest, Object *ob, DagNode *obNode) { UVProjectModifierData *umd = (UVProjectModifierData*) md; int i; @@ -3069,7 +3793,7 @@ static void uvprojectModifier_updateDepgraph(ModifierData *md, DagNode *curNode = dag_get_node(forest, umd->projectors[i]); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier"); } } } @@ -3081,7 +3805,7 @@ typedef struct Projector { } Projector; static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, - Object *ob, DerivedMesh *dm) + Object *ob, DerivedMesh *dm) { float (*coords)[3], (*co)[3]; MTFace *tface; @@ -3110,13 +3834,13 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, /* make sure we are not modifying the original UV layer */ tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, - CD_MTFACE, - umd->uvlayer_name); + CD_MTFACE, + umd->uvlayer_name); numVerts = dm->getNumVerts(dm); coords = MEM_callocN(sizeof(*coords) * numVerts, - "uvprojectModifier_do coords"); + "uvprojectModifier_do coords"); dm->getVertCos(dm, coords); /* convert coords to world space */ @@ -3127,12 +3851,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, for(i = 0; i < num_projectors; ++i) { float tmpmat[4][4]; float offsetmat[4][4]; - + Camera *cam = NULL; /* calculate projection matrix */ Mat4Invert(projectors[i].projmat, projectors[i].ob->obmat); if(projectors[i].ob->type == OB_CAMERA) { - Camera *cam = (Camera *)projectors[i].ob->data; + cam = (Camera *)projectors[i].ob->data; if(cam->type == CAM_PERSP) { float perspmat[4][4]; float xmax; @@ -3152,7 +3876,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, ymin = -ymax; i_window(xmin, xmax, ymin, ymax, - cam->clipsta, cam->clipend, perspmat); + cam->clipsta, cam->clipend, perspmat); Mat4MulMat4(tmpmat, projectors[i].projmat, perspmat); } else if(cam->type == CAM_ORTHO) { float orthomat[4][4]; @@ -3172,7 +3896,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, ymin = -ymax; i_ortho(xmin, xmax, ymin, ymax, - cam->clipsta, cam->clipend, orthomat); + cam->clipsta, cam->clipend, orthomat); Mat4MulMat4(tmpmat, projectors[i].projmat, orthomat); } } else { @@ -3182,6 +3906,20 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, Mat4One(offsetmat); Mat4MulFloat3(offsetmat[0], 0.5); offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5; + + if (cam) { + if (umd->aspectx == umd->aspecty) { + offsetmat[3][0] -= cam->shiftx; + offsetmat[3][1] -= cam->shifty; + } else if (umd->aspectx < umd->aspecty) { + offsetmat[3][0] -=(cam->shiftx * umd->aspecty/umd->aspectx); + offsetmat[3][1] -= cam->shifty; + } else { + offsetmat[3][0] -= cam->shiftx; + offsetmat[3][1] -=(cam->shifty * umd->aspectx/umd->aspecty); + } + } + Mat4MulMat4(projectors[i].projmat, tmpmat, offsetmat); /* calculate worldspace projector normal (for best projector test) */ @@ -3216,8 +3954,8 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } } else { /* multiple projectors, select the closest to face normal - * direction - */ + * direction + */ float co1[3], co2[3], co3[3], co4[3]; float face_no[3]; int j; @@ -3237,14 +3975,14 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } /* find the projector which the face points at most directly - * (projector normal with largest dot product is best) - */ + * (projector normal with largest dot product is best) + */ best_dot = MTC_dot3Float(projectors[0].normal, face_no); best_projector = &projectors[0]; for(j = 1; j < num_projectors; ++j) { float tmp_dot = MTC_dot3Float(projectors[j].normal, - face_no); + face_no); if(tmp_dot > best_dot) { best_dot = tmp_dot; best_projector = &projectors[j]; @@ -3283,8 +4021,8 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } static DerivedMesh *uvprojectModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *result; UVProjectModifierData *umd = (UVProjectModifierData*) md; @@ -3295,8 +4033,8 @@ static DerivedMesh *uvprojectModifier_applyModifier( } static DerivedMesh *uvprojectModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1); } @@ -3321,8 +4059,8 @@ static void decimateModifier_copyData(ModifierData *md, ModifierData *target) //XXX #if 0 static DerivedMesh *decimateModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DecimateModifierData *dmd = (DecimateModifierData*) md; DerivedMesh *dm = derivedData, *result = NULL; @@ -3346,7 +4084,7 @@ static DerivedMesh *decimateModifier_applyModifier( if(numTris<3) { modifier_setError(md, - "There must be more than 3 input faces (triangles)."); + "Modifier requires more than 3 input faces (triangles)."); goto exit; } @@ -3436,7 +4174,7 @@ static DerivedMesh *decimateModifier_applyModifier( MEM_freeN(lod.triangle_index_buffer); exit: - return result; + return result; } #endif @@ -3488,8 +4226,8 @@ CustomDataMask smoothModifier_requiredDataMask(ModifierData *md) } static void smoothModifier_do( - SmoothModifierData *smd, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) + SmoothModifierData *smd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { MDeformVert *dvert = NULL; MEdge *medges = NULL; @@ -3499,10 +4237,10 @@ static void smoothModifier_do( float *ftmp, fac, facm; ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts, - "smoothmodifier_f"); + "smoothmodifier_f"); if (!ftmp) return; uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts, - "smoothmodifier_uc"); + "smoothmodifier_uc"); if (!uctmp) { if (ftmp) MEM_freeN(ftmp); return; @@ -3531,7 +4269,7 @@ static void smoothModifier_do( dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* NOTICE: this can be optimized a little bit by moving the - * if (dvert) out of the loop, if needed */ + * if (dvert) out of the loop, if needed */ for (j = 0; j < smd->repeat; j++) { for (i = 0; i < numDMEdges; i++) { float fvec[3]; @@ -3627,8 +4365,8 @@ static void smoothModifier_do( } static void smoothModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -3639,14 +4377,14 @@ static void smoothModifier_deformVerts( CDDM_calc_normals(dm); smoothModifier_do((SmoothModifierData *)md, ob, dm, - vertexCos, numVerts); + vertexCos, numVerts); dm->release(dm); } static void smoothModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -3657,7 +4395,7 @@ static void smoothModifier_deformVertsEM( CDDM_calc_normals(dm); smoothModifier_do((SmoothModifierData *)md, ob, dm, - vertexCos, numVerts); + vertexCos, numVerts); dm->release(dm); } @@ -3672,7 +4410,7 @@ static void castModifier_initData(ModifierData *md) cmd->radius = 0.0f; cmd->size = 0.0f; cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z - | MOD_CAST_SIZE_FROM_RADIUS; + | MOD_CAST_SIZE_FROM_RADIUS; cmd->type = MOD_CAST_TYPE_SPHERE; cmd->defgrp_name[0] = '\0'; cmd->object = NULL; @@ -3717,9 +4455,9 @@ CustomDataMask castModifier_requiredDataMask(ModifierData *md) } static void castModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { CastModifierData *cmd = (CastModifierData*) md; @@ -3727,21 +4465,22 @@ static void castModifier_foreachObjectLink( } static void castModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, - DagNode *obNode) + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) { CastModifierData *cmd = (CastModifierData*) md; if (cmd->object) { DagNode *curNode = dag_get_node(forest, cmd->object); - dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA); + dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, + "Cast Modifier"); } } static void castModifier_sphere_do( - CastModifierData *cmd, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) + CastModifierData *cmd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { MDeformVert *dvert = NULL; @@ -3766,8 +4505,8 @@ static void castModifier_sphere_do( ctrl_ob = cmd->object; /* spherify's center is {0, 0, 0} (the ob's own center in its local - * space), by default, but if the user defined a control object, - * we use its location, transformed to ob's local space */ + * space), by default, but if the user defined a control object, + * we use its location, transformed to ob's local space */ if (ctrl_ob) { if(flag & MOD_CAST_USE_OB_TRANSFORM) { Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat); @@ -3784,11 +4523,11 @@ static void castModifier_sphere_do( /* 1) (flag was checked in the "if (ctrl_ob)" block above) */ /* 2) cmd->radius > 0.0f: only the vertices within this radius from - * the center of the effect should be deformed */ + * the center of the effect should be deformed */ if (cmd->radius > FLT_EPSILON) has_radius = 1; /* 3) if we were given a vertex group name, - * only those vertices should be affected */ + * only those vertices should be affected */ if (cmd->defgrp_name[0]) { bDeformGroup *def; @@ -3820,10 +4559,10 @@ static void castModifier_sphere_do( } /* ready to apply the effect, one vertex at a time; - * tiny optimization: the code is separated (with parts repeated) + * tiny optimization: the code is separated (with parts repeated) * in two possible cases: - * with or w/o a vgroup. With lots of if's in the code below, - * further optimizations are possible, if needed */ + * with or w/o a vgroup. With lots of if's in the code below, + * further optimizations are possible, if needed */ if (dvert) { /* with a vgroup */ float fac_orig = fac; for (i = 0; i < numVerts; i++) { @@ -3926,8 +4665,8 @@ static void castModifier_sphere_do( } static void castModifier_cuboid_do( - CastModifierData *cmd, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) + CastModifierData *cmd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { MDeformVert *dvert = NULL; Object *ctrl_ob = NULL; @@ -3951,11 +4690,11 @@ static void castModifier_cuboid_do( /* 1) (flag was checked in the "if (ctrl_ob)" block above) */ /* 2) cmd->radius > 0.0f: only the vertices within this radius from - * the center of the effect should be deformed */ + * the center of the effect should be deformed */ if (cmd->radius > FLT_EPSILON) has_radius = 1; /* 3) if we were given a vertex group name, - * only those vertices should be affected */ + * only those vertices should be affected */ if (cmd->defgrp_name[0]) { bDeformGroup *def; @@ -3995,12 +4734,12 @@ static void castModifier_cuboid_do( } else { /* get bound box */ /* We can't use the object's bound box because other modifiers - * may have changed the vertex data. */ + * may have changed the vertex data. */ INIT_MINMAX(min, max); /* Cast's center is the ob's own center in its local space, - * by default, but if the user defined a control object, we use - * its location, transformed to ob's local space. */ + * by default, but if the user defined a control object, we use + * its location, transformed to ob's local space. */ if (ctrl_ob) { float vec[3]; @@ -4036,10 +4775,10 @@ static void castModifier_cuboid_do( bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2]; /* ready to apply the effect, one vertex at a time; - * tiny optimization: the code is separated (with parts repeated) + * tiny optimization: the code is separated (with parts repeated) * in two possible cases: - * with or w/o a vgroup. With lots of if's in the code below, - * further optimizations are possible, if needed */ + * with or w/o a vgroup. With lots of if's in the code below, + * further optimizations are possible, if needed */ if (dvert) { /* with a vgroup */ float fac_orig = fac; for (i = 0; i < numVerts; i++) { @@ -4059,8 +4798,8 @@ static void castModifier_cuboid_do( if (has_radius) { if (fabs(tmp_co[0]) > cmd->radius || - fabs(tmp_co[1]) > cmd->radius || - fabs(tmp_co[2]) > cmd->radius) continue; + fabs(tmp_co[1]) > cmd->radius || + fabs(tmp_co[2]) > cmd->radius) continue; } for (j = 0; j < dvert[i].totweight; ++j) { @@ -4077,10 +4816,10 @@ static void castModifier_cuboid_do( /* The algo used to project the vertices to their * bounding box (bb) is pretty simple: * for each vertex v: - * 1) find in which octant v is in; - * 2) find which outer "wall" of that octant is closer to v; - * 3) calculate factor (var fbb) to project v to that wall; - * 4) project. */ + * 1) find in which octant v is in; + * 2) find which outer "wall" of that octant is closer to v; + * 3) calculate factor (var fbb) to project v to that wall; + * 4) project. */ /* find in which octant this vertex is in */ octant = 0; @@ -4114,7 +4853,7 @@ static void castModifier_cuboid_do( continue; /* finally, this is the factor we wanted, to project the vertex - * to its bounding box (bb) */ + * to its bounding box (bb) */ fbb = apex[coord] / tmp_co[coord]; /* calculate the new vertex position */ @@ -4155,8 +4894,8 @@ static void castModifier_cuboid_do( if (has_radius) { if (fabs(tmp_co[0]) > cmd->radius || - fabs(tmp_co[1]) > cmd->radius || - fabs(tmp_co[2]) > cmd->radius) continue; + fabs(tmp_co[1]) > cmd->radius || + fabs(tmp_co[2]) > cmd->radius) continue; } octant = 0; @@ -4206,8 +4945,8 @@ static void castModifier_cuboid_do( } static void castModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; CastModifierData *cmd = (CastModifierData *)md; @@ -4225,8 +4964,8 @@ static void castModifier_deformVerts( } static void castModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; CastModifierData *cmd = (CastModifierData *)md; @@ -4245,13 +4984,13 @@ static void castModifier_deformVertsEM( /* Wave */ -static void waveModifier_initData(ModifierData *md) +static void waveModifier_initData(ModifierData *md) { WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq - + wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL - | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z); - + | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z); + wmd->objectcenter = NULL; wmd->texture = NULL; wmd->map_object = NULL; @@ -4261,6 +5000,7 @@ static void waveModifier_initData(ModifierData *md) wmd->narrow= 1.5f; wmd->lifetime= 0.0f; wmd->damp= 10.0f; + wmd->falloff= 0.0f; wmd->texmapping = MOD_WAV_MAP_LOCAL; wmd->defgrp_name[0] = 0; } @@ -4280,6 +5020,7 @@ static void waveModifier_copyData(ModifierData *md, ModifierData *target) twmd->starty = wmd->starty; twmd->timeoffs = wmd->timeoffs; twmd->width = wmd->width; + twmd->falloff = wmd->falloff; twmd->objectcenter = wmd->objectcenter; twmd->texture = wmd->texture; twmd->map_object = wmd->map_object; @@ -4293,8 +5034,8 @@ static int waveModifier_dependsOnTime(ModifierData *md) } static void waveModifier_foreachObjectLink( - ModifierData *md, Object *ob, - ObjectWalkFunc walk, void *userData) + ModifierData *md, Object *ob, + ObjectWalkFunc walk, void *userData) { WaveModifierData *wmd = (WaveModifierData*) md; @@ -4303,7 +5044,7 @@ static void waveModifier_foreachObjectLink( } static void waveModifier_foreachIDLink(ModifierData *md, Object *ob, - IDWalkFunc walk, void *userData) + IDWalkFunc walk, void *userData) { WaveModifierData *wmd = (WaveModifierData*) md; @@ -4313,21 +5054,23 @@ static void waveModifier_foreachIDLink(ModifierData *md, Object *ob, } static void waveModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, - DagNode *obNode) + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) { WaveModifierData *wmd = (WaveModifierData*) md; if(wmd->objectcenter) { DagNode *curNode = dag_get_node(forest, wmd->objectcenter); - dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA); + dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, + "Wave Modifier"); } if(wmd->map_object) { DagNode *curNode = dag_get_node(forest, wmd->map_object); - dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA); + dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, + "Wave Modifer"); } } @@ -4349,9 +5092,9 @@ CustomDataMask waveModifier_requiredDataMask(ModifierData *md) } static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob, - DerivedMesh *dm, - float (*co)[3], float (*texco)[3], - int numVerts) + DerivedMesh *dm, + float (*co)[3], float (*texco)[3], + int numVerts) { int i; int texmapping = wmd->texmapping; @@ -4369,14 +5112,14 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob, MFace *mface = dm->getFaceArray(dm); MFace *mf; char *done = MEM_callocN(sizeof(*done) * numVerts, - "get_texture_coords done"); + "get_texture_coords done"); int numFaces = dm->getNumFaces(dm); MTFace *tf; validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name); tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, - wmd->uvlayer_name); + wmd->uvlayer_name); /* verts are given the UV from the first face that uses them */ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { @@ -4420,25 +5163,25 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob, for(i = 0; i < numVerts; ++i, ++co, ++texco) { switch(texmapping) { - case MOD_WAV_MAP_LOCAL: - VECCOPY(*texco, *co); - break; - case MOD_WAV_MAP_GLOBAL: - VECCOPY(*texco, *co); - Mat4MulVecfl(ob->obmat, *texco); - break; - case MOD_WAV_MAP_OBJECT: - VECCOPY(*texco, *co); - Mat4MulVecfl(ob->obmat, *texco); - Mat4MulVecfl(wmd->map_object->imat, *texco); - break; + case MOD_WAV_MAP_LOCAL: + VECCOPY(*texco, *co); + break; + case MOD_WAV_MAP_GLOBAL: + VECCOPY(*texco, *co); + Mat4MulVecfl(ob->obmat, *texco); + break; + case MOD_WAV_MAP_OBJECT: + VECCOPY(*texco, *co); + Mat4MulVecfl(ob->obmat, *texco); + Mat4MulVecfl(wmd->map_object->imat, *texco); + break; } } } static void waveModifier_do( - WaveModifierData *md, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) + WaveModifierData *md, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { WaveModifierData *wmd = (WaveModifierData*) md; MVert *mvert = NULL; @@ -4446,7 +5189,7 @@ static void waveModifier_do( int defgrp_index; float ctime = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); float minfac = - (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); + (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); float lifefac = wmd->height; float (*tex_co)[3] = NULL; @@ -4488,16 +5231,16 @@ static void waveModifier_do( if(x > wmd->lifetime) { lifefac = x - wmd->lifetime; - + if(lifefac > wmd->damp) lifefac = 0.0; else lifefac = - (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp))); + (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp))); } } if(wmd->texture) { tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, - "waveModifier_do tex_co"); + "waveModifier_do tex_co"); wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts); } @@ -4509,6 +5252,8 @@ static void waveModifier_do( float x = co[0] - wmd->startx; float y = co[1] - wmd->starty; float amplit= 0.0f; + float dist = 0.0f; + float falloff_fac = 0.0f; TexResult texres; MDeformWeight *def_weight = NULL; @@ -4531,32 +5276,54 @@ static void waveModifier_do( get_texture_value(wmd->texture, tex_co[i], &texres); } + /*get dist*/ + if(wmd->flag & MOD_WAVE_X) { + if(wmd->flag & MOD_WAVE_Y){ + dist = (float)sqrt(x*x + y*y); + } + else{ + dist = fabs(x); + } + } + else if(wmd->flag & MOD_WAVE_Y) { + dist = fabs(y); + } + + falloff_fac = (1.0-(dist / wmd->falloff)); + CLAMP(falloff_fac,0,1); if(wmd->flag & MOD_WAVE_X) { if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y); else amplit = x; } - else if(wmd->flag & MOD_WAVE_Y) + else if(wmd->flag & MOD_WAVE_Y) amplit= y; - + /* this way it makes nice circles */ amplit -= (ctime - wmd->timeoffs) * wmd->speed; if(wmd->flag & MOD_WAVE_CYCL) { amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width) - + wmd->width; + + wmd->width; } /* GAUSSIAN */ if(amplit > -wmd->width && amplit < wmd->width) { amplit = amplit * wmd->narrow; amplit = (float)(1.0 / exp(amplit * amplit) - minfac); + + /*apply texture*/ if(wmd->texture) amplit = amplit * texres.tin; + /*apply weight*/ if(def_weight) amplit = amplit * def_weight->weight; + /*apply falloff*/ + if (wmd->falloff > 0) + amplit = amplit * falloff_fac; + if(mvert) { /* move along normals */ if(wmd->flag & MOD_WAVE_NORM_X) { @@ -4581,8 +5348,8 @@ static void waveModifier_do( } static void waveModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; WaveModifierData *wmd = (WaveModifierData *)md; @@ -4604,15 +5371,15 @@ static void waveModifier_deformVerts( } static void waveModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; WaveModifierData *wmd = (WaveModifierData *)md; if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM)) dm = derivedData; - else if(derivedData) dm = derivedData; + else if(derivedData) dm = CDDM_copy(derivedData); else dm = CDDM_from_editmesh(editData, ob->data); if(wmd->flag & MOD_WAVE_NORM) { @@ -4662,9 +5429,9 @@ static int armatureModifier_isDisabled(ModifierData *md) } static void armatureModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -4672,8 +5439,8 @@ static void armatureModifier_foreachObjectLink( } static void armatureModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, - DagNode *obNode) + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -4681,21 +5448,21 @@ static void armatureModifier_updateDepgraph( DagNode *curNode = dag_get_node(forest, amd->object); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier"); } } static void armatureModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData*) md; modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL, - numVerts, amd->deformflag, - (float(*)[3])amd->prevCos, amd->defgrp_name); + numVerts, amd->deformflag, + (float(*)[3])amd->prevCos, amd->defgrp_name); /* free cache */ if(amd->prevCos) { MEM_freeN(amd->prevCos); @@ -4704,8 +5471,8 @@ static void armatureModifier_deformVerts( } static void armatureModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData*) md; DerivedMesh *dm = derivedData; @@ -4713,15 +5480,15 @@ static void armatureModifier_deformVertsEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts, - amd->deformflag, NULL, amd->defgrp_name); + amd->deformflag, NULL, amd->defgrp_name); if(!derivedData) dm->release(dm); } static void armatureModifier_deformMatricesEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], - float (*defMats)[3][3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], + float (*defMats)[3][3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData*) md; DerivedMesh *dm = derivedData; @@ -4729,7 +5496,7 @@ static void armatureModifier_deformMatricesEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts, - amd->deformflag, NULL, amd->defgrp_name); + amd->deformflag, NULL, amd->defgrp_name); if(!derivedData) dm->release(dm); } @@ -4784,9 +5551,9 @@ static int hookModifier_isDisabled(ModifierData *md) } static void hookModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { HookModifierData *hmd = (HookModifierData*) md; @@ -4794,20 +5561,21 @@ static void hookModifier_foreachObjectLink( } static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Object *ob, DagNode *obNode) { HookModifierData *hmd = (HookModifierData*) md; if (hmd->object) { DagNode *curNode = dag_get_node(forest, hmd->object); - dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA); + dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, + "Hook Modifier"); } } static void hookModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { HookModifierData *hmd = (HookModifierData*) md; float vec[3], mat[4][4]; @@ -4816,7 +5584,7 @@ static void hookModifier_deformVerts( Mat4Invert(ob->imat, ob->obmat); Mat4MulSerie(mat, ob->imat, hmd->object->obmat, hmd->parentinv, - NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); /* vertex indices? */ if(hmd->indexar) { @@ -4824,24 +5592,24 @@ static void hookModifier_deformVerts( int index = hmd->indexar[i]; /* This should always be true and I don't generally like - * "paranoid" style code like this, but old files can have - * indices that are out of range because old blender did - * not correct them on exit editmode. - zr - */ + * "paranoid" style code like this, but old files can have + * indices that are out of range because old blender did + * not correct them on exit editmode. - zr + */ if(index < numVerts) { float *co = vertexCos[index]; float fac = hmd->force; /* if DerivedMesh is present and has original index data, - * use it - */ + * use it + */ if(dm && dm->getVertData(dm, 0, CD_ORIGINDEX)) { int j; int orig_index; for(j = 0; j < numVerts; ++j) { fac = hmd->force; orig_index = *(int *)dm->getVertData(dm, j, - CD_ORIGINDEX); + CD_ORIGINDEX); if(orig_index == index) { co = vertexCos[j]; if(hmd->falloff != 0.0) { @@ -4885,44 +5653,44 @@ static void hookModifier_deformVerts( if(dm) if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) { + use_dverts = 1; + maxVerts = dm->getNumVerts(dm); + } else use_dverts = 0; + else if(me->dvert) { use_dverts = 1; - maxVerts = dm->getNumVerts(dm); + maxVerts = me->totvert; } else use_dverts = 0; - else if(me->dvert) { - use_dverts = 1; - maxVerts = me->totvert; - } else use_dverts = 0; - if(curdef && use_dverts) { - MDeformVert *dvert = me->dvert; - int i, j; + if(curdef && use_dverts) { + MDeformVert *dvert = me->dvert; + int i, j; - for(i = 0; i < maxVerts; i++, dvert++) { - if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); - for(j = 0; j < dvert->totweight; j++) { - if(dvert->dw[j].def_nr == index) { - float fac = hmd->force*dvert->dw[j].weight; - float *co = vertexCos[i]; + for(i = 0; i < maxVerts; i++, dvert++) { + if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); + for(j = 0; j < dvert->totweight; j++) { + if(dvert->dw[j].def_nr == index) { + float fac = hmd->force*dvert->dw[j].weight; + float *co = vertexCos[i]; - if(hmd->falloff != 0.0) { - float len = VecLenf(co, hmd->cent); - if(len > hmd->falloff) fac = 0.0; - else if(len > 0.0) - fac *= sqrt(1.0 - len / hmd->falloff); - } + if(hmd->falloff != 0.0) { + float len = VecLenf(co, hmd->cent); + if(len > hmd->falloff) fac = 0.0; + else if(len > 0.0) + fac *= sqrt(1.0 - len / hmd->falloff); + } - VecMat4MulVecfl(vec, mat, co); - VecLerpf(co, co, vec, fac); + VecMat4MulVecfl(vec, mat, co); + VecLerpf(co, co, vec, fac); + } } } } - } } } static void hookModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; @@ -4936,12 +5704,322 @@ static void hookModifier_deformVertsEM( /* Softbody */ static void softbodyModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } +static int softbodyModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + + +/* Cloth */ + +static void clothModifier_initData(ModifierData *md) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms"); + clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms"); + clmd->point_cache = BKE_ptcache_add(); + + /* check for alloc failing */ + if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache) + return; + + cloth_init (clmd); +} + +static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + DerivedMesh *result=NULL; + + /* check for alloc failing */ + if(!clmd->sim_parms || !clmd->coll_parms) + { + clothModifier_initData(md); + + if(!clmd->sim_parms || !clmd->coll_parms) + return derivedData; + } + + result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); + + if(result) + { + CDDM_calc_normals(result); + return result; + } + return derivedData; +} + +static void clothModifier_updateDepgraph( + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + Base *base; + + if(clmd) + { + for(base = G.scene->base.first; base; base= base->next) + { + Object *ob1= base->object; + if(ob1 != ob) + { + CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); + if(coll_clmd) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Cloth Collision"); + } + } + } + } +} + +CustomDataMask clothModifier_requiredDataMask(ModifierData *md) +{ + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + +static void clothModifier_copyData(ModifierData *md, ModifierData *target) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + ClothModifierData *tclmd = (ClothModifierData*) target; + + if(tclmd->sim_parms) + MEM_freeN(tclmd->sim_parms); + if(tclmd->coll_parms) + MEM_freeN(tclmd->coll_parms); + if(tclmd->point_cache) + BKE_ptcache_free(tclmd->point_cache); + + tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms); + tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); + tclmd->point_cache = BKE_ptcache_copy(clmd->point_cache); + tclmd->clothObject = NULL; +} + +static int clothModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void clothModifier_freeData(ModifierData *md) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + if (clmd) + { + if(G.rt > 0) + printf("clothModifier_freeData\n"); + + cloth_free_modifier_extern (clmd); + + if(clmd->sim_parms) + MEM_freeN(clmd->sim_parms); + if(clmd->coll_parms) + MEM_freeN(clmd->coll_parms); + if(clmd->point_cache) + BKE_ptcache_free(clmd->point_cache); + } +} + +/* Collision */ + +static void collisionModifier_initData(ModifierData *md) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + + collmd->x = NULL; + collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; + collmd->current_v = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->bvhtree = NULL; +} + +static void collisionModifier_freeData(ModifierData *md) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + + if (collmd) + { + if(collmd->bvhtree) + BLI_bvhtree_free(collmd->bvhtree); + if(collmd->x) + MEM_freeN(collmd->x); + if(collmd->xnew) + MEM_freeN(collmd->xnew); + if(collmd->current_x) + MEM_freeN(collmd->current_x); + if(collmd->current_xnew) + MEM_freeN(collmd->current_xnew); + if(collmd->current_v) + MEM_freeN(collmd->current_v); + if(collmd->mfaces) + MEM_freeN(collmd->mfaces); + + collmd->x = NULL; + collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; + collmd->current_v = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->bvhtree = NULL; + collmd->mfaces = NULL; + } +} + +static int collisionModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void collisionModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + DerivedMesh *dm = NULL; + float current_time = 0; + unsigned int numverts = 0, i = 0; + MVert *tempVert = NULL; + + /* if possible use/create DerivedMesh */ + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + + if(!ob->pd) + { + printf("collisionModifier_deformVerts: Should not happen!\n"); + return; + } + + if(dm) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + + current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + + if(G.rt > 0) + printf("current_time %f, collmd->time %f\n", current_time, collmd->time); + + numverts = dm->getNumVerts ( dm ); + + if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics())) + { + // check if mesh has changed + if(collmd->x && (numverts != collmd->numverts)) + collisionModifier_freeData((ModifierData *)collmd); + + if(collmd->time == -1) // first time + { + collmd->x = dm->dupVertArray(dm); // frame start position + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); + } + + collmd->xnew = MEM_dupallocN(collmd->x); // frame end position + collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame + + collmd->numverts = numverts; + + collmd->mfaces = dm->dupFaceArray(dm); + collmd->numfaces = dm->getNumFaces(dm); + + // create bounding box hierarchy + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft); + + collmd->time = current_time; + } + else if(numverts == collmd->numverts) + { + // put positions to old positions + tempVert = collmd->x; + collmd->x = collmd->xnew; + collmd->xnew = tempVert; + + memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); + } + + memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert)); + memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert)); + + /* check if GUI setting has changed for bvh */ + if(collmd->bvhtree) + { + if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) + { + BLI_bvhtree_free(collmd->bvhtree); + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); + } + + } + + /* happens on file load (ONLY when i decomment changes in readfile.c) */ + if(!collmd->bvhtree) + { + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); + } + else + { + // recalc static bounding boxes + bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); + } + + collmd->time = current_time; + } + else if(numverts != collmd->numverts) + { + collisionModifier_freeData((ModifierData *)collmd); + } + + } + else if(current_time < collmd->time) + { + collisionModifier_freeData((ModifierData *)collmd); + } + else + { + if(numverts != collmd->numverts) + { + collisionModifier_freeData((ModifierData *)collmd); + } + } + } + + if(dm) + dm->release(dm); +} + + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -4961,9 +6039,9 @@ static int booleanModifier_isDisabled(ModifierData *md) } static void booleanModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { BooleanModifierData *bmd = (BooleanModifierData*) md; @@ -4971,8 +6049,8 @@ static void booleanModifier_foreachObjectLink( } static void booleanModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, - DagNode *obNode) + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) { BooleanModifierData *bmd = (BooleanModifierData*) md; @@ -4980,32 +6058,32 @@ static void booleanModifier_updateDepgraph( DagNode *curNode = dag_get_node(forest, bmd->object); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier"); } } static DerivedMesh *booleanModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { // XXX doesn't handle derived data BooleanModifierData *bmd = (BooleanModifierData*) md; /* we do a quick sanity check */ if(((Mesh *)ob->data)->totface > 3 - && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) { + && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) { DerivedMesh *result = NewBooleanDerivedMesh(bmd->object, ob, - 1 + bmd->operation); + 1 + bmd->operation); /* if new mesh returned, return it; otherwise there was - * an error, so delete the modifier object */ + * an error, so delete the modifier object */ if(result) return result; else bmd->object = NULL; - } + } - return derivedData; + return derivedData; } /* Particles */ @@ -5026,7 +6104,6 @@ static void particleSystemModifier_freeData(ModifierData *md) psmd->dm=0; } - psmd->psys->flag &= ~PSYS_ENABLED; psmd->psys->flag |= PSYS_DELETE; } static void particleSystemModifier_copyData(ModifierData *md, ModifierData *target) @@ -5035,6 +6112,7 @@ static void particleSystemModifier_copyData(ModifierData *md, ModifierData *targ ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target; tpsmd->dm = 0; + tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; //tpsmd->facepa = 0; tpsmd->flag = psmd->flag; /* need to keep this to recognise a bit later in copy_object */ @@ -5056,7 +6134,7 @@ CustomDataMask particleSystemModifier_requiredDataMask(ModifierData *md) } /* particles only need this if they are after a non deform modifier, and - * the modifier stack will only create them in that case. */ + * the modifier stack will only create them in that case. */ dataMask |= CD_MASK_ORIGSPACE; dataMask |= CD_MASK_ORCO; @@ -5088,12 +6166,13 @@ static int is_last_displist(Object *ob) } /* saves the current emitter state for a particle system and calculates particles */ static void particleSystemModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; ParticleSystem * psys=0; + Mesh *me; int needsFree=0; if(ob->particlesystem.first) @@ -5101,6 +6180,14 @@ static void particleSystemModifier_deformVerts( else return; + /* multires check */ + if(ob->type == OB_MESH) { + me= (Mesh*)ob->data; + if(me->mr && me->mr->current != 1) + modifier_setError(md, + "Particles only supported on first multires level."); + } + if(!psys_check_enabled(ob, psys)) return; @@ -5151,6 +6238,7 @@ static void particleSystemModifier_deformVerts( /* make new dm */ psmd->dm=CDDM_copy(dm); + CDDM_apply_vert_coords(psmd->dm, vertexCos); CDDM_calc_normals(psmd->dm); if(needsFree){ @@ -5163,8 +6251,8 @@ static void particleSystemModifier_deformVerts( /* report change in mesh structure */ if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert || - psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge || - psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){ + psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge || + psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){ /* in file read dm hasn't really changed but just wasn't saved in file */ psys->recalc |= PSYS_RECALC_HAIR; @@ -5174,13 +6262,13 @@ static void particleSystemModifier_deformVerts( psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm); psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm); psmd->totdmface= psmd->dm->getNumFaces(psmd->dm); - } + } - if(psys){ - particle_system_update(ob,psys); - psmd->flag |= eParticleSystemFlag_psys_updated; - psmd->flag &= ~eParticleSystemFlag_DM_changed; - } + if(psys){ + particle_system_update(ob,psys); + psmd->flag |= eParticleSystemFlag_psys_updated; + psmd->flag &= ~eParticleSystemFlag_DM_changed; + } } /* disabled particles in editmode for now, until support for proper derivedmesh @@ -5206,7 +6294,7 @@ static void particleInstanceModifier_initData(ModifierData *md) ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn| - eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead; + eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead; pimd->psys = 1; } @@ -5225,7 +6313,7 @@ static int particleInstanceModifier_dependsOnTime(ModifierData *md) return 0; } static void particleInstanceModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Object *ob, DagNode *obNode) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md; @@ -5233,12 +6321,13 @@ static void particleInstanceModifier_updateDepgraph(ModifierData *md, DagForest DagNode *curNode = dag_get_node(forest, pimd->ob); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, + "Particle Instance Modifier"); } } static void particleInstanceModifier_foreachObjectLink(ModifierData *md, Object *ob, - ObjectWalkFunc walk, void *userData) + ObjectWalkFunc walk, void *userData) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md; @@ -5246,8 +6335,8 @@ static void particleInstanceModifier_foreachObjectLink(ModifierData *md, Object } static DerivedMesh * particleInstanceModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *dm = derivedData, *result; ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; @@ -5257,7 +6346,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( MVert *mvert, *orig_mvert; int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0; short track=ob->trackflag%3, trackneg; - float max_co=0.0, min_co=0.0, temp_co[3]; + float max_co=0.0, min_co=0.0, temp_co[3], cross[3]; trackneg=((ob->trackflag>2)?1:0); @@ -5336,15 +6425,29 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if(trackneg) state.time=1.0f-state.time; psys_get_particle_on_path(pimd->ob,psys,first_particle + i/totvert,&state,1); + + mv->co[0] = 0.0; + + Normalize(state.vel); + + if(state.vel[0] < -0.9999 || state.vel[0] > 0.9999) { + state.rot[0] = 1.0; + state.rot[1] = state.rot[2] = state.rot[3] = 0.0f; + } + else { + /* a cross product of state.vel and a unit vector in x-direction */ + cross[0] = 0.0f; + cross[1] = -state.vel[2]; + cross[2] = state.vel[1]; + + /* state.vel[0] is the only component surviving from a dot product with a vector in x-direction*/ + VecRotToQuat(cross,saacos(state.vel[0]),state.rot); + } } else{ state.time=-1.0; psys_get_particle_state(pimd->ob,psys,i/totvert,&state,1); - } - - /*displace vertice to path location*/ - if(pimd->flag & eParticleInstanceFlag_Path) - mv->co[0]=0.0; + } QuatMulVecf(state.rot,mv->co); VECADD(mv->co,mv->co,state.co); @@ -5402,8 +6505,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier( return result; } static DerivedMesh *particleInstanceModifier_applyModifierEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) { return particleInstanceModifier_applyModifier(md, ob, derivedData, 0, 1); } @@ -5429,6 +6532,8 @@ static void explodeModifier_copyData(ModifierData *md, ModifierData *target) temd->facepa = 0; temd->flag = emd->flag; + temd->protect = emd->protect; + temd->vgroup = emd->vgroup; } static int explodeModifier_dependsOnTime(ModifierData *md) { @@ -5445,25 +6550,9 @@ CustomDataMask explodeModifier_requiredDataMask(ModifierData *md) return dataMask; } -/* this should really be put somewhere permanently */ -static float vert_weight(MDeformVert *dvert, int group) -{ - MDeformWeight *dw; - int i; - - if(dvert) { - dw= dvert->dw; - for(i= dvert->totweight; i>0; i--, dw++) { - if(dw->def_nr == group) return dw->weight; - if(i==1) break; /*otherwise dw will point to somewhere it shouldn't*/ - } - } - return 0.0; -} - static void explodeModifier_createFacepa(ExplodeModifierData *emd, - ParticleSystemModifierData *psmd, - Object *ob, DerivedMesh *dm) + ParticleSystemModifierData *psmd, + Object *ob, DerivedMesh *dm) { ParticleSystem *psys=psmd->psys; MFace *fa=0, *mface=0; @@ -5504,7 +6593,7 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd, for(i=0; i<totvert; i++){ val = BLI_frand(); val = (1.0f-emd->protect)*val + emd->protect*0.5f; - if(val < vert_weight(dvert+i,emd->vgroup-1)) + if(val < deformvert_get_weight(dvert+i,emd->vgroup-1)) vertpa[i] = -1; } } @@ -5513,7 +6602,7 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd, /* make tree of emitter locations */ tree=BLI_kdtree_new(totpart); for(p=0,pa=psys->particles; p<totpart; p++,pa++){ - psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0); + psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0); BLI_kdtree_insert(tree, p, co, NULL); } BLI_kdtree_balance(tree); @@ -5549,20 +6638,29 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd, if(vertpa) MEM_freeN(vertpa); BLI_kdtree_free(tree); } + +static int edgesplit_get(EdgeHash *edgehash, int v1, int v2) +{ + return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2)); +} + static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){ DerivedMesh *splitdm; MFace *mf=0,*df1=0,*df2=0,*df3=0; MFace *mface=CDDM_get_faces(dm); MVert *dupve, *mv; + EdgeHash *edgehash; + EdgeHashIterator *ehi; int totvert=dm->getNumVerts(dm); int totface=dm->getNumFaces(dm); - int *edgesplit = MEM_callocN(sizeof(int)*totvert*totvert,"explode_edgesplit"); - int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_edgesplit"); + int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit"); int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2"); int *facepa = emd->facepa; int *fs, totesplit=0,totfsplit=0,totin=0,curdupvert=0,curdupface=0,curdupin=0; - int i,j,v1,v2,v3,v4; + int i,j,v1,v2,v3,v4,esplit; + + edgehash= BLI_edgehash_new(); /* recreate vertpa from facepa calculation */ for (i=0,mf=mface; i<totface; i++,mf++) { @@ -5582,22 +6680,22 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive v4=vertpa[mf->v4]; if(v1!=v2){ - edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); (*fs)++; } if(v2!=v3){ - edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1; + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); (*fs)++; } if(v3!=v4){ - edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1; + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); (*fs)++; } if(v1!=v4){ - edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); (*fs)++; } @@ -5606,28 +6704,29 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive *fs=1; else if(v1!=v2){ if(v1!=v4) - edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1; + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); else - edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1; + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); } else{ if(v1!=v4) - edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); else - edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); } } } } /* count splits & reindex */ + ehi= BLI_edgehashIterator_new(edgehash); totesplit=totvert; - for(j=0; j<totvert; j++){ - for(i=j+1; i<totvert; i++){ - if(edgesplit[j*totvert+i]) - edgesplit[j*totvert+i]=edgesplit[i*totvert+j]=totesplit++; - } + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit)); + totesplit++; } + BLI_edgehashIterator_free(ehi); + /* count new faces due to splitting */ for(i=0,fs=facesplit; i<totface; i++,fs++){ if(*fs==1) @@ -5675,23 +6774,23 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive /* create new verts */ curdupvert=totvert; - for(j=0; j<totvert; j++){ - for(i=j+1; i<totvert; i++){ - if(edgesplit[j*totvert+i]){ - mv=CDDM_get_vert(splitdm,j); - dupve=CDDM_get_vert(splitdm,edgesplit[j*totvert+i]); + ehi= BLI_edgehashIterator_new(edgehash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_getKey(ehi, &i, &j); + esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + mv=CDDM_get_vert(splitdm,j); + dupve=CDDM_get_vert(splitdm,esplit); - DM_copy_vert_data(splitdm,splitdm,j,edgesplit[j*totvert+i],1); + DM_copy_vert_data(splitdm,splitdm,j,esplit,1); - *dupve=*mv; + *dupve=*mv; - mv=CDDM_get_vert(splitdm,i); + mv=CDDM_get_vert(splitdm,i); - VECADD(dupve->co,dupve->co,mv->co); - VecMulf(dupve->co,0.5); - } - } + VECADD(dupve->co,dupve->co,mv->co); + VecMulf(dupve->co,0.5); } + BLI_edgehashIterator_free(ehi); /* create new faces */ curdupface=totface; @@ -5712,14 +6811,14 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v1==v2){ - df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df1->v2=edgesplit[mf->v2*totvert+mf->v3]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); mf->v3=df1->v2; mf->v4=df1->v1; } else{ - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df1->v4=edgesplit[mf->v3*totvert+mf->v4]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); mf->v2=df1->v1; mf->v3=df1->v4; } @@ -5742,8 +6841,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive if(v1!=v2){ if(v1!=v4){ - df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df1->v2=edgesplit[mf->v1*totvert+mf->v2]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); df2->v1=df1->v3=mf->v2; df2->v3=df1->v4=mf->v4; df2->v2=mf->v3; @@ -5756,8 +6855,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[i]=v1; } else{ - df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df1->v3=edgesplit[mf->v2*totvert+mf->v3]; + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); df1->v4=mf->v3; df2->v2=mf->v3; df2->v3=mf->v4; @@ -5773,8 +6872,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } else{ if(v1!=v4){ - df1->v3=edgesplit[mf->v3*totvert+mf->v4]; - df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); df1->v2=mf->v3; mf->v1=df1->v4; @@ -5786,8 +6885,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[i]=v4; } else{ - df1->v3=edgesplit[mf->v2*totvert+mf->v3]; - df1->v4=edgesplit[mf->v3*totvert+mf->v4]; + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); df1->v1=mf->v4; df1->v2=mf->v2; df2->v3=mf->v4; @@ -5823,9 +6922,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v1==v2){ - df2->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df3->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df3->v3=df2->v2=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v3; df2->v3=mf->v4; df1->v4=df2->v4=df3->v4=0; @@ -5838,9 +6937,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v4; } else if(v2==v3){ - df3->v1=df2->v3=df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df2->v2=df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df3->v2=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v3=mf->v4; df2->v1=mf->v1; @@ -5854,9 +6953,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v1; } else if(v3==v4){ - df3->v2=df2->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df2->v3=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df3->v3=df1->v3=edgesplit[mf->v1*totvert+mf->v4]; + df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4); df3->v1=mf->v1; df2->v2=mf->v2; @@ -5870,9 +6969,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v2; } else{ - df3->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v3=df2->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df2->v3=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v2; df2->v2=mf->v3; @@ -5923,11 +7022,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive *df3=*mf; curdupface++; - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); - df2->v1=edgesplit[mf->v1*totvert+mf->v4]; - df3->v4=df2->v3=edgesplit[mf->v3*totvert+mf->v4]; + df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v1=df2->v2=df1->v4=curdupin; @@ -5964,11 +7063,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v2==v3){ - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v1=df1->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3]; - df2->v1=df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); - df3->v3=df2->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v3; df3->v4=0; @@ -5982,11 +7081,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-1]=v3; } else{ - df3->v1=df2->v1=df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df2->v4=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; - df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); - df3->v3=df2->v2=edgesplit[mf->v2*totvert+mf->v3]; + df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3); df3->v4=0; @@ -6010,7 +7109,7 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } } - MEM_freeN(edgesplit); + BLI_edgehash_free(edgehash, NULL); MEM_freeN(facesplit); MEM_freeN(vertpa); @@ -6018,19 +7117,20 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, - ParticleSystemModifierData *psmd, Object *ob, - DerivedMesh *to_explode) + ParticleSystemModifierData *psmd, Object *ob, + DerivedMesh *to_explode) { DerivedMesh *explode, *dm=to_explode; MFace *mf=0; - MVert *dupvert=0; ParticleSettings *part=psmd->psys->part; - ParticleData *pa, *pars=psmd->psys->particles; + ParticleData *pa=NULL, *pars=psmd->psys->particles; ParticleKey state; + EdgeHash *vertpahash; + EdgeHashIterator *ehi; float *vertco=0, imat[4][4]; float loc0[3], nor[3]; float timestep, cfra; - int *facepa=emd->facepa, *vertpa=0; + int *facepa=emd->facepa; int totdup=0,totvert=0,totface=0,totpart=0; int i, j, v, mindex=0; @@ -6045,81 +7145,87 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, else cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0); - /* table for vertice <-> particle relations (row totpart+1 is for yet unexploded verts) */ - vertpa = MEM_callocN(sizeof(int)*(totpart+1)*totvert, "explode_vertpatab"); - for(i=0; i<(totpart+1)*totvert; i++) - vertpa[i] = -1; + /* hash table for vertice <-> particle relations */ + vertpahash= BLI_edgehash_new(); for (i=0; i<totface; i++) { + /* do mindex + totvert to ensure the vertex index to be the first + * with BLI_edgehashIterator_getKey */ if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time) - mindex = totpart*totvert; + mindex = totvert+totpart; else - mindex = facepa[i]*totvert; + mindex = totvert+facepa[i]; mf=CDDM_get_face(dm,i); - /*set face vertices to exist in particle group*/ - vertpa[mindex+mf->v1] = 1; - vertpa[mindex+mf->v2] = 1; - vertpa[mindex+mf->v3] = 1; + /* set face vertices to exist in particle group */ + BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL); + BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL); + BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL); if(mf->v4) - vertpa[mindex+mf->v4] = 1; + BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL); } - /*make new vertice indexes & count total vertices after duplication*/ - for(i=0; i<(totpart+1)*totvert; i++){ - if(vertpa[i] != -1) - vertpa[i] = totdup++; + /* make new vertice indexes & count total vertices after duplication */ + ehi= BLI_edgehashIterator_new(vertpahash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup)); + totdup++; } + BLI_edgehashIterator_free(ehi); - /*the final duplicated vertices*/ + /* the final duplicated vertices */ explode= CDDM_from_template(dm, totdup, 0,totface); - dupvert= CDDM_get_verts(explode); + /*dupvert= CDDM_get_verts(explode);*/ /* getting back to object space */ Mat4Invert(imat,ob->obmat); psmd->psys->lattice = psys_get_lattice(ob, psmd->psys); - /*duplicate & displace vertices*/ - for(i=0, pa=pars; i<=totpart; i++, pa++){ - if(i!=totpart){ - psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0,0,0); - Mat4MulVecfl(ob->obmat,loc0); + /* duplicate & displace vertices */ + ehi= BLI_edgehashIterator_new(vertpahash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + MVert source; + MVert *dest; - state.time=cfra; - psys_get_particle_state(ob,psmd->psys,i,&state,1); - } + /* get particle + vertex from hash */ + BLI_edgehashIterator_getKey(ehi, &j, &i); + i -= totvert; + v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - for(j=0; j<totvert; j++){ - v=vertpa[i*totvert+j]; - if(v != -1) { - MVert source; - MVert *dest; + dm->getVert(dm, j, &source); + dest = CDDM_get_vert(explode,v); - dm->getVert(dm, j, &source); - dest = CDDM_get_vert(explode,v); + DM_copy_vert_data(dm,explode,j,v,1); + *dest = source; - DM_copy_vert_data(dm,explode,j,v,1); - *dest = source; + if(i!=totpart) { + /* get particle */ + pa= pars+i; - if(i!=totpart){ - vertco=CDDM_get_vert(explode,v)->co; - - Mat4MulVecfl(ob->obmat,vertco); + /* get particle state */ + psys_particle_on_emitter(psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0,0,0); + Mat4MulVecfl(ob->obmat,loc0); - VECSUB(vertco,vertco,loc0); + state.time=cfra; + psys_get_particle_state(ob,psmd->psys,i,&state,1); - /* apply rotation, size & location */ - QuatMulVecf(state.rot,vertco); - VecMulf(vertco,pa->size); - VECADD(vertco,vertco,state.co); + vertco=CDDM_get_vert(explode,v)->co; + + Mat4MulVecfl(ob->obmat,vertco); - Mat4MulVecfl(imat,vertco); - } - } + VECSUB(vertco,vertco,loc0); + + /* apply rotation, size & location */ + QuatMulVecf(state.rot,vertco); + VecMulf(vertco,pa->size); + VECADD(vertco,vertco,state.co); + + Mat4MulVecfl(imat,vertco); } } + BLI_edgehashIterator_free(ehi); /*map new vertices to faces*/ for (i=0; i<totface; i++) { @@ -6141,15 +7247,15 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, orig_v4 = source.v4; if(facepa[i]!=totpart && cfra <= pa->time) - mindex = totpart*totvert; + mindex = totvert+totpart; else - mindex = facepa[i]*totvert; + mindex = totvert+facepa[i]; - source.v1 = vertpa[mindex+source.v1]; - source.v2 = vertpa[mindex+source.v2]; - source.v3 = vertpa[mindex+source.v3]; + source.v1 = edgesplit_get(vertpahash, source.v1, mindex); + source.v2 = edgesplit_get(vertpahash, source.v2, mindex); + source.v3 = edgesplit_get(vertpahash, source.v3, mindex); if(source.v4) - source.v4 = vertpa[mindex+source.v4]; + source.v4 = edgesplit_get(vertpahash, source.v4, mindex); DM_copy_face_data(dm,explode,i,i,1); @@ -6158,9 +7264,10 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, test_index_face(mf, &explode->faceData, i, (mf->v4 ? 4 : 3)); } + MEM_printmemlist_stats(); /* cleanup */ - if(vertpa) MEM_freeN(vertpa); + BLI_edgehash_free(vertpahash, NULL); /* finalization */ CDDM_calc_edges(explode); @@ -6186,8 +7293,8 @@ static ParticleSystemModifierData * explodeModifier_findPrecedingParticlesystem( return psmd; } static DerivedMesh * explodeModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { DerivedMesh *dm = derivedData; ExplodeModifierData *emd= (ExplodeModifierData*) md; @@ -6198,12 +7305,13 @@ static DerivedMesh * explodeModifier_applyModifier( if(psys==0 || psys->totpart==0) return derivedData; if(psys->part==0 || psys->particles==0) return derivedData; + if(psmd->dm==0) return derivedData; /* 1. find faces to be exploded if needed */ if(emd->facepa==0 - || psmd->flag&eParticleSystemFlag_Pars - || emd->flag&eExplodeFlag_CalcFaces - || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){ + || psmd->flag&eParticleSystemFlag_Pars + || emd->flag&eExplodeFlag_CalcFaces + || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){ if(psmd->flag & eParticleSystemFlag_Pars) psmd->flag &= ~eParticleSystemFlag_Pars; @@ -6211,24 +7319,111 @@ static DerivedMesh * explodeModifier_applyModifier( emd->flag &= ~eExplodeFlag_CalcFaces; explodeModifier_createFacepa(emd,psmd,ob,derivedData); - } + } + + /* 2. create new mesh */ + if(emd->flag & eExplodeFlag_EdgeSplit){ + int *facepa = emd->facepa; + DerivedMesh *splitdm=explodeModifier_splitEdges(emd,dm); + DerivedMesh *explode=explodeModifier_explodeMesh(emd,psmd,ob,splitdm); + + MEM_freeN(emd->facepa); + emd->facepa=facepa; + splitdm->release(splitdm); + return explode; + } + else + return explodeModifier_explodeMesh(emd,psmd,ob,derivedData); + } + return derivedData; +} - /* 2. create new mesh */ - if(emd->flag & eExplodeFlag_EdgeSplit){ - int *facepa = emd->facepa; - DerivedMesh *splitdm=explodeModifier_splitEdges(emd,dm); - DerivedMesh *explode=explodeModifier_explodeMesh(emd,psmd,ob,splitdm); +/* Fluidsim */ +static void fluidsimModifier_initData(ModifierData *md) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + + fluidsim_init(fluidmd); +} +static void fluidsimModifier_freeData(ModifierData *md) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + + fluidsim_free(fluidmd); +} - MEM_freeN(emd->facepa); - emd->facepa=facepa; - splitdm->release(splitdm); - return explode; - } - else - return explodeModifier_explodeMesh(emd,psmd,ob,derivedData); +static void fluidsimModifier_copyData(ModifierData *md, ModifierData *target) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + FluidsimModifierData *tfluidmd= (FluidsimModifierData*) target; + + if(tfluidmd->fss) + MEM_freeN(tfluidmd->fss); + + tfluidmd->fss = MEM_dupallocN(fluidmd->fss); +} + +static DerivedMesh * fluidsimModifier_applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + DerivedMesh *result = NULL; + + /* check for alloc failing */ + if(!fluidmd->fss) + { + fluidsimModifier_initData(md); + + if(!fluidmd->fss) + return derivedData; + } + + result = fluidsimModifier_do(fluidmd, ob, derivedData, useRenderParams, isFinalCalc); + + if(result) + { + return result; } + return derivedData; } + +static void fluidsimModifier_updateDepgraph( + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + Base *base; + + if(fluidmd && fluidmd->fss) + { + if(fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) + { + for(base = G.scene->base.first; base; base= base->next) + { + Object *ob1= base->object; + if(ob1 != ob) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim); + + // only put dependancies from NON-DOMAIN fluids in here + if(fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type!=OB_FLUIDSIM_DOMAIN)) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Fluidsim Object"); + } + } + } + } + } +} + +static int fluidsimModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* MeshDeform */ static void meshdeformModifier_initData(ModifierData *md) @@ -6277,9 +7472,9 @@ static int meshdeformModifier_isDisabled(ModifierData *md) } static void meshdeformModifier_foreachObjectLink( - ModifierData *md, Object *ob, - void (*walk)(void *userData, Object *ob, Object **obpoin), - void *userData) + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; @@ -6287,8 +7482,8 @@ static void meshdeformModifier_foreachObjectLink( } static void meshdeformModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, - DagNode *obNode) + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; @@ -6296,7 +7491,8 @@ static void meshdeformModifier_updateDepgraph( DagNode *curNode = dag_get_node(forest, mmd->object); dag_add_relation(forest, curNode, obNode, - DAG_RL_DATA_DATA|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_OB_OB); + DAG_RL_DATA_DATA|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_OB_OB, + "Mesh Deform Modifier"); } } @@ -6353,11 +7549,11 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3 } static void meshdeformModifier_do( - ModifierData *md, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; - float imat[4][4], cagemat[4][4], icagemat[4][4], iobmat[3][3]; + float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3]; int a, b, totvert, totcagevert, defgrp_index; DerivedMesh *tmpdm, *cagedm; @@ -6380,15 +7576,24 @@ static void meshdeformModifier_do( if(!cagedm) return; - /* compute matrices to go in and out of cage object space */ + /* compute matrices to go in and out of cage object space */ Mat4Invert(imat, mmd->object->obmat); Mat4MulMat4(cagemat, ob->obmat, imat); - Mat4Invert(icagemat, cagemat); - Mat3CpyMat4(iobmat, icagemat); + Mat4MulMat4(cmat, cagemat, mmd->bindmat); + Mat4Invert(iobmat, cmat); + Mat3CpyMat4(icagemat, iobmat); /* bind weights if needed */ - if(!mmd->bindcos) - //XXX harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); + if(!mmd->bindcos) { + static int recursive = 0; + + /* progress bar redraw can make this recursive .. */ + if(!recursive) { + recursive = 1; + //XXX harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); + recursive = 0; + } + } /* verify we have compatible weights */ totvert= numVerts; @@ -6482,11 +7687,11 @@ static void meshdeformModifier_do( if(totweight > 0.0f) { VecMulf(co, fac/totweight); - Mat3MulVecfl(iobmat, co); + Mat3MulVecfl(icagemat, co); if(G.rt != 527) VECADD(vertexCos[b], vertexCos[b], co) - else - VECCOPY(vertexCos[b], co) + else + VECCOPY(vertexCos[b], co) } } @@ -6496,8 +7701,8 @@ static void meshdeformModifier_do( } static void meshdeformModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -6515,8 +7720,8 @@ static void meshdeformModifier_deformVerts( } static void meshdeformModifier_deformVertsEM( - ModifierData *md, Object *ob, EditMesh *editData, - DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm; @@ -6531,6 +7736,235 @@ static void meshdeformModifier_deformVertsEM( dm->release(dm); } + +/* Shrinkwrap */ + +static void shrinkwrapModifier_initData(ModifierData *md) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; + smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE; + smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR; + smd->keepDist = 0.0f; + + smd->target = NULL; + smd->auxTarget = NULL; +} + +static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*)md; + ShrinkwrapModifierData *tsmd = (ShrinkwrapModifierData*)target; + + tsmd->target = smd->target; + tsmd->auxTarget = smd->auxTarget; + + strcpy(tsmd->vgroup_name, smd->vgroup_name); + + tsmd->keepDist = smd->keepDist; + tsmd->shrinkType= smd->shrinkType; + tsmd->shrinkOpts= smd->shrinkOpts; + tsmd->projAxis = smd->projAxis; + tsmd->subsurfLevels = smd->subsurfLevels; +} + +CustomDataMask shrinkwrapModifier_requiredDataMask(ModifierData *md) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if(smd->vgroup_name[0]) + dataMask |= (1 << CD_MDEFORMVERT); + + if(smd->shrinkType == MOD_SHRINKWRAP_PROJECT + && smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) + dataMask |= (1 << CD_MVERT); + + return dataMask; +} + +static int shrinkwrapModifier_isDisabled(ModifierData *md) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; + return !smd->target; +} + + +static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; + + walk(userData, ob, &smd->target); + walk(userData, ob, &smd->auxTarget); +} + +static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); + + /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else if(ob->type==OB_LATTICE) dm = NULL; + else return; + + if(dm != NULL && (dataMask & CD_MVERT)) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); +} + +static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); + + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); + else if(ob->type==OB_LATTICE) dm = NULL; + else return; + + if(dm != NULL && (dataMask & CD_MVERT)) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); +} + +static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; + + if (smd->target) + dag_add_relation(forest, dag_get_node(forest, smd->target), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier"); + + if (smd->auxTarget) + dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier"); +} + +/* SimpleDeform */ +static void simpledeformModifier_initData(ModifierData *md) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md; + + smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST; + smd->axis = 0; + + smd->origin = NULL; + smd->factor = 0.35f; + smd->limit[0] = 0.0f; + smd->limit[1] = 1.0f; +} + +static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md; + SimpleDeformModifierData *tsmd = (SimpleDeformModifierData*)target; + + tsmd->mode = smd->mode; + tsmd->axis = smd->axis; + tsmd->origin= smd->origin; + tsmd->factor= smd->factor; + memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit)); +} + +static CustomDataMask simpledeformModifier_requiredDataMask(ModifierData *md) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if(smd->vgroup_name[0]) + dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + +static void simpledeformModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md; + walk(userData, ob, &smd->origin); +} + +static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md; + + if (smd->origin) + dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier"); +} + +static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + + /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else if(ob->type==OB_LATTICE) dm = NULL; + else return; + + if(dm != NULL && (dataMask & CD_MVERT)) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); + +} + +static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + + /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); + else if(ob->type==OB_LATTICE) dm = NULL; + else return; + + if(dm != NULL && (dataMask & CD_MVERT)) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); +} + /***/ static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; @@ -6545,15 +7979,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) /* Initialize and return the appropriate type info structure, * assumes that modifier has: - * name == typeName, - * structName == typeName + 'ModifierData' - */ + * name == typeName, + * structName == typeName + 'ModifierData' + */ #define INIT_TYPE(typeName) \ (strcpy(typeArr[eModifierType_##typeName].name, #typeName), \ strcpy(typeArr[eModifierType_##typeName].structName, \ - #typeName "ModifierData"), \ +#typeName "ModifierData"), \ typeArr[eModifierType_##typeName].structSize = \ - sizeof(typeName##ModifierData), \ + sizeof(typeName##ModifierData), \ &typeArr[eModifierType_##typeName]) mti = &typeArr[eModifierType_None]; @@ -6562,13 +7996,13 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->structSize = sizeof(ModifierData); mti->type = eModifierType_None; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_AcceptsCVs; + | eModifierTypeFlag_AcceptsCVs; mti->isDisabled = noneModifier_isDisabled; mti = INIT_TYPE(Curve); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = curveModifier_initData; mti->copyData = curveModifier_copyData; mti->requiredDataMask = curveModifier_requiredDataMask; @@ -6581,7 +8015,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Lattice); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->copyData = latticeModifier_copyData; mti->requiredDataMask = latticeModifier_requiredDataMask; mti->isDisabled = latticeModifier_isDisabled; @@ -6593,9 +8027,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Subsurf); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = subsurfModifier_initData; mti->copyData = subsurfModifier_copyData; mti->freeData = subsurfModifier_freeData; @@ -6609,13 +8043,22 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->copyData = buildModifier_copyData; mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + + mti = INIT_TYPE(Mask); + mti->type = eModifierTypeType_Nonconstructive; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->copyData = maskModifier_copyData; + mti->requiredDataMask= maskModifier_requiredDataMask; + mti->foreachObjectLink = maskModifier_foreachObjectLink; + mti->updateDepgraph = maskModifier_updateDepgraph; + mti->applyModifier = maskModifier_applyModifier; mti = INIT_TYPE(Array); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = arrayModifier_initData; mti->copyData = arrayModifier_copyData; mti->foreachObjectLink = arrayModifier_foreachObjectLink; @@ -6626,9 +8069,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Mirror); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = mirrorModifier_initData; mti->copyData = mirrorModifier_copyData; mti->foreachObjectLink = mirrorModifier_foreachObjectLink; @@ -6639,20 +8082,32 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(EdgeSplit); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = edgesplitModifier_initData; mti->copyData = edgesplitModifier_copyData; mti->applyModifier = edgesplitModifier_applyModifier; mti->applyModifierEM = edgesplitModifier_applyModifierEM; + mti = INIT_TYPE(Bevel); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + mti->initData = bevelModifier_initData; + mti->copyData = bevelModifier_copyData; + mti->requiredDataMask = bevelModifier_requiredDataMask; + mti->applyModifier = bevelModifier_applyModifier; + mti->applyModifierEM = bevelModifier_applyModifierEM; + mti = INIT_TYPE(Displace); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsEditmode; mti->initData = displaceModifier_initData; mti->copyData = displaceModifier_copyData; mti->requiredDataMask = displaceModifier_requiredDataMask; + mti->dependsOnTime = displaceModifier_dependsOnTime; mti->foreachObjectLink = displaceModifier_foreachObjectLink; mti->foreachIDLink = displaceModifier_foreachIDLink; mti->updateDepgraph = displaceModifier_updateDepgraph; @@ -6663,9 +8118,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(UVProject); mti->type = eModifierTypeType_Nonconstructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = uvprojectModifier_initData; mti->copyData = uvprojectModifier_copyData; mti->requiredDataMask = uvprojectModifier_requiredDataMask; @@ -6685,7 +8140,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Smooth); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = smoothModifier_initData; mti->copyData = smoothModifier_copyData; mti->requiredDataMask = smoothModifier_requiredDataMask; @@ -6695,7 +8150,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Cast); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = castModifier_initData; mti->copyData = castModifier_copyData; mti->requiredDataMask = castModifier_requiredDataMask; @@ -6707,7 +8162,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Wave); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = waveModifier_initData; mti->copyData = waveModifier_copyData; mti->dependsOnTime = waveModifier_dependsOnTime; @@ -6721,7 +8176,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Armature); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = armatureModifier_initData; mti->copyData = armatureModifier_copyData; mti->requiredDataMask = armatureModifier_requiredDataMask; @@ -6735,7 +8190,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Hook); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = hookModifier_initData; mti->copyData = hookModifier_copyData; mti->requiredDataMask = hookModifier_requiredDataMask; @@ -6749,14 +8204,36 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Softbody); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_RequiresOriginalData; + | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; + mti->dependsOnTime = softbodyModifier_dependsOnTime; + + mti = INIT_TYPE(Cloth); + mti->type = eModifierTypeType_Nonconstructive; + mti->initData = clothModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_UsesPointCache; + mti->dependsOnTime = clothModifier_dependsOnTime; + mti->freeData = clothModifier_freeData; + mti->requiredDataMask = clothModifier_requiredDataMask; + mti->copyData = clothModifier_copyData; + mti->applyModifier = clothModifier_applyModifier; + mti->updateDepgraph = clothModifier_updateDepgraph; + + mti = INIT_TYPE(Collision); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = collisionModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->dependsOnTime = collisionModifier_dependsOnTime; + mti->freeData = collisionModifier_freeData; + mti->deformVerts = collisionModifier_deformVerts; + // mti->copyData = collisionModifier_copyData; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_RequiresOriginalData - | eModifierTypeFlag_UsesPointCache; + | eModifierTypeFlag_RequiresOriginalData + | eModifierTypeFlag_UsesPointCache; mti->copyData = booleanModifier_copyData; mti->isDisabled = booleanModifier_isDisabled; mti->applyModifier = booleanModifier_applyModifier; @@ -6766,7 +8243,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(MeshDeform); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_SupportsEditmode; + | eModifierTypeFlag_SupportsEditmode; mti->initData = meshdeformModifier_initData; mti->freeData = meshdeformModifier_freeData; mti->copyData = meshdeformModifier_copyData; @@ -6780,11 +8257,11 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(ParticleSystem); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_UsesPointCache; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_UsesPointCache; #if 0 - | eModifierTypeFlag_SupportsEditmode; - |eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsEditmode; + |eModifierTypeFlag_EnableInEditmode; #endif mti->initData = particleSystemModifier_initData; mti->freeData = particleSystemModifier_freeData; @@ -6798,9 +8275,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(ParticleInstance); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping - | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; mti->initData = particleInstanceModifier_initData; mti->copyData = particleInstanceModifier_copyData; mti->dependsOnTime = particleInstanceModifier_dependsOnTime; @@ -6818,6 +8295,46 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->dependsOnTime = explodeModifier_dependsOnTime; mti->requiredDataMask = explodeModifier_requiredDataMask; mti->applyModifier = explodeModifier_applyModifier; + + mti = INIT_TYPE(Fluidsim); + mti->type = eModifierTypeType_Nonconstructive + | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->initData = fluidsimModifier_initData; + mti->freeData = fluidsimModifier_freeData; + mti->copyData = fluidsimModifier_copyData; + mti->dependsOnTime = fluidsimModifier_dependsOnTime; + mti->applyModifier = fluidsimModifier_applyModifier; + mti->updateDepgraph = fluidsimModifier_updateDepgraph; + + mti = INIT_TYPE(Shrinkwrap); + mti->type = eModifierTypeType_OnlyDeform; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_AcceptsCVs + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + mti->initData = shrinkwrapModifier_initData; + mti->copyData = shrinkwrapModifier_copyData; + mti->requiredDataMask = shrinkwrapModifier_requiredDataMask; + mti->isDisabled = shrinkwrapModifier_isDisabled; + mti->foreachObjectLink = shrinkwrapModifier_foreachObjectLink; + mti->deformVerts = shrinkwrapModifier_deformVerts; + mti->deformVertsEM = shrinkwrapModifier_deformVertsEM; + mti->updateDepgraph = shrinkwrapModifier_updateDepgraph; + + mti = INIT_TYPE(SimpleDeform); + mti->type = eModifierTypeType_OnlyDeform; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_AcceptsCVs + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + mti->initData = simpledeformModifier_initData; + mti->copyData = simpledeformModifier_copyData; + mti->requiredDataMask = simpledeformModifier_requiredDataMask; + mti->deformVerts = simpledeformModifier_deformVerts; + mti->deformVertsEM = simpledeformModifier_deformVertsEM; + mti->foreachObjectLink = simpledeformModifier_foreachObjectLink; + mti->updateDepgraph = simpledeformModifier_updateDepgraph; typeArrInit = 0; #undef INIT_TYPE @@ -6841,7 +8358,7 @@ ModifierData *modifier_new(int type) md->type = type; md->mode = eModifierMode_Realtime - | eModifierMode_Render | eModifierMode_Expanded; + | eModifierMode_Render | eModifierMode_Expanded; if (mti->flags & eModifierTypeFlag_EnableInEditmode) md->mode |= eModifierMode_Editmode; @@ -6873,7 +8390,7 @@ int modifier_supportsMapping(ModifierData *md) ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type==eModifierTypeType_OnlyDeform || - (mti->flags & eModifierTypeFlag_SupportsMapping)); + (mti->flags & eModifierTypeFlag_SupportsMapping)); } ModifierData *modifiers_findByType(Object *ob, ModifierType type) @@ -6905,7 +8422,7 @@ void modifiers_clearErrors(Object *ob) } void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, - void *userData) + void *userData) { ModifierData *md = ob->modifiers.first; @@ -6948,9 +8465,9 @@ int modifier_couldBeCage(ModifierData *md) ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ( (md->mode & eModifierMode_Realtime) && - (md->mode & eModifierMode_Editmode) && - (!mti->isDisabled || !mti->isDisabled(md)) && - modifier_supportsMapping(md)); + (md->mode & eModifierMode_Editmode) && + (!mti->isDisabled || !mti->isDisabled(md)) && + modifier_supportsMapping(md)); } void modifier_setError(ModifierData *md, char *format, ...) @@ -6981,7 +8498,7 @@ int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r) ModifierData *md = ob->modifiers.first; int i, cageIndex = -1; - /* Find the last modifier acting on the cage. */ + /* Find the last modifier acting on the cage. */ for (i=0; md; i++,md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -7010,6 +8527,13 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } +int modifiers_isClothEnabled(Object *ob) +{ + ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + + return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); +} + int modifiers_isParticleEnabled(Object *ob) { ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem); @@ -7033,11 +8557,11 @@ LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) } /* build the list of required data masks - each mask in the list must - * include all elements of the masks that follow it - * - * note the list is currently in reverse order, so "masks that follow it" - * actually means "masks that precede it" at the moment - */ + * include all elements of the masks that follow it + * + * note the list is currently in reverse order, so "masks that follow it" + * actually means "masks that precede it" at the moment + */ for(curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) { if(prev) { CustomDataMask prev_mask = (CustomDataMask)prev->link; @@ -7060,8 +8584,8 @@ LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) ModifierData *modifiers_getVirtualModifierList(Object *ob) { /* Kinda hacky, but should be fine since we are never - * reentrant and avoid free hassles. - */ + * reentrant and avoid free hassles. + */ static ArmatureModifierData amd; static CurveModifierData cmd; static LatticeModifierData lmd; @@ -7119,7 +8643,7 @@ Object *modifiers_isDeformedByArmature(Object *ob) ArmatureModifierData *amd= NULL; /* return the first selected armature, this lets us use multiple armatures - */ + */ for (; md; md=md->next) { if (md->type==eModifierType_Armature) { amd = (ArmatureModifierData*) md; @@ -7144,7 +8668,7 @@ Object *modifiers_isDeformedByLattice(Object *ob) LatticeModifierData *lmd= NULL; /* return the first selected armature, this lets us use multiple armatures - */ + */ for (; md; md=md->next) { if (md->type==eModifierType_Lattice) { lmd = (LatticeModifierData*) md; @@ -7234,3 +8758,4 @@ void modifier_freeTemporaryData(ModifierData *md) } + |