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 * The Original Code is: all of this file.
25 * Contributor(s): Daniel Dunbar
31 * ***** END GPL LICENSE BLOCK *****
33 * Modifier stack implementation.
35 * BKE_modifier.h contains the function prototypes for this file.
44 #include "BLI_blenlib.h"
46 #include "BLI_arithb.h"
47 #include "BLI_linklist.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_ghash.h"
50 #include "BLI_memarena.h"
52 #include "MEM_guardedalloc.h"
54 #include "DNA_armature_types.h"
55 #include "DNA_cloth_types.h"
56 #include "DNA_effect_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_mesh_types.h"
59 #include "DNA_meshdata_types.h"
60 #include "DNA_modifier_types.h"
61 #include "DNA_object_types.h"
62 #include "DNA_object_force.h"
63 #include "DNA_scene_types.h"
64 #include "DNA_texture_types.h"
65 #include "DNA_curve_types.h"
66 #include "DNA_camera_types.h"
68 #include "BLI_editVert.h"
70 #include "MTC_matrixops.h"
71 #include "MTC_vectorops.h"
75 #include "BKE_bad_level_calls.h"
76 #include "BKE_collisions.h"
77 #include "BKE_customdata.h"
78 #include "BKE_global.h"
79 #include "BKE_utildefines.h"
80 #include "BKE_cdderivedmesh.h"
81 #include "BKE_DerivedMesh.h"
82 #include "BKE_booleanops.h"
83 #include "BKE_displist.h"
84 #include "BKE_modifier.h"
85 #include "BKE_lattice.h"
86 #include "BKE_subsurf.h"
87 #include "BKE_object.h"
89 #include "BKE_softbody.h"
90 #include "BKE_cloth.h"
91 #include "BKE_material.h"
92 #include "depsgraph_private.h"
94 #include "LOD_DependKludge.h"
95 #include "LOD_decimation.h"
97 #include "CCGSubSurf.h"
99 #include "RE_shader_ext.h"
103 static int noneModifier_isDisabled(ModifierData *md)
110 static void curveModifier_initData(ModifierData *md)
112 CurveModifierData *cmd = (CurveModifierData*) md;
114 cmd->defaxis = MOD_CURVE_POSX;
117 static void curveModifier_copyData(ModifierData *md, ModifierData *target)
119 CurveModifierData *cmd = (CurveModifierData*) md;
120 CurveModifierData *tcmd = (CurveModifierData*) target;
122 tcmd->defaxis = cmd->defaxis;
123 tcmd->object = cmd->object;
124 strncpy(tcmd->name, cmd->name, 32);
127 CustomDataMask curveModifier_requiredDataMask(ModifierData *md)
129 CurveModifierData *cmd = (CurveModifierData *)md;
130 CustomDataMask dataMask = 0;
132 /* ask for vertexgroups if we need them */
133 if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
138 static int curveModifier_isDisabled(ModifierData *md)
140 CurveModifierData *cmd = (CurveModifierData*) md;
145 static void curveModifier_foreachObjectLink(
146 ModifierData *md, Object *ob,
147 void (*walk)(void *userData, Object *ob, Object **obpoin),
150 CurveModifierData *cmd = (CurveModifierData*) md;
152 walk(userData, ob, &cmd->object);
155 static void curveModifier_updateDepgraph(
156 ModifierData *md, DagForest *forest,
157 Object *ob, DagNode *obNode)
159 CurveModifierData *cmd = (CurveModifierData*) md;
162 DagNode *curNode = dag_get_node(forest, cmd->object);
164 dag_add_relation(forest, curNode, obNode,
165 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
169 static void curveModifier_deformVerts(
170 ModifierData *md, Object *ob, DerivedMesh *derivedData,
171 float (*vertexCos)[3], int numVerts)
173 CurveModifierData *cmd = (CurveModifierData*) md;
175 curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts,
176 cmd->name, cmd->defaxis);
179 static void curveModifier_deformVertsEM(
180 ModifierData *md, Object *ob, EditMesh *editData,
181 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
183 DerivedMesh *dm = derivedData;
185 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
187 curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
189 if(!derivedData) dm->release(dm);
194 static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
196 LatticeModifierData *lmd = (LatticeModifierData*) md;
197 LatticeModifierData *tlmd = (LatticeModifierData*) target;
199 tlmd->object = lmd->object;
200 strncpy(tlmd->name, lmd->name, 32);
203 CustomDataMask latticeModifier_requiredDataMask(ModifierData *md)
205 LatticeModifierData *lmd = (LatticeModifierData *)md;
206 CustomDataMask dataMask = 0;
208 /* ask for vertexgroups if we need them */
209 if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
214 static int latticeModifier_isDisabled(ModifierData *md)
216 LatticeModifierData *lmd = (LatticeModifierData*) md;
221 static void latticeModifier_foreachObjectLink(
222 ModifierData *md, Object *ob,
223 void (*walk)(void *userData, Object *ob, Object **obpoin),
226 LatticeModifierData *lmd = (LatticeModifierData*) md;
228 walk(userData, ob, &lmd->object);
231 static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest,
232 Object *ob, DagNode *obNode)
234 LatticeModifierData *lmd = (LatticeModifierData*) md;
237 DagNode *latNode = dag_get_node(forest, lmd->object);
239 dag_add_relation(forest, latNode, obNode,
240 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
244 static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
248 if(md->type==eModifierType_Armature) {
249 ArmatureModifierData *amd = (ArmatureModifierData*) md;
251 amd->prevCos= MEM_dupallocN(vertexCos);
253 /* lattice/mesh modifier too */
258 static void latticeModifier_deformVerts(
259 ModifierData *md, Object *ob, DerivedMesh *derivedData,
260 float (*vertexCos)[3], int numVerts)
262 LatticeModifierData *lmd = (LatticeModifierData*) md;
265 modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
267 lattice_deform_verts(lmd->object, ob, derivedData,
268 vertexCos, numVerts, lmd->name);
271 static void latticeModifier_deformVertsEM(
272 ModifierData *md, Object *ob, EditMesh *editData,
273 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
275 DerivedMesh *dm = derivedData;
277 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
279 latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
281 if(!derivedData) dm->release(dm);
286 static void subsurfModifier_initData(ModifierData *md)
288 SubsurfModifierData *smd = (SubsurfModifierData*) md;
291 smd->renderLevels = 2;
292 smd->flags |= eSubsurfModifierFlag_SubsurfUv;
295 static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
297 SubsurfModifierData *smd = (SubsurfModifierData*) md;
298 SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
300 tsmd->flags = smd->flags;
301 tsmd->levels = smd->levels;
302 tsmd->renderLevels = smd->renderLevels;
303 tsmd->subdivType = smd->subdivType;
306 static void subsurfModifier_freeData(ModifierData *md)
308 SubsurfModifierData *smd = (SubsurfModifierData*) md;
311 ccgSubSurf_free(smd->mCache);
314 ccgSubSurf_free(smd->emCache);
318 static DerivedMesh *subsurfModifier_applyModifier(
319 ModifierData *md, Object *ob, DerivedMesh *derivedData,
320 int useRenderParams, int isFinalCalc)
322 SubsurfModifierData *smd = (SubsurfModifierData*) md;
325 result = subsurf_make_derived_from_derived(derivedData, smd,
326 useRenderParams, NULL,
332 static DerivedMesh *subsurfModifier_applyModifierEM(
333 ModifierData *md, Object *ob, EditMesh *editData,
334 DerivedMesh *derivedData)
336 SubsurfModifierData *smd = (SubsurfModifierData*) md;
339 result = subsurf_make_derived_from_derived(derivedData, smd, 0,
347 static void buildModifier_initData(ModifierData *md)
349 BuildModifierData *bmd = (BuildModifierData*) md;
355 static void buildModifier_copyData(ModifierData *md, ModifierData *target)
357 BuildModifierData *bmd = (BuildModifierData*) md;
358 BuildModifierData *tbmd = (BuildModifierData*) target;
360 tbmd->start = bmd->start;
361 tbmd->length = bmd->length;
362 tbmd->randomize = bmd->randomize;
363 tbmd->seed = bmd->seed;
366 static int buildModifier_dependsOnTime(ModifierData *md)
371 static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
372 DerivedMesh *derivedData,
373 int useRenderParams, int isFinalCalc)
375 DerivedMesh *dm = derivedData;
377 BuildModifierData *bmd = (BuildModifierData*) md;
379 int numFaces, numEdges;
380 int maxVerts, maxEdges, maxFaces;
381 int *vertMap, *edgeMap, *faceMap;
383 GHashIterator *hashIter;
384 /* maps vert indices in old mesh to indices in new mesh */
385 GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
386 BLI_ghashutil_intcmp);
387 /* maps edge indices in new mesh to indices in old mesh */
388 GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
389 BLI_ghashutil_intcmp);
391 maxVerts = dm->getNumVerts(dm);
392 vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
393 "build modifier vertMap");
394 for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
396 maxEdges = dm->getNumEdges(dm);
397 edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
398 "build modifier edgeMap");
399 for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
401 maxFaces = dm->getNumFaces(dm);
402 faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
403 "build modifier faceMap");
404 for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
407 frac = bsystem_time(ob, (float)G.scene->r.cfra,
408 bmd->start - 1.0f) / bmd->length;
410 frac = G.scene->r.cfra - bmd->start / bmd->length;
412 CLAMP(frac, 0.0, 1.0);
414 numFaces = dm->getNumFaces(dm) * frac;
415 numEdges = dm->getNumEdges(dm) * frac;
417 /* if there's at least one face, build based on faces */
422 BLI_array_randomize(faceMap, sizeof(*faceMap),
423 maxFaces, bmd->seed);
425 /* get the set of all vert indices that will be in the final mesh,
426 * mapped to the new indices
428 for(i = 0; i < numFaces; ++i) {
430 dm->getFace(dm, faceMap[i], &mf);
432 if(!BLI_ghash_haskey(vertHash, (void *)mf.v1))
433 BLI_ghash_insert(vertHash, (void *)mf.v1,
434 (void *)BLI_ghash_size(vertHash));
435 if(!BLI_ghash_haskey(vertHash, (void *)mf.v2))
436 BLI_ghash_insert(vertHash, (void *)mf.v2,
437 (void *)BLI_ghash_size(vertHash));
438 if(!BLI_ghash_haskey(vertHash, (void *)mf.v3))
439 BLI_ghash_insert(vertHash, (void *)mf.v3,
440 (void *)BLI_ghash_size(vertHash));
441 if(mf.v4 && !BLI_ghash_haskey(vertHash, (void *)mf.v4))
442 BLI_ghash_insert(vertHash, (void *)mf.v4,
443 (void *)BLI_ghash_size(vertHash));
446 /* get the set of edges that will be in the new mesh (i.e. all edges
447 * that have both verts in the new mesh)
449 maxEdges = dm->getNumEdges(dm);
450 for(i = 0; i < maxEdges; ++i) {
452 dm->getEdge(dm, i, &me);
454 if(BLI_ghash_haskey(vertHash, (void *)me.v1)
455 && BLI_ghash_haskey(vertHash, (void *)me.v2))
456 BLI_ghash_insert(edgeHash,
457 (void *)BLI_ghash_size(edgeHash), (void *)i);
459 } else if(numEdges) {
461 BLI_array_randomize(edgeMap, sizeof(*edgeMap),
462 maxEdges, bmd->seed);
464 /* get the set of all vert indices that will be in the final mesh,
465 * mapped to the new indices
467 for(i = 0; i < numEdges; ++i) {
469 dm->getEdge(dm, edgeMap[i], &me);
471 if(!BLI_ghash_haskey(vertHash, (void *)me.v1))
472 BLI_ghash_insert(vertHash, (void *)me.v1,
473 (void *)BLI_ghash_size(vertHash));
474 if(!BLI_ghash_haskey(vertHash, (void *)me.v2))
475 BLI_ghash_insert(vertHash, (void *)me.v2,
476 (void *)BLI_ghash_size(vertHash));
479 /* get the set of edges that will be in the new mesh
481 for(i = 0; i < numEdges; ++i) {
483 dm->getEdge(dm, edgeMap[i], &me);
485 BLI_ghash_insert(edgeHash, (void *)BLI_ghash_size(edgeHash),
489 int numVerts = dm->getNumVerts(dm) * frac;
492 BLI_array_randomize(vertMap, sizeof(*vertMap),
493 maxVerts, bmd->seed);
495 /* get the set of all vert indices that will be in the final mesh,
496 * mapped to the new indices
498 for(i = 0; i < numVerts; ++i)
499 BLI_ghash_insert(vertHash, (void *)vertMap[i], (void *)i);
502 /* now we know the number of verts, edges and faces, we can create
505 result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
506 BLI_ghash_size(edgeHash), numFaces);
508 /* copy the vertices across */
509 for(hashIter = BLI_ghashIterator_new(vertHash);
510 !BLI_ghashIterator_isDone(hashIter);
511 BLI_ghashIterator_step(hashIter)) {
514 int oldIndex = (int)BLI_ghashIterator_getKey(hashIter);
515 int newIndex = (int)BLI_ghashIterator_getValue(hashIter);
517 dm->getVert(dm, oldIndex, &source);
518 dest = CDDM_get_vert(result, newIndex);
520 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
523 BLI_ghashIterator_free(hashIter);
525 /* copy the edges across, remapping indices */
526 for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
529 int oldIndex = (int)BLI_ghash_lookup(edgeHash, (void *)i);
531 dm->getEdge(dm, oldIndex, &source);
532 dest = CDDM_get_edge(result, i);
534 source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
535 source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
537 DM_copy_edge_data(dm, result, oldIndex, i, 1);
541 /* copy the faces across, remapping indices */
542 for(i = 0; i < numFaces; ++i) {
547 dm->getFace(dm, faceMap[i], &source);
548 dest = CDDM_get_face(result, i);
552 source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
553 source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
554 source.v3 = (int)BLI_ghash_lookup(vertHash, (void *)source.v3);
556 source.v4 = (int)BLI_ghash_lookup(vertHash, (void *)source.v4);
558 DM_copy_face_data(dm, result, faceMap[i], i, 1);
561 test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
564 CDDM_calc_normals(result);
566 BLI_ghash_free(vertHash, NULL, NULL);
567 BLI_ghash_free(edgeHash, NULL, NULL);
577 /* Array modifier: duplicates the object multiple times along an axis
580 static void arrayModifier_initData(ModifierData *md)
582 ArrayModifierData *amd = (ArrayModifierData*) md;
584 /* default to 2 duplicates distributed along the x-axis by an
585 offset of 1 object-width
587 amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
589 amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
591 amd->scale[1] = amd->scale[2] = 0;
593 amd->merge_dist = 0.01;
594 amd->fit_type = MOD_ARR_FIXEDCOUNT;
595 amd->offset_type = MOD_ARR_OFF_RELATIVE;
599 static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
601 ArrayModifierData *amd = (ArrayModifierData*) md;
602 ArrayModifierData *tamd = (ArrayModifierData*) target;
604 tamd->start_cap = amd->start_cap;
605 tamd->end_cap = amd->end_cap;
606 tamd->curve_ob = amd->curve_ob;
607 tamd->offset_ob = amd->offset_ob;
608 tamd->count = amd->count;
609 VECCOPY(tamd->offset, amd->offset);
610 VECCOPY(tamd->scale, amd->scale);
611 tamd->length = amd->length;
612 tamd->merge_dist = amd->merge_dist;
613 tamd->fit_type = amd->fit_type;
614 tamd->offset_type = amd->offset_type;
615 tamd->flags = amd->flags;
618 static void arrayModifier_foreachObjectLink(
619 ModifierData *md, Object *ob,
620 void (*walk)(void *userData, Object *ob, Object **obpoin),
623 ArrayModifierData *amd = (ArrayModifierData*) md;
625 walk(userData, ob, &amd->start_cap);
626 walk(userData, ob, &amd->end_cap);
627 walk(userData, ob, &amd->curve_ob);
628 walk(userData, ob, &amd->offset_ob);
631 static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest,
632 Object *ob, DagNode *obNode)
634 ArrayModifierData *amd = (ArrayModifierData*) md;
636 if (amd->start_cap) {
637 DagNode *curNode = dag_get_node(forest, amd->start_cap);
639 dag_add_relation(forest, curNode, obNode,
640 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
643 DagNode *curNode = dag_get_node(forest, amd->end_cap);
645 dag_add_relation(forest, curNode, obNode,
646 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
649 DagNode *curNode = dag_get_node(forest, amd->curve_ob);
651 dag_add_relation(forest, curNode, obNode,
652 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
654 if (amd->offset_ob) {
655 DagNode *curNode = dag_get_node(forest, amd->offset_ob);
657 dag_add_relation(forest, curNode, obNode,
658 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
662 float vertarray_size(MVert *mvert, int numVerts, int axis)
665 float min_co, max_co;
667 /* if there are no vertices, width is 0 */
668 if(numVerts == 0) return 0;
670 /* find the minimum and maximum coordinates on the desired axis */
671 min_co = max_co = mvert->co[axis];
673 for(i = 1; i < numVerts; ++i, ++mvert) {
674 if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
675 if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
678 return max_co - min_co;
681 typedef struct IndexMapEntry {
682 /* the new vert index that this old vert index maps to */
684 /* -1 if this vert isn't merged, otherwise the old vert index it
685 * should be replaced with
688 /* 1 if this vert's first copy is merged with the last copy of its
689 * merge target, otherwise 0
694 /* indexMap - an array of IndexMap entries
695 * oldIndex - the old index to map
696 * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
698 static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
700 if(indexMap[oldIndex].merge < 0) {
701 /* vert wasn't merged, so use copy of this vert */
702 return indexMap[oldIndex].new + copyNum;
703 } else if(indexMap[oldIndex].merge == oldIndex) {
704 /* vert was merged with itself */
705 return indexMap[oldIndex].new;
707 /* vert was merged with another vert */
708 /* follow the chain of merges to the end, or until we've passed
709 * a number of vertices equal to the copy number
712 return indexMap[oldIndex].new;
714 return calc_mapping(indexMap, indexMap[oldIndex].merge,
719 static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
720 Object *ob, DerivedMesh *dm,
726 float final_offset[4][4];
728 float length = amd->length;
729 int count = amd->count;
730 int numVerts, numEdges, numFaces;
731 int maxVerts, maxEdges, maxFaces;
732 int finalVerts, finalEdges, finalFaces;
733 DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
734 MVert *mvert, *src_mvert;
738 IndexMapEntry *indexMap;
742 /* need to avoid infinite recursion here */
743 if(amd->start_cap && amd->start_cap != ob)
744 start_cap = mesh_get_derived_final(amd->start_cap, CD_MASK_MESH);
745 if(amd->end_cap && amd->end_cap != ob)
746 end_cap = mesh_get_derived_final(amd->end_cap, CD_MASK_MESH);
750 indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
753 src_mvert = dm->getVertArray(dm);
755 maxVerts = dm->getNumVerts(dm);
757 if(amd->offset_type & MOD_ARR_OFF_CONST)
758 VecAddf(offset[3], offset[3], amd->offset);
759 if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
760 for(j = 0; j < 3; j++)
761 offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
765 if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
767 float result_mat[4][4];
770 MTC_Mat4Invert(obinv, ob->obmat);
774 MTC_Mat4MulSerie(result_mat, offset,
775 obinv, amd->offset_ob->obmat,
776 NULL, NULL, NULL, NULL, NULL);
777 MTC_Mat4CpyMat4(offset, result_mat);
780 if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
781 Curve *cu = amd->curve_ob->data;
784 cu->flag |= CU_PATH; // needed for path & bevlist
785 makeDispListCurveTypes(amd->curve_ob, 0);
788 length = cu->path->totdist;
792 /* calculate the maximum number of copies which will fit within the
794 if(amd->fit_type == MOD_ARR_FITLENGTH
795 || amd->fit_type == MOD_ARR_FITCURVE) {
796 float dist = sqrt(MTC_dot3Float(offset[3], offset[3]));
798 if(dist > FLT_EPSILON)
799 /* this gives length = first copy start to last copy end
800 add a tiny offset for floating point rounding errors */
801 count = (length + FLT_EPSILON) / dist;
803 /* if the offset has no translation, just make one copy */
810 /* allocate memory for count duplicates (including original) plus
813 finalVerts = dm->getNumVerts(dm) * count;
814 finalEdges = dm->getNumEdges(dm) * count;
815 finalFaces = dm->getNumFaces(dm) * count;
817 finalVerts += start_cap->getNumVerts(start_cap);
818 finalEdges += start_cap->getNumEdges(start_cap);
819 finalFaces += start_cap->getNumFaces(start_cap);
822 finalVerts += end_cap->getNumVerts(end_cap);
823 finalEdges += end_cap->getNumEdges(end_cap);
824 finalFaces += end_cap->getNumFaces(end_cap);
826 result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
828 /* calculate the offset matrix of the final copy (for merging) */
829 MTC_Mat4One(final_offset);
831 for(j=0; j < count - 1; j++) {
832 MTC_Mat4MulMat4(tmp_mat, final_offset, offset);
833 MTC_Mat4CpyMat4(final_offset, tmp_mat);
836 numVerts = numEdges = numFaces = 0;
837 mvert = CDDM_get_verts(result);
839 for (i = 0; i < maxVerts; i++) {
841 MVert *mv = &mvert[numVerts];
845 inMV = &src_mvert[i];
847 DM_copy_vert_data(dm, result, i, numVerts, 1);
851 indexMap[i].new = numVerts - 1;
852 indexMap[i].merge = -1; /* default to no merge */
853 indexMap[i].merge_final = 0; /* default to no merge */
857 /* Attempts to merge verts from one duplicate with verts from the
858 * next duplicate which are closer than amd->merge_dist.
859 * Only the first such vert pair is merged.
860 * If verts are merged in the first duplicate pair, they are merged
863 if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
865 VECCOPY(tmp_co, mv->co);
866 MTC_Mat4MulVecfl(offset, tmp_co);
868 for(j = 0; j < maxVerts; j++) {
869 inMV = &src_mvert[j];
870 /* if this vert is within merge limit, merge */
871 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) {
872 indexMap[i].merge = j;
874 /* test for merging with final copy of merge target */
875 if(amd->flags & MOD_ARR_MERGEFINAL) {
876 VECCOPY(tmp_co, inMV->co);
877 inMV = &src_mvert[i];
878 MTC_Mat4MulVecfl(final_offset, tmp_co);
879 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist))
880 indexMap[i].merge_final = 1;
887 /* if no merging, generate copies of this vert */
888 if(indexMap[i].merge < 0) {
889 for(j=0; j < count - 1; j++) {
890 mv2 = &mvert[numVerts];
892 DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
896 MTC_Mat4MulVecfl(offset, co);
897 VECCOPY(mv2->co, co);
899 } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
900 /* if this vert is not merging with itself, and it is merging
901 * with the final copy of its merge target, remove the first copy
904 DM_free_vert_data(result, numVerts, 1);
908 /* make a hashtable so we can avoid duplicate edges from merging */
909 edges = BLI_edgehash_new();
911 maxEdges = dm->getNumEdges(dm);
912 medge = CDDM_get_edges(result);
913 for(i = 0; i < maxEdges; i++) {
919 dm->getEdge(dm, i, &inMED);
922 med.v1 = indexMap[inMED.v1].new;
923 med.v2 = indexMap[inMED.v2].new;
925 /* if vertices are to be merged with the final copies of their
926 * merge targets, calculate that final copy
928 if(indexMap[inMED.v1].merge_final) {
929 med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
932 if(indexMap[inMED.v2].merge_final) {
933 med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
938 med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
941 if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
942 DM_copy_edge_data(dm, result, i, numEdges, 1);
943 medge[numEdges] = med;
946 BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
949 for(j = 1; j < count; j++)
951 vert1 = calc_mapping(indexMap, inMED.v1, j);
952 vert2 = calc_mapping(indexMap, inMED.v2, j);
953 /* avoid duplicate edges */
954 if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
955 med2 = &medge[numEdges];
957 DM_copy_edge_data(dm, result, i, numEdges, 1);
964 BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
969 maxFaces = dm->getNumFaces(dm);
970 mface = CDDM_get_faces(result);
971 for (i=0; i < maxFaces; i++) {
973 MFace *mf = &mface[numFaces];
975 dm->getFace(dm, i, &inMF);
977 DM_copy_face_data(dm, result, i, numFaces, 1);
980 mf->v1 = indexMap[inMF.v1].new;
981 mf->v2 = indexMap[inMF.v2].new;
982 mf->v3 = indexMap[inMF.v3].new;
984 mf->v4 = indexMap[inMF.v4].new;
986 /* if vertices are to be merged with the final copies of their
987 * merge targets, calculate that final copy
989 if(indexMap[inMF.v1].merge_final)
990 mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
991 if(indexMap[inMF.v2].merge_final)
992 mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
993 if(indexMap[inMF.v3].merge_final)
994 mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
995 if(inMF.v4 && indexMap[inMF.v4].merge_final)
996 mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
998 test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3);
1001 /* if the face has fewer than 3 vertices, don't create it */
1004 DM_free_face_data(result, numFaces, 1);
1007 for(j = 1; j < count; j++)
1009 MFace *mf2 = &mface[numFaces];
1011 DM_copy_face_data(dm, result, i, numFaces, 1);
1014 mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
1015 mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
1016 mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
1018 mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
1020 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
1023 /* if the face has fewer than 3 vertices, don't create it */
1026 DM_free_face_data(result, numFaces, 1);
1031 /* add start and end caps */
1033 float startoffset[4][4];
1039 int capVerts, capEdges, capFaces;
1041 capVerts = start_cap->getNumVerts(start_cap);
1042 capEdges = start_cap->getNumEdges(start_cap);
1043 capFaces = start_cap->getNumFaces(start_cap);
1044 cap_mvert = start_cap->getVertArray(start_cap);
1045 cap_medge = start_cap->getEdgeArray(start_cap);
1046 cap_mface = start_cap->getFaceArray(start_cap);
1048 Mat4Invert(startoffset, offset);
1050 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1051 "arrayModifier_doArray vert_map");
1053 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1054 for(i = 0; i < capVerts; i++) {
1055 MVert *mv = &cap_mvert[i];
1058 if(amd->flags & MOD_ARR_MERGE) {
1063 VECCOPY(tmp_co, mv->co);
1064 Mat4MulVecfl(startoffset, tmp_co);
1066 for(j = 0; j < maxVerts; j++) {
1067 in_mv = &src_mvert[j];
1068 /* if this vert is within merge limit, merge */
1069 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1070 vert_map[i] = calc_mapping(indexMap, j, 0);
1078 DM_copy_vert_data(start_cap, result, i, numVerts, 1);
1079 mvert[numVerts] = *mv;
1080 Mat4MulVecfl(startoffset, mvert[numVerts].co);
1081 origindex[numVerts] = ORIGINDEX_NONE;
1083 vert_map[i] = numVerts;
1088 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1089 for(i = 0; i < capEdges; i++) {
1092 v1 = vert_map[cap_medge[i].v1];
1093 v2 = vert_map[cap_medge[i].v2];
1095 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1096 DM_copy_edge_data(start_cap, result, i, numEdges, 1);
1097 medge[numEdges] = cap_medge[i];
1098 medge[numEdges].v1 = v1;
1099 medge[numEdges].v2 = v2;
1100 origindex[numEdges] = ORIGINDEX_NONE;
1105 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1106 for(i = 0; i < capFaces; i++) {
1107 DM_copy_face_data(start_cap, result, i, numFaces, 1);
1108 mface[numFaces] = cap_mface[i];
1109 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1110 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1111 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1112 if(mface[numFaces].v4)
1113 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1114 origindex[numFaces] = ORIGINDEX_NONE;
1119 MEM_freeN(vert_map);
1120 start_cap->release(start_cap);
1124 float endoffset[4][4];
1130 int capVerts, capEdges, capFaces;
1132 capVerts = end_cap->getNumVerts(end_cap);
1133 capEdges = end_cap->getNumEdges(end_cap);
1134 capFaces = end_cap->getNumFaces(end_cap);
1135 cap_mvert = end_cap->getVertArray(end_cap);
1136 cap_medge = end_cap->getEdgeArray(end_cap);
1137 cap_mface = end_cap->getFaceArray(end_cap);
1139 Mat4MulMat4(endoffset, final_offset, offset);
1141 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1142 "arrayModifier_doArray vert_map");
1144 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1145 for(i = 0; i < capVerts; i++) {
1146 MVert *mv = &cap_mvert[i];
1149 if(amd->flags & MOD_ARR_MERGE) {
1154 VECCOPY(tmp_co, mv->co);
1155 Mat4MulVecfl(offset, tmp_co);
1157 for(j = 0; j < maxVerts; j++) {
1158 in_mv = &src_mvert[j];
1159 /* if this vert is within merge limit, merge */
1160 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1161 vert_map[i] = calc_mapping(indexMap, j, count - 1);
1169 DM_copy_vert_data(end_cap, result, i, numVerts, 1);
1170 mvert[numVerts] = *mv;
1171 Mat4MulVecfl(endoffset, mvert[numVerts].co);
1172 origindex[numVerts] = ORIGINDEX_NONE;
1174 vert_map[i] = numVerts;
1179 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1180 for(i = 0; i < capEdges; i++) {
1183 v1 = vert_map[cap_medge[i].v1];
1184 v2 = vert_map[cap_medge[i].v2];
1186 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1187 DM_copy_edge_data(end_cap, result, i, numEdges, 1);
1188 medge[numEdges] = cap_medge[i];
1189 medge[numEdges].v1 = v1;
1190 medge[numEdges].v2 = v2;
1191 origindex[numEdges] = ORIGINDEX_NONE;
1196 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1197 for(i = 0; i < capFaces; i++) {
1198 DM_copy_face_data(end_cap, result, i, numFaces, 1);
1199 mface[numFaces] = cap_mface[i];
1200 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1201 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1202 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1203 if(mface[numFaces].v4)
1204 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1205 origindex[numFaces] = ORIGINDEX_NONE;
1210 MEM_freeN(vert_map);
1211 end_cap->release(end_cap);
1214 BLI_edgehash_free(edges, NULL);
1215 MEM_freeN(indexMap);
1217 CDDM_lower_num_verts(result, numVerts);
1218 CDDM_lower_num_edges(result, numEdges);
1219 CDDM_lower_num_faces(result, numFaces);
1224 static DerivedMesh *arrayModifier_applyModifier(
1225 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1226 int useRenderParams, int isFinalCalc)
1228 DerivedMesh *result;
1229 ArrayModifierData *amd = (ArrayModifierData*) md;
1231 result = arrayModifier_doArray(amd, ob, derivedData, 0);
1233 CDDM_calc_normals(result);
1238 static DerivedMesh *arrayModifier_applyModifierEM(
1239 ModifierData *md, Object *ob, EditMesh *editData,
1240 DerivedMesh *derivedData)
1242 return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
1247 static void mirrorModifier_initData(ModifierData *md)
1249 MirrorModifierData *mmd = (MirrorModifierData*) md;
1251 mmd->flag |= MOD_MIR_AXIS_X;
1252 mmd->tolerance = 0.001;
1253 mmd->mirror_ob = NULL;
1256 static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
1258 MirrorModifierData *mmd = (MirrorModifierData*) md;
1259 MirrorModifierData *tmmd = (MirrorModifierData*) target;
1261 tmmd->axis = mmd->axis;
1262 tmmd->flag = mmd->flag;
1263 tmmd->tolerance = mmd->tolerance;
1264 tmmd->mirror_ob = mmd->mirror_ob;;
1267 static void mirrorModifier_foreachObjectLink(
1268 ModifierData *md, Object *ob,
1269 void (*walk)(void *userData, Object *ob, Object **obpoin),
1272 MirrorModifierData *mmd = (MirrorModifierData*) md;
1274 walk(userData, ob, &mmd->mirror_ob);
1277 static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest,
1278 Object *ob, DagNode *obNode)
1280 MirrorModifierData *mmd = (MirrorModifierData*) md;
1282 if(mmd->mirror_ob) {
1283 DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
1285 dag_add_relation(forest, latNode, obNode,
1286 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
1290 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
1297 float tolerance = mmd->tolerance;
1298 DerivedMesh *result;
1299 int numVerts, numEdges, numFaces;
1300 int maxVerts = dm->getNumVerts(dm);
1301 int maxEdges = dm->getNumEdges(dm);
1302 int maxFaces = dm->getNumFaces(dm);
1304 float mtx[4][4], imtx[4][4];
1306 numVerts = numEdges = numFaces = 0;
1308 indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
1310 result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
1312 if (mmd->mirror_ob) {
1315 Mat4Invert(obinv, mmd->mirror_ob->obmat);
1316 Mat4MulMat4(mtx, ob->obmat, obinv);
1317 Mat4Invert(imtx, mtx);
1320 for(i = 0; i < maxVerts; i++) {
1322 MVert *mv = CDDM_get_vert(result, numVerts);
1326 dm->getVert(dm, i, &inMV);
1328 VecCopyf(co, inMV.co);
1330 if (mmd->mirror_ob) {
1331 VecMat4MulVecfl(co, mtx, co);
1333 isShared = ABS(co[axis])<=tolerance;
1335 /* Because the topology result (# of vertices) must be the same if
1336 * the mesh data is overridden by vertex cos, have to calc sharedness
1337 * based on original coordinates. This is why we test before copy.
1339 DM_copy_vert_data(dm, result, i, numVerts, 1);
1343 indexMap[i][0] = numVerts - 1;
1344 indexMap[i][1] = !isShared;
1348 if (mmd->mirror_ob) {
1349 VecMat4MulVecfl(co, imtx, co);
1351 VecCopyf(mv->co, co);
1353 mv->flag |= ME_VERT_MERGED;
1355 MVert *mv2 = CDDM_get_vert(result, numVerts);
1357 DM_copy_vert_data(dm, result, i, numVerts, 1);
1361 co[axis] = -co[axis];
1362 if (mmd->mirror_ob) {
1363 VecMat4MulVecfl(co, imtx, co);
1365 VecCopyf(mv2->co, co);
1369 for(i = 0; i < maxEdges; i++) {
1371 MEdge *med = CDDM_get_edge(result, numEdges);
1373 dm->getEdge(dm, i, &inMED);
1375 DM_copy_edge_data(dm, result, i, numEdges, 1);
1379 med->v1 = indexMap[inMED.v1][0];
1380 med->v2 = indexMap[inMED.v2][0];
1382 med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
1384 if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
1385 MEdge *med2 = CDDM_get_edge(result, numEdges);
1387 DM_copy_edge_data(dm, result, i, numEdges, 1);
1391 med2->v1 += indexMap[inMED.v1][1];
1392 med2->v2 += indexMap[inMED.v2][1];
1396 for(i = 0; i < maxFaces; i++) {
1398 MFace *mf = CDDM_get_face(result, numFaces);
1400 dm->getFace(dm, i, &inMF);
1402 DM_copy_face_data(dm, result, i, numFaces, 1);
1406 mf->v1 = indexMap[inMF.v1][0];
1407 mf->v2 = indexMap[inMF.v2][0];
1408 mf->v3 = indexMap[inMF.v3][0];
1409 mf->v4 = indexMap[inMF.v4][0];
1411 if(indexMap[inMF.v1][1]
1412 || indexMap[inMF.v2][1]
1413 || indexMap[inMF.v3][1]
1414 || (mf->v4 && indexMap[inMF.v4][1])) {
1415 MFace *mf2 = CDDM_get_face(result, numFaces);
1416 static int corner_indices[4] = {2, 1, 0, 3};
1418 DM_copy_face_data(dm, result, i, numFaces, 1);
1421 mf2->v1 += indexMap[inMF.v1][1];
1422 mf2->v2 += indexMap[inMF.v2][1];
1423 mf2->v3 += indexMap[inMF.v3][1];
1424 if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
1426 /* mirror UVs if enabled */
1427 if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
1428 MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
1431 for(j = 0; j < 4; ++j) {
1432 if(mmd->flag & MOD_MIR_MIRROR_U)
1433 tf->uv[j][0] = 1.0f - tf->uv[j][0];
1434 if(mmd->flag & MOD_MIR_MIRROR_V)
1435 tf->uv[j][1] = 1.0f - tf->uv[j][1];
1440 /* Flip face normal */
1441 SWAP(int, mf2->v1, mf2->v3);
1442 DM_swap_face_data(result, numFaces, corner_indices);
1444 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
1449 MEM_freeN(indexMap);
1451 CDDM_lower_num_verts(result, numVerts);
1452 CDDM_lower_num_edges(result, numEdges);
1453 CDDM_lower_num_faces(result, numFaces);
1458 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
1459 Object *ob, DerivedMesh *dm,
1462 DerivedMesh *result = dm;
1464 /* check which axes have been toggled and mirror accordingly */
1465 if(mmd->flag & MOD_MIR_AXIS_X) {
1466 result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
1468 if(mmd->flag & MOD_MIR_AXIS_Y) {
1469 DerivedMesh *tmp = result;
1470 result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
1471 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
1473 if(mmd->flag & MOD_MIR_AXIS_Z) {
1474 DerivedMesh *tmp = result;
1475 result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
1476 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
1482 static DerivedMesh *mirrorModifier_applyModifier(
1483 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1484 int useRenderParams, int isFinalCalc)
1486 DerivedMesh *result;
1487 MirrorModifierData *mmd = (MirrorModifierData*) md;
1489 result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
1491 CDDM_calc_normals(result);
1496 static DerivedMesh *mirrorModifier_applyModifierEM(
1497 ModifierData *md, Object *ob, EditMesh *editData,
1498 DerivedMesh *derivedData)
1500 return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
1504 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
1505 * or edge angle (can be used to achieve autosmoothing)
1508 #define EDGESPLIT_DEBUG_3
1509 #define EDGESPLIT_DEBUG_2
1510 #define EDGESPLIT_DEBUG_1
1511 #define EDGESPLIT_DEBUG_0
1514 static void edgesplitModifier_initData(ModifierData *md)
1516 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1518 /* default to 30-degree split angle, sharpness from both angle & flag
1520 emd->split_angle = 30;
1521 emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
1524 static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
1526 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1527 EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
1529 temd->split_angle = emd->split_angle;
1530 temd->flags = emd->flags;
1533 /* Mesh data for edgesplit operation */
1534 typedef struct SmoothVert {
1535 LinkNode *faces; /* all faces which use this vert */
1536 int oldIndex; /* the index of the original DerivedMesh vert */
1537 int newIndex; /* the index of the new DerivedMesh vert */
1540 #define SMOOTHEDGE_NUM_VERTS 2
1542 typedef struct SmoothEdge {
1543 SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
1544 LinkNode *faces; /* all faces which use this edge */
1545 int oldIndex; /* the index of the original DerivedMesh edge */
1546 int newIndex; /* the index of the new DerivedMesh edge */
1547 short flag; /* the flags from the original DerivedMesh edge */
1550 #define SMOOTHFACE_MAX_EDGES 4
1552 typedef struct SmoothFace {
1553 SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
1554 int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
1555 float normal[3]; /* the normal of this face */
1556 int oldIndex; /* the index of the original DerivedMesh face */
1557 int newIndex; /* the index of the new DerivedMesh face */
1560 typedef struct SmoothMesh {
1564 int num_verts, num_edges, num_faces;
1565 int max_verts, max_edges, max_faces;
1567 float threshold; /* the cosine of the smoothing angle */
1571 static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
1573 SmoothVert *copy = &mesh->verts[mesh->num_verts];
1575 if(mesh->num_verts >= mesh->max_verts) {
1576 printf("Attempted to add a SmoothMesh vert beyond end of array\n");
1582 copy->newIndex = mesh->num_verts;
1585 #ifdef EDGESPLIT_DEBUG_2
1586 printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
1591 static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
1593 SmoothEdge *copy = &mesh->edges[mesh->num_edges];
1595 if(mesh->num_edges >= mesh->max_edges) {
1596 printf("Attempted to add a SmoothMesh edge beyond end of array\n");
1602 copy->newIndex = mesh->num_edges;
1605 #ifdef EDGESPLIT_DEBUG_2
1606 printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
1611 static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
1614 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
1615 if(edge->verts[i] == vert) return 1;
1620 static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
1621 int max_verts, int max_edges, int max_faces)
1623 SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
1624 mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
1625 "SmoothMesh.verts");
1626 mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
1627 "SmoothMesh.edges");
1628 mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
1629 "SmoothMesh.faces");
1631 mesh->num_verts = num_verts;
1632 mesh->num_edges = num_edges;
1633 mesh->num_faces = num_faces;
1635 mesh->max_verts = max_verts;
1636 mesh->max_edges = max_edges;
1637 mesh->max_faces = max_faces;
1642 static void smoothmesh_free(SmoothMesh *mesh)
1646 for(i = 0; i < mesh->num_verts; ++i)
1647 BLI_linklist_free(mesh->verts[i].faces, NULL);
1649 for(i = 0; i < mesh->num_edges; ++i)
1650 BLI_linklist_free(mesh->edges[i].faces, NULL);
1652 MEM_freeN(mesh->verts);
1653 MEM_freeN(mesh->edges);
1654 MEM_freeN(mesh->faces);
1658 static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
1663 if(max_verts <= mesh->max_verts) return;
1665 tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
1667 memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
1669 /* remap vert pointers in edges */
1670 for(i = 0; i < mesh->num_edges; ++i) {
1672 SmoothEdge *edge = &mesh->edges[i];
1674 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
1675 /* pointer arithmetic to get vert array index */
1676 edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
1679 MEM_freeN(mesh->verts);
1681 mesh->max_verts = max_verts;
1684 static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
1689 if(max_edges <= mesh->max_edges) return;
1691 tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
1693 memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
1695 /* remap edge pointers in faces */
1696 for(i = 0; i < mesh->num_faces; ++i) {
1698 SmoothFace *face = &mesh->faces[i];
1700 for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
1702 /* pointer arithmetic to get edge array index */
1703 face->edges[j] = &tmp[face->edges[j] - mesh->edges];
1706 MEM_freeN(mesh->edges);
1708 mesh->max_edges = max_edges;
1711 #ifdef EDGESPLIT_DEBUG_0
1712 static void smoothmesh_print(SmoothMesh *mesh)
1715 DerivedMesh *dm = mesh->dm;
1717 printf("--- SmoothMesh ---\n");
1718 printf("--- Vertices ---\n");
1719 for(i = 0; i < mesh->num_verts; i++) {
1720 SmoothVert *vert = &mesh->verts[i];
1724 dm->getVert(dm, vert->oldIndex, &mv);
1726 printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
1727 i, vert->oldIndex, vert->newIndex,
1728 mv.co[0], mv.co[1], mv.co[2]);
1729 printf(", faces={");
1730 for(node = vert->faces; node != NULL; node = node->next) {
1731 printf(" %d", ((SmoothFace *)node->link)->newIndex);
1736 printf("\n--- Edges ---\n");
1737 for(i = 0; i < mesh->num_edges; i++) {
1738 SmoothEdge *edge = &mesh->edges[i];
1741 printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
1743 edge->oldIndex, edge->newIndex,
1744 edge->verts[0]->newIndex, edge->verts[1]->newIndex);
1745 if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
1746 printf(", faces={");
1747 for(node = edge->faces; node != NULL; node = node->next) {
1748 printf(" %d", ((SmoothFace *)node->link)->newIndex);
1753 printf("\n--- Faces ---\n");
1754 for(i = 0; i < mesh->num_faces; i++) {
1755 SmoothFace *face = &mesh->faces[i];
1757 printf("%4d: indices={%4d, %4d}, edges={", i,
1758 face->oldIndex, face->newIndex);
1759 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1761 printf(" -%-2d", face->edges[j]->newIndex);
1763 printf(" %-2d", face->edges[j]->newIndex);
1765 printf("}, verts={");
1766 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1767 printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
1774 static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
1777 EdgeHash *edges = BLI_edgehash_new();
1779 int totvert, totedge, totface;
1781 totvert = dm->getNumVerts(dm);
1782 totedge = dm->getNumEdges(dm);
1783 totface = dm->getNumFaces(dm);
1785 mesh = smoothmesh_new(totvert, totedge, totface,
1786 totvert, totedge, totface);
1790 for(i = 0; i < totvert; i++) {
1791 SmoothVert *vert = &mesh->verts[i];
1793 vert->oldIndex = vert->newIndex = i;
1796 for(i = 0; i < totedge; i++) {
1797 SmoothEdge *edge = &mesh->edges[i];
1800 dm->getEdge(dm, i, &med);
1801 edge->verts[0] = &mesh->verts[med.v1];
1802 edge->verts[1] = &mesh->verts[med.v2];
1803 edge->oldIndex = edge->newIndex = i;
1804 edge->flag = med.flag;
1806 BLI_edgehash_insert(edges, med.v1, med.v2, edge);
1809 for(i = 0; i < totface; i++) {
1810 SmoothFace *face = &mesh->faces[i];
1815 dm->getFace(dm, i, &mf);
1817 dm->getVert(dm, mf.v1, &v1);
1818 dm->getVert(dm, mf.v2, &v2);
1819 dm->getVert(dm, mf.v3, &v3);
1820 face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
1821 if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
1822 face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
1823 if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
1826 dm->getVert(dm, mf.v4, &v4);
1827 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
1828 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
1829 face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
1830 if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
1831 CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
1833 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
1834 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
1835 face->edges[3] = NULL;
1836 CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
1839 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1840 SmoothEdge *edge = face->edges[j];
1841 BLI_linklist_prepend(&edge->faces, face);
1842 BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
1845 face->oldIndex = face->newIndex = i;
1848 BLI_edgehash_free(edges, NULL);
1853 static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
1855 DerivedMesh *result = CDDM_from_template(mesh->dm,
1859 MVert *new_verts = CDDM_get_verts(result);
1860 MEdge *new_edges = CDDM_get_edges(result);
1861 MFace *new_faces = CDDM_get_faces(result);
1864 for(i = 0; i < mesh->num_verts; ++i) {
1865 SmoothVert *vert = &mesh->verts[i];
1866 MVert *newMV = &new_verts[vert->newIndex];
1868 DM_copy_vert_data(mesh->dm, result,
1869 vert->oldIndex, vert->newIndex, 1);
1870 mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
1873 for(i = 0; i < mesh->num_edges; ++i) {
1874 SmoothEdge *edge = &mesh->edges[i];
1875 MEdge *newME = &new_edges[edge->newIndex];
1877 DM_copy_edge_data(mesh->dm, result,
1878 edge->oldIndex, edge->newIndex, 1);
1879 mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
1880 newME->v1 = edge->verts[0]->newIndex;
1881 newME->v2 = edge->verts[1]->newIndex;
1884 for(i = 0; i < mesh->num_faces; ++i) {
1885 SmoothFace *face = &mesh->faces[i];
1886 MFace *newMF = &new_faces[face->newIndex];
1888 DM_copy_face_data(mesh->dm, result,
1889 face->oldIndex, face->newIndex, 1);
1890 mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
1892 newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
1893 newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
1894 newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
1896 if(face->edges[3]) {
1897 newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
1906 /* returns the other vert in the given edge
1908 static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
1910 if(edge->verts[0] == vert) return edge->verts[1];
1911 else return edge->verts[0];
1914 /* returns the other edge in the given face that uses the given vert
1915 * returns NULL if no other edge in the given face uses the given vert
1916 * (this should never happen)
1918 static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
1922 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
1923 SmoothEdge *tmp_edge = face->edges[i];
1924 if(tmp_edge == edge) continue;
1926 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
1927 if(tmp_edge->verts[j] == vert) return tmp_edge;
1930 /* if we get to here, something's wrong (there should always be 2 edges
1931 * which use the same vert in a face)
1936 /* returns a face attached to the given edge which is not the given face.
1937 * returns NULL if no other faces use this edge.
1939 static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
1943 for(node = edge->faces; node != NULL; node = node->next)
1944 if(node->link != face) return node->link;
1950 /* copies source list to target, overwriting target (target is not freed)
1951 * nodes in the copy will be in the same order as in source
1953 static void linklist_copy(LinkNode **target, LinkNode *source)
1955 LinkNode *node = NULL;
1958 for(; source; source = source->next) {
1960 node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
1963 node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
1965 node->link = source->link;
1971 /* appends source to target if it's not already in target */
1972 static void linklist_append_unique(LinkNode **target, void *source)
1975 LinkNode *prev = NULL;
1977 /* check if source value is already in the list */
1978 for(node = *target; node; prev = node, node = node->next)
1979 if(node->link == source) return;
1981 node = MEM_mallocN(sizeof(*node), "nlink");
1983 node->link = source;
1985 if(prev) prev->next = node;
1986 else *target = node;
1989 /* appends elements of source which aren't already in target to target */
1990 static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
1992 for(; source; source = source->next)
1993 linklist_append_unique(target, source->link);
1996 #if 0 /* this is no longer used, it should possibly be removed */
1997 /* prepends prepend to list - doesn't copy nodes, just joins the lists */
1998 static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
2001 LinkNode *node = prepend;
2002 while(node->next) node = node->next;
2010 /* returns 1 if the linked list contains the given pointer, 0 otherwise
2012 static int linklist_contains(LinkNode *list, void *ptr)
2016 for(node = list; node; node = node->next)
2017 if(node->link == ptr) return 1;
2022 /* returns 1 if the first linked list is a subset of the second (comparing
2023 * pointer values), 0 if not
2025 static int linklist_subset(LinkNode *list1, LinkNode *list2)
2027 for(; list1; list1 = list1->next)
2028 if(!linklist_contains(list2, list1->link))
2035 /* empties the linked list
2036 * frees pointers with freefunc if freefunc is not NULL
2038 static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
2040 BLI_linklist_free(*list, freefunc);
2045 /* removes the first instance of value from the linked list
2046 * frees the pointer with freefunc if freefunc is not NULL
2048 static void linklist_remove_first(LinkNode **list, void *value,
2049 LinkNodeFreeFP freefunc)
2051 LinkNode *node = *list;
2052 LinkNode *prev = NULL;
2054 while(node && node->link != value) {
2061 prev->next = node->next;
2066 freefunc(node->link);
2072 /* removes all elements in source from target */
2073 static void linklist_remove_list(LinkNode **target, LinkNode *source,
2074 LinkNodeFreeFP freefunc)
2076 for(; source; source = source->next)
2077 linklist_remove_first(target, source->link, freefunc);
2080 #ifdef EDGESPLIT_DEBUG_0
2081 static void print_ptr(void *ptr)
2083 printf("%p\n", ptr);
2086 static void print_edge(void *ptr)
2088 SmoothEdge *edge = ptr;
2089 printf(" %4d", edge->newIndex);
2092 static void print_face(void *ptr)
2094 SmoothFace *face = ptr;
2095 printf(" %4d", face->newIndex);
2099 typedef struct ReplaceData {
2104 static void edge_replace_vert(void *ptr, void *userdata)
2106 SmoothEdge *edge = ptr;
2107 SmoothVert *find = ((ReplaceData *)userdata)->find;
2108 SmoothVert *replace = ((ReplaceData *)userdata)->replace;
2111 #ifdef EDGESPLIT_DEBUG_3
2112 printf("replacing vert %4d with %4d in edge %4d",
2113 find->newIndex, replace->newIndex, edge->newIndex);
2114 printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2117 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
2118 if(edge->verts[i] == find) {
2119 linklist_append_list_unique(&replace->faces, edge->faces);
2120 linklist_remove_list(&find->faces, edge->faces, NULL);
2122 edge->verts[i] = replace;
2126 #ifdef EDGESPLIT_DEBUG_3
2127 printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2131 static void face_replace_vert(void *ptr, void *userdata)
2133 SmoothFace *face = ptr;
2136 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
2137 edge_replace_vert(face->edges[i], userdata);
2140 static void face_replace_edge(void *ptr, void *userdata)
2142 SmoothFace *face = ptr;
2143 SmoothEdge *find = ((ReplaceData *)userdata)->find;
2144 SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
2147 #ifdef EDGESPLIT_DEBUG_3
2148 printf("replacing edge %4d with %4d in face %4d",
2149 find->newIndex, replace->newIndex, face->newIndex);
2151 printf(": {%2d %2d %2d %2d}",
2152 face->edges[0]->newIndex, face->edges[1]->newIndex,
2153 face->edges[2]->newIndex, face->edges[3]->newIndex);
2155 printf(": {%2d %2d %2d}",
2156 face->edges[0]->newIndex, face->edges[1]->newIndex,
2157 face->edges[2]->newIndex);
2160 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
2161 if(face->edges[i] == find) {
2162 linklist_remove_first(&face->edges[i]->faces, face, NULL);
2163 BLI_linklist_prepend(&replace->faces, face);
2164 face->edges[i] = replace;
2168 #ifdef EDGESPLIT_DEBUG_3
2170 printf(" -> {%2d %2d %2d %2d}\n",
2171 face->edges[0]->newIndex, face->edges[1]->newIndex,
2172 face->edges[2]->newIndex, face->edges[3]->newIndex);
2174 printf(" -> {%2d %2d %2d}\n",
2175 face->edges[0]->newIndex, face->edges[1]->newIndex,
2176 face->edges[2]->newIndex);
2180 static int edge_is_loose(SmoothEdge *edge)
2182 return !(edge->faces && edge->faces->next);
2185 static int edge_is_sharp(SmoothEdge *edge, int flags,
2188 #ifdef EDGESPLIT_DEBUG_1
2189 printf("edge %d: ", edge->newIndex);
2191 if(edge->flag & ME_SHARP) {
2192 /* edge can only be sharp if it has at least 2 faces */
2193 if(!edge_is_loose(edge)) {
2194 #ifdef EDGESPLIT_DEBUG_1
2199 /* edge is loose, so it can't be sharp */
2200 edge->flag &= ~ME_SHARP;
2204 #ifdef EDGESPLIT_DEBUG_1
2205 printf("not sharp\n");
2210 /* finds another sharp edge which uses vert, by traversing faces around the
2211 * vert until it does one of the following:
2212 * - hits a loose edge (the edge is returned)
2213 * - hits a sharp edge (the edge is returned)
2214 * - returns to the start edge (NULL is returned)
2216 static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
2217 LinkNode **visited_faces, float threshold, int flags)
2219 SmoothFace *face = NULL;
2220 SmoothEdge *edge2 = NULL;
2221 /* holds the edges we've seen so we can avoid looping indefinitely */
2222 LinkNode *visited_edges = NULL;
2223 #ifdef EDGESPLIT_DEBUG_1
2224 printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
2225 edge->newIndex, vert->newIndex);
2228 /* get a face on which to start */
2229 if(edge->faces) face = edge->faces->link;
2232 /* record this edge as visited */
2233 BLI_linklist_prepend(&visited_edges, edge);
2235 /* get the next edge */
2236 edge2 = other_edge(face, vert, edge);
2238 /* record this face as visited */
2240 BLI_linklist_prepend(visited_faces, face);
2242 /* search until we hit a loose edge or a sharp edge or an edge we've
2245 while(face && !edge_is_sharp(edge2, flags, threshold)
2246 && !linklist_contains(visited_edges, edge2)) {
2247 #ifdef EDGESPLIT_DEBUG_3
2248 printf("current face %4d; current edge %4d\n", face->newIndex,
2251 /* get the next face */
2252 face = other_face(edge2, face);
2254 /* if face == NULL, edge2 is a loose edge */
2256 /* record this face as visited */
2258 BLI_linklist_prepend(visited_faces, face);
2260 /* record this edge as visited */
2261 BLI_linklist_prepend(&visited_edges, edge2);
2263 /* get the next edge */
2264 edge2 = other_edge(face, vert, edge2);
2265 #ifdef EDGESPLIT_DEBUG_3
2266 printf("next face %4d; next edge %4d\n",
2267 face->newIndex, edge2->newIndex);
2269 printf("loose edge: %4d\n", edge2->newIndex);
2274 /* either we came back to the start edge or we found a sharp/loose edge */
2275 if(linklist_contains(visited_edges, edge2))
2276 /* we came back to the start edge */
2279 BLI_linklist_free(visited_edges, NULL);
2281 #ifdef EDGESPLIT_DEBUG_1
2282 printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
2283 "returning edge %d\n",
2284 edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
2289 static void split_single_vert(SmoothVert *vert, SmoothFace *face,
2292 SmoothVert *copy_vert;
2293 ReplaceData repdata;
2295 copy_vert = smoothvert_copy(vert, mesh);
2297 repdata.find = vert;
2298 repdata.replace = copy_vert;
2299 face_replace_vert(face, &repdata);
2302 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
2304 static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
2308 LinkNode *visited_faces = NULL;
2309 #ifdef EDGESPLIT_DEBUG_1
2310 printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
2311 edge->newIndex, vert->newIndex);
2314 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
2315 mesh->threshold, mesh->flags);
2318 /* didn't find a sharp or loose edge, so we've hit a dead end */
2319 } else if(!edge_is_loose(edge2)) {
2320 /* edge2 is not loose, so it must be sharp */
2321 if(edge_is_loose(edge)) {
2322 /* edge is loose, so we can split edge2 at this vert */
2323 split_edge(edge2, vert, mesh);
2324 } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
2325 /* both edges are sharp, so we can split the pair at vert */
2326 split_edge(edge, vert, mesh);
2328 /* edge is not sharp, so try to split edge2 at its other vert */
2329 split_edge(edge2, other_vert(edge2, vert), mesh);
2331 } else { /* edge2 is loose */
2332 if(edge_is_loose(edge)) {
2334 ReplaceData repdata;
2336 /* can't split edge, what should we do with vert? */
2337 if(linklist_subset(vert->faces, visited_faces)) {
2338 /* vert has only one fan of faces attached; don't split it */
2340 /* vert has more than one fan of faces attached; split it */
2341 vert2 = smoothvert_copy(vert, mesh);
2343 /* replace vert with its copy in visited_faces */
2344 repdata.find = vert;
2345 repdata.replace = vert2;
2346 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2349 /* edge is not loose, so it must be sharp; split it */
2350 split_edge(edge, vert, mesh);
2354 BLI_linklist_free(visited_faces, NULL);
2355 #ifdef EDGESPLIT_DEBUG_1
2356 printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
2357 edge->newIndex, vert->newIndex);
2361 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
2365 ReplaceData repdata;
2366 /* the list of faces traversed while looking for a sharp edge */
2367 LinkNode *visited_faces = NULL;
2368 #ifdef EDGESPLIT_DEBUG_1
2369 printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
2370 edge->newIndex, vert->newIndex);
2373 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
2374 mesh->threshold, mesh->flags);
2377 /* didn't find a sharp or loose edge, so try the other vert */
2378 vert2 = other_vert(edge, vert);
2379 propagate_split(edge, vert2, mesh);
2380 } else if(!edge_is_loose(edge2)) {
2381 /* edge2 is not loose, so it must be sharp */
2382 SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
2383 SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
2386 /* replace edge with its copy in visited_faces */
2387 repdata.find = edge;
2388 repdata.replace = copy_edge;
2389 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2391 /* replace edge2 with its copy in visited_faces */
2392 repdata.find = edge2;
2393 repdata.replace = copy_edge2;
2394 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2396 vert2 = smoothvert_copy(vert, mesh);
2398 /* replace vert with its copy in visited_faces (must be done after
2399 * edge replacement so edges have correct vertices)
2401 repdata.find = vert;
2402 repdata.replace = vert2;
2403 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2405 /* all copying and replacing is done; the mesh should be consistent.
2406 * now propagate the split to the vertices at either end
2408 propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
2409 propagate_split(copy_edge2, other_vert(copy_edge2, vert2), mesh);
2411 if(smoothedge_has_vert(edge, vert))
2412 propagate_split(edge, vert, mesh);
2414 /* edge2 is loose */
2415 SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
2418 /* replace edge with its copy in visited_faces */
2419 repdata.find = edge;
2420 repdata.replace = copy_edge;
2421 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2423 vert2 = smoothvert_copy(vert, mesh);
2425 /* replace vert with its copy in visited_faces (must be done after
2426 * edge replacement so edges have correct vertices)
2428 repdata.find = vert;
2429 repdata.replace = vert2;
2430 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2432 /* copying and replacing is done; the mesh should be consistent.
2433 * now propagate the split to the vertex at the other end
2435 propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
2437 if(smoothedge_has_vert(edge, vert))
2438 propagate_split(edge, vert, mesh);
2441 BLI_linklist_free(visited_faces, NULL);
2442 #ifdef EDGESPLIT_DEBUG_1
2443 printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
2444 edge->newIndex, vert->newIndex);
2448 static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
2449 int flags, int *extra_edges)
2451 /* if normal1 dot normal2 < threshold, angle is greater, so split */
2452 /* FIXME not sure if this always works */
2453 /* 0.00001 added for floating-point rounding */
2454 float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
2459 /* loop through edges, counting potential new ones */
2460 for(i = 0; i < mesh->num_edges; i++) {
2461 SmoothEdge *edge = &mesh->edges[i];
2464 /* treat all non-manifold edges (3 or more faces) as sharp */
2465 if(edge->faces && edge->faces->next && edge->faces->next->next) {
2468 /* this edge is sharp */
2471 /* add an extra edge for every face beyond the first */
2473 for(node = edge->faces->next->next->next; node; node = node->next)
2475 } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
2476 && !edge_is_loose(edge)) {
2477 /* (the edge can only be sharp if we're checking angle or flag,
2478 * and it has at least 2 faces) */
2480 /* if we're checking the sharp flag and it's set, good */
2481 if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
2482 /* this edge is sharp */
2486 } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
2487 /* we know the edge has 2 faces, so check the angle */
2488 SmoothFace *face1 = edge->faces->link;
2489 SmoothFace *face2 = edge->faces->next->link;
2490 float edge_angle_cos = MTC_dot3Float(face1->normal,
2493 if(edge_angle_cos < threshold) {
2494 /* this edge is sharp */
2502 /* set/clear sharp flag appropriately */
2503 if(sharp) edge->flag |= ME_SHARP;
2504 else edge->flag &= ~ME_SHARP;
2508 static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
2511 /* if normal1 dot normal2 < threshold, angle is greater, so split */
2512 /* FIXME not sure if this always works */
2513 /* 0.00001 added for floating-point rounding */
2514 mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
2515 mesh->flags = flags;
2517 /* loop through edges, splitting sharp ones */
2518 /* can't use an iterator here, because we'll be adding edges */
2519 for(i = 0; i < mesh->num_edges; i++) {
2520 SmoothEdge *edge = &mesh->edges[i];
2522 if(edge_is_sharp(edge, flags, mesh->threshold))
2523 split_edge(edge, edge->verts[0], mesh);
2528 static int count_bridge_verts(SmoothMesh *mesh)
2530 int i, j, count = 0;
2532 for(i = 0; i < mesh->num_faces; i++) {
2533 SmoothFace *face = &mesh->faces[i];
2535 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2536 SmoothEdge *edge = face->edges[j];
2537 SmoothEdge *next_edge;
2538 SmoothVert *vert = edge->verts[1 - face->flip[j]];
2539 int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
2541 /* wrap next around if at last edge */
2542 if(!face->edges[next]) next = 0;
2544 next_edge = face->edges[next];
2546 /* if there are other faces sharing this vertex but not
2547 * these edges, the vertex will be split, so count it
2549 /* vert has to have at least one face (this one), so faces != 0 */
2550 if(!edge->faces->next && !next_edge->faces->next
2551 && vert->faces->next) {
2557 /* each bridge vert will be counted once per face that uses it,
2558 * so count is too high, but it's ok for now
2563 static void split_bridge_verts(SmoothMesh *mesh)
2567 for(i = 0; i < mesh->num_faces; i++) {
2568 SmoothFace *face = &mesh->faces[i];
2570 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2571 SmoothEdge *edge = face->edges[j];
2572 SmoothEdge *next_edge;
2573 SmoothVert *vert = edge->verts[1 - face->flip[j]];
2574 int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
2576 /* wrap next around if at last edge */
2577 if(!face->edges[next]) next = 0;
2579 next_edge = face->edges[next];
2581 /* if there are other faces sharing this vertex but not
2582 * these edges, split the vertex
2584 /* vert has to have at least one face (this one), so faces != 0 */
2585 if(!edge->faces->next && !next_edge->faces->next
2586 && vert->faces->next)
2587 /* FIXME this needs to find all faces that share edges with
2588 * this one and split off together
2590 split_single_vert(vert, face, mesh);
2595 static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
2596 Object *ob, DerivedMesh *dm)
2599 DerivedMesh *result;
2600 int max_verts, max_edges;
2602 if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
2605 /* 1. make smoothmesh with initial number of elements */
2606 mesh = smoothmesh_from_derivedmesh(dm);
2608 /* 2. count max number of elements to add */
2609 tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
2610 max_verts = max_edges * 2 + mesh->max_verts;
2611 max_verts += count_bridge_verts(mesh);
2612 max_edges += mesh->max_edges;
2614 /* 3. reallocate smoothmesh arrays & copy elements across */
2615 /* 4. remap copied elements' pointers to point into the new arrays */
2616 smoothmesh_resize_verts(mesh, max_verts);
2617 smoothmesh_resize_edges(mesh, max_edges);
2619 #ifdef EDGESPLIT_DEBUG_1
2620 printf("********** Pre-split **********\n");
2621 smoothmesh_print(mesh);
2624 split_sharp_edges(mesh, emd->split_angle, emd->flags);
2625 #ifdef EDGESPLIT_DEBUG_1
2626 printf("********** Post-edge-split **********\n");
2627 smoothmesh_print(mesh);
2630 split_bridge_verts(mesh);
2632 #ifdef EDGESPLIT_DEBUG_1
2633 printf("********** Post-vert-split **********\n");
2634 smoothmesh_print(mesh);
2637 #ifdef EDGESPLIT_DEBUG_0
2638 printf("Edgesplit: Estimated %d verts & %d edges, "
2639 "found %d verts & %d edges\n", max_verts, max_edges,
2640 mesh->num_verts, mesh->num_edges);
2643 result = CDDM_from_smoothmesh(mesh);
2644 smoothmesh_free(mesh);
2649 static DerivedMesh *edgesplitModifier_applyModifier(
2650 ModifierData *md, Object *ob, DerivedMesh *derivedData,
2651 int useRenderParams, int isFinalCalc)
2653 DerivedMesh *result;
2654 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2656 result = edgesplitModifier_do(emd, ob, derivedData);
2658 CDDM_calc_normals(result);
2663 static DerivedMesh *edgesplitModifier_applyModifierEM(
2664 ModifierData *md, Object *ob, EditMesh *editData,
2665 DerivedMesh *derivedData)
2667 return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
2672 static void displaceModifier_initData(ModifierData *md)
2674 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2676 dmd->texture = NULL;
2678 dmd->direction = MOD_DISP_DIR_NOR;
2679 dmd->midlevel = 0.5;
2682 static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
2684 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2685 DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
2687 tdmd->texture = dmd->texture;
2688 tdmd->strength = dmd->strength;
2689 tdmd->direction = dmd->direction;
2690 strncpy(tdmd->defgrp_name, dmd->defgrp_name, 32);
2691 tdmd->midlevel = dmd->midlevel;
2692 tdmd->texmapping = dmd->texmapping;
2693 tdmd->map_object = dmd->map_object;
2694 strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32);
2697 CustomDataMask displaceModifier_requiredDataMask(ModifierData *md)
2699 DisplaceModifierData *dmd = (DisplaceModifierData *)md;
2700 CustomDataMask dataMask = 0;
2702 /* ask for vertexgroups if we need them */
2703 if(dmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
2705 /* ask for UV coordinates if we need them */
2706 if(dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
2711 static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
2712 ObjectWalkFunc walk, void *userData)
2714 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2716 walk(userData, ob, &dmd->map_object);
2719 static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
2720 IDWalkFunc walk, void *userData)
2722 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2724 walk(userData, ob, (ID **)&dmd->texture);
2726 displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData);
2729 static int displaceModifier_isDisabled(ModifierData *md)
2731 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2733 return !dmd->texture;
2736 static void displaceModifier_updateDepgraph(
2737 ModifierData *md, DagForest *forest,
2738 Object *ob, DagNode *obNode)
2740 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2742 if(dmd->map_object) {
2743 DagNode *curNode = dag_get_node(forest, dmd->map_object);
2745 dag_add_relation(forest, curNode, obNode,
2746 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
2750 static void validate_layer_name(const CustomData *data, int type, char *name)
2754 /* if a layer name was given, try to find that layer */
2756 index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
2759 /* either no layer was specified, or the layer we want has been
2760 * deleted, so assign the active layer to name
2762 index = CustomData_get_active_layer_index(data, CD_MTFACE);
2763 strcpy(name, data->layers[index].name);
2767 static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
2769 float (*co)[3], float (*texco)[3],
2773 int texmapping = dmd->texmapping;
2775 if(texmapping == MOD_DISP_MAP_OBJECT) {
2777 Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
2778 else /* if there is no map object, default to local */
2779 texmapping = MOD_DISP_MAP_LOCAL;
2782 /* UVs need special handling, since they come from faces */
2783 if(texmapping == MOD_DISP_MAP_UV) {
2784 if(dm->getFaceDataArray(dm, CD_MTFACE)) {
2785 MFace *mface = dm->getFaceArray(dm);
2787 char *done = MEM_callocN(sizeof(*done) * numVerts,
2788 "get_texture_coords done");
2789 int numFaces = dm->getNumFaces(dm);
2792 validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
2794 tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
2797 /* verts are given the UV from the first face that uses them */
2798 for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
2800 texco[mf->v1][0] = tf->uv[0][0];
2801 texco[mf->v1][1] = tf->uv[0][1];
2802 texco[mf->v1][2] = 0;
2806 texco[mf->v2][0] = tf->uv[1][0];
2807 texco[mf->v2][1] = tf->uv[1][1];
2808 texco[mf->v2][2] = 0;
2812 texco[mf->v3][0] = tf->uv[2][0];
2813 texco[mf->v3][1] = tf->uv[2][1];
2814 texco[mf->v3][2] = 0;
2818 texco[mf->v4][0] = tf->uv[3][0];
2819 texco[mf->v4][1] = tf->uv[3][1];
2820 texco[mf->v4][2] = 0;
2825 /* remap UVs from [0, 1] to [-1, 1] */
2826 for(i = 0; i < numVerts; ++i) {
2827 texco[i][0] = texco[i][0] * 2 - 1;
2828 texco[i][1] = texco[i][1] * 2 - 1;
2833 } else /* if there are no UVs, default to local */
2834 texmapping = MOD_DISP_MAP_LOCAL;
2837 for(i = 0; i < numVerts; ++i, ++co, ++texco) {
2838 switch(texmapping) {
2839 case MOD_DISP_MAP_LOCAL:
2840 VECCOPY(*texco, *co);
2842 case MOD_DISP_MAP_GLOBAL:
2843 VECCOPY(*texco, *co);
2844 Mat4MulVecfl(ob->obmat, *texco);
2846 case MOD_DISP_MAP_OBJECT:
2847 VECCOPY(*texco, *co);
2848 Mat4MulVecfl(ob->obmat, *texco);
2849 Mat4MulVecfl(dmd->map_object->imat, *texco);
2855 static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
2859 result_type = multitex_ext(texture, tex_co, NULL,
2862 /* if the texture gave an RGB value, we assume it didn't give a valid
2863 * intensity, so calculate one (formula from do_material_tex).
2864 * if the texture didn't give an RGB value, copy the intensity across
2866 if(result_type & TEX_RGB)
2867 texres->tin = (0.35 * texres->tr + 0.45 * texres->tg
2868 + 0.2 * texres->tb);
2870 texres->tr = texres->tg = texres->tb = texres->tin;
2873 /* dm must be a CDDerivedMesh */
2874 static void displaceModifier_do(
2875 DisplaceModifierData *dmd, Object *ob,
2876 DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
2880 MDeformVert *dvert = NULL;
2884 if(!dmd->texture) return;
2888 if(dmd->defgrp_name[0]) {
2890 for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
2891 if(!strcmp(def->name, dmd->defgrp_name)) {
2898 mvert = CDDM_get_verts(dm);
2899 if(defgrp_index >= 0)
2900 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
2902 tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
2903 "displaceModifier_do tex_co");
2904 get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
2906 for(i = 0; i < numVerts; ++i) {
2908 float delta = 0, strength = dmd->strength;
2909 MDeformWeight *def_weight = NULL;
2913 for(j = 0; j < dvert[i].totweight; ++j) {
2914 if(dvert[i].dw[j].def_nr == defgrp_index) {
2915 def_weight = &dvert[i].dw[j];
2919 if(!def_weight) continue;
2923 get_texture_value(dmd->texture, tex_co[i], &texres);
2925 delta = texres.tin - dmd->midlevel;
2927 if(def_weight) strength *= def_weight->weight;
2931 switch(dmd->direction) {
2932 case MOD_DISP_DIR_X:
2933 vertexCos[i][0] += delta;
2935 case MOD_DISP_DIR_Y:
2936 vertexCos[i][1] += delta;
2938 case MOD_DISP_DIR_Z:
2939 vertexCos[i][2] += delta;
2941 case MOD_DISP_DIR_RGB_XYZ:
2942 vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength;
2943 vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength;
2944 vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength;
2946 case MOD_DISP_DIR_NOR:
2947 vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
2948 vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
2949 vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
2957 static void displaceModifier_deformVerts(
2958 ModifierData *md, Object *ob, DerivedMesh *derivedData,
2959 float (*vertexCos)[3], int numVerts)
2963 if(derivedData) dm = CDDM_copy(derivedData);
2964 else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
2967 CDDM_apply_vert_coords(dm, vertexCos);
2968 CDDM_calc_normals(dm);
2970 displaceModifier_do((DisplaceModifierData *)md, ob, dm,
2971 vertexCos, numVerts);
2976 static void displaceModifier_deformVertsEM(
2977 ModifierData *md, Object *ob, EditMesh *editData,
2978 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
2982 if(derivedData) dm = CDDM_copy(derivedData);
2983 else dm = CDDM_from_editmesh(editData, ob->data);
2985 CDDM_apply_vert_coords(dm, vertexCos);
2986 CDDM_calc_normals(dm);
2988 displaceModifier_do((DisplaceModifierData *)md, ob, dm,
2989 vertexCos, numVerts);
2995 /* UV Project modifier: Generates UVs projected from an object
2998 static void uvprojectModifier_initData(ModifierData *md)
3000 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3003 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
3004 umd->projectors[i] = NULL;
3007 umd->num_projectors = 1;
3008 umd->aspectx = umd->aspecty = 1.0f;
3011 static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
3013 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3014 UVProjectModifierData *tumd = (UVProjectModifierData*) target;
3017 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
3018 tumd->projectors[i] = umd->projectors[i];
3019 tumd->image = umd->image;
3020 tumd->flags = umd->flags;
3021 tumd->num_projectors = umd->num_projectors;
3022 tumd->aspectx = umd->aspectx;
3023 tumd->aspecty = umd->aspecty;
3026 CustomDataMask uvprojectModifier_requiredDataMask(ModifierData *md)
3028 CustomDataMask dataMask = 0;
3030 /* ask for UV coordinates */
3031 dataMask |= (1 << CD_MTFACE);
3036 static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
3037 ObjectWalkFunc walk, void *userData)
3039 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3042 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
3043 walk(userData, ob, &umd->projectors[i]);
3046 static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
3047 IDWalkFunc walk, void *userData)
3049 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3051 walk(userData, ob, (ID **)&umd->image);
3053 uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
3057 static void uvprojectModifier_updateDepgraph(ModifierData *md,
3058 DagForest *forest, Object *ob, DagNode *obNode)
3060 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3063 for(i = 0; i < umd->num_projectors; ++i) {
3064 if(umd->projectors[i]) {
3065 DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
3067 dag_add_relation(forest, curNode, obNode,
3068 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
3073 typedef struct Projector {
3074 Object *ob; /* object this projector is derived from */
3075 float projmat[4][4]; /* projection matrix */
3076 float normal[3]; /* projector normal in world space */
3079 static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
3080 Object *ob, DerivedMesh *dm)
3082 float (*coords)[3], (*co)[3];
3084 int i, numVerts, numFaces;
3085 Image *image = umd->image;
3087 int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
3088 Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
3089 int num_projectors = 0;
3092 if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty;
3095 for(i = 0; i < umd->num_projectors; ++i)
3096 if(umd->projectors[i])
3097 projectors[num_projectors++].ob = umd->projectors[i];
3099 if(num_projectors == 0) return dm;
3101 /* make sure there are UV layers available */
3102 if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
3104 /* make sure we're using an existing layer */
3105 validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
3107 /* make sure we are not modifying the original UV layer */
3108 tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
3112 numVerts = dm->getNumVerts(dm);
3114 coords = MEM_callocN(sizeof(*coords) * numVerts,
3115 "uvprojectModifier_do coords");
3116 dm->getVertCos(dm, coords);
3118 /* convert coords to world space */
3119 for(i = 0, co = coords; i < numVerts; ++i, ++co)
3120 Mat4MulVecfl(ob->obmat, *co);
3122 /* calculate a projection matrix and normal for each projector */
3123 for(i = 0; i < num_projectors; ++i) {
3125 float offsetmat[4][4];
3127 /* calculate projection matrix */
3128 Mat4Invert(projectors[i].projmat, projectors[i].ob->obmat);
3130 if(projectors[i].ob->type == OB_CAMERA) {
3131 Camera *cam = (Camera *)projectors[i].ob->data;
3132 if(cam->type == CAM_PERSP) {
3133 float perspmat[4][4];
3138 float pixsize = cam->clipsta * 32.0 / cam->lens;
3141 xmax = 0.5f * pixsize;
3142 ymax = xmax / aspect;
3144 ymax = 0.5f * pixsize;
3145 xmax = ymax * aspect;