4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): Daniel Dunbar
29 * ***** END GPL LICENSE BLOCK *****
31 * Modifier stack implementation.
33 * BKE_modifier.h contains the function prototypes for this file.
43 #include "BLI_arithb.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_kdopbvh.h"
46 #include "BLI_kdtree.h"
47 #include "BLI_linklist.h"
49 #include "BLI_edgehash.h"
50 #include "BLI_ghash.h"
51 #include "BLI_memarena.h"
53 #include "MEM_guardedalloc.h"
55 #include "DNA_action_types.h"
56 #include "DNA_armature_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_cloth_types.h"
59 #include "DNA_curve_types.h"
60 #include "DNA_effect_types.h"
61 #include "DNA_group_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_mesh_types.h"
64 #include "DNA_meshdata_types.h"
65 #include "DNA_modifier_types.h"
66 #include "DNA_object_types.h"
67 #include "DNA_object_fluidsim.h"
68 #include "DNA_object_force.h"
69 #include "DNA_particle_types.h"
70 #include "DNA_scene_types.h"
71 #include "DNA_smoke_types.h"
72 #include "DNA_texture_types.h"
74 #include "BLI_editVert.h"
76 #include "MTC_matrixops.h"
77 #include "MTC_vectorops.h"
81 #include "BKE_bmesh.h"
82 // XXX #include "BKE_booleanops.h"
83 #include "BKE_cloth.h"
84 #include "BKE_collision.h"
85 #include "BKE_cdderivedmesh.h"
86 #include "BKE_curve.h"
87 #include "BKE_customdata.h"
88 #include "BKE_DerivedMesh.h"
89 #include "BKE_displist.h"
90 #include "BKE_fluidsim.h"
91 #include "BKE_global.h"
92 #include "BKE_multires.h"
93 #include "BKE_lattice.h"
94 #include "BKE_library.h"
95 #include "BKE_material.h"
97 #include "BKE_modifier.h"
98 #include "BKE_object.h"
99 #include "BKE_particle.h"
100 #include "BKE_pointcache.h"
101 #include "BKE_smoke.h"
102 #include "BKE_softbody.h"
103 #include "BKE_subsurf.h"
104 #include "BKE_texture.h"
105 #include "BKE_utildefines.h"
107 #include "depsgraph_private.h"
108 #include "BKE_deform.h"
109 #include "BKE_shrinkwrap.h"
110 #include "BKE_simple_deform.h"
112 //XXX #include "LOD_DependKludge.h"
113 #include "LOD_decimation.h"
116 static struct DerivedMesh *NewBooleanDerivedMesh() {return NULL;}
118 #include "CCGSubSurf.h"
120 #include "RE_shader_ext.h"
122 //XXX #include "BIF_meshlaplacian.h"
126 static int is_last_displist(Object *ob)
128 Curve *cu = ob->data;
129 static int curvecount=0, totcurve=0;
135 for(dl=cu->disp.first; dl; dl=dl->next)
141 if(curvecount == totcurve){
149 static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos)[3], int orco)
151 DerivedMesh *dm= NULL;
153 if(ob->type==OB_MESH) {
154 dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
157 CDDM_apply_vert_coords(dm, vertexCos);
158 //CDDM_calc_normals(dm);
162 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
164 else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) {
168 if(is_last_displist(ob)) {
169 /* copies object and modifiers (but not the data) */
170 tmpobj= copy_object(ob);
171 tmpcu = (Curve *)tmpobj->data;
174 /* copies the data */
175 tmpobj->data = copy_curve((Curve *) ob->data);
177 makeDispListCurveTypes(scene, tmpobj, 1);
178 nurbs_to_mesh(tmpobj);
180 dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj);
181 //CDDM_calc_normals(dm);
183 free_libblock_us(&G.main->object, tmpobj);
192 static int noneModifier_isDisabled(ModifierData *md)
199 static void curveModifier_initData(ModifierData *md)
201 CurveModifierData *cmd = (CurveModifierData*) md;
203 cmd->defaxis = MOD_CURVE_POSX;
206 static void curveModifier_copyData(ModifierData *md, ModifierData *target)
208 CurveModifierData *cmd = (CurveModifierData*) md;
209 CurveModifierData *tcmd = (CurveModifierData*) target;
211 tcmd->defaxis = cmd->defaxis;
212 tcmd->object = cmd->object;
213 strncpy(tcmd->name, cmd->name, 32);
216 CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md)
218 CurveModifierData *cmd = (CurveModifierData *)md;
219 CustomDataMask dataMask = 0;
221 /* ask for vertexgroups if we need them */
222 if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
227 static int curveModifier_isDisabled(ModifierData *md)
229 CurveModifierData *cmd = (CurveModifierData*) md;
234 static void curveModifier_foreachObjectLink(
235 ModifierData *md, Object *ob,
236 void (*walk)(void *userData, Object *ob, Object **obpoin),
239 CurveModifierData *cmd = (CurveModifierData*) md;
241 walk(userData, ob, &cmd->object);
244 static void curveModifier_updateDepgraph(
245 ModifierData *md, DagForest *forest, Scene *scene,
246 Object *ob, DagNode *obNode)
248 CurveModifierData *cmd = (CurveModifierData*) md;
251 DagNode *curNode = dag_get_node(forest, cmd->object);
253 dag_add_relation(forest, curNode, obNode,
254 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
258 static void curveModifier_deformVerts(
259 ModifierData *md, Object *ob, DerivedMesh *derivedData,
260 float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
262 CurveModifierData *cmd = (CurveModifierData*) md;
264 curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts,
265 cmd->name, cmd->defaxis);
268 static void curveModifier_deformVertsEM(
269 ModifierData *md, Object *ob, EditMesh *editData,
270 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
272 DerivedMesh *dm = derivedData;
274 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
276 curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
278 if(!derivedData) dm->release(dm);
283 static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
285 LatticeModifierData *lmd = (LatticeModifierData*) md;
286 LatticeModifierData *tlmd = (LatticeModifierData*) target;
288 tlmd->object = lmd->object;
289 strncpy(tlmd->name, lmd->name, 32);
292 CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md)
294 LatticeModifierData *lmd = (LatticeModifierData *)md;
295 CustomDataMask dataMask = 0;
297 /* ask for vertexgroups if we need them */
298 if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
303 static int latticeModifier_isDisabled(ModifierData *md)
305 LatticeModifierData *lmd = (LatticeModifierData*) md;
310 static void latticeModifier_foreachObjectLink(
311 ModifierData *md, Object *ob,
312 void (*walk)(void *userData, Object *ob, Object **obpoin),
315 LatticeModifierData *lmd = (LatticeModifierData*) md;
317 walk(userData, ob, &lmd->object);
320 static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
321 Object *ob, DagNode *obNode)
323 LatticeModifierData *lmd = (LatticeModifierData*) md;
326 DagNode *latNode = dag_get_node(forest, lmd->object);
328 dag_add_relation(forest, latNode, obNode,
329 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
333 static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
337 if(md->type==eModifierType_Armature) {
338 ArmatureModifierData *amd = (ArmatureModifierData*) md;
340 amd->prevCos= MEM_dupallocN(vertexCos);
342 /* lattice/mesh modifier too */
347 static void latticeModifier_deformVerts(
348 ModifierData *md, Object *ob, DerivedMesh *derivedData,
349 float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
351 LatticeModifierData *lmd = (LatticeModifierData*) md;
354 modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
356 lattice_deform_verts(lmd->object, ob, derivedData,
357 vertexCos, numVerts, lmd->name);
360 static void latticeModifier_deformVertsEM(
361 ModifierData *md, Object *ob, EditMesh *editData,
362 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
364 DerivedMesh *dm = derivedData;
366 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
368 latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
370 if(!derivedData) dm->release(dm);
375 static void subsurfModifier_initData(ModifierData *md)
377 SubsurfModifierData *smd = (SubsurfModifierData*) md;
380 smd->renderLevels = 2;
381 smd->flags |= eSubsurfModifierFlag_SubsurfUv;
384 static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
386 SubsurfModifierData *smd = (SubsurfModifierData*) md;
387 SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
389 tsmd->flags = smd->flags;
390 tsmd->levels = smd->levels;
391 tsmd->renderLevels = smd->renderLevels;
392 tsmd->subdivType = smd->subdivType;
395 static void subsurfModifier_freeData(ModifierData *md)
397 SubsurfModifierData *smd = (SubsurfModifierData*) md;
400 ccgSubSurf_free(smd->mCache);
403 ccgSubSurf_free(smd->emCache);
407 static DerivedMesh *subsurfModifier_applyModifier(
408 ModifierData *md, Object *ob, DerivedMesh *derivedData,
409 int useRenderParams, int isFinalCalc)
411 SubsurfModifierData *smd = (SubsurfModifierData*) md;
414 result = subsurf_make_derived_from_derived(derivedData, smd,
415 useRenderParams, NULL,
421 static DerivedMesh *subsurfModifier_applyModifierEM(
422 ModifierData *md, Object *ob, EditMesh *editData,
423 DerivedMesh *derivedData)
425 SubsurfModifierData *smd = (SubsurfModifierData*) md;
428 result = subsurf_make_derived_from_derived(derivedData, smd, 0,
436 static void buildModifier_initData(ModifierData *md)
438 BuildModifierData *bmd = (BuildModifierData*) md;
444 static void buildModifier_copyData(ModifierData *md, ModifierData *target)
446 BuildModifierData *bmd = (BuildModifierData*) md;
447 BuildModifierData *tbmd = (BuildModifierData*) target;
449 tbmd->start = bmd->start;
450 tbmd->length = bmd->length;
451 tbmd->randomize = bmd->randomize;
452 tbmd->seed = bmd->seed;
455 static int buildModifier_dependsOnTime(ModifierData *md)
460 static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
461 DerivedMesh *derivedData,
462 int useRenderParams, int isFinalCalc)
464 DerivedMesh *dm = derivedData;
466 BuildModifierData *bmd = (BuildModifierData*) md;
468 int numFaces, numEdges;
469 int maxVerts, maxEdges, maxFaces;
470 int *vertMap, *edgeMap, *faceMap;
472 GHashIterator *hashIter;
473 /* maps vert indices in old mesh to indices in new mesh */
474 GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
475 BLI_ghashutil_intcmp);
476 /* maps edge indices in new mesh to indices in old mesh */
477 GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
478 BLI_ghashutil_intcmp);
480 maxVerts = dm->getNumVerts(dm);
481 vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
482 "build modifier vertMap");
483 for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
485 maxEdges = dm->getNumEdges(dm);
486 edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
487 "build modifier edgeMap");
488 for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
490 maxFaces = dm->getNumFaces(dm);
491 faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
492 "build modifier faceMap");
493 for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
496 frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
497 bmd->start - 1.0f) / bmd->length;
499 frac = md->scene->r.cfra - bmd->start / bmd->length;
501 CLAMP(frac, 0.0, 1.0);
503 numFaces = dm->getNumFaces(dm) * frac;
504 numEdges = dm->getNumEdges(dm) * frac;
506 /* if there's at least one face, build based on faces */
511 BLI_array_randomize(faceMap, sizeof(*faceMap),
512 maxFaces, bmd->seed);
514 /* get the set of all vert indices that will be in the final mesh,
515 * mapped to the new indices
517 for(i = 0; i < numFaces; ++i) {
519 dm->getFace(dm, faceMap[i], &mf);
521 if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
522 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
523 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
524 if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
525 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
526 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
527 if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
528 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
529 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
530 if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
531 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
532 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
535 /* get the set of edges that will be in the new mesh (i.e. all edges
536 * that have both verts in the new mesh)
538 maxEdges = dm->getNumEdges(dm);
539 for(i = 0; i < maxEdges; ++i) {
541 dm->getEdge(dm, i, &me);
543 if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
544 && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
545 BLI_ghash_insert(edgeHash,
546 SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
548 } else if(numEdges) {
550 BLI_array_randomize(edgeMap, sizeof(*edgeMap),
551 maxEdges, bmd->seed);
553 /* get the set of all vert indices that will be in the final mesh,
554 * mapped to the new indices
556 for(i = 0; i < numEdges; ++i) {
558 dm->getEdge(dm, edgeMap[i], &me);
560 if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
561 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
562 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
563 if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
564 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
565 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
568 /* get the set of edges that will be in the new mesh
570 for(i = 0; i < numEdges; ++i) {
572 dm->getEdge(dm, edgeMap[i], &me);
574 BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
575 SET_INT_IN_POINTER(edgeMap[i]));
578 int numVerts = dm->getNumVerts(dm) * frac;
581 BLI_array_randomize(vertMap, sizeof(*vertMap),
582 maxVerts, bmd->seed);
584 /* get the set of all vert indices that will be in the final mesh,
585 * mapped to the new indices
587 for(i = 0; i < numVerts; ++i)
588 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
591 /* now we know the number of verts, edges and faces, we can create
594 result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
595 BLI_ghash_size(edgeHash), numFaces);
597 /* copy the vertices across */
598 for(hashIter = BLI_ghashIterator_new(vertHash);
599 !BLI_ghashIterator_isDone(hashIter);
600 BLI_ghashIterator_step(hashIter)) {
603 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
604 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
606 dm->getVert(dm, oldIndex, &source);
607 dest = CDDM_get_vert(result, newIndex);
609 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
612 BLI_ghashIterator_free(hashIter);
614 /* copy the edges across, remapping indices */
615 for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
618 int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
620 dm->getEdge(dm, oldIndex, &source);
621 dest = CDDM_get_edge(result, i);
623 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
624 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
626 DM_copy_edge_data(dm, result, oldIndex, i, 1);
630 /* copy the faces across, remapping indices */
631 for(i = 0; i < numFaces; ++i) {
636 dm->getFace(dm, faceMap[i], &source);
637 dest = CDDM_get_face(result, i);
641 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
642 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
643 source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
645 source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
647 DM_copy_face_data(dm, result, faceMap[i], i, 1);
650 test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
653 CDDM_calc_normals(result);
655 BLI_ghash_free(vertHash, NULL, NULL);
656 BLI_ghash_free(edgeHash, NULL, NULL);
667 static void maskModifier_copyData(ModifierData *md, ModifierData *target)
669 MaskModifierData *mmd = (MaskModifierData*) md;
670 MaskModifierData *tmmd = (MaskModifierData*) target;
672 strcpy(tmmd->vgroup, mmd->vgroup);
675 static CustomDataMask maskModifier_requiredDataMask(Object *ob, ModifierData *md)
677 return (1 << CD_MDEFORMVERT);
680 static void maskModifier_foreachObjectLink(
681 ModifierData *md, Object *ob,
682 void (*walk)(void *userData, Object *ob, Object **obpoin),
685 MaskModifierData *mmd = (MaskModifierData *)md;
686 walk(userData, ob, &mmd->ob_arm);
689 static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
690 Object *ob, DagNode *obNode)
692 MaskModifierData *mmd = (MaskModifierData *)md;
696 DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
698 dag_add_relation(forest, armNode, obNode,
699 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
703 static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
704 DerivedMesh *derivedData,
705 int useRenderParams, int isFinalCalc)
707 MaskModifierData *mmd= (MaskModifierData *)md;
708 DerivedMesh *dm= derivedData, *result= NULL;
709 GHash *vertHash=NULL, *edgeHash, *faceHash;
710 GHashIterator *hashIter;
711 MDeformVert *dvert= NULL;
712 int numFaces=0, numEdges=0, numVerts=0;
713 int maxVerts, maxEdges, maxFaces;
716 /* Overview of Method:
717 * 1. Get the vertices that are in the vertexgroup of interest
718 * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
719 * 3. Make a new mesh containing only the mapping data
722 /* get original number of verts, edges, and faces */
723 maxVerts= dm->getNumVerts(dm);
724 maxEdges= dm->getNumEdges(dm);
725 maxFaces= dm->getNumFaces(dm);
727 /* check if we can just return the original mesh
728 * - must have verts and therefore verts assigned to vgroups to do anything useful
730 if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
731 (maxVerts == 0) || (ob->defbase.first == NULL) )
736 /* if mode is to use selected armature bones, aggregate the bone groups */
737 if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */
739 GHash *vgroupHash, *boneHash;
740 Object *oba= mmd->ob_arm;
744 /* check that there is armature object with bones to use, otherwise return original mesh */
745 if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose))
748 /* hashes for finding mapping of:
749 * - vgroups to indicies -> vgroupHash (string, int)
750 * - bones to vgroup indices -> boneHash (index of vgroup, dummy)
752 vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
753 boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
755 /* build mapping of names of vertex groups to indices */
756 for (i = 0, def = ob->defbase.first; def; def = def->next, i++)
757 BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i));
759 /* get selected-posechannel <-> vertexgroup index mapping */
760 for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next)
762 /* check if bone is selected */
763 // TODO: include checks for visibility too?
764 // FIXME: the depsgraph needs extensions to make this work in realtime...
765 if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) )
767 /* check if hash has group for this bone */
768 if (BLI_ghash_haskey(vgroupHash, pchan->name))
770 int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name));
772 /* add index to hash (store under key only) */
773 BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan);
778 /* if no bones selected, free hashes and return original mesh */
779 if (BLI_ghash_size(boneHash) == 0)
781 BLI_ghash_free(vgroupHash, NULL, NULL);
782 BLI_ghash_free(boneHash, NULL, NULL);
787 /* repeat the previous check, but for dverts */
788 dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
791 BLI_ghash_free(vgroupHash, NULL, NULL);
792 BLI_ghash_free(boneHash, NULL, NULL);
797 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
798 vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
800 /* add vertices which exist in vertexgroups into vertHash for filtering */
801 for (i = 0; i < maxVerts; i++)
803 MDeformWeight *def_weight = NULL;
806 for (j= 0; j < dvert[i].totweight; j++)
808 if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr)))
810 def_weight = &dvert[i].dw[j];
815 /* check if include vert in vertHash */
816 if (mmd->flag & MOD_MASK_INV) {
817 /* if this vert is in the vgroup, don't include it in vertHash */
818 if (def_weight) continue;
821 /* if this vert isn't in the vgroup, don't include it in vertHash */
822 if (!def_weight) continue;
825 /* add to ghash for verts (numVerts acts as counter for mapping) */
826 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
830 /* free temp hashes */
831 BLI_ghash_free(vgroupHash, NULL, NULL);
832 BLI_ghash_free(boneHash, NULL, NULL);
834 else /* --- Using Nominated VertexGroup only --- */
836 int defgrp_index = -1;
838 /* get index of vertex group */
843 /* find index by comparing names - SLOW... */
844 for (i = 0, def = ob->defbase.first; def; def = def->next, i++)
846 if (!strcmp(def->name, mmd->vgroup))
855 if (defgrp_index >= 0)
856 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
858 /* if no vgroup (i.e. dverts) found, return the initial mesh */
859 if ((defgrp_index < 0) || (dvert == NULL))
862 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
863 vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
865 /* add vertices which exist in vertexgroup into ghash for filtering */
866 for (i = 0; i < maxVerts; i++)
868 MDeformWeight *def_weight = NULL;
871 for (j= 0; j < dvert[i].totweight; j++)
873 if (dvert[i].dw[j].def_nr == defgrp_index)
875 def_weight = &dvert[i].dw[j];
880 /* check if include vert in vertHash */
881 if (mmd->flag & MOD_MASK_INV) {
882 /* if this vert is in the vgroup, don't include it in vertHash */
883 if (def_weight) continue;
886 /* if this vert isn't in the vgroup, don't include it in vertHash */
887 if (!def_weight) continue;
890 /* add to ghash for verts (numVerts acts as counter for mapping) */
891 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
896 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
897 edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
898 faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
900 /* loop over edges and faces, and do the same thing to
901 * ensure that they only reference existing verts
903 for (i = 0; i < maxEdges; i++)
906 dm->getEdge(dm, i, &me);
908 /* only add if both verts will be in new mesh */
909 if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
910 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) )
912 BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
916 for (i = 0; i < maxFaces; i++)
919 dm->getFace(dm, i, &mf);
921 /* all verts must be available */
922 if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
923 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) &&
924 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) &&
925 (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) )
927 BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces));
933 /* now we know the number of verts, edges and faces,
934 * we can create the new (reduced) mesh
936 result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
939 /* using ghash-iterators, map data into new mesh */
941 for ( hashIter = BLI_ghashIterator_new(vertHash);
942 !BLI_ghashIterator_isDone(hashIter);
943 BLI_ghashIterator_step(hashIter) )
947 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
948 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
950 dm->getVert(dm, oldIndex, &source);
951 dest = CDDM_get_vert(result, newIndex);
953 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
956 BLI_ghashIterator_free(hashIter);
959 for ( hashIter = BLI_ghashIterator_new(edgeHash);
960 !BLI_ghashIterator_isDone(hashIter);
961 BLI_ghashIterator_step(hashIter) )
965 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
966 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
968 dm->getEdge(dm, oldIndex, &source);
969 dest = CDDM_get_edge(result, newIndex);
971 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
972 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
974 DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
977 BLI_ghashIterator_free(hashIter);
980 for ( hashIter = BLI_ghashIterator_new(faceHash);
981 !BLI_ghashIterator_isDone(hashIter);
982 BLI_ghashIterator_step(hashIter) )
986 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
987 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
990 dm->getFace(dm, oldIndex, &source);
991 dest = CDDM_get_face(result, newIndex);
995 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
996 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
997 source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
999 source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
1001 DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
1004 test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
1006 BLI_ghashIterator_free(hashIter);
1008 /* recalculate normals */
1009 CDDM_calc_normals(result);
1012 BLI_ghash_free(vertHash, NULL, NULL);
1013 BLI_ghash_free(edgeHash, NULL, NULL);
1014 BLI_ghash_free(faceHash, NULL, NULL);
1016 /* return the new mesh */
1021 /* Array modifier: duplicates the object multiple times along an axis
1024 static void arrayModifier_initData(ModifierData *md)
1026 ArrayModifierData *amd = (ArrayModifierData*) md;
1028 /* default to 2 duplicates distributed along the x-axis by an
1029 offset of 1 object-width
1031 amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
1033 amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
1035 amd->scale[1] = amd->scale[2] = 0;
1037 amd->merge_dist = 0.01;
1038 amd->fit_type = MOD_ARR_FIXEDCOUNT;
1039 amd->offset_type = MOD_ARR_OFF_RELATIVE;
1043 static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
1045 ArrayModifierData *amd = (ArrayModifierData*) md;
1046 ArrayModifierData *tamd = (ArrayModifierData*) target;
1048 tamd->start_cap = amd->start_cap;
1049 tamd->end_cap = amd->end_cap;
1050 tamd->curve_ob = amd->curve_ob;
1051 tamd->offset_ob = amd->offset_ob;
1052 tamd->count = amd->count;
1053 VECCOPY(tamd->offset, amd->offset);
1054 VECCOPY(tamd->scale, amd->scale);
1055 tamd->length = amd->length;
1056 tamd->merge_dist = amd->merge_dist;
1057 tamd->fit_type = amd->fit_type;
1058 tamd->offset_type = amd->offset_type;
1059 tamd->flags = amd->flags;
1062 static void arrayModifier_foreachObjectLink(
1063 ModifierData *md, Object *ob,
1064 void (*walk)(void *userData, Object *ob, Object **obpoin),
1067 ArrayModifierData *amd = (ArrayModifierData*) md;
1069 walk(userData, ob, &amd->start_cap);
1070 walk(userData, ob, &amd->end_cap);
1071 walk(userData, ob, &amd->curve_ob);
1072 walk(userData, ob, &amd->offset_ob);
1075 static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
1076 Object *ob, DagNode *obNode)
1078 ArrayModifierData *amd = (ArrayModifierData*) md;
1080 if (amd->start_cap) {
1081 DagNode *curNode = dag_get_node(forest, amd->start_cap);
1083 dag_add_relation(forest, curNode, obNode,
1084 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
1087 DagNode *curNode = dag_get_node(forest, amd->end_cap);
1089 dag_add_relation(forest, curNode, obNode,
1090 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
1092 if (amd->curve_ob) {
1093 DagNode *curNode = dag_get_node(forest, amd->curve_ob);
1095 dag_add_relation(forest, curNode, obNode,
1096 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
1098 if (amd->offset_ob) {
1099 DagNode *curNode = dag_get_node(forest, amd->offset_ob);
1101 dag_add_relation(forest, curNode, obNode,
1102 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
1106 float vertarray_size(MVert *mvert, int numVerts, int axis)
1109 float min_co, max_co;
1111 /* if there are no vertices, width is 0 */
1112 if(numVerts == 0) return 0;
1114 /* find the minimum and maximum coordinates on the desired axis */
1115 min_co = max_co = mvert->co[axis];
1117 for(i = 1; i < numVerts; ++i, ++mvert) {
1118 if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
1119 if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
1122 return max_co - min_co;
1125 typedef struct IndexMapEntry {
1126 /* the new vert index that this old vert index maps to */
1128 /* -1 if this vert isn't merged, otherwise the old vert index it
1129 * should be replaced with
1132 /* 1 if this vert's first copy is merged with the last copy of its
1133 * merge target, otherwise 0
1138 /* indexMap - an array of IndexMap entries
1139 * oldIndex - the old index to map
1140 * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
1142 static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
1144 if(indexMap[oldIndex].merge < 0) {
1145 /* vert wasn't merged, so use copy of this vert */
1146 return indexMap[oldIndex].new + copyNum;
1147 } else if(indexMap[oldIndex].merge == oldIndex) {
1148 /* vert was merged with itself */
1149 return indexMap[oldIndex].new;
1151 /* vert was merged with another vert */
1152 /* follow the chain of merges to the end, or until we've passed
1153 * a number of vertices equal to the copy number
1156 return indexMap[oldIndex].new;
1158 return calc_mapping(indexMap, indexMap[oldIndex].merge,
1163 static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
1164 Scene *scene, Object *ob, DerivedMesh *dm,
1170 float final_offset[4][4];
1171 float tmp_mat[4][4];
1172 float length = amd->length;
1173 int count = amd->count;
1174 int numVerts, numEdges, numFaces;
1175 int maxVerts, maxEdges, maxFaces;
1176 int finalVerts, finalEdges, finalFaces;
1177 DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
1178 MVert *mvert, *src_mvert;
1182 IndexMapEntry *indexMap;
1186 /* need to avoid infinite recursion here */
1187 if(amd->start_cap && amd->start_cap != ob)
1188 start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
1189 if(amd->end_cap && amd->end_cap != ob)
1190 end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
1192 MTC_Mat4One(offset);
1194 indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
1197 src_mvert = dm->getVertArray(dm);
1199 maxVerts = dm->getNumVerts(dm);
1201 if(amd->offset_type & MOD_ARR_OFF_CONST)
1202 VecAddf(offset[3], offset[3], amd->offset);
1203 if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
1204 for(j = 0; j < 3; j++)
1205 offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
1209 if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
1211 float result_mat[4][4];
1214 MTC_Mat4Invert(obinv, ob->obmat);
1218 MTC_Mat4MulSerie(result_mat, offset,
1219 obinv, amd->offset_ob->obmat,
1220 NULL, NULL, NULL, NULL, NULL);
1221 MTC_Mat4CpyMat4(offset, result_mat);
1224 if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
1225 Curve *cu = amd->curve_ob->data;
1227 float tmp_mat[3][3];
1230 object_to_mat3(amd->curve_ob, tmp_mat);
1231 scale = Mat3ToScalef(tmp_mat);
1234 cu->flag |= CU_PATH; // needed for path & bevlist
1235 makeDispListCurveTypes(scene, amd->curve_ob, 0);
1238 length = scale*cu->path->totdist;
1242 /* calculate the maximum number of copies which will fit within the
1243 prescribed length */
1244 if(amd->fit_type == MOD_ARR_FITLENGTH
1245 || amd->fit_type == MOD_ARR_FITCURVE) {
1246 float dist = sqrt(MTC_dot3Float(offset[3], offset[3]));
1249 /* this gives length = first copy start to last copy end
1250 add a tiny offset for floating point rounding errors */
1251 count = (length + 1e-6f) / dist;
1253 /* if the offset has no translation, just make one copy */
1260 /* allocate memory for count duplicates (including original) plus
1261 * start and end caps
1263 finalVerts = dm->getNumVerts(dm) * count;
1264 finalEdges = dm->getNumEdges(dm) * count;
1265 finalFaces = dm->getNumFaces(dm) * count;
1267 finalVerts += start_cap->getNumVerts(start_cap);
1268 finalEdges += start_cap->getNumEdges(start_cap);
1269 finalFaces += start_cap->getNumFaces(start_cap);
1272 finalVerts += end_cap->getNumVerts(end_cap);
1273 finalEdges += end_cap->getNumEdges(end_cap);
1274 finalFaces += end_cap->getNumFaces(end_cap);
1276 result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
1278 /* calculate the offset matrix of the final copy (for merging) */
1279 MTC_Mat4One(final_offset);
1281 for(j=0; j < count - 1; j++) {
1282 MTC_Mat4MulMat4(tmp_mat, final_offset, offset);
1283 MTC_Mat4CpyMat4(final_offset, tmp_mat);
1286 numVerts = numEdges = numFaces = 0;
1287 mvert = CDDM_get_verts(result);
1289 for (i = 0; i < maxVerts; i++) {
1290 indexMap[i].merge = -1; /* default to no merge */
1291 indexMap[i].merge_final = 0; /* default to no merge */
1294 for (i = 0; i < maxVerts; i++) {
1296 MVert *mv = &mvert[numVerts];
1300 inMV = &src_mvert[i];
1302 DM_copy_vert_data(dm, result, i, numVerts, 1);
1306 indexMap[i].new = numVerts - 1;
1308 VECCOPY(co, mv->co);
1310 /* Attempts to merge verts from one duplicate with verts from the
1311 * next duplicate which are closer than amd->merge_dist.
1312 * Only the first such vert pair is merged.
1313 * If verts are merged in the first duplicate pair, they are merged
1316 if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
1318 VECCOPY(tmp_co, mv->co);
1319 MTC_Mat4MulVecfl(offset, tmp_co);
1321 for(j = 0; j < maxVerts; j++) {
1322 /* if vertex already merged, don't use it */
1323 if( indexMap[j].merge != -1 ) continue;
1325 inMV = &src_mvert[j];
1326 /* if this vert is within merge limit, merge */
1327 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) {
1328 indexMap[i].merge = j;
1330 /* test for merging with final copy of merge target */
1331 if(amd->flags & MOD_ARR_MERGEFINAL) {
1332 VECCOPY(tmp_co, inMV->co);
1333 inMV = &src_mvert[i];
1334 MTC_Mat4MulVecfl(final_offset, tmp_co);
1335 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist))
1336 indexMap[i].merge_final = 1;
1343 /* if no merging, generate copies of this vert */
1344 if(indexMap[i].merge < 0) {
1345 for(j=0; j < count - 1; j++) {
1346 mv2 = &mvert[numVerts];
1348 DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
1352 MTC_Mat4MulVecfl(offset, co);
1353 VECCOPY(mv2->co, co);
1355 } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
1356 /* if this vert is not merging with itself, and it is merging
1357 * with the final copy of its merge target, remove the first copy
1360 DM_free_vert_data(result, numVerts, 1);
1364 /* make a hashtable so we can avoid duplicate edges from merging */
1365 edges = BLI_edgehash_new();
1367 maxEdges = dm->getNumEdges(dm);
1368 medge = CDDM_get_edges(result);
1369 for(i = 0; i < maxEdges; i++) {
1375 dm->getEdge(dm, i, &inMED);
1378 med.v1 = indexMap[inMED.v1].new;
1379 med.v2 = indexMap[inMED.v2].new;
1381 /* if vertices are to be merged with the final copies of their
1382 * merge targets, calculate that final copy
1384 if(indexMap[inMED.v1].merge_final) {
1385 med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
1388 if(indexMap[inMED.v2].merge_final) {
1389 med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
1393 if(med.v1 == med.v2) continue;
1396 med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
1399 if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
1400 DM_copy_edge_data(dm, result, i, numEdges, 1);
1401 medge[numEdges] = med;
1404 BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
1407 for(j = 1; j < count; j++)
1409 vert1 = calc_mapping(indexMap, inMED.v1, j);
1410 vert2 = calc_mapping(indexMap, inMED.v2, j);
1411 /* avoid duplicate edges */
1412 if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
1413 med2 = &medge[numEdges];
1415 DM_copy_edge_data(dm, result, i, numEdges, 1);
1422 BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
1427 maxFaces = dm->getNumFaces(dm);
1428 mface = CDDM_get_faces(result);
1429 for (i=0; i < maxFaces; i++) {
1431 MFace *mf = &mface[numFaces];
1433 dm->getFace(dm, i, &inMF);
1435 DM_copy_face_data(dm, result, i, numFaces, 1);
1438 mf->v1 = indexMap[inMF.v1].new;
1439 mf->v2 = indexMap[inMF.v2].new;
1440 mf->v3 = indexMap[inMF.v3].new;
1442 mf->v4 = indexMap[inMF.v4].new;
1444 /* if vertices are to be merged with the final copies of their
1445 * merge targets, calculate that final copy
1447 if(indexMap[inMF.v1].merge_final)
1448 mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
1449 if(indexMap[inMF.v2].merge_final)
1450 mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
1451 if(indexMap[inMF.v3].merge_final)
1452 mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
1453 if(inMF.v4 && indexMap[inMF.v4].merge_final)
1454 mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
1456 if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3)
1461 /* if the face has fewer than 3 vertices, don't create it */
1462 if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
1464 DM_free_face_data(result, numFaces, 1);
1467 for(j = 1; j < count; j++)
1469 MFace *mf2 = &mface[numFaces];
1471 DM_copy_face_data(dm, result, i, numFaces, 1);
1474 mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
1475 mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
1476 mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
1478 mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
1480 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
1483 /* if the face has fewer than 3 vertices, don't create it */
1484 if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 ==
1487 DM_free_face_data(result, numFaces, 1);
1492 /* add start and end caps */
1494 float startoffset[4][4];
1500 int capVerts, capEdges, capFaces;
1502 capVerts = start_cap->getNumVerts(start_cap);
1503 capEdges = start_cap->getNumEdges(start_cap);
1504 capFaces = start_cap->getNumFaces(start_cap);
1505 cap_mvert = start_cap->getVertArray(start_cap);
1506 cap_medge = start_cap->getEdgeArray(start_cap);
1507 cap_mface = start_cap->getFaceArray(start_cap);
1509 Mat4Invert(startoffset, offset);
1511 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1512 "arrayModifier_doArray vert_map");
1514 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1515 for(i = 0; i < capVerts; i++) {
1516 MVert *mv = &cap_mvert[i];
1519 if(amd->flags & MOD_ARR_MERGE) {
1524 VECCOPY(tmp_co, mv->co);
1525 Mat4MulVecfl(startoffset, tmp_co);
1527 for(j = 0; j < maxVerts; j++) {
1528 in_mv = &src_mvert[j];
1529 /* if this vert is within merge limit, merge */
1530 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1531 vert_map[i] = calc_mapping(indexMap, j, 0);
1539 DM_copy_vert_data(start_cap, result, i, numVerts, 1);
1540 mvert[numVerts] = *mv;
1541 Mat4MulVecfl(startoffset, mvert[numVerts].co);
1542 origindex[numVerts] = ORIGINDEX_NONE;
1544 vert_map[i] = numVerts;
1549 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1550 for(i = 0; i < capEdges; i++) {
1553 v1 = vert_map[cap_medge[i].v1];
1554 v2 = vert_map[cap_medge[i].v2];
1556 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1557 DM_copy_edge_data(start_cap, result, i, numEdges, 1);
1558 medge[numEdges] = cap_medge[i];
1559 medge[numEdges].v1 = v1;
1560 medge[numEdges].v2 = v2;
1561 origindex[numEdges] = ORIGINDEX_NONE;
1566 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1567 for(i = 0; i < capFaces; i++) {
1568 DM_copy_face_data(start_cap, result, i, numFaces, 1);
1569 mface[numFaces] = cap_mface[i];
1570 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1571 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1572 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1573 if(mface[numFaces].v4) {
1574 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1576 test_index_face(&mface[numFaces], &result->faceData,
1581 test_index_face(&mface[numFaces], &result->faceData,
1585 origindex[numFaces] = ORIGINDEX_NONE;
1590 MEM_freeN(vert_map);
1591 start_cap->release(start_cap);
1595 float endoffset[4][4];
1601 int capVerts, capEdges, capFaces;
1603 capVerts = end_cap->getNumVerts(end_cap);
1604 capEdges = end_cap->getNumEdges(end_cap);
1605 capFaces = end_cap->getNumFaces(end_cap);
1606 cap_mvert = end_cap->getVertArray(end_cap);
1607 cap_medge = end_cap->getEdgeArray(end_cap);
1608 cap_mface = end_cap->getFaceArray(end_cap);
1610 Mat4MulMat4(endoffset, final_offset, offset);
1612 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1613 "arrayModifier_doArray vert_map");
1615 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1616 for(i = 0; i < capVerts; i++) {
1617 MVert *mv = &cap_mvert[i];
1620 if(amd->flags & MOD_ARR_MERGE) {
1625 VECCOPY(tmp_co, mv->co);
1626 Mat4MulVecfl(offset, tmp_co);
1628 for(j = 0; j < maxVerts; j++) {
1629 in_mv = &src_mvert[j];
1630 /* if this vert is within merge limit, merge */
1631 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1632 vert_map[i] = calc_mapping(indexMap, j, count - 1);
1640 DM_copy_vert_data(end_cap, result, i, numVerts, 1);
1641 mvert[numVerts] = *mv;
1642 Mat4MulVecfl(endoffset, mvert[numVerts].co);
1643 origindex[numVerts] = ORIGINDEX_NONE;
1645 vert_map[i] = numVerts;
1650 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1651 for(i = 0; i < capEdges; i++) {
1654 v1 = vert_map[cap_medge[i].v1];
1655 v2 = vert_map[cap_medge[i].v2];
1657 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1658 DM_copy_edge_data(end_cap, result, i, numEdges, 1);
1659 medge[numEdges] = cap_medge[i];
1660 medge[numEdges].v1 = v1;
1661 medge[numEdges].v2 = v2;
1662 origindex[numEdges] = ORIGINDEX_NONE;
1667 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1668 for(i = 0; i < capFaces; i++) {
1669 DM_copy_face_data(end_cap, result, i, numFaces, 1);
1670 mface[numFaces] = cap_mface[i];
1671 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1672 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1673 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1674 if(mface[numFaces].v4) {
1675 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1677 test_index_face(&mface[numFaces], &result->faceData,
1682 test_index_face(&mface[numFaces], &result->faceData,
1685 origindex[numFaces] = ORIGINDEX_NONE;
1690 MEM_freeN(vert_map);
1691 end_cap->release(end_cap);
1694 BLI_edgehash_free(edges, NULL);
1695 MEM_freeN(indexMap);
1697 CDDM_lower_num_verts(result, numVerts);
1698 CDDM_lower_num_edges(result, numEdges);
1699 CDDM_lower_num_faces(result, numFaces);
1704 static DerivedMesh *arrayModifier_applyModifier(
1705 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1706 int useRenderParams, int isFinalCalc)
1708 DerivedMesh *result;
1709 ArrayModifierData *amd = (ArrayModifierData*) md;
1711 result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
1713 if(result != derivedData)
1714 CDDM_calc_normals(result);
1719 static DerivedMesh *arrayModifier_applyModifierEM(
1720 ModifierData *md, Object *ob, EditMesh *editData,
1721 DerivedMesh *derivedData)
1723 return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
1728 static void mirrorModifier_initData(ModifierData *md)
1730 MirrorModifierData *mmd = (MirrorModifierData*) md;
1732 mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
1733 mmd->tolerance = 0.001;
1734 mmd->mirror_ob = NULL;
1737 static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
1739 MirrorModifierData *mmd = (MirrorModifierData*) md;
1740 MirrorModifierData *tmmd = (MirrorModifierData*) target;
1742 tmmd->axis = mmd->axis;
1743 tmmd->flag = mmd->flag;
1744 tmmd->tolerance = mmd->tolerance;
1745 tmmd->mirror_ob = mmd->mirror_ob;;
1748 static void mirrorModifier_foreachObjectLink(
1749 ModifierData *md, Object *ob,
1750 void (*walk)(void *userData, Object *ob, Object **obpoin),
1753 MirrorModifierData *mmd = (MirrorModifierData*) md;
1755 walk(userData, ob, &mmd->mirror_ob);
1758 static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
1759 Object *ob, DagNode *obNode)
1761 MirrorModifierData *mmd = (MirrorModifierData*) md;
1763 if(mmd->mirror_ob) {
1764 DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
1766 dag_add_relation(forest, latNode, obNode,
1767 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
1771 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
1772 /* if strip_number: removes number extensions */
1773 void vertgroup_flip_name (char *name, int strip_number)
1776 char prefix[128]={""}; /* The part before the facing */
1777 char suffix[128]={""}; /* The part after the facing */
1778 char replace[128]={""}; /* The replacement string */
1779 char number[128]={""}; /* The number extension string */
1783 if(len<3) return; // we don't do names like .R or .L
1785 /* We first check the case with a .### extension, let's find the last period */
1786 if(isdigit(name[len-1])) {
1787 index= strrchr(name, '.'); // last occurrance
1788 if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
1790 strcpy(number, index);
1796 strcpy (prefix, name);
1798 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
1800 /* first case; separator . - _ with extensions r R l L */
1801 if( IS_SEPARATOR(name[len-2]) ) {
1802 switch(name[len-1]) {
1805 strcpy(replace, "r");
1809 strcpy(replace, "l");
1813 strcpy(replace, "R");
1817 strcpy(replace, "L");
1821 /* case; beginning with r R l L , with separator after it */
1822 else if( IS_SEPARATOR(name[1]) ) {
1825 strcpy(replace, "r");
1826 strcpy(suffix, name+1);
1830 strcpy(replace, "l");
1831 strcpy(suffix, name+1);
1835 strcpy(replace, "R");
1836 strcpy(suffix, name+1);
1840 strcpy(replace, "L");
1841 strcpy(suffix, name+1);
1847 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
1848 index = BLI_strcasestr(prefix, "right");
1849 if (index==prefix || index==prefix+len-5) {
1851 strcpy (replace, "left");
1854 strcpy (replace, "LEFT");
1856 strcpy (replace, "Left");
1859 strcpy (suffix, index+5);
1862 index = BLI_strcasestr(prefix, "left");
1863 if (index==prefix || index==prefix+len-4) {
1865 strcpy (replace, "right");
1868 strcpy (replace, "RIGHT");
1870 strcpy (replace, "Right");
1873 strcpy (suffix, index+4);
1880 sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
1883 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
1890 float tolerance = mmd->tolerance;
1891 DerivedMesh *result;
1892 int numVerts, numEdges, numFaces;
1893 int maxVerts = dm->getNumVerts(dm);
1894 int maxEdges = dm->getNumEdges(dm);
1895 int maxFaces = dm->getNumFaces(dm);
1896 int vector_size=0, j, a, b;
1897 bDeformGroup *def, *defb;
1898 bDeformGroup **vector_def = NULL;
1900 float mtx[4][4], imtx[4][4];
1902 numVerts = numEdges = numFaces = 0;
1904 indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
1906 result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
1909 if (mmd->flag & MOD_MIR_VGROUP) {
1910 /* calculate the number of deformedGroups */
1911 for(vector_size = 0, def = ob->defbase.first; def;
1912 def = def->next, vector_size++);
1914 /* load the deformedGroups for fast access */
1916 (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
1918 for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
1919 vector_def[a] = def;
1923 if (mmd->mirror_ob) {
1926 Mat4Invert(obinv, mmd->mirror_ob->obmat);
1927 Mat4MulMat4(mtx, ob->obmat, obinv);
1928 Mat4Invert(imtx, mtx);
1931 for(i = 0; i < maxVerts; i++) {
1933 MVert *mv = CDDM_get_vert(result, numVerts);
1937 dm->getVert(dm, i, &inMV);
1939 VecCopyf(co, inMV.co);
1941 if (mmd->mirror_ob) {
1942 VecMat4MulVecfl(co, mtx, co);
1944 isShared = ABS(co[axis])<=tolerance;
1946 /* Because the topology result (# of vertices) must be the same if
1947 * the mesh data is overridden by vertex cos, have to calc sharedness
1948 * based on original coordinates. This is why we test before copy.
1950 DM_copy_vert_data(dm, result, i, numVerts, 1);
1954 indexMap[i][0] = numVerts - 1;
1955 indexMap[i][1] = !isShared;
1959 if (mmd->mirror_ob) {
1960 VecMat4MulVecfl(co, imtx, co);
1962 VecCopyf(mv->co, co);
1964 mv->flag |= ME_VERT_MERGED;
1966 MVert *mv2 = CDDM_get_vert(result, numVerts);
1967 MDeformVert *dvert = NULL;
1969 DM_copy_vert_data(dm, result, i, numVerts, 1);
1972 co[axis] = -co[axis];
1973 if (mmd->mirror_ob) {
1974 VecMat4MulVecfl(co, imtx, co);
1976 VecCopyf(mv2->co, co);
1978 if (mmd->flag & MOD_MIR_VGROUP){
1979 dvert = DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
1983 for(j = 0; j < dvert[0].totweight; ++j)
1987 if(dvert->dw[j].def_nr < 0 ||
1988 dvert->dw[j].def_nr >= vector_size)
1991 def = vector_def[dvert->dw[j].def_nr];
1992 strcpy(tmpname, def->name);
1993 vertgroup_flip_name(tmpname,0);
1995 for(b = 0, defb = ob->defbase.first; defb;
1996 defb = defb->next, b++)
1998 if(!strcmp(defb->name, tmpname))
2000 dvert->dw[j].def_nr = b;
2012 for(i = 0; i < maxEdges; i++) {
2014 MEdge *med = CDDM_get_edge(result, numEdges);
2016 dm->getEdge(dm, i, &inMED);
2018 DM_copy_edge_data(dm, result, i, numEdges, 1);
2022 med->v1 = indexMap[inMED.v1][0];
2023 med->v2 = indexMap[inMED.v2][0];
2025 med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
2027 if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
2028 MEdge *med2 = CDDM_get_edge(result, numEdges);
2030 DM_copy_edge_data(dm, result, i, numEdges, 1);
2034 med2->v1 += indexMap[inMED.v1][1];
2035 med2->v2 += indexMap[inMED.v2][1];
2039 for(i = 0; i < maxFaces; i++) {
2041 MFace *mf = CDDM_get_face(result, numFaces);
2043 dm->getFace(dm, i, &inMF);
2045 DM_copy_face_data(dm, result, i, numFaces, 1);
2049 mf->v1 = indexMap[inMF.v1][0];
2050 mf->v2 = indexMap[inMF.v2][0];
2051 mf->v3 = indexMap[inMF.v3][0];
2052 mf->v4 = indexMap[inMF.v4][0];
2054 if(indexMap[inMF.v1][1]
2055 || indexMap[inMF.v2][1]
2056 || indexMap[inMF.v3][1]
2057 || (mf->v4 && indexMap[inMF.v4][1])) {
2058 MFace *mf2 = CDDM_get_face(result, numFaces);
2059 static int corner_indices[4] = {2, 1, 0, 3};
2061 DM_copy_face_data(dm, result, i, numFaces, 1);
2064 mf2->v1 += indexMap[inMF.v1][1];
2065 mf2->v2 += indexMap[inMF.v2][1];
2066 mf2->v3 += indexMap[inMF.v3][1];
2067 if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
2069 /* mirror UVs if enabled */
2070 if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
2071 MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
2074 for(j = 0; j < 4; ++j) {
2075 if(mmd->flag & MOD_MIR_MIRROR_U)
2076 tf->uv[j][0] = 1.0f - tf->uv[j][0];
2077 if(mmd->flag & MOD_MIR_MIRROR_V)
2078 tf->uv[j][1] = 1.0f - tf->uv[j][1];
2083 /* Flip face normal */
2084 SWAP(int, mf2->v1, mf2->v3);
2085 DM_swap_face_data(result, numFaces, corner_indices);
2087 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
2092 if (vector_def) MEM_freeN(vector_def);
2094 MEM_freeN(indexMap);
2096 CDDM_lower_num_verts(result, numVerts);
2097 CDDM_lower_num_edges(result, numEdges);
2098 CDDM_lower_num_faces(result, numFaces);
2103 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
2104 Object *ob, DerivedMesh *dm,
2107 DerivedMesh *result = dm;
2109 /* check which axes have been toggled and mirror accordingly */
2110 if(mmd->flag & MOD_MIR_AXIS_X) {
2111 result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
2113 if(mmd->flag & MOD_MIR_AXIS_Y) {
2114 DerivedMesh *tmp = result;
2115 result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
2116 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
2118 if(mmd->flag & MOD_MIR_AXIS_Z) {
2119 DerivedMesh *tmp = result;
2120 result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
2121 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
2127 static DerivedMesh *mirrorModifier_applyModifier(
2128 ModifierData *md, Object *ob, DerivedMesh *derivedData,
2129 int useRenderParams, int isFinalCalc)
2131 DerivedMesh *result;
2132 MirrorModifierData *mmd = (MirrorModifierData*) md;
2134 result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
2136 if(result != derivedData)
2137 CDDM_calc_normals(result);
2142 static DerivedMesh *mirrorModifier_applyModifierEM(
2143 ModifierData *md, Object *ob, EditMesh *editData,
2144 DerivedMesh *derivedData)
2146 return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
2150 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
2151 * or edge angle (can be used to achieve autosmoothing)
2154 #define EDGESPLIT_DEBUG_3
2155 #define EDGESPLIT_DEBUG_2
2156 #define EDGESPLIT_DEBUG_1
2157 #define EDGESPLIT_DEBUG_0
2160 static void edgesplitModifier_initData(ModifierData *md)
2162 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2164 /* default to 30-degree split angle, sharpness from both angle & flag
2166 emd->split_angle = 30;
2167 emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
2170 static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
2172 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2173 EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
2175 temd->split_angle = emd->split_angle;
2176 temd->flags = emd->flags;
2179 /* Mesh data for edgesplit operation */
2180 typedef struct SmoothVert {
2181 LinkNode *faces; /* all faces which use this vert */
2182 int oldIndex; /* the index of the original DerivedMesh vert */
2183 int newIndex; /* the index of the new DerivedMesh vert */
2186 #define SMOOTHEDGE_NUM_VERTS 2
2188 typedef struct SmoothEdge {
2189 SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
2190 LinkNode *faces; /* all faces which use this edge */
2191 int oldIndex; /* the index of the original DerivedMesh edge */
2192 int newIndex; /* the index of the new DerivedMesh edge */
2193 short flag; /* the flags from the original DerivedMesh edge */
2196 #define SMOOTHFACE_MAX_EDGES 4
2198 typedef struct SmoothFace {
2199 SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
2200 int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
2201 float normal[3]; /* the normal of this face */
2202 int oldIndex; /* the index of the original DerivedMesh face */
2203 int newIndex; /* the index of the new DerivedMesh face */
2206 typedef struct SmoothMesh {
2210 int num_verts, num_edges, num_faces;
2211 int max_verts, max_edges, max_faces;
2213 float threshold; /* the cosine of the smoothing angle */
2216 ListBase propagatestack, reusestack;
2219 static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
2221 SmoothVert *copy = &mesh->verts[mesh->num_verts];
2223 if(mesh->num_verts >= mesh->max_verts) {
2224 printf("Attempted to add a SmoothMesh vert beyond end of array\n");
2230 copy->newIndex = mesh->num_verts;
2233 #ifdef EDGESPLIT_DEBUG_2
2234 printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
2239 static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
2241 SmoothEdge *copy = &mesh->edges[mesh->num_edges];
2243 if(mesh->num_edges >= mesh->max_edges) {
2244 printf("Attempted to add a SmoothMesh edge beyond end of array\n");
2250 copy->newIndex = mesh->num_edges;
2253 #ifdef EDGESPLIT_DEBUG_2
2254 printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
2259 static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
2262 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
2263 if(edge->verts[i] == vert) return 1;
2268 static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
2269 int max_verts, int max_edges, int max_faces)
2271 SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
2272 mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
2273 "SmoothMesh.verts");
2274 mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
2275 "SmoothMesh.edges");
2276 mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
2277 "SmoothMesh.faces");
2279 mesh->num_verts = num_verts;
2280 mesh->num_edges = num_edges;
2281 mesh->num_faces = num_faces;
2283 mesh->max_verts = max_verts;
2284 mesh->max_edges = max_edges;
2285 mesh->max_faces = max_faces;
2290 static void smoothmesh_free(SmoothMesh *mesh)
2294 for(i = 0; i < mesh->num_verts; ++i)
2295 BLI_linklist_free(mesh->verts[i].faces, NULL);
2297 for(i = 0; i < mesh->num_edges; ++i)
2298 BLI_linklist_free(mesh->edges[i].faces, NULL);
2301 BLI_memarena_free(mesh->arena);
2303 MEM_freeN(mesh->verts);
2304 MEM_freeN(mesh->edges);
2305 MEM_freeN(mesh->faces);
2309 static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
2314 if(max_verts <= mesh->max_verts) return;
2316 tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
2318 memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
2320 /* remap vert pointers in edges */
2321 for(i = 0; i < mesh->num_edges; ++i) {
2323 SmoothEdge *edge = &mesh->edges[i];
2325 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
2326 /* pointer arithmetic to get vert array index */
2327 edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
2330 MEM_freeN(mesh->verts);
2332 mesh->max_verts = max_verts;
2335 static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
2340 if(max_edges <= mesh->max_edges) return;
2342 tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
2344 memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
2346 /* remap edge pointers in faces */
2347 for(i = 0; i < mesh->num_faces; ++i) {
2349 SmoothFace *face = &mesh->faces[i];
2351 for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
2353 /* pointer arithmetic to get edge array index */
2354 face->edges[j] = &tmp[face->edges[j] - mesh->edges];
2357 MEM_freeN(mesh->edges);
2359 mesh->max_edges = max_edges;
2362 #ifdef EDGESPLIT_DEBUG_0
2363 static void smoothmesh_print(SmoothMesh *mesh)
2366 DerivedMesh *dm = mesh->dm;
2368 printf("--- SmoothMesh ---\n");
2369 printf("--- Vertices ---\n");
2370 for(i = 0; i < mesh->num_verts; i++) {
2371 SmoothVert *vert = &mesh->verts[i];
2375 dm->getVert(dm, vert->oldIndex, &mv);
2377 printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
2378 i, vert->oldIndex, vert->newIndex,
2379 mv.co[0], mv.co[1], mv.co[2]);
2380 printf(", faces={");
2381 for(node = vert->faces; node != NULL; node = node->next) {
2382 printf(" %d", ((SmoothFace *)node->link)->newIndex);
2387 printf("\n--- Edges ---\n");
2388 for(i = 0; i < mesh->num_edges; i++) {
2389 SmoothEdge *edge = &mesh->edges[i];
2392 printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
2394 edge->oldIndex, edge->newIndex,
2395 edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2396 if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
2397 printf(", faces={");
2398 for(node = edge->faces; node != NULL; node = node->next) {
2399 printf(" %d", ((SmoothFace *)node->link)->newIndex);
2404 printf("\n--- Faces ---\n");
2405 for(i = 0; i < mesh->num_faces; i++) {
2406 SmoothFace *face = &mesh->faces[i];
2408 printf("%4d: indices={%4d, %4d}, edges={", i,
2409 face->oldIndex, face->newIndex);
2410 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2412 printf(" -%-2d", face->edges[j]->newIndex);
2414 printf(" %-2d", face->edges[j]->newIndex);
2416 printf("}, verts={");
2417 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2418 printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
2425 static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
2428 EdgeHash *edges = BLI_edgehash_new();
2430 int totvert, totedge, totface;
2432 totvert = dm->getNumVerts(dm);
2433 totedge = dm->getNumEdges(dm);
2434 totface = dm->getNumFaces(dm);
2436 mesh = smoothmesh_new(totvert, totedge, totface,
2437 totvert, totedge, totface);
2441 for(i = 0; i < totvert; i++) {
2442 SmoothVert *vert = &mesh->verts[i];
2444 vert->oldIndex = vert->newIndex = i;
2447 for(i = 0; i < totedge; i++) {
2448 SmoothEdge *edge = &mesh->edges[i];
2451 dm->getEdge(dm, i, &med);
2452 edge->verts[0] = &mesh->verts[med.v1];
2453 edge->verts[1] = &mesh->verts[med.v2];
2454 edge->oldIndex = edge->newIndex = i;
2455 edge->flag = med.flag;
2457 BLI_edgehash_insert(edges, med.v1, med.v2, edge);
2460 for(i = 0; i < totface; i++) {
2461 SmoothFace *face = &mesh->faces[i];
2466 dm->getFace(dm, i, &mf);
2468 dm->getVert(dm, mf.v1, &v1);
2469 dm->getVert(dm, mf.v2, &v2);
2470 dm->getVert(dm, mf.v3, &v3);
2471 face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
2472 if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
2473 face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
2474 if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
2477 dm->getVert(dm, mf.v4, &v4);
2478 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
2479 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
2480 face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
2481 if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
2482 CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
2484 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
2485 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
2486 face->edges[3] = NULL;
2487 CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
2490 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2491 SmoothEdge *edge = face->edges[j];
2492 BLI_linklist_prepend(&edge->faces, face);
2493 BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
2496 face->oldIndex = face->newIndex = i;
2499 BLI_edgehash_free(edges, NULL);
2504 static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
2506 DerivedMesh *result = CDDM_from_template(mesh->dm,
2510 MVert *new_verts = CDDM_get_verts(result);
2511 MEdge *new_edges = CDDM_get_edges(result);
2512 MFace *new_faces = CDDM_get_faces(result);
2515 for(i = 0; i < mesh->num_verts; ++i) {
2516 SmoothVert *vert = &mesh->verts[i];
2517 MVert *newMV = &new_verts[vert->newIndex];
2519 DM_copy_vert_data(mesh->dm, result,
2520 vert->oldIndex, vert->newIndex, 1);
2521 mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
2524 for(i = 0; i < mesh->num_edges; ++i) {
2525 SmoothEdge *edge = &mesh->edges[i];
2526 MEdge *newME = &new_edges[edge->newIndex];
2528 DM_copy_edge_data(mesh->dm, result,
2529 edge->oldIndex, edge->newIndex, 1);
2530 mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
2531 newME->v1 = edge->verts[0]->newIndex;
2532 newME->v2 = edge->verts[1]->newIndex;
2535 for(i = 0; i < mesh->num_faces; ++i) {
2536 SmoothFace *face = &mesh->faces[i];
2537 MFace *newMF = &new_faces[face->newIndex];
2539 DM_copy_face_data(mesh->dm, result,
2540 face->oldIndex, face->newIndex, 1);
2541 mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
2543 newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
2544 newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
2545 newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
2547 if(face->edges[3]) {
2548 newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
2557 /* returns the other vert in the given edge
2559 static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
2561 if(edge->verts[0] == vert) return edge->verts[1];
2562 else return edge->verts[0];
2565 /* returns the other edge in the given face that uses the given vert
2566 * returns NULL if no other edge in the given face uses the given vert
2567 * (this should never happen)
2569 static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
2573 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
2574 SmoothEdge *tmp_edge = face->edges[i];
2575 if(tmp_edge == edge) continue;
2577 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
2578 if(tmp_edge->verts[j] == vert) return tmp_edge;
2581 /* if we get to here, something's wrong (there should always be 2 edges
2582 * which use the same vert in a face)
2587 /* returns a face attached to the given edge which is not the given face.
2588 * returns NULL if no other faces use this edge.
2590 static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
2594 for(node = edge->faces; node != NULL; node = node->next)
2595 if(node->link != face) return node->link;
2601 /* copies source list to target, overwriting target (target is not freed)
2602 * nodes in the copy will be in the same order as in source
2604 static void linklist_copy(LinkNode **target, LinkNode *source)
2606 LinkNode *node = NULL;
2609 for(; source; source = source->next) {
2611 node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
2614 node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
2616 node->link = source->link;
2622 /* appends source to target if it's not already in target */
2623 static void linklist_append_unique(LinkNode **target, void *source)
2626 LinkNode *prev = NULL;
2628 /* check if source value is already in the list */
2629 for(node = *target; node; prev = node, node = node->next)
2630 if(node->link == source) return;
2632 node = MEM_mallocN(sizeof(*node), "nlink");
2634 node->link = source;
2636 if(prev) prev->next = node;
2637 else *target = node;
2640 /* appends elements of source which aren't already in target to target */
2641 static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
2643 for(; source; source = source->next)
2644 linklist_append_unique(target, source->link);
2647 #if 0 /* this is no longer used, it should possibly be removed */
2648 /* prepends prepend to list - doesn't copy nodes, just joins the lists */
2649 static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
2652 LinkNode *node = prepend;
2653 while(node->next) node = node->next;
2661 /* returns 1 if the linked list contains the given pointer, 0 otherwise
2663 static int linklist_contains(LinkNode *list, void *ptr)
2667 for(node = list; node; node = node->next)
2668 if(node->link == ptr) return 1;
2673 /* returns 1 if the first linked list is a subset of the second (comparing
2674 * pointer values), 0 if not
2676 static int linklist_subset(LinkNode *list1, LinkNode *list2)
2678 for(; list1; list1 = list1->next)
2679 if(!linklist_contains(list2, list1->link))
2686 /* empties the linked list
2687 * frees pointers with freefunc if freefunc is not NULL
2689 static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
2691 BLI_linklist_free(*list, freefunc);
2696 /* removes the first instance of value from the linked list
2697 * frees the pointer with freefunc if freefunc is not NULL
2699 static void linklist_remove_first(LinkNode **list, void *value,
2700 LinkNodeFreeFP freefunc)
2702 LinkNode *node = *list;
2703 LinkNode *prev = NULL;
2705 while(node && node->link != value) {
2712 prev->next = node->next;
2717 freefunc(node->link);
2723 /* removes all elements in source from target */
2724 static void linklist_remove_list(LinkNode **target, LinkNode *source,
2725 LinkNodeFreeFP freefunc)
2727 for(; source; source = source->next)
2728 linklist_remove_first(target, source->link, freefunc);
2731 #ifdef EDGESPLIT_DEBUG_0
2732 static void print_ptr(void *ptr)
2734 printf("%p\n", ptr);
2737 static void print_edge(void *ptr)
2739 SmoothEdge *edge = ptr;
2740 printf(" %4d", edge->newIndex);
2743 static void print_face(void *ptr)
2745 SmoothFace *face = ptr;
2746 printf(" %4d", face->newIndex);
2750 typedef struct ReplaceData {
2755 static void edge_replace_vert(void *ptr, void *userdata)
2757 SmoothEdge *edge = ptr;
2758 SmoothVert *find = ((ReplaceData *)userdata)->find;
2759 SmoothVert *replace = ((ReplaceData *)userdata)->replace;
2762 #ifdef EDGESPLIT_DEBUG_3
2763 printf("replacing vert %4d with %4d in edge %4d",
2764 find->newIndex, replace->newIndex, edge->newIndex);
2765 printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2768 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
2769 if(edge->verts[i] == find) {
2770 linklist_append_list_unique(&replace->faces, edge->faces);
2771 linklist_remove_list(&find->faces, edge->faces, NULL);
2773 edge->verts[i] = replace;
2777 #ifdef EDGESPLIT_DEBUG_3
2778 printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2782 static void face_replace_vert(void *ptr, void *userdata)
2784 SmoothFace *face = ptr;
2787 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
2788 edge_replace_vert(face->edges[i], userdata);
2791 static void face_replace_edge(void *ptr, void *userdata)
2793 SmoothFace *face = ptr;
2794 SmoothEdge *find = ((ReplaceData *)userdata)->find;
2795 SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
2798 #ifdef EDGESPLIT_DEBUG_3
2799 printf("replacing edge %4d with %4d in face %4d",
2800 find->newIndex, replace->newIndex, face->newIndex);
2802 printf(": {%2d %2d %2d %2d}",
2803 face->edges[0]->newIndex, face->edges[1]->newIndex,
2804 face->edges[2]->newIndex, face->edges[3]->newIndex);
2806 printf(": {%2d %2d %2d}",
2807 face->edges[0]->newIndex, face->edges[1]->newIndex,
2808 face->edges[2]->newIndex);
2811 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
2812 if(face->edges[i] == find) {
2813 linklist_remove_first(&face->edges[i]->faces, face, NULL);
2814 BLI_linklist_prepend(&replace->faces, face);
2815 face->edges[i] = replace;
2819 #ifdef EDGESPLIT_DEBUG_3
2821 printf(" -> {%2d %2d %2d %2d}\n",
2822 face->edges[0]->newIndex, face->edges[1]->newIndex,
2823 face->edges[2]->newIndex, face->edges[3]->newIndex);
2825 printf(" -> {%2d %2d %2d}\n",
2826 face->edges[0]->newIndex, face->edges[1]->newIndex,
2827 face->edges[2]->newIndex);
2831 static int edge_is_loose(SmoothEdge *edge)
2833 return !(edge->faces && edge->faces->next);
2836 static int edge_is_sharp(SmoothEdge *edge, int flags,
2839 #ifdef EDGESPLIT_DEBUG_1
2840 printf("edge %d: ", edge->newIndex);
2842 if(edge->flag & ME_SHARP) {
2843 /* edge can only be sharp if it has at least 2 faces */
2844 if(!edge_is_loose(edge)) {
2845 #ifdef EDGESPLIT_DEBUG_1
2850 /* edge is loose, so it can't be sharp */
2851 edge->flag &= ~ME_SHARP;
2855 #ifdef EDGESPLIT_DEBUG_1
2856 printf("not sharp\n");
2861 /* finds another sharp edge which uses vert, by traversing faces around the
2862 * vert until it does one of the following:
2863 * - hits a loose edge (the edge is returned)
2864 * - hits a sharp edge (the edge is returned)
2865 * - returns to the start edge (NULL is returned)
2867 static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
2868 LinkNode **visited_faces, float threshold, int flags)
2870 SmoothFace *face = NULL;
2871 SmoothEdge *edge2 = NULL;
2872 /* holds the edges we've seen so we can avoid looping indefinitely */
2873 LinkNode *visited_edges = NULL;
2874 #ifdef EDGESPLIT_DEBUG_1
2875 printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
2876 edge->newIndex, vert->newIndex);
2879 /* get a face on which to start */
2880 if(edge->faces) face = edge->faces->link;
2883 /* record this edge as visited */
2884 BLI_linklist_prepend(&visited_edges, edge);
2886 /* get the next edge */
2887 edge2 = other_edge(face, vert, edge);
2889 /* record this face as visited */
2891 BLI_linklist_prepend(visited_faces, face);
2893 /* search until we hit a loose edge or a sharp edge or an edge we've
2896 while(face && !edge_is_sharp(edge2, flags, threshold)
2897 && !linklist_contains(visited_edges, edge2)) {
2898 #ifdef EDGESPLIT_DEBUG_3
2899 printf("current face %4d; current edge %4d\n", face->newIndex,
2902 /* get the next face */
2903 face = other_face(edge2, face);
2905 /* if face == NULL, edge2 is a loose edge */
2907 /* record this face as visited */
2909 BLI_linklist_prepend(visited_faces, face);
2911 /* record this edge as visited */
2912 BLI_linklist_prepend(&visited_edges, edge2);
2914 /* get the next edge */
2915 edge2 = other_edge(face, vert, edge2);
2916 #ifdef EDGESPLIT_DEBUG_3
2917 printf("next face %4d; next edge %4d\n",
2918 face->newIndex, edge2->newIndex);
2920 printf("loose edge: %4d\n", edge2->newIndex);
2925 /* either we came back to the start edge or we found a sharp/loose edge */
2926 if(linklist_contains(visited_edges, edge2))
2927 /* we came back to the start edge */
2930 BLI_linklist_free(visited_edges, NULL);
2932 #ifdef EDGESPLIT_DEBUG_1
2933 printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
2934 "returning edge %d\n",
2935 edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
2940 static void split_single_vert(SmoothVert *vert, SmoothFace *face,
2943 SmoothVert *copy_vert;
2944 ReplaceData repdata;
2946 copy_vert = smoothvert_copy(vert, mesh);
2948 repdata.find = vert;
2949 repdata.replace = copy_vert;
2950 face_replace_vert(face, &repdata);
2953 typedef struct PropagateEdge {
2954 struct PropagateEdge *next, *prev;
2959 static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
2961 PropagateEdge *pedge = mesh->reusestack.first;
2964 BLI_remlink(&mesh->reusestack, pedge);
2968 mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
2969 BLI_memarena_use_calloc(mesh->arena);
2972 pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
2977 BLI_addhead(&mesh->propagatestack, pedge);
2980 static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
2982 PropagateEdge *pedge = mesh->propagatestack.first;
2985 *edge = pedge->edge;
2986 *vert = pedge->vert;
2987 BLI_remlink(&mesh->propagatestack, pedge);
2988 BLI_addhead(&mesh->reusestack, pedge);
2996 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
2998 static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
3002 LinkNode *visited_faces = NULL;
3003 #ifdef EDGESPLIT_DEBUG_1
3004 printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
3005 edge->newIndex, vert->newIndex);
3008 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
3009 mesh->threshold, mesh->flags);
3012 /* didn't find a sharp or loose edge, so we've hit a dead end */
3013 } else if(!edge_is_loose(edge2)) {
3014 /* edge2 is not loose, so it must be sharp */
3015 if(edge_is_loose(edge)) {
3016 /* edge is loose, so we can split edge2 at this vert */
3017 split_edge(edge2, vert, mesh);
3018 } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
3019 /* both edges are sharp, so we can split the pair at vert */
3020 split_edge(edge, vert, mesh);
3022 /* edge is not sharp, so try to split edge2 at its other vert */
3023 split_edge(edge2, other_vert(edge2, vert), mesh);
3025 } else { /* edge2 is loose */
3026 if(edge_is_loose(edge)) {
3028 ReplaceData repdata;
3030 /* can't split edge, what should we do with vert? */
3031 if(linklist_subset(vert->faces, visited_faces)) {
3032 /* vert has only one fan of faces attached; don't split it */
3034 /* vert has more than one fan of faces attached; split it */
3035 vert2 = smoothvert_copy(vert, mesh);
3037 /* replace vert with its copy in visited_faces */
3038 repdata.find = vert;
3039 repdata.replace = vert2;
3040 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
3043 /* edge is not loose, so it must be sharp; split it */
3044 split_edge(edge, vert, mesh);
3048 BLI_linklist_free(visited_faces, NULL);
3049 #ifdef EDGESPLIT_DEBUG_1
3050 printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
3051 edge->newIndex, vert->newIndex);
3055 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
3059 ReplaceData repdata;
3060 /* the list of faces traversed while looking for a sharp edge */
3061 LinkNode *visited_faces = NULL;
3062 #ifdef EDGESPLIT_DEBUG_1
3063 printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
3064 edge->newIndex, vert->newIndex);
3067 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
3068 mesh->threshold, mesh->flags);
3071 /* didn't find a sharp or loose edge, so try the other vert */
3072 vert2 = other_vert(edge, vert);
3073 push_propagate_stack(edge, vert2, mesh);
3074 } else if(!edge_is_loose(edge2)) {
3075 /* edge2 is not loose, so it must be sharp */
3076 SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
3077 SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
3080 /* replace edge with its copy in visited_faces */
3081 repdata.find = edge;
3082 repdata.replace = copy_edge;
3083 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
3085 /* replace edge2 with its copy in visited_faces */
3086 repdata.find = edge2;
3087 repdata.replace = copy_edge2;
3088 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
3090 vert2 = smoothvert_copy(vert, mesh);