Fixed bug #8597, Subsurf error
[plumiferos.git] / source / blender / blenkernel / intern / modifier.c
blob26c6cc02f10d884bd84e0da369a5046385cad26c
1 /*
2 * $Id: modifier.c 10624 2007-04-30 19:20:43Z ianwill $
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
26 * Ton Roosendaal,
27 * Ben Batt,
28 * Brecht Van Lommel,
29 * Campbell Barton
31 * ***** END GPL LICENSE BLOCK *****
33 * Modifier stack implementation.
35 * BKE_modifier.h contains the function prototypes for this file.
39 #include "string.h"
40 #include "stdarg.h"
41 #include "math.h"
42 #include "float.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_rand.h"
46 #include "BLI_arithb.h"
47 #include "BLI_linklist.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_ghash.h"
51 #include "MEM_guardedalloc.h"
53 #include "DNA_armature_types.h"
54 #include "DNA_effect_types.h"
55 #include "DNA_material_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_modifier_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_texture_types.h"
63 #include "DNA_curve_types.h"
64 #include "DNA_camera_types.h"
66 #include "BLI_editVert.h"
68 #include "MTC_matrixops.h"
69 #include "MTC_vectorops.h"
71 #include "BKE_main.h"
72 #include "BKE_anim.h"
73 #include "BKE_bad_level_calls.h"
74 #include "BKE_customdata.h"
75 #include "BKE_global.h"
76 #include "BKE_utildefines.h"
77 #include "BKE_cdderivedmesh.h"
78 #include "BKE_DerivedMesh.h"
79 #include "BKE_booleanops.h"
80 #include "BKE_displist.h"
81 #include "BKE_modifier.h"
82 #include "BKE_lattice.h"
83 #include "BKE_subsurf.h"
84 #include "BKE_object.h"
85 #include "BKE_mesh.h"
86 #include "BKE_softbody.h"
87 #include "BKE_material.h"
88 #include "depsgraph_private.h"
90 #include "LOD_DependKludge.h"
91 #include "LOD_decimation.h"
93 #include "CCGSubSurf.h"
95 #include "RE_shader_ext.h"
97 /***/
99 static int noneModifier_isDisabled(ModifierData *md)
101 return 1;
104 /* Curve */
106 static void curveModifier_initData(ModifierData *md)
108 CurveModifierData *cmd = (CurveModifierData*) md;
110 cmd->defaxis = MOD_CURVE_POSX;
113 static void curveModifier_copyData(ModifierData *md, ModifierData *target)
115 CurveModifierData *cmd = (CurveModifierData*) md;
116 CurveModifierData *tcmd = (CurveModifierData*) target;
118 tcmd->defaxis = cmd->defaxis;
119 tcmd->object = cmd->object;
120 strncpy(tcmd->name, cmd->name, 32);
123 CustomDataMask curveModifier_requiredDataMask(ModifierData *md)
125 CurveModifierData *cmd = (CurveModifierData *)md;
126 CustomDataMask dataMask = 0;
128 /* ask for vertexgroups if we need them */
129 if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
131 return dataMask;
134 static int curveModifier_isDisabled(ModifierData *md)
136 CurveModifierData *cmd = (CurveModifierData*) md;
138 return !cmd->object;
141 static void curveModifier_foreachObjectLink(
142 ModifierData *md, Object *ob,
143 void (*walk)(void *userData, Object *ob, Object **obpoin),
144 void *userData)
146 CurveModifierData *cmd = (CurveModifierData*) md;
148 walk(userData, ob, &cmd->object);
151 static void curveModifier_updateDepgraph(
152 ModifierData *md, DagForest *forest,
153 Object *ob, DagNode *obNode)
155 CurveModifierData *cmd = (CurveModifierData*) md;
157 if (cmd->object) {
158 DagNode *curNode = dag_get_node(forest, cmd->object);
160 dag_add_relation(forest, curNode, obNode,
161 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
165 static void curveModifier_deformVerts(
166 ModifierData *md, Object *ob, DerivedMesh *derivedData,
167 float (*vertexCos)[3], int numVerts)
169 CurveModifierData *cmd = (CurveModifierData*) md;
171 curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts,
172 cmd->name, cmd->defaxis);
175 static void curveModifier_deformVertsEM(
176 ModifierData *md, Object *ob, EditMesh *editData,
177 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
179 DerivedMesh *dm = derivedData;
181 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
183 curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
185 if(!derivedData) dm->release(dm);
188 /* Lattice */
190 static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
192 LatticeModifierData *lmd = (LatticeModifierData*) md;
193 LatticeModifierData *tlmd = (LatticeModifierData*) target;
195 tlmd->object = lmd->object;
196 strncpy(tlmd->name, lmd->name, 32);
199 CustomDataMask latticeModifier_requiredDataMask(ModifierData *md)
201 LatticeModifierData *lmd = (LatticeModifierData *)md;
202 CustomDataMask dataMask = 0;
204 /* ask for vertexgroups if we need them */
205 if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
207 return dataMask;
210 static int latticeModifier_isDisabled(ModifierData *md)
212 LatticeModifierData *lmd = (LatticeModifierData*) md;
214 return !lmd->object;
217 static void latticeModifier_foreachObjectLink(
218 ModifierData *md, Object *ob,
219 void (*walk)(void *userData, Object *ob, Object **obpoin),
220 void *userData)
222 LatticeModifierData *lmd = (LatticeModifierData*) md;
224 walk(userData, ob, &lmd->object);
227 static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest,
228 Object *ob, DagNode *obNode)
230 LatticeModifierData *lmd = (LatticeModifierData*) md;
232 if(lmd->object) {
233 DagNode *latNode = dag_get_node(forest, lmd->object);
235 dag_add_relation(forest, latNode, obNode,
236 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
240 static void latticeModifier_deformVerts(
241 ModifierData *md, Object *ob, DerivedMesh *derivedData,
242 float (*vertexCos)[3], int numVerts)
244 LatticeModifierData *lmd = (LatticeModifierData*) md;
246 lattice_deform_verts(lmd->object, ob, derivedData,
247 vertexCos, numVerts, lmd->name);
250 static void latticeModifier_deformVertsEM(
251 ModifierData *md, Object *ob, EditMesh *editData,
252 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
254 DerivedMesh *dm = derivedData;
256 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
258 latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
260 if(!derivedData) dm->release(dm);
263 /* Subsurf */
265 static void subsurfModifier_initData(ModifierData *md)
267 SubsurfModifierData *smd = (SubsurfModifierData*) md;
269 smd->levels = 1;
270 smd->renderLevels = 2;
271 smd->flags |= eSubsurfModifierFlag_SubsurfUv;
274 static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
276 SubsurfModifierData *smd = (SubsurfModifierData*) md;
277 SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
279 tsmd->flags = smd->flags;
280 tsmd->levels = smd->levels;
281 tsmd->renderLevels = smd->renderLevels;
282 tsmd->subdivType = smd->subdivType;
285 static void subsurfModifier_freeData(ModifierData *md)
287 SubsurfModifierData *smd = (SubsurfModifierData*) md;
289 if(smd->mCache) {
290 ccgSubSurf_free(smd->mCache);
292 if(smd->emCache) {
293 ccgSubSurf_free(smd->emCache);
297 static DerivedMesh *subsurfModifier_applyModifier(
298 ModifierData *md, Object *ob, DerivedMesh *derivedData,
299 int useRenderParams, int isFinalCalc)
301 SubsurfModifierData *smd = (SubsurfModifierData*) md;
302 DerivedMesh *result;
304 result = subsurf_make_derived_from_derived(derivedData, smd,
305 useRenderParams, NULL,
306 isFinalCalc, 0);
308 return result;
311 static DerivedMesh *subsurfModifier_applyModifierEM(
312 ModifierData *md, Object *ob, EditMesh *editData,
313 DerivedMesh *derivedData)
315 SubsurfModifierData *smd = (SubsurfModifierData*) md;
316 DerivedMesh *result;
318 result = subsurf_make_derived_from_derived(derivedData, smd, 0,
319 NULL, 0, 1);
321 return result;
324 /* Build */
326 static void buildModifier_initData(ModifierData *md)
328 BuildModifierData *bmd = (BuildModifierData*) md;
330 bmd->start = 1.0;
331 bmd->length = 100.0;
334 static void buildModifier_copyData(ModifierData *md, ModifierData *target)
336 BuildModifierData *bmd = (BuildModifierData*) md;
337 BuildModifierData *tbmd = (BuildModifierData*) target;
339 tbmd->start = bmd->start;
340 tbmd->length = bmd->length;
341 tbmd->randomize = bmd->randomize;
342 tbmd->seed = bmd->seed;
345 static int buildModifier_dependsOnTime(ModifierData *md)
347 return 1;
350 static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
351 DerivedMesh *derivedData,
352 int useRenderParams, int isFinalCalc)
354 DerivedMesh *dm = derivedData;
355 DerivedMesh *result;
356 BuildModifierData *bmd = (BuildModifierData*) md;
357 int i;
358 int numFaces, numEdges;
359 int maxVerts, maxEdges, maxFaces;
360 int *vertMap, *edgeMap, *faceMap;
361 float frac;
362 GHashIterator *hashIter;
363 /* maps vert indices in old mesh to indices in new mesh */
364 GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
365 BLI_ghashutil_intcmp);
366 /* maps edge indices in new mesh to indices in old mesh */
367 GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
368 BLI_ghashutil_intcmp);
370 maxVerts = dm->getNumVerts(dm);
371 vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
372 "build modifier vertMap");
373 for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
375 maxEdges = dm->getNumEdges(dm);
376 edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
377 "build modifier edgeMap");
378 for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
380 maxFaces = dm->getNumFaces(dm);
381 faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
382 "build modifier faceMap");
383 for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
385 if (ob) {
386 frac = bsystem_time(ob, 0, (float)G.scene->r.cfra,
387 bmd->start - 1.0f) / bmd->length;
388 } else {
389 frac = G.scene->r.cfra - bmd->start / bmd->length;
391 CLAMP(frac, 0.0, 1.0);
393 numFaces = dm->getNumFaces(dm) * frac;
394 numEdges = dm->getNumEdges(dm) * frac;
396 /* if there's at least one face, build based on faces */
397 if(numFaces) {
398 int maxEdges;
400 if(bmd->randomize)
401 BLI_array_randomize(faceMap, sizeof(*faceMap),
402 maxFaces, bmd->seed);
404 /* get the set of all vert indices that will be in the final mesh,
405 * mapped to the new indices
407 for(i = 0; i < numFaces; ++i) {
408 MFace mf;
409 dm->getFace(dm, faceMap[i], &mf);
411 if(!BLI_ghash_haskey(vertHash, (void *)mf.v1))
412 BLI_ghash_insert(vertHash, (void *)mf.v1,
413 (void *)BLI_ghash_size(vertHash));
414 if(!BLI_ghash_haskey(vertHash, (void *)mf.v2))
415 BLI_ghash_insert(vertHash, (void *)mf.v2,
416 (void *)BLI_ghash_size(vertHash));
417 if(!BLI_ghash_haskey(vertHash, (void *)mf.v3))
418 BLI_ghash_insert(vertHash, (void *)mf.v3,
419 (void *)BLI_ghash_size(vertHash));
420 if(mf.v4 && !BLI_ghash_haskey(vertHash, (void *)mf.v4))
421 BLI_ghash_insert(vertHash, (void *)mf.v4,
422 (void *)BLI_ghash_size(vertHash));
425 /* get the set of edges that will be in the new mesh (i.e. all edges
426 * that have both verts in the new mesh)
428 maxEdges = dm->getNumEdges(dm);
429 for(i = 0; i < maxEdges; ++i) {
430 MEdge me;
431 dm->getEdge(dm, i, &me);
433 if(BLI_ghash_haskey(vertHash, (void *)me.v1)
434 && BLI_ghash_haskey(vertHash, (void *)me.v2))
435 BLI_ghash_insert(edgeHash,
436 (void *)BLI_ghash_size(edgeHash), (void *)i);
438 } else if(numEdges) {
439 if(bmd->randomize)
440 BLI_array_randomize(edgeMap, sizeof(*edgeMap),
441 maxEdges, bmd->seed);
443 /* get the set of all vert indices that will be in the final mesh,
444 * mapped to the new indices
446 for(i = 0; i < numEdges; ++i) {
447 MEdge me;
448 dm->getEdge(dm, edgeMap[i], &me);
450 if(!BLI_ghash_haskey(vertHash, (void *)me.v1))
451 BLI_ghash_insert(vertHash, (void *)me.v1,
452 (void *)BLI_ghash_size(vertHash));
453 if(!BLI_ghash_haskey(vertHash, (void *)me.v2))
454 BLI_ghash_insert(vertHash, (void *)me.v2,
455 (void *)BLI_ghash_size(vertHash));
458 /* get the set of edges that will be in the new mesh
460 for(i = 0; i < numEdges; ++i) {
461 MEdge me;
462 dm->getEdge(dm, edgeMap[i], &me);
464 BLI_ghash_insert(edgeHash, (void *)BLI_ghash_size(edgeHash),
465 (void *)edgeMap[i]);
467 } else {
468 int numVerts = dm->getNumVerts(dm) * frac;
470 if(bmd->randomize)
471 BLI_array_randomize(vertMap, sizeof(*vertMap),
472 maxVerts, bmd->seed);
474 /* get the set of all vert indices that will be in the final mesh,
475 * mapped to the new indices
477 for(i = 0; i < numVerts; ++i)
478 BLI_ghash_insert(vertHash, (void *)vertMap[i], (void *)i);
481 /* now we know the number of verts, edges and faces, we can create
482 * the mesh
484 result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
485 BLI_ghash_size(edgeHash), numFaces);
487 /* copy the vertices across */
488 for(hashIter = BLI_ghashIterator_new(vertHash);
489 !BLI_ghashIterator_isDone(hashIter);
490 BLI_ghashIterator_step(hashIter)) {
491 MVert source;
492 MVert *dest;
493 int oldIndex = (int)BLI_ghashIterator_getKey(hashIter);
494 int newIndex = (int)BLI_ghashIterator_getValue(hashIter);
496 dm->getVert(dm, oldIndex, &source);
497 dest = CDDM_get_vert(result, newIndex);
499 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
500 *dest = source;
502 BLI_ghashIterator_free(hashIter);
504 /* copy the edges across, remapping indices */
505 for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
506 MEdge source;
507 MEdge *dest;
508 int oldIndex = (int)BLI_ghash_lookup(edgeHash, (void *)i);
510 dm->getEdge(dm, oldIndex, &source);
511 dest = CDDM_get_edge(result, i);
513 source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
514 source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
516 DM_copy_edge_data(dm, result, oldIndex, i, 1);
517 *dest = source;
520 /* copy the faces across, remapping indices */
521 for(i = 0; i < numFaces; ++i) {
522 MFace source;
523 MFace *dest;
524 int orig_v4;
526 dm->getFace(dm, faceMap[i], &source);
527 dest = CDDM_get_face(result, i);
529 orig_v4 = source.v4;
531 source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
532 source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
533 source.v3 = (int)BLI_ghash_lookup(vertHash, (void *)source.v3);
534 if(source.v4)
535 source.v4 = (int)BLI_ghash_lookup(vertHash, (void *)source.v4);
537 DM_copy_face_data(dm, result, faceMap[i], i, 1);
538 *dest = source;
540 test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
543 CDDM_calc_normals(result);
545 BLI_ghash_free(vertHash, NULL, NULL);
546 BLI_ghash_free(edgeHash, NULL, NULL);
548 MEM_freeN(vertMap);
549 MEM_freeN(edgeMap);
550 MEM_freeN(faceMap);
552 return result;
555 /* Array */
556 /* Array modifier: duplicates the object multiple times along an axis
559 static void arrayModifier_initData(ModifierData *md)
561 ArrayModifierData *amd = (ArrayModifierData*) md;
563 /* default to 2 duplicates distributed along the x-axis by an
564 offset of 1 object-width
566 amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
567 amd->count = 2;
568 amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
569 amd->scale[0] = 1;
570 amd->scale[1] = amd->scale[2] = 0;
571 amd->length = 0;
572 amd->merge_dist = 0.01;
573 amd->fit_type = MOD_ARR_FIXEDCOUNT;
574 amd->offset_type = MOD_ARR_OFF_RELATIVE;
575 amd->flags = 0;
578 static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
580 ArrayModifierData *amd = (ArrayModifierData*) md;
581 ArrayModifierData *tamd = (ArrayModifierData*) target;
583 tamd->start_cap = amd->start_cap;
584 tamd->end_cap = amd->end_cap;
585 tamd->curve_ob = amd->curve_ob;
586 tamd->offset_ob = amd->offset_ob;
587 tamd->count = amd->count;
588 VECCOPY(tamd->offset, amd->offset);
589 VECCOPY(tamd->scale, amd->scale);
590 tamd->length = amd->length;
591 tamd->merge_dist = amd->merge_dist;
592 tamd->fit_type = amd->fit_type;
593 tamd->offset_type = amd->offset_type;
594 tamd->flags = amd->flags;
597 static void arrayModifier_foreachObjectLink(
598 ModifierData *md, Object *ob,
599 void (*walk)(void *userData, Object *ob, Object **obpoin),
600 void *userData)
602 ArrayModifierData *amd = (ArrayModifierData*) md;
604 walk(userData, ob, &amd->start_cap);
605 walk(userData, ob, &amd->end_cap);
606 walk(userData, ob, &amd->curve_ob);
607 walk(userData, ob, &amd->offset_ob);
610 static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest,
611 Object *ob, DagNode *obNode)
613 ArrayModifierData *amd = (ArrayModifierData*) md;
615 if (amd->start_cap) {
616 DagNode *curNode = dag_get_node(forest, amd->start_cap);
618 dag_add_relation(forest, curNode, obNode,
619 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
621 if (amd->end_cap) {
622 DagNode *curNode = dag_get_node(forest, amd->end_cap);
624 dag_add_relation(forest, curNode, obNode,
625 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
627 if (amd->curve_ob) {
628 DagNode *curNode = dag_get_node(forest, amd->curve_ob);
630 dag_add_relation(forest, curNode, obNode,
631 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
633 if (amd->offset_ob) {
634 DagNode *curNode = dag_get_node(forest, amd->offset_ob);
636 dag_add_relation(forest, curNode, obNode,
637 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
641 float vertarray_size(MVert *mvert, int numVerts, int axis)
643 int i;
644 float min_co, max_co;
646 /* if there are no vertices, width is 0 */
647 if(numVerts == 0) return 0;
649 /* find the minimum and maximum coordinates on the desired axis */
650 min_co = max_co = mvert->co[axis];
651 ++mvert;
652 for(i = 1; i < numVerts; ++i, ++mvert) {
653 if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
654 if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
657 return max_co - min_co;
660 typedef struct IndexMapEntry {
661 /* the new vert index that this old vert index maps to */
662 int new;
663 /* -1 if this vert isn't merged, otherwise the old vert index it
664 * should be replaced with
666 int merge;
667 /* 1 if this vert's first copy is merged with the last copy of its
668 * merge target, otherwise 0
670 short merge_final;
671 } IndexMapEntry;
673 /* indexMap - an array of IndexMap entries
674 * oldIndex - the old index to map
675 * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
677 static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
679 if(indexMap[oldIndex].merge < 0) {
680 /* vert wasn't merged, so use copy of this vert */
681 return indexMap[oldIndex].new + copyNum;
682 } else if(indexMap[oldIndex].merge == oldIndex) {
683 /* vert was merged with itself */
684 return indexMap[oldIndex].new;
685 } else {
686 /* vert was merged with another vert */
687 /* follow the chain of merges to the end, or until we've passed
688 * a number of vertices equal to the copy number
690 if(copyNum <= 0)
691 return indexMap[oldIndex].new;
692 else
693 return calc_mapping(indexMap, indexMap[oldIndex].merge,
694 copyNum - 1);
698 static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
699 Object *ob, DerivedMesh *dm,
700 int initFlags)
702 int i, j;
703 /* offset matrix */
704 float offset[4][4];
705 float final_offset[4][4];
706 float tmp_mat[4][4];
707 float length = amd->length;
708 int count = amd->count;
709 int numVerts, numEdges, numFaces;
710 int maxVerts, maxEdges, maxFaces;
711 int finalVerts, finalEdges, finalFaces;
712 DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
713 MVert *mvert, *src_mvert;
714 MEdge *medge;
715 MFace *mface;
717 IndexMapEntry *indexMap;
719 EdgeHash *edges;
721 /* need to avoid infinite recursion here */
722 if(amd->start_cap && amd->start_cap != ob)
723 start_cap = mesh_get_derived_final(amd->start_cap, CD_MASK_MESH);
724 if(amd->end_cap && amd->end_cap != ob)
725 end_cap = mesh_get_derived_final(amd->end_cap, CD_MASK_MESH);
727 MTC_Mat4One(offset);
729 indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
730 "indexmap");
732 src_mvert = dm->getVertArray(dm);
734 maxVerts = dm->getNumVerts(dm);
736 if(amd->offset_type & MOD_ARR_OFF_CONST)
737 VecAddf(offset[3], offset[3], amd->offset);
738 if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
739 for(j = 0; j < 3; j++)
740 offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
741 maxVerts, j);
744 if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
745 float obinv[4][4];
746 float result_mat[4][4];
748 if(ob)
749 MTC_Mat4Invert(obinv, ob->obmat);
750 else
751 MTC_Mat4One(obinv);
753 MTC_Mat4MulSerie(result_mat, offset,
754 obinv, amd->offset_ob->obmat,
755 NULL, NULL, NULL, NULL, NULL);
756 MTC_Mat4CpyMat4(offset, result_mat);
759 if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
760 Curve *cu = amd->curve_ob->data;
761 if(cu) {
762 if(!cu->path) {
763 cu->flag |= CU_PATH; // needed for path & bevlist
764 makeDispListCurveTypes(amd->curve_ob, 0);
766 if(cu->path)
767 length = cu->path->totdist;
771 /* calculate the maximum number of copies which will fit within the
772 prescribed length */
773 if(amd->fit_type == MOD_ARR_FITLENGTH
774 || amd->fit_type == MOD_ARR_FITCURVE) {
775 float dist = sqrt(MTC_dot3Float(offset[3], offset[3]));
777 if(dist > FLT_EPSILON)
778 /* this gives length = first copy start to last copy end
779 add a tiny offset for floating point rounding errors */
780 count = (length + FLT_EPSILON) / dist;
781 else
782 /* if the offset has no translation, just make one copy */
783 count = 1;
786 if(count < 1)
787 count = 1;
789 /* allocate memory for count duplicates (including original) plus
790 * start and end caps
792 finalVerts = dm->getNumVerts(dm) * count;
793 finalEdges = dm->getNumEdges(dm) * count;
794 finalFaces = dm->getNumFaces(dm) * count;
795 if(start_cap) {
796 finalVerts += start_cap->getNumVerts(start_cap);
797 finalEdges += start_cap->getNumEdges(start_cap);
798 finalFaces += start_cap->getNumFaces(start_cap);
800 if(end_cap) {
801 finalVerts += end_cap->getNumVerts(end_cap);
802 finalEdges += end_cap->getNumEdges(end_cap);
803 finalFaces += end_cap->getNumFaces(end_cap);
805 result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
807 /* calculate the offset matrix of the final copy (for merging) */
808 MTC_Mat4One(final_offset);
810 for(j=0; j < count - 1; j++) {
811 MTC_Mat4MulMat4(tmp_mat, final_offset, offset);
812 MTC_Mat4CpyMat4(final_offset, tmp_mat);
815 numVerts = numEdges = numFaces = 0;
816 mvert = CDDM_get_verts(result);
818 for (i = 0; i < maxVerts; i++) {
819 MVert *inMV;
820 MVert *mv = &mvert[numVerts];
821 MVert *mv2;
822 float co[3];
824 inMV = &src_mvert[i];
826 DM_copy_vert_data(dm, result, i, numVerts, 1);
827 *mv = *inMV;
828 numVerts++;
830 indexMap[i].new = numVerts - 1;
831 indexMap[i].merge = -1; /* default to no merge */
832 indexMap[i].merge_final = 0; /* default to no merge */
834 VECCOPY(co, mv->co);
836 /* Attempts to merge verts from one duplicate with verts from the
837 * next duplicate which are closer than amd->merge_dist.
838 * Only the first such vert pair is merged.
839 * If verts are merged in the first duplicate pair, they are merged
840 * in all pairs.
842 if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
843 float tmp_co[3];
844 VECCOPY(tmp_co, mv->co);
845 MTC_Mat4MulVecfl(offset, tmp_co);
847 for(j = 0; j < maxVerts; j++) {
848 inMV = &src_mvert[j];
849 /* if this vert is within merge limit, merge */
850 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) {
851 indexMap[i].merge = j;
853 /* test for merging with final copy of merge target */
854 if(amd->flags & MOD_ARR_MERGEFINAL) {
855 VECCOPY(tmp_co, inMV->co);
856 inMV = &src_mvert[i];
857 MTC_Mat4MulVecfl(final_offset, tmp_co);
858 if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist))
859 indexMap[i].merge_final = 1;
861 break;
866 /* if no merging, generate copies of this vert */
867 if(indexMap[i].merge < 0) {
868 for(j=0; j < count - 1; j++) {
869 mv2 = &mvert[numVerts];
871 DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
872 *mv2 = *mv;
873 numVerts++;
875 MTC_Mat4MulVecfl(offset, co);
876 VECCOPY(mv2->co, co);
878 } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
879 /* if this vert is not merging with itself, and it is merging
880 * with the final copy of its merge target, remove the first copy
882 numVerts--;
883 DM_free_vert_data(result, numVerts, 1);
887 /* make a hashtable so we can avoid duplicate edges from merging */
888 edges = BLI_edgehash_new();
890 maxEdges = dm->getNumEdges(dm);
891 medge = CDDM_get_edges(result);
892 for(i = 0; i < maxEdges; i++) {
893 MEdge inMED;
894 MEdge med;
895 MEdge *med2;
896 int vert1, vert2;
898 dm->getEdge(dm, i, &inMED);
900 med = inMED;
901 med.v1 = indexMap[inMED.v1].new;
902 med.v2 = indexMap[inMED.v2].new;
904 /* if vertices are to be merged with the final copies of their
905 * merge targets, calculate that final copy
907 if(indexMap[inMED.v1].merge_final) {
908 med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
909 count - 1);
911 if(indexMap[inMED.v2].merge_final) {
912 med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
913 count - 1);
916 if (initFlags) {
917 med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
920 if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
921 DM_copy_edge_data(dm, result, i, numEdges, 1);
922 medge[numEdges] = med;
923 numEdges++;
925 BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
928 for(j = 1; j < count; j++)
930 vert1 = calc_mapping(indexMap, inMED.v1, j);
931 vert2 = calc_mapping(indexMap, inMED.v2, j);
932 /* avoid duplicate edges */
933 if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
934 med2 = &medge[numEdges];
936 DM_copy_edge_data(dm, result, i, numEdges, 1);
937 *med2 = med;
938 numEdges++;
940 med2->v1 = vert1;
941 med2->v2 = vert2;
943 BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
948 maxFaces = dm->getNumFaces(dm);
949 mface = CDDM_get_faces(result);
950 for (i=0; i < maxFaces; i++) {
951 MFace inMF;
952 MFace *mf = &mface[numFaces];
954 dm->getFace(dm, i, &inMF);
956 DM_copy_face_data(dm, result, i, numFaces, 1);
957 *mf = inMF;
959 mf->v1 = indexMap[inMF.v1].new;
960 mf->v2 = indexMap[inMF.v2].new;
961 mf->v3 = indexMap[inMF.v3].new;
962 if(inMF.v4)
963 mf->v4 = indexMap[inMF.v4].new;
965 /* if vertices are to be merged with the final copies of their
966 * merge targets, calculate that final copy
968 if(indexMap[inMF.v1].merge_final)
969 mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
970 if(indexMap[inMF.v2].merge_final)
971 mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
972 if(indexMap[inMF.v3].merge_final)
973 mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
974 if(inMF.v4 && indexMap[inMF.v4].merge_final)
975 mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
977 test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3);
978 numFaces++;
980 /* if the face has fewer than 3 vertices, don't create it */
981 if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
982 numFaces--;
983 DM_free_face_data(result, numFaces, 1);
986 for(j = 1; j < count; j++)
988 MFace *mf2 = &mface[numFaces];
990 DM_copy_face_data(dm, result, i, numFaces, 1);
991 *mf2 = *mf;
993 mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
994 mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
995 mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
996 if (inMF.v4)
997 mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
999 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
1000 numFaces++;
1002 /* if the face has fewer than 3 vertices, don't create it */
1003 if(mf2->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
1004 numFaces--;
1005 DM_free_face_data(result, numFaces, 1);
1010 /* add start and end caps */
1011 if(start_cap) {
1012 float startoffset[4][4];
1013 MVert *cap_mvert;
1014 MEdge *cap_medge;
1015 MFace *cap_mface;
1016 int *origindex;
1017 int *vert_map;
1018 int capVerts, capEdges, capFaces;
1020 capVerts = start_cap->getNumVerts(start_cap);
1021 capEdges = start_cap->getNumEdges(start_cap);
1022 capFaces = start_cap->getNumFaces(start_cap);
1023 cap_mvert = start_cap->getVertArray(start_cap);
1024 cap_medge = start_cap->getEdgeArray(start_cap);
1025 cap_mface = start_cap->getFaceArray(start_cap);
1027 Mat4Invert(startoffset, offset);
1029 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1030 "arrayModifier_doArray vert_map");
1032 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1033 for(i = 0; i < capVerts; i++) {
1034 MVert *mv = &cap_mvert[i];
1035 short merged = 0;
1037 if(amd->flags & MOD_ARR_MERGE) {
1038 float tmp_co[3];
1039 MVert *in_mv;
1040 int j;
1042 VECCOPY(tmp_co, mv->co);
1043 Mat4MulVecfl(startoffset, tmp_co);
1045 for(j = 0; j < maxVerts; j++) {
1046 in_mv = &src_mvert[j];
1047 /* if this vert is within merge limit, merge */
1048 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1049 vert_map[i] = calc_mapping(indexMap, j, 0);
1050 merged = 1;
1051 break;
1056 if(!merged) {
1057 DM_copy_vert_data(start_cap, result, i, numVerts, 1);
1058 mvert[numVerts] = *mv;
1059 Mat4MulVecfl(startoffset, mvert[numVerts].co);
1060 origindex[numVerts] = ORIGINDEX_NONE;
1062 vert_map[i] = numVerts;
1064 numVerts++;
1067 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1068 for(i = 0; i < capEdges; i++) {
1069 int v1, v2;
1071 v1 = vert_map[cap_medge[i].v1];
1072 v2 = vert_map[cap_medge[i].v2];
1074 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1075 DM_copy_edge_data(start_cap, result, i, numEdges, 1);
1076 medge[numEdges] = cap_medge[i];
1077 medge[numEdges].v1 = v1;
1078 medge[numEdges].v2 = v2;
1079 origindex[numEdges] = ORIGINDEX_NONE;
1081 numEdges++;
1084 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1085 for(i = 0; i < capFaces; i++) {
1086 DM_copy_face_data(start_cap, result, i, numFaces, 1);
1087 mface[numFaces] = cap_mface[i];
1088 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1089 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1090 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1091 if(mface[numFaces].v4)
1092 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1093 origindex[numFaces] = ORIGINDEX_NONE;
1095 numFaces++;
1098 MEM_freeN(vert_map);
1099 start_cap->release(start_cap);
1102 if(end_cap) {
1103 float endoffset[4][4];
1104 MVert *cap_mvert;
1105 MEdge *cap_medge;
1106 MFace *cap_mface;
1107 int *origindex;
1108 int *vert_map;
1109 int capVerts, capEdges, capFaces;
1111 capVerts = end_cap->getNumVerts(end_cap);
1112 capEdges = end_cap->getNumEdges(end_cap);
1113 capFaces = end_cap->getNumFaces(end_cap);
1114 cap_mvert = end_cap->getVertArray(end_cap);
1115 cap_medge = end_cap->getEdgeArray(end_cap);
1116 cap_mface = end_cap->getFaceArray(end_cap);
1118 Mat4MulMat4(endoffset, final_offset, offset);
1120 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1121 "arrayModifier_doArray vert_map");
1123 origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1124 for(i = 0; i < capVerts; i++) {
1125 MVert *mv = &cap_mvert[i];
1126 short merged = 0;
1128 if(amd->flags & MOD_ARR_MERGE) {
1129 float tmp_co[3];
1130 MVert *in_mv;
1131 int j;
1133 VECCOPY(tmp_co, mv->co);
1134 Mat4MulVecfl(offset, tmp_co);
1136 for(j = 0; j < maxVerts; j++) {
1137 in_mv = &src_mvert[j];
1138 /* if this vert is within merge limit, merge */
1139 if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1140 vert_map[i] = calc_mapping(indexMap, j, count - 1);
1141 merged = 1;
1142 break;
1147 if(!merged) {
1148 DM_copy_vert_data(end_cap, result, i, numVerts, 1);
1149 mvert[numVerts] = *mv;
1150 Mat4MulVecfl(endoffset, mvert[numVerts].co);
1151 origindex[numVerts] = ORIGINDEX_NONE;
1153 vert_map[i] = numVerts;
1155 numVerts++;
1158 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1159 for(i = 0; i < capEdges; i++) {
1160 int v1, v2;
1162 v1 = vert_map[cap_medge[i].v1];
1163 v2 = vert_map[cap_medge[i].v2];
1165 if(!BLI_edgehash_haskey(edges, v1, v2)) {
1166 DM_copy_edge_data(end_cap, result, i, numEdges, 1);
1167 medge[numEdges] = cap_medge[i];
1168 medge[numEdges].v1 = v1;
1169 medge[numEdges].v2 = v2;
1170 origindex[numEdges] = ORIGINDEX_NONE;
1172 numEdges++;
1175 origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1176 for(i = 0; i < capFaces; i++) {
1177 DM_copy_face_data(end_cap, result, i, numFaces, 1);
1178 mface[numFaces] = cap_mface[i];
1179 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1180 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1181 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1182 if(mface[numFaces].v4)
1183 mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1184 origindex[numFaces] = ORIGINDEX_NONE;
1186 numFaces++;
1189 MEM_freeN(vert_map);
1190 end_cap->release(end_cap);
1193 BLI_edgehash_free(edges, NULL);
1194 MEM_freeN(indexMap);
1196 CDDM_lower_num_verts(result, numVerts);
1197 CDDM_lower_num_edges(result, numEdges);
1198 CDDM_lower_num_faces(result, numFaces);
1200 return result;
1203 static DerivedMesh *arrayModifier_applyModifier(
1204 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1205 int useRenderParams, int isFinalCalc)
1207 DerivedMesh *result;
1208 ArrayModifierData *amd = (ArrayModifierData*) md;
1210 result = arrayModifier_doArray(amd, ob, derivedData, 0);
1212 CDDM_calc_normals(result);
1214 return result;
1217 static DerivedMesh *arrayModifier_applyModifierEM(
1218 ModifierData *md, Object *ob, EditMesh *editData,
1219 DerivedMesh *derivedData)
1221 return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
1224 /* Mirror */
1226 static void mirrorModifier_initData(ModifierData *md)
1228 MirrorModifierData *mmd = (MirrorModifierData*) md;
1230 mmd->flag |= MOD_MIR_AXIS_X;
1231 mmd->tolerance = 0.001;
1232 mmd->mirror_ob = NULL;
1235 static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
1237 MirrorModifierData *mmd = (MirrorModifierData*) md;
1238 MirrorModifierData *tmmd = (MirrorModifierData*) target;
1240 tmmd->axis = mmd->axis;
1241 tmmd->flag = mmd->flag;
1242 tmmd->tolerance = mmd->tolerance;
1243 tmmd->mirror_ob = mmd->mirror_ob;;
1246 static void mirrorModifier_foreachObjectLink(
1247 ModifierData *md, Object *ob,
1248 void (*walk)(void *userData, Object *ob, Object **obpoin),
1249 void *userData)
1251 MirrorModifierData *mmd = (MirrorModifierData*) md;
1253 walk(userData, ob, &mmd->mirror_ob);
1256 static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest,
1257 Object *ob, DagNode *obNode)
1259 MirrorModifierData *mmd = (MirrorModifierData*) md;
1261 if(mmd->mirror_ob) {
1262 DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
1264 dag_add_relation(forest, latNode, obNode,
1265 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
1269 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
1270 Object *ob,
1271 DerivedMesh *dm,
1272 int initFlags,
1273 int axis)
1275 int i;
1276 float tolerance = mmd->tolerance;
1277 DerivedMesh *result;
1278 int numVerts, numEdges, numFaces;
1279 int maxVerts = dm->getNumVerts(dm);
1280 int maxEdges = dm->getNumEdges(dm);
1281 int maxFaces = dm->getNumFaces(dm);
1282 int (*indexMap)[2];
1283 float mtx[4][4], imtx[4][4];
1285 numVerts = numEdges = numFaces = 0;
1287 indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
1289 result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
1291 if (mmd->mirror_ob) {
1292 float obinv[4][4];
1294 Mat4Invert(obinv, mmd->mirror_ob->obmat);
1295 Mat4MulMat4(mtx, ob->obmat, obinv);
1296 Mat4Invert(imtx, mtx);
1299 for(i = 0; i < maxVerts; i++) {
1300 MVert inMV;
1301 MVert *mv = CDDM_get_vert(result, numVerts);
1302 int isShared;
1303 float co[3];
1305 dm->getVert(dm, i, &inMV);
1307 VecCopyf(co, inMV.co);
1309 if (mmd->mirror_ob) {
1310 VecMat4MulVecfl(co, mtx, co);
1312 isShared = ABS(co[axis])<=tolerance;
1314 /* Because the topology result (# of vertices) must be the same if
1315 * the mesh data is overridden by vertex cos, have to calc sharedness
1316 * based on original coordinates. This is why we test before copy.
1318 DM_copy_vert_data(dm, result, i, numVerts, 1);
1319 *mv = inMV;
1320 numVerts++;
1322 indexMap[i][0] = numVerts - 1;
1323 indexMap[i][1] = !isShared;
1325 if(isShared) {
1326 co[axis] = 0;
1327 if (mmd->mirror_ob) {
1328 VecMat4MulVecfl(co, imtx, co);
1330 VecCopyf(mv->co, co);
1332 mv->flag |= ME_VERT_MERGED;
1333 } else {
1334 MVert *mv2 = CDDM_get_vert(result, numVerts);
1336 DM_copy_vert_data(dm, result, i, numVerts, 1);
1337 *mv2 = *mv;
1338 numVerts++;
1340 co[axis] = -co[axis];
1341 if (mmd->mirror_ob) {
1342 VecMat4MulVecfl(co, imtx, co);
1344 VecCopyf(mv2->co, co);
1348 for(i = 0; i < maxEdges; i++) {
1349 MEdge inMED;
1350 MEdge *med = CDDM_get_edge(result, numEdges);
1352 dm->getEdge(dm, i, &inMED);
1354 DM_copy_edge_data(dm, result, i, numEdges, 1);
1355 *med = inMED;
1356 numEdges++;
1358 med->v1 = indexMap[inMED.v1][0];
1359 med->v2 = indexMap[inMED.v2][0];
1360 if(initFlags)
1361 med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
1363 if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
1364 MEdge *med2 = CDDM_get_edge(result, numEdges);
1366 DM_copy_edge_data(dm, result, i, numEdges, 1);
1367 *med2 = *med;
1368 numEdges++;
1370 med2->v1 += indexMap[inMED.v1][1];
1371 med2->v2 += indexMap[inMED.v2][1];
1375 for(i = 0; i < maxFaces; i++) {
1376 MFace inMF;
1377 MFace *mf = CDDM_get_face(result, numFaces);
1379 dm->getFace(dm, i, &inMF);
1381 DM_copy_face_data(dm, result, i, numFaces, 1);
1382 *mf = inMF;
1383 numFaces++;
1385 mf->v1 = indexMap[inMF.v1][0];
1386 mf->v2 = indexMap[inMF.v2][0];
1387 mf->v3 = indexMap[inMF.v3][0];
1388 mf->v4 = indexMap[inMF.v4][0];
1390 if(indexMap[inMF.v1][1]
1391 || indexMap[inMF.v2][1]
1392 || indexMap[inMF.v3][1]
1393 || (mf->v4 && indexMap[inMF.v4][1])) {
1394 MFace *mf2 = CDDM_get_face(result, numFaces);
1395 static int corner_indices[4] = {2, 1, 0, 3};
1397 DM_copy_face_data(dm, result, i, numFaces, 1);
1398 *mf2 = *mf;
1400 mf2->v1 += indexMap[inMF.v1][1];
1401 mf2->v2 += indexMap[inMF.v2][1];
1402 mf2->v3 += indexMap[inMF.v3][1];
1403 if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
1405 /* mirror UVs if enabled */
1406 if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
1407 MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
1408 if(tf) {
1409 int j;
1410 for(j = 0; j < 4; ++j) {
1411 if(mmd->flag & MOD_MIR_MIRROR_U)
1412 tf->uv[j][0] = 1.0f - tf->uv[j][0];
1413 if(mmd->flag & MOD_MIR_MIRROR_V)
1414 tf->uv[j][1] = 1.0f - tf->uv[j][1];
1419 /* Flip face normal */
1420 SWAP(int, mf2->v1, mf2->v3);
1421 DM_swap_face_data(result, numFaces, corner_indices);
1423 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
1424 numFaces++;
1428 MEM_freeN(indexMap);
1430 CDDM_lower_num_verts(result, numVerts);
1431 CDDM_lower_num_edges(result, numEdges);
1432 CDDM_lower_num_faces(result, numFaces);
1434 return result;
1437 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
1438 Object *ob, DerivedMesh *dm,
1439 int initFlags)
1441 DerivedMesh *result = dm;
1443 /* check which axes have been toggled and mirror accordingly */
1444 if(mmd->flag & MOD_MIR_AXIS_X) {
1445 result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
1447 if(mmd->flag & MOD_MIR_AXIS_Y) {
1448 DerivedMesh *tmp = result;
1449 result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
1450 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
1452 if(mmd->flag & MOD_MIR_AXIS_Z) {
1453 DerivedMesh *tmp = result;
1454 result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
1455 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
1458 return result;
1461 static DerivedMesh *mirrorModifier_applyModifier(
1462 ModifierData *md, Object *ob, DerivedMesh *derivedData,
1463 int useRenderParams, int isFinalCalc)
1465 DerivedMesh *result;
1466 MirrorModifierData *mmd = (MirrorModifierData*) md;
1468 result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
1470 CDDM_calc_normals(result);
1472 return result;
1475 static DerivedMesh *mirrorModifier_applyModifierEM(
1476 ModifierData *md, Object *ob, EditMesh *editData,
1477 DerivedMesh *derivedData)
1479 return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
1482 /* EdgeSplit */
1483 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
1484 * or edge angle (can be used to achieve autosmoothing)
1486 #if 0
1487 #define EDGESPLIT_DEBUG_3
1488 #define EDGESPLIT_DEBUG_2
1489 #define EDGESPLIT_DEBUG_1
1490 #define EDGESPLIT_DEBUG_0
1491 #endif
1493 static void edgesplitModifier_initData(ModifierData *md)
1495 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1497 /* default to 30-degree split angle, sharpness from both angle & flag
1499 emd->split_angle = 30;
1500 emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
1503 static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
1505 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1506 EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
1508 temd->split_angle = emd->split_angle;
1509 temd->flags = emd->flags;
1512 /* Mesh data for edgesplit operation */
1513 typedef struct SmoothVert {
1514 LinkNode *faces; /* all faces which use this vert */
1515 int oldIndex; /* the index of the original DerivedMesh vert */
1516 int newIndex; /* the index of the new DerivedMesh vert */
1517 } SmoothVert;
1519 #define SMOOTHEDGE_NUM_VERTS 2
1521 typedef struct SmoothEdge {
1522 SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
1523 LinkNode *faces; /* all faces which use this edge */
1524 int oldIndex; /* the index of the original DerivedMesh edge */
1525 int newIndex; /* the index of the new DerivedMesh edge */
1526 short flag; /* the flags from the original DerivedMesh edge */
1527 } SmoothEdge;
1529 #define SMOOTHFACE_MAX_EDGES 4
1531 typedef struct SmoothFace {
1532 SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
1533 int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
1534 float normal[3]; /* the normal of this face */
1535 int oldIndex; /* the index of the original DerivedMesh face */
1536 int newIndex; /* the index of the new DerivedMesh face */
1537 } SmoothFace;
1539 typedef struct SmoothMesh {
1540 SmoothVert *verts;
1541 SmoothEdge *edges;
1542 SmoothFace *faces;
1543 int num_verts, num_edges, num_faces;
1544 int max_verts, max_edges, max_faces;
1545 DerivedMesh *dm;
1546 float threshold; /* the cosine of the smoothing angle */
1547 int flags;
1548 } SmoothMesh;
1550 static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
1552 SmoothVert *copy = &mesh->verts[mesh->num_verts];
1554 if(mesh->num_verts >= mesh->max_verts) {
1555 printf("Attempted to add a SmoothMesh vert beyond end of array\n");
1556 return NULL;
1559 *copy = *vert;
1560 copy->faces = NULL;
1561 copy->newIndex = mesh->num_verts;
1562 ++mesh->num_verts;
1564 #ifdef EDGESPLIT_DEBUG_2
1565 printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
1566 #endif
1567 return copy;
1570 static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
1572 SmoothEdge *copy = &mesh->edges[mesh->num_edges];
1574 if(mesh->num_edges >= mesh->max_edges) {
1575 printf("Attempted to add a SmoothMesh edge beyond end of array\n");
1576 return NULL;
1579 *copy = *edge;
1580 copy->faces = NULL;
1581 copy->newIndex = mesh->num_edges;
1582 ++mesh->num_edges;
1584 #ifdef EDGESPLIT_DEBUG_2
1585 printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
1586 #endif
1587 return copy;
1590 static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
1592 int i;
1593 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
1594 if(edge->verts[i] == vert) return 1;
1596 return 0;
1599 static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
1600 int max_verts, int max_edges, int max_faces)
1602 SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
1603 mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
1604 "SmoothMesh.verts");
1605 mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
1606 "SmoothMesh.edges");
1607 mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
1608 "SmoothMesh.faces");
1610 mesh->num_verts = num_verts;
1611 mesh->num_edges = num_edges;
1612 mesh->num_faces = num_faces;
1614 mesh->max_verts = max_verts;
1615 mesh->max_edges = max_edges;
1616 mesh->max_faces = max_faces;
1618 return mesh;
1621 static void smoothmesh_free(SmoothMesh *mesh)
1623 int i;
1625 for(i = 0; i < mesh->num_verts; ++i)
1626 BLI_linklist_free(mesh->verts[i].faces, NULL);
1628 for(i = 0; i < mesh->num_edges; ++i)
1629 BLI_linklist_free(mesh->edges[i].faces, NULL);
1631 MEM_freeN(mesh->verts);
1632 MEM_freeN(mesh->edges);
1633 MEM_freeN(mesh->faces);
1634 MEM_freeN(mesh);
1637 static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
1639 int i;
1640 SmoothVert *tmp;
1642 if(max_verts <= mesh->max_verts) return;
1644 tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
1646 memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
1648 /* remap vert pointers in edges */
1649 for(i = 0; i < mesh->num_edges; ++i) {
1650 int j;
1651 SmoothEdge *edge = &mesh->edges[i];
1653 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
1654 /* pointer arithmetic to get vert array index */
1655 edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
1658 MEM_freeN(mesh->verts);
1659 mesh->verts = tmp;
1660 mesh->max_verts = max_verts;
1663 static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
1665 int i;
1666 SmoothEdge *tmp;
1668 if(max_edges <= mesh->max_edges) return;
1670 tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
1672 memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
1674 /* remap edge pointers in faces */
1675 for(i = 0; i < mesh->num_faces; ++i) {
1676 int j;
1677 SmoothFace *face = &mesh->faces[i];
1679 for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
1680 if(face->edges[j])
1681 /* pointer arithmetic to get edge array index */
1682 face->edges[j] = &tmp[face->edges[j] - mesh->edges];
1685 MEM_freeN(mesh->edges);
1686 mesh->edges = tmp;
1687 mesh->max_edges = max_edges;
1690 #ifdef EDGESPLIT_DEBUG_0
1691 static void smoothmesh_print(SmoothMesh *mesh)
1693 int i, j;
1694 DerivedMesh *dm = mesh->dm;
1696 printf("--- SmoothMesh ---\n");
1697 printf("--- Vertices ---\n");
1698 for(i = 0; i < mesh->num_verts; i++) {
1699 SmoothVert *vert = &mesh->verts[i];
1700 LinkNode *node;
1701 MVert mv;
1703 dm->getVert(dm, vert->oldIndex, &mv);
1705 printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
1706 i, vert->oldIndex, vert->newIndex,
1707 mv.co[0], mv.co[1], mv.co[2]);
1708 printf(", faces={");
1709 for(node = vert->faces; node != NULL; node = node->next) {
1710 printf(" %d", ((SmoothFace *)node->link)->newIndex);
1712 printf("}\n");
1715 printf("\n--- Edges ---\n");
1716 for(i = 0; i < mesh->num_edges; i++) {
1717 SmoothEdge *edge = &mesh->edges[i];
1718 LinkNode *node;
1720 printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
1722 edge->oldIndex, edge->newIndex,
1723 edge->verts[0]->newIndex, edge->verts[1]->newIndex);
1724 if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
1725 printf(", faces={");
1726 for(node = edge->faces; node != NULL; node = node->next) {
1727 printf(" %d", ((SmoothFace *)node->link)->newIndex);
1729 printf("}\n");
1732 printf("\n--- Faces ---\n");
1733 for(i = 0; i < mesh->num_faces; i++) {
1734 SmoothFace *face = &mesh->faces[i];
1736 printf("%4d: indices={%4d, %4d}, edges={", i,
1737 face->oldIndex, face->newIndex);
1738 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1739 if(face->flip[j])
1740 printf(" -%-2d", face->edges[j]->newIndex);
1741 else
1742 printf(" %-2d", face->edges[j]->newIndex);
1744 printf("}, verts={");
1745 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1746 printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
1748 printf("}\n");
1751 #endif
1753 static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
1755 SmoothMesh *mesh;
1756 EdgeHash *edges = BLI_edgehash_new();
1757 int i;
1758 int totvert, totedge, totface;
1760 totvert = dm->getNumVerts(dm);
1761 totedge = dm->getNumEdges(dm);
1762 totface = dm->getNumFaces(dm);
1764 mesh = smoothmesh_new(totvert, totedge, totface,
1765 totvert, totedge, totface);
1767 mesh->dm = dm;
1769 for(i = 0; i < totvert; i++) {
1770 SmoothVert *vert = &mesh->verts[i];
1772 vert->oldIndex = vert->newIndex = i;
1775 for(i = 0; i < totedge; i++) {
1776 SmoothEdge *edge = &mesh->edges[i];
1777 MEdge med;
1779 dm->getEdge(dm, i, &med);
1780 edge->verts[0] = &mesh->verts[med.v1];
1781 edge->verts[1] = &mesh->verts[med.v2];
1782 edge->oldIndex = edge->newIndex = i;
1783 edge->flag = med.flag;
1785 BLI_edgehash_insert(edges, med.v1, med.v2, edge);
1788 for(i = 0; i < totface; i++) {
1789 SmoothFace *face = &mesh->faces[i];
1790 MFace mf;
1791 MVert v1, v2, v3;
1792 int j;
1794 dm->getFace(dm, i, &mf);
1796 dm->getVert(dm, mf.v1, &v1);
1797 dm->getVert(dm, mf.v2, &v2);
1798 dm->getVert(dm, mf.v3, &v3);
1799 face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
1800 if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
1801 face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
1802 if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
1803 if(mf.v4) {
1804 MVert v4;
1805 dm->getVert(dm, mf.v4, &v4);
1806 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
1807 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
1808 face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
1809 if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
1810 CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
1811 } else {
1812 face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
1813 if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
1814 face->edges[3] = NULL;
1815 CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
1818 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
1819 SmoothEdge *edge = face->edges[j];
1820 BLI_linklist_prepend(&edge->faces, face);
1821 BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
1824 face->oldIndex = face->newIndex = i;
1827 BLI_edgehash_free(edges, NULL);
1829 return mesh;
1832 static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
1834 DerivedMesh *result = CDDM_from_template(mesh->dm,
1835 mesh->num_verts,
1836 mesh->num_edges,
1837 mesh->num_faces);
1838 MVert *new_verts = CDDM_get_verts(result);
1839 MEdge *new_edges = CDDM_get_edges(result);
1840 MFace *new_faces = CDDM_get_faces(result);
1841 int i;
1843 for(i = 0; i < mesh->num_verts; ++i) {
1844 SmoothVert *vert = &mesh->verts[i];
1845 MVert *newMV = &new_verts[vert->newIndex];
1847 DM_copy_vert_data(mesh->dm, result,
1848 vert->oldIndex, vert->newIndex, 1);
1849 mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
1852 for(i = 0; i < mesh->num_edges; ++i) {
1853 SmoothEdge *edge = &mesh->edges[i];
1854 MEdge *newME = &new_edges[edge->newIndex];
1856 DM_copy_edge_data(mesh->dm, result,
1857 edge->oldIndex, edge->newIndex, 1);
1858 mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
1859 newME->v1 = edge->verts[0]->newIndex;
1860 newME->v2 = edge->verts[1]->newIndex;
1863 for(i = 0; i < mesh->num_faces; ++i) {
1864 SmoothFace *face = &mesh->faces[i];
1865 MFace *newMF = &new_faces[face->newIndex];
1867 DM_copy_face_data(mesh->dm, result,
1868 face->oldIndex, face->newIndex, 1);
1869 mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
1871 newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
1872 newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
1873 newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
1875 if(face->edges[3]) {
1876 newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
1877 } else {
1878 newMF->v4 = 0;
1882 return result;
1885 /* returns the other vert in the given edge
1887 static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
1889 if(edge->verts[0] == vert) return edge->verts[1];
1890 else return edge->verts[0];
1893 /* returns the other edge in the given face that uses the given vert
1894 * returns NULL if no other edge in the given face uses the given vert
1895 * (this should never happen)
1897 static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
1898 SmoothEdge *edge)
1900 int i,j;
1901 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
1902 SmoothEdge *tmp_edge = face->edges[i];
1903 if(tmp_edge == edge) continue;
1905 for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
1906 if(tmp_edge->verts[j] == vert) return tmp_edge;
1909 /* if we get to here, something's wrong (there should always be 2 edges
1910 * which use the same vert in a face)
1912 return NULL;
1915 /* returns a face attached to the given edge which is not the given face.
1916 * returns NULL if no other faces use this edge.
1918 static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
1920 LinkNode *node;
1922 for(node = edge->faces; node != NULL; node = node->next)
1923 if(node->link != face) return node->link;
1925 return NULL;
1928 #if 0
1929 /* copies source list to target, overwriting target (target is not freed)
1930 * nodes in the copy will be in the same order as in source
1932 static void linklist_copy(LinkNode **target, LinkNode *source)
1934 LinkNode *node = NULL;
1935 *target = NULL;
1937 for(; source; source = source->next) {
1938 if(node) {
1939 node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
1940 node = node->next;
1941 } else {
1942 node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
1944 node->link = source->link;
1945 node->next = NULL;
1948 #endif
1950 /* appends source to target if it's not already in target */
1951 static void linklist_append_unique(LinkNode **target, void *source)
1953 LinkNode *node;
1954 LinkNode *prev = NULL;
1956 /* check if source value is already in the list */
1957 for(node = *target; node; prev = node, node = node->next)
1958 if(node->link == source) return;
1960 node = MEM_mallocN(sizeof(*node), "nlink");
1961 node->next = NULL;
1962 node->link = source;
1964 if(prev) prev->next = node;
1965 else *target = node;
1968 /* appends elements of source which aren't already in target to target */
1969 static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
1971 for(; source; source = source->next)
1972 linklist_append_unique(target, source->link);
1975 #if 0 /* this is no longer used, it should possibly be removed */
1976 /* prepends prepend to list - doesn't copy nodes, just joins the lists */
1977 static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
1979 if(prepend) {
1980 LinkNode *node = prepend;
1981 while(node->next) node = node->next;
1983 node->next = *list;
1984 *list = prepend;
1987 #endif
1989 /* returns 1 if the linked list contains the given pointer, 0 otherwise
1991 static int linklist_contains(LinkNode *list, void *ptr)
1993 LinkNode *node;
1995 for(node = list; node; node = node->next)
1996 if(node->link == ptr) return 1;
1998 return 0;
2001 /* returns 1 if the first linked list is a subset of the second (comparing
2002 * pointer values), 0 if not
2004 static int linklist_subset(LinkNode *list1, LinkNode *list2)
2006 for(; list1; list1 = list1->next)
2007 if(!linklist_contains(list2, list1->link))
2008 return 0;
2010 return 1;
2013 #if 0
2014 /* empties the linked list
2015 * frees pointers with freefunc if freefunc is not NULL
2017 static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
2019 BLI_linklist_free(*list, freefunc);
2020 *list = NULL;
2022 #endif
2024 /* removes the first instance of value from the linked list
2025 * frees the pointer with freefunc if freefunc is not NULL
2027 static void linklist_remove_first(LinkNode **list, void *value,
2028 LinkNodeFreeFP freefunc)
2030 LinkNode *node = *list;
2031 LinkNode *prev = NULL;
2033 while(node && node->link != value) {
2034 prev = node;
2035 node = node->next;
2038 if(node) {
2039 if(prev)
2040 prev->next = node->next;
2041 else
2042 *list = node->next;
2044 if(freefunc)
2045 freefunc(node->link);
2047 MEM_freeN(node);
2051 /* removes all elements in source from target */
2052 static void linklist_remove_list(LinkNode **target, LinkNode *source,
2053 LinkNodeFreeFP freefunc)
2055 for(; source; source = source->next)
2056 linklist_remove_first(target, source->link, freefunc);
2059 #ifdef EDGESPLIT_DEBUG_0
2060 static void print_ptr(void *ptr)
2062 printf("%p\n", ptr);
2065 static void print_edge(void *ptr)
2067 SmoothEdge *edge = ptr;
2068 printf(" %4d", edge->newIndex);
2071 static void print_face(void *ptr)
2073 SmoothFace *face = ptr;
2074 printf(" %4d", face->newIndex);
2076 #endif
2078 typedef struct ReplaceData {
2079 void *find;
2080 void *replace;
2081 } ReplaceData;
2083 static void edge_replace_vert(void *ptr, void *userdata)
2085 SmoothEdge *edge = ptr;
2086 SmoothVert *find = ((ReplaceData *)userdata)->find;
2087 SmoothVert *replace = ((ReplaceData *)userdata)->replace;
2088 int i;
2090 #ifdef EDGESPLIT_DEBUG_3
2091 printf("replacing vert %4d with %4d in edge %4d",
2092 find->newIndex, replace->newIndex, edge->newIndex);
2093 printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2094 #endif
2096 for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
2097 if(edge->verts[i] == find) {
2098 linklist_append_list_unique(&replace->faces, edge->faces);
2099 linklist_remove_list(&find->faces, edge->faces, NULL);
2101 edge->verts[i] = replace;
2105 #ifdef EDGESPLIT_DEBUG_3
2106 printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
2107 #endif
2110 static void face_replace_vert(void *ptr, void *userdata)
2112 SmoothFace *face = ptr;
2113 int i;
2115 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
2116 edge_replace_vert(face->edges[i], userdata);
2119 static void face_replace_edge(void *ptr, void *userdata)
2121 SmoothFace *face = ptr;
2122 SmoothEdge *find = ((ReplaceData *)userdata)->find;
2123 SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
2124 int i;
2126 #ifdef EDGESPLIT_DEBUG_3
2127 printf("replacing edge %4d with %4d in face %4d",
2128 find->newIndex, replace->newIndex, face->newIndex);
2129 if(face->edges[3])
2130 printf(": {%2d %2d %2d %2d}",
2131 face->edges[0]->newIndex, face->edges[1]->newIndex,
2132 face->edges[2]->newIndex, face->edges[3]->newIndex);
2133 else
2134 printf(": {%2d %2d %2d}",
2135 face->edges[0]->newIndex, face->edges[1]->newIndex,
2136 face->edges[2]->newIndex);
2137 #endif
2139 for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
2140 if(face->edges[i] == find) {
2141 linklist_remove_first(&face->edges[i]->faces, face, NULL);
2142 BLI_linklist_prepend(&replace->faces, face);
2143 face->edges[i] = replace;
2147 #ifdef EDGESPLIT_DEBUG_3
2148 if(face->edges[3])
2149 printf(" -> {%2d %2d %2d %2d}\n",
2150 face->edges[0]->newIndex, face->edges[1]->newIndex,
2151 face->edges[2]->newIndex, face->edges[3]->newIndex);
2152 else
2153 printf(" -> {%2d %2d %2d}\n",
2154 face->edges[0]->newIndex, face->edges[1]->newIndex,
2155 face->edges[2]->newIndex);
2156 #endif
2159 static int edge_is_loose(SmoothEdge *edge)
2161 return !(edge->faces && edge->faces->next);
2164 static int edge_is_sharp(SmoothEdge *edge, int flags,
2165 float threshold)
2167 #ifdef EDGESPLIT_DEBUG_1
2168 printf("edge %d: ", edge->newIndex);
2169 #endif
2170 if(edge->flag & ME_SHARP) {
2171 /* edge can only be sharp if it has at least 2 faces */
2172 if(!edge_is_loose(edge)) {
2173 #ifdef EDGESPLIT_DEBUG_1
2174 printf("sharp\n");
2175 #endif
2176 return 1;
2177 } else {
2178 /* edge is loose, so it can't be sharp */
2179 edge->flag &= ~ME_SHARP;
2183 #ifdef EDGESPLIT_DEBUG_1
2184 printf("not sharp\n");
2185 #endif
2186 return 0;
2189 /* finds another sharp edge which uses vert, by traversing faces around the
2190 * vert until it does one of the following:
2191 * - hits a loose edge (the edge is returned)
2192 * - hits a sharp edge (the edge is returned)
2193 * - returns to the start edge (NULL is returned)
2195 static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
2196 LinkNode **visited_faces, float threshold, int flags)
2198 SmoothFace *face = NULL;
2199 SmoothEdge *edge2 = NULL;
2200 /* holds the edges we've seen so we can avoid looping indefinitely */
2201 LinkNode *visited_edges = NULL;
2202 #ifdef EDGESPLIT_DEBUG_1
2203 printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
2204 edge->newIndex, vert->newIndex);
2205 #endif
2207 /* get a face on which to start */
2208 if(edge->faces) face = edge->faces->link;
2209 else return NULL;
2211 /* record this edge as visited */
2212 BLI_linklist_prepend(&visited_edges, edge);
2214 /* get the next edge */
2215 edge2 = other_edge(face, vert, edge);
2217 /* record this face as visited */
2218 if(visited_faces)
2219 BLI_linklist_prepend(visited_faces, face);
2221 /* search until we hit a loose edge or a sharp edge or an edge we've
2222 * seen before
2224 while(face && !edge_is_sharp(edge2, flags, threshold)
2225 && !linklist_contains(visited_edges, edge2)) {
2226 #ifdef EDGESPLIT_DEBUG_3
2227 printf("current face %4d; current edge %4d\n", face->newIndex,
2228 edge2->newIndex);
2229 #endif
2230 /* get the next face */
2231 face = other_face(edge2, face);
2233 /* if face == NULL, edge2 is a loose edge */
2234 if(face) {
2235 /* record this face as visited */
2236 if(visited_faces)
2237 BLI_linklist_prepend(visited_faces, face);
2239 /* record this edge as visited */
2240 BLI_linklist_prepend(&visited_edges, edge2);
2242 /* get the next edge */
2243 edge2 = other_edge(face, vert, edge2);
2244 #ifdef EDGESPLIT_DEBUG_3
2245 printf("next face %4d; next edge %4d\n",
2246 face->newIndex, edge2->newIndex);
2247 } else {
2248 printf("loose edge: %4d\n", edge2->newIndex);
2249 #endif
2253 /* either we came back to the start edge or we found a sharp/loose edge */
2254 if(linklist_contains(visited_edges, edge2))
2255 /* we came back to the start edge */
2256 edge2 = NULL;
2258 BLI_linklist_free(visited_edges, NULL);
2260 #ifdef EDGESPLIT_DEBUG_1
2261 printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
2262 "returning edge %d\n",
2263 edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
2264 #endif
2265 return edge2;
2268 static void split_single_vert(SmoothVert *vert, SmoothFace *face,
2269 SmoothMesh *mesh)
2271 SmoothVert *copy_vert;
2272 ReplaceData repdata;
2274 copy_vert = smoothvert_copy(vert, mesh);
2276 repdata.find = vert;
2277 repdata.replace = copy_vert;
2278 face_replace_vert(face, &repdata);
2281 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
2283 static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
2284 SmoothMesh *mesh)
2286 SmoothEdge *edge2;
2287 LinkNode *visited_faces = NULL;
2288 #ifdef EDGESPLIT_DEBUG_1
2289 printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
2290 edge->newIndex, vert->newIndex);
2291 #endif
2293 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
2294 mesh->threshold, mesh->flags);
2296 if(!edge2) {
2297 /* didn't find a sharp or loose edge, so we've hit a dead end */
2298 } else if(!edge_is_loose(edge2)) {
2299 /* edge2 is not loose, so it must be sharp */
2300 if(edge_is_loose(edge)) {
2301 /* edge is loose, so we can split edge2 at this vert */
2302 split_edge(edge2, vert, mesh);
2303 } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
2304 /* both edges are sharp, so we can split the pair at vert */
2305 split_edge(edge, vert, mesh);
2306 } else {
2307 /* edge is not sharp, so try to split edge2 at its other vert */
2308 split_edge(edge2, other_vert(edge2, vert), mesh);
2310 } else { /* edge2 is loose */
2311 if(edge_is_loose(edge)) {
2312 SmoothVert *vert2;
2313 ReplaceData repdata;
2315 /* can't split edge, what should we do with vert? */
2316 if(linklist_subset(vert->faces, visited_faces)) {
2317 /* vert has only one fan of faces attached; don't split it */
2318 } else {
2319 /* vert has more than one fan of faces attached; split it */
2320 vert2 = smoothvert_copy(vert, mesh);
2322 /* replace vert with its copy in visited_faces */
2323 repdata.find = vert;
2324 repdata.replace = vert2;
2325 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2327 } else {
2328 /* edge is not loose, so it must be sharp; split it */
2329 split_edge(edge, vert, mesh);
2333 BLI_linklist_free(visited_faces, NULL);
2334 #ifdef EDGESPLIT_DEBUG_1
2335 printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
2336 edge->newIndex, vert->newIndex);
2337 #endif
2340 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
2342 SmoothEdge *edge2;
2343 SmoothVert *vert2;
2344 ReplaceData repdata;
2345 /* the list of faces traversed while looking for a sharp edge */
2346 LinkNode *visited_faces = NULL;
2347 #ifdef EDGESPLIT_DEBUG_1
2348 printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
2349 edge->newIndex, vert->newIndex);
2350 #endif
2352 edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
2353 mesh->threshold, mesh->flags);
2355 if(!edge2) {
2356 /* didn't find a sharp or loose edge, so try the other vert */
2357 vert2 = other_vert(edge, vert);
2358 propagate_split(edge, vert2, mesh);
2359 } else if(!edge_is_loose(edge2)) {
2360 /* edge2 is not loose, so it must be sharp */
2361 SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
2362 SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
2363 SmoothVert *vert2;
2365 /* replace edge with its copy in visited_faces */
2366 repdata.find = edge;
2367 repdata.replace = copy_edge;
2368 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2370 /* replace edge2 with its copy in visited_faces */
2371 repdata.find = edge2;
2372 repdata.replace = copy_edge2;
2373 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2375 vert2 = smoothvert_copy(vert, mesh);
2377 /* replace vert with its copy in visited_faces (must be done after
2378 * edge replacement so edges have correct vertices)
2380 repdata.find = vert;
2381 repdata.replace = vert2;
2382 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2384 /* all copying and replacing is done; the mesh should be consistent.
2385 * now propagate the split to the vertices at either end
2387 propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
2388 propagate_split(copy_edge2, other_vert(copy_edge2, vert2), mesh);
2390 if(smoothedge_has_vert(edge, vert))
2391 propagate_split(edge, vert, mesh);
2392 } else {
2393 /* edge2 is loose */
2394 SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
2395 SmoothVert *vert2;
2397 /* replace edge with its copy in visited_faces */
2398 repdata.find = edge;
2399 repdata.replace = copy_edge;
2400 BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
2402 vert2 = smoothvert_copy(vert, mesh);
2404 /* replace vert with its copy in visited_faces (must be done after
2405 * edge replacement so edges have correct vertices)
2407 repdata.find = vert;
2408 repdata.replace = vert2;
2409 BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
2411 /* copying and replacing is done; the mesh should be consistent.
2412 * now propagate the split to the vertex at the other end
2414 propagate_split(copy_edge, other_vert(copy_edge, vert2), mesh);
2416 if(smoothedge_has_vert(edge, vert))
2417 propagate_split(edge, vert, mesh);
2420 BLI_linklist_free(visited_faces, NULL);
2421 #ifdef EDGESPLIT_DEBUG_1
2422 printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
2423 edge->newIndex, vert->newIndex);
2424 #endif
2427 static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
2428 int flags, int *extra_edges)
2430 /* if normal1 dot normal2 < threshold, angle is greater, so split */
2431 /* FIXME not sure if this always works */
2432 /* 0.00001 added for floating-point rounding */
2433 float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
2434 int i;
2436 *extra_edges = 0;
2438 /* loop through edges, counting potential new ones */
2439 for(i = 0; i < mesh->num_edges; i++) {
2440 SmoothEdge *edge = &mesh->edges[i];
2441 int sharp = 0;
2443 /* treat all non-manifold edges (3 or more faces) as sharp */
2444 if(edge->faces && edge->faces->next && edge->faces->next->next) {
2445 LinkNode *node;
2447 /* this edge is sharp */
2448 sharp = 1;
2450 /* add an extra edge for every face beyond the first */
2451 *extra_edges += 2;
2452 for(node = edge->faces->next->next->next; node; node = node->next)
2453 (*extra_edges)++;
2454 } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
2455 && !edge_is_loose(edge)) {
2456 /* (the edge can only be sharp if we're checking angle or flag,
2457 * and it has at least 2 faces) */
2459 /* if we're checking the sharp flag and it's set, good */
2460 if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
2461 /* this edge is sharp */
2462 sharp = 1;
2464 (*extra_edges)++;
2465 } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
2466 /* we know the edge has 2 faces, so check the angle */
2467 SmoothFace *face1 = edge->faces->link;
2468 SmoothFace *face2 = edge->faces->next->link;
2469 float edge_angle_cos = MTC_dot3Float(face1->normal,
2470 face2->normal);
2472 if(edge_angle_cos < threshold) {
2473 /* this edge is sharp */
2474 sharp = 1;
2476 (*extra_edges)++;
2481 /* set/clear sharp flag appropriately */
2482 if(sharp) edge->flag |= ME_SHARP;
2483 else edge->flag &= ~ME_SHARP;
2487 static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
2489 int i;
2490 /* if normal1 dot normal2 < threshold, angle is greater, so split */
2491 /* FIXME not sure if this always works */
2492 /* 0.00001 added for floating-point rounding */
2493 mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
2494 mesh->flags = flags;
2496 /* loop through edges, splitting sharp ones */
2497 /* can't use an iterator here, because we'll be adding edges */
2498 for(i = 0; i < mesh->num_edges; i++) {
2499 SmoothEdge *edge = &mesh->edges[i];
2501 if(edge_is_sharp(edge, flags, mesh->threshold))
2502 split_edge(edge, edge->verts[0], mesh);
2507 static int count_bridge_verts(SmoothMesh *mesh)
2509 int i, j, count = 0;
2511 for(i = 0; i < mesh->num_faces; i++) {
2512 SmoothFace *face = &mesh->faces[i];
2514 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2515 SmoothEdge *edge = face->edges[j];
2516 SmoothEdge *next_edge;
2517 SmoothVert *vert = edge->verts[1 - face->flip[j]];
2518 int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
2520 /* wrap next around if at last edge */
2521 if(!face->edges[next]) next = 0;
2523 next_edge = face->edges[next];
2525 /* if there are other faces sharing this vertex but not
2526 * these edges, the vertex will be split, so count it
2528 /* vert has to have at least one face (this one), so faces != 0 */
2529 if(!edge->faces->next && !next_edge->faces->next
2530 && vert->faces->next) {
2531 count++;
2536 /* each bridge vert will be counted once per face that uses it,
2537 * so count is too high, but it's ok for now
2539 return count;
2542 static void split_bridge_verts(SmoothMesh *mesh)
2544 int i,j;
2546 for(i = 0; i < mesh->num_faces; i++) {
2547 SmoothFace *face = &mesh->faces[i];
2549 for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
2550 SmoothEdge *edge = face->edges[j];
2551 SmoothEdge *next_edge;
2552 SmoothVert *vert = edge->verts[1 - face->flip[j]];
2553 int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
2555 /* wrap next around if at last edge */
2556 if(!face->edges[next]) next = 0;
2558 next_edge = face->edges[next];
2560 /* if there are other faces sharing this vertex but not
2561 * these edges, split the vertex
2563 /* vert has to have at least one face (this one), so faces != 0 */
2564 if(!edge->faces->next && !next_edge->faces->next
2565 && vert->faces->next)
2566 /* FIXME this needs to find all faces that share edges with
2567 * this one and split off together
2569 split_single_vert(vert, face, mesh);
2574 static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
2575 Object *ob, DerivedMesh *dm)
2577 SmoothMesh *mesh;
2578 DerivedMesh *result;
2579 int max_verts, max_edges;
2581 if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
2582 return dm;
2584 /* 1. make smoothmesh with initial number of elements */
2585 mesh = smoothmesh_from_derivedmesh(dm);
2587 /* 2. count max number of elements to add */
2588 tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
2589 max_verts = max_edges * 2 + mesh->max_verts;
2590 max_verts += count_bridge_verts(mesh);
2591 max_edges += mesh->max_edges;
2593 /* 3. reallocate smoothmesh arrays & copy elements across */
2594 /* 4. remap copied elements' pointers to point into the new arrays */
2595 smoothmesh_resize_verts(mesh, max_verts);
2596 smoothmesh_resize_edges(mesh, max_edges);
2598 #ifdef EDGESPLIT_DEBUG_1
2599 printf("********** Pre-split **********\n");
2600 smoothmesh_print(mesh);
2601 #endif
2603 split_sharp_edges(mesh, emd->split_angle, emd->flags);
2604 #ifdef EDGESPLIT_DEBUG_1
2605 printf("********** Post-edge-split **********\n");
2606 smoothmesh_print(mesh);
2607 #endif
2609 split_bridge_verts(mesh);
2611 #ifdef EDGESPLIT_DEBUG_1
2612 printf("********** Post-vert-split **********\n");
2613 smoothmesh_print(mesh);
2614 #endif
2616 #ifdef EDGESPLIT_DEBUG_0
2617 printf("Edgesplit: Estimated %d verts & %d edges, "
2618 "found %d verts & %d edges\n", max_verts, max_edges,
2619 mesh->num_verts, mesh->num_edges);
2620 #endif
2622 result = CDDM_from_smoothmesh(mesh);
2623 smoothmesh_free(mesh);
2625 return result;
2628 static DerivedMesh *edgesplitModifier_applyModifier(
2629 ModifierData *md, Object *ob, DerivedMesh *derivedData,
2630 int useRenderParams, int isFinalCalc)
2632 DerivedMesh *result;
2633 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2635 result = edgesplitModifier_do(emd, ob, derivedData);
2637 CDDM_calc_normals(result);
2639 return result;
2642 static DerivedMesh *edgesplitModifier_applyModifierEM(
2643 ModifierData *md, Object *ob, EditMesh *editData,
2644 DerivedMesh *derivedData)
2646 return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
2649 /* Displace */
2651 static void displaceModifier_initData(ModifierData *md)
2653 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2655 dmd->texture = NULL;
2656 dmd->strength = 1;
2657 dmd->direction = MOD_DISP_DIR_NOR;
2658 dmd->midlevel = 0.5;
2661 static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
2663 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2664 DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
2666 tdmd->texture = dmd->texture;
2667 tdmd->strength = dmd->strength;
2668 tdmd->direction = dmd->direction;
2669 strncpy(tdmd->defgrp_name, dmd->defgrp_name, 32);
2670 tdmd->midlevel = dmd->midlevel;
2671 tdmd->texmapping = dmd->texmapping;
2672 tdmd->map_object = dmd->map_object;
2673 strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32);
2676 CustomDataMask displaceModifier_requiredDataMask(ModifierData *md)
2678 DisplaceModifierData *dmd = (DisplaceModifierData *)md;
2679 CustomDataMask dataMask = 0;
2681 /* ask for vertexgroups if we need them */
2682 if(dmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
2684 /* ask for UV coordinates if we need them */
2685 if(dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
2687 return dataMask;
2690 static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
2691 ObjectWalkFunc walk, void *userData)
2693 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2695 walk(userData, ob, &dmd->map_object);
2698 static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
2699 IDWalkFunc walk, void *userData)
2701 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2703 walk(userData, ob, (ID **)&dmd->texture);
2705 displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData);
2708 static int displaceModifier_isDisabled(ModifierData *md)
2710 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2712 return !dmd->texture;
2715 static void displaceModifier_updateDepgraph(
2716 ModifierData *md, DagForest *forest,
2717 Object *ob, DagNode *obNode)
2719 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2721 if(dmd->map_object) {
2722 DagNode *curNode = dag_get_node(forest, dmd->map_object);
2724 dag_add_relation(forest, curNode, obNode,
2725 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
2729 static void validate_layer_name(const CustomData *data, int type, char *name)
2731 int index = -1;
2733 /* if a layer name was given, try to find that layer */
2734 if(name[0])
2735 index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
2737 if(index < 0) {
2738 /* either no layer was specified, or the layer we want has been
2739 * deleted, so assign the active layer to name
2741 index = CustomData_get_active_layer_index(data, CD_MTFACE);
2742 strcpy(name, data->layers[index].name);
2746 static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
2747 DerivedMesh *dm,
2748 float (*co)[3], float (*texco)[3],
2749 int numVerts)
2751 int i;
2752 int texmapping = dmd->texmapping;
2754 if(texmapping == MOD_DISP_MAP_OBJECT) {
2755 if(dmd->map_object)
2756 Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
2757 else /* if there is no map object, default to local */
2758 texmapping = MOD_DISP_MAP_LOCAL;
2761 /* UVs need special handling, since they come from faces */
2762 if(texmapping == MOD_DISP_MAP_UV) {
2763 if(dm->getFaceDataArray(dm, CD_MTFACE)) {
2764 MFace *mface = dm->getFaceArray(dm);
2765 MFace *mf;
2766 char *done = MEM_callocN(sizeof(*done) * numVerts,
2767 "get_texture_coords done");
2768 int numFaces = dm->getNumFaces(dm);
2769 MTFace *tf;
2771 validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
2773 tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
2774 dmd->uvlayer_name);
2776 /* verts are given the UV from the first face that uses them */
2777 for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
2778 if(!done[mf->v1]) {
2779 texco[mf->v1][0] = tf->uv[0][0];
2780 texco[mf->v1][1] = tf->uv[0][1];
2781 texco[mf->v1][2] = 0;
2782 done[mf->v1] = 1;
2784 if(!done[mf->v2]) {
2785 texco[mf->v2][0] = tf->uv[1][0];
2786 texco[mf->v2][1] = tf->uv[1][1];
2787 texco[mf->v2][2] = 0;
2788 done[mf->v2] = 1;
2790 if(!done[mf->v3]) {
2791 texco[mf->v3][0] = tf->uv[2][0];
2792 texco[mf->v3][1] = tf->uv[2][1];
2793 texco[mf->v3][2] = 0;
2794 done[mf->v3] = 1;
2796 if(!done[mf->v4]) {
2797 texco[mf->v4][0] = tf->uv[3][0];
2798 texco[mf->v4][1] = tf->uv[3][1];
2799 texco[mf->v4][2] = 0;
2800 done[mf->v4] = 1;
2804 /* remap UVs from [0, 1] to [-1, 1] */
2805 for(i = 0; i < numVerts; ++i) {
2806 texco[i][0] = texco[i][0] * 2 - 1;
2807 texco[i][1] = texco[i][1] * 2 - 1;
2810 MEM_freeN(done);
2811 return;
2812 } else /* if there are no UVs, default to local */
2813 texmapping = MOD_DISP_MAP_LOCAL;
2816 for(i = 0; i < numVerts; ++i, ++co, ++texco) {
2817 switch(texmapping) {
2818 case MOD_DISP_MAP_LOCAL:
2819 VECCOPY(*texco, *co);
2820 break;
2821 case MOD_DISP_MAP_GLOBAL:
2822 VECCOPY(*texco, *co);
2823 Mat4MulVecfl(ob->obmat, *texco);
2824 break;
2825 case MOD_DISP_MAP_OBJECT:
2826 VECCOPY(*texco, *co);
2827 Mat4MulVecfl(ob->obmat, *texco);
2828 Mat4MulVecfl(dmd->map_object->imat, *texco);
2829 break;
2834 static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
2836 int result_type;
2838 result_type = multitex_ext(texture, tex_co, NULL,
2839 NULL, 1, texres);
2841 /* if the texture gave an RGB value, we assume it didn't give a valid
2842 * intensity, so calculate one (formula from do_material_tex).
2843 * if the texture didn't give an RGB value, copy the intensity across
2845 if(result_type & TEX_RGB)
2846 texres->tin = (0.35 * texres->tr + 0.45 * texres->tg
2847 + 0.2 * texres->tb);
2848 else
2849 texres->tr = texres->tg = texres->tb = texres->tin;
2852 /* dm must be a CDDerivedMesh */
2853 static void displaceModifier_do(
2854 DisplaceModifierData *dmd, Object *ob,
2855 DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
2857 int i;
2858 MVert *mvert;
2859 MDeformVert *dvert = NULL;
2860 int defgrp_index;
2861 float (*tex_co)[3];
2863 if(!dmd->texture) return;
2865 defgrp_index = -1;
2867 if(dmd->defgrp_name[0]) {
2868 bDeformGroup *def;
2869 for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
2870 if(!strcmp(def->name, dmd->defgrp_name)) {
2871 defgrp_index = i;
2872 break;
2877 mvert = CDDM_get_verts(dm);
2878 if(defgrp_index >= 0)
2879 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
2881 tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
2882 "displaceModifier_do tex_co");
2883 get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
2885 for(i = 0; i < numVerts; ++i) {
2886 TexResult texres;
2887 float delta = 0, strength = dmd->strength;
2888 MDeformWeight *def_weight = NULL;
2890 if(dvert) {
2891 int j;
2892 for(j = 0; j < dvert[i].totweight; ++j) {
2893 if(dvert[i].dw[j].def_nr == defgrp_index) {
2894 def_weight = &dvert[i].dw[j];
2895 break;
2898 if(!def_weight) continue;
2901 texres.nor = NULL;
2902 get_texture_value(dmd->texture, tex_co[i], &texres);
2904 delta = texres.tin - dmd->midlevel;
2906 if(def_weight) strength *= def_weight->weight;
2908 delta *= strength;
2910 switch(dmd->direction) {
2911 case MOD_DISP_DIR_X:
2912 vertexCos[i][0] += delta;
2913 break;
2914 case MOD_DISP_DIR_Y:
2915 vertexCos[i][1] += delta;
2916 break;
2917 case MOD_DISP_DIR_Z:
2918 vertexCos[i][2] += delta;
2919 break;
2920 case MOD_DISP_DIR_RGB_XYZ:
2921 vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength;
2922 vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength;
2923 vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength;
2924 break;
2925 case MOD_DISP_DIR_NOR:
2926 vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
2927 vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
2928 vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
2929 break;
2933 MEM_freeN(tex_co);
2936 static void displaceModifier_deformVerts(
2937 ModifierData *md, Object *ob, DerivedMesh *derivedData,
2938 float (*vertexCos)[3], int numVerts)
2940 DerivedMesh *dm;
2942 if(derivedData) dm = CDDM_copy(derivedData);
2943 else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
2944 else return;
2946 CDDM_apply_vert_coords(dm, vertexCos);
2947 CDDM_calc_normals(dm);
2949 displaceModifier_do((DisplaceModifierData *)md, ob, dm,
2950 vertexCos, numVerts);
2952 dm->release(dm);
2955 static void displaceModifier_deformVertsEM(
2956 ModifierData *md, Object *ob, EditMesh *editData,
2957 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
2959 DerivedMesh *dm;
2961 if(derivedData) dm = CDDM_copy(derivedData);
2962 else dm = CDDM_from_editmesh(editData, ob->data);
2964 CDDM_apply_vert_coords(dm, vertexCos);
2965 CDDM_calc_normals(dm);
2967 displaceModifier_do((DisplaceModifierData *)md, ob, dm,
2968 vertexCos, numVerts);
2970 dm->release(dm);
2973 /* UVProject */
2974 /* UV Project modifier: Generates UVs projected from an object
2977 static void uvprojectModifier_initData(ModifierData *md)
2979 UVProjectModifierData *umd = (UVProjectModifierData*) md;
2980 int i;
2982 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
2983 umd->projectors[i] = NULL;
2984 umd->image = NULL;
2985 umd->flags = 0;
2986 umd->num_projectors = 1;
2987 umd->aspectx = umd->aspecty = 1.0f;
2990 static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
2992 UVProjectModifierData *umd = (UVProjectModifierData*) md;
2993 UVProjectModifierData *tumd = (UVProjectModifierData*) target;
2994 int i;
2996 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
2997 tumd->projectors[i] = umd->projectors[i];
2998 tumd->image = umd->image;
2999 tumd->flags = umd->flags;
3000 tumd->num_projectors = umd->num_projectors;
3001 tumd->aspectx = umd->aspectx;
3002 tumd->aspecty = umd->aspecty;
3005 CustomDataMask uvprojectModifier_requiredDataMask(ModifierData *md)
3007 CustomDataMask dataMask = 0;
3009 /* ask for UV coordinates */
3010 dataMask |= (1 << CD_MTFACE);
3012 return dataMask;
3015 static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
3016 ObjectWalkFunc walk, void *userData)
3018 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3019 int i;
3021 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
3022 walk(userData, ob, &umd->projectors[i]);
3025 static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
3026 IDWalkFunc walk, void *userData)
3028 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3030 walk(userData, ob, (ID **)&umd->image);
3032 uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
3033 userData);
3036 static void uvprojectModifier_updateDepgraph(ModifierData *md,
3037 DagForest *forest, Object *ob, DagNode *obNode)
3039 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3040 int i;
3042 for(i = 0; i < umd->num_projectors; ++i) {
3043 if(umd->projectors[i]) {
3044 DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
3046 dag_add_relation(forest, curNode, obNode,
3047 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
3052 typedef struct Projector {
3053 Object *ob; /* object this projector is derived from */
3054 float projmat[4][4]; /* projection matrix */
3055 float normal[3]; /* projector normal in world space */
3056 } Projector;
3058 static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
3059 Object *ob, DerivedMesh *dm)
3061 float (*coords)[3], (*co)[3];
3062 MTFace *tface;
3063 int i, numVerts, numFaces;
3064 Image *image = umd->image;
3065 MFace *mface, *mf;
3066 int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
3067 Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
3068 int num_projectors = 0;
3069 float aspect;
3071 if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty;
3072 else aspect = 1.0f;
3074 for(i = 0; i < umd->num_projectors; ++i)
3075 if(umd->projectors[i])
3076 projectors[num_projectors++].ob = umd->projectors[i];
3078 if(num_projectors == 0) return dm;
3080 /* make sure there are UV layers available */
3081 if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
3083 /* make sure we're using an existing layer */
3084 validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
3086 /* make sure we are not modifying the original UV layer */
3087 tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
3088 CD_MTFACE,
3089 umd->uvlayer_name);
3091 numVerts = dm->getNumVerts(dm);
3093 coords = MEM_callocN(sizeof(*coords) * numVerts,
3094 "uvprojectModifier_do coords");
3095 dm->getVertCos(dm, coords);
3097 /* convert coords to world space */
3098 for(i = 0, co = coords; i < numVerts; ++i, ++co)
3099 Mat4MulVecfl(ob->obmat, *co);
3101 /* calculate a projection matrix and normal for each projector */
3102 for(i = 0; i < num_projectors; ++i) {
3103 float tmpmat[4][4];
3104 float offsetmat[4][4];
3106 /* calculate projection matrix */
3107 Mat4Invert(projectors[i].projmat, projectors[i].ob->obmat);
3109 if(projectors[i].ob->type == OB_CAMERA) {
3110 Camera *cam = (Camera *)projectors[i].ob->data;
3111 if(cam->type == CAM_PERSP) {
3112 float perspmat[4][4];
3113 float xmax;
3114 float xmin;
3115 float ymax;
3116 float ymin;
3117 float pixsize = cam->clipsta * 32.0 / cam->lens;
3119 if(aspect > 1.0f) {
3120 xmax = 0.5f * pixsize;
3121 ymax = xmax / aspect;
3122 } else {
3123 ymax = 0.5f * pixsize;
3124 xmax = ymax * aspect;
3126 xmin = -xmax;
3127 ymin = -ymax;
3129 i_window(xmin, xmax, ymin, ymax,
3130 cam->clipsta, cam->clipend, perspmat);
3131 Mat4MulMat4(tmpmat, projectors[i].projmat, perspmat);
3132 } else if(cam->type == CAM_ORTHO) {
3133 float orthomat[4][4];
3134 float xmax;
3135 float xmin;
3136 float ymax;
3137 float ymin;
3139 if(aspect > 1.0f) {
3140 xmax = 0.5f * cam->ortho_scale;
3141 ymax = xmax / aspect;
3142 } else {
3143 ymax = 0.5f * cam->ortho_scale;
3144 xmax = ymax * aspect;
3146 xmin = -xmax;
3147 ymin = -ymax;
3149 i_ortho(xmin, xmax, ymin, ymax,
3150 cam->clipsta, cam->clipend, orthomat);
3151 Mat4MulMat4(tmpmat, projectors[i].projmat, orthomat);
3153 } else {
3154 Mat4CpyMat4(tmpmat, projectors[i].projmat);
3157 Mat4One(offsetmat);
3158 Mat4MulFloat3(offsetmat[0], 0.5);
3159 offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
3160 Mat4MulMat4(projectors[i].projmat, tmpmat, offsetmat);
3162 /* calculate worldspace projector normal (for best projector test) */
3163 projectors[i].normal[0] = 0;
3164 projectors[i].normal[1] = 0;
3165 projectors[i].normal[2] = 1;
3166 Mat4Mul3Vecfl(projectors[i].ob->obmat, projectors[i].normal);
3169 /* if only one projector, project coords to UVs */
3170 if(num_projectors == 1)
3171 for(i = 0, co = coords; i < numVerts; ++i, ++co)
3172 Mat4MulVec3Project(projectors[0].projmat, *co);
3174 mface = dm->getFaceArray(dm);
3175 numFaces = dm->getNumFaces(dm);
3177 /* apply coords as UVs, and apply image if tfaces are new */
3178 for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
3179 if(override_image || !image || tface->tpage == image) {
3180 if(num_projectors == 1) {
3181 /* apply transformed coords as UVs */
3182 tface->uv[0][0] = coords[mf->v1][0];
3183 tface->uv[0][1] = coords[mf->v1][1];
3184 tface->uv[1][0] = coords[mf->v2][0];
3185 tface->uv[1][1] = coords[mf->v2][1];
3186 tface->uv[2][0] = coords[mf->v3][0];
3187 tface->uv[2][1] = coords[mf->v3][1];
3188 if(mf->v4) {
3189 tface->uv[3][0] = coords[mf->v4][0];
3190 tface->uv[3][1] = coords[mf->v4][1];
3192 } else {
3193 /* multiple projectors, select the closest to face normal
3194 * direction
3196 float co1[3], co2[3], co3[3], co4[3];
3197 float face_no[3];
3198 int j;
3199 Projector *best_projector;
3200 float best_dot;
3202 VECCOPY(co1, coords[mf->v1]);
3203 VECCOPY(co2, coords[mf->v2]);
3204 VECCOPY(co3, coords[mf->v3]);
3206 /* get the untransformed face normal */
3207 if(mf->v4) {
3208 VECCOPY(co4, coords[mf->v4]);
3209 CalcNormFloat4(co1, co2, co3, co4, face_no);
3210 } else {
3211 CalcNormFloat(co1, co2, co3, face_no);
3214 /* find the projector which the face points at most directly
3215 * (projector normal with largest dot product is best)
3217 best_dot = MTC_dot3Float(projectors[0].normal, face_no);
3218 best_projector = &projectors[0];
3220 for(j = 1; j < num_projectors; ++j) {
3221 float tmp_dot = MTC_dot3Float(projectors[j].normal,
3222 face_no);
3223 if(tmp_dot > best_dot) {
3224 best_dot = tmp_dot;
3225 best_projector = &projectors[j];
3229 Mat4MulVec3Project(best_projector->projmat, co1);
3230 Mat4MulVec3Project(best_projector->projmat, co2);
3231 Mat4MulVec3Project(best_projector->projmat, co3);
3232 if(mf->v4)
3233 Mat4MulVec3Project(best_projector->projmat, co4);
3235 /* apply transformed coords as UVs */
3236 tface->uv[0][0] = co1[0];
3237 tface->uv[0][1] = co1[1];
3238 tface->uv[1][0] = co2[0];
3239 tface->uv[1][1] = co2[1];
3240 tface->uv[2][0] = co3[0];
3241 tface->uv[2][1] = co3[1];
3242 if(mf->v4) {
3243 tface->uv[3][0] = co4[0];
3244 tface->uv[3][1] = co4[1];
3249 if(override_image) {
3250 tface->mode = TF_TEX;
3251 tface->tpage = image;
3255 MEM_freeN(coords);
3257 return dm;
3260 static DerivedMesh *uvprojectModifier_applyModifier(
3261 ModifierData *md, Object *ob, DerivedMesh *derivedData,
3262 int useRenderParams, int isFinalCalc)
3264 DerivedMesh *result;
3265 UVProjectModifierData *umd = (UVProjectModifierData*) md;
3267 result = uvprojectModifier_do(umd, ob, derivedData);
3269 return result;
3272 static DerivedMesh *uvprojectModifier_applyModifierEM(
3273 ModifierData *md, Object *ob, EditMesh *editData,
3274 DerivedMesh *derivedData)
3276 return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
3279 /* Decimate */
3281 static void decimateModifier_initData(ModifierData *md)
3283 DecimateModifierData *dmd = (DecimateModifierData*) md;
3285 dmd->percent = 1.0;
3288 static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
3290 DecimateModifierData *dmd = (DecimateModifierData*) md;
3291 DecimateModifierData *tdmd = (DecimateModifierData*) target;
3293 tdmd->percent = dmd->percent;
3296 static DerivedMesh *decimateModifier_applyModifier(
3297 ModifierData *md, Object *ob, DerivedMesh *derivedData,
3298 int useRenderParams, int isFinalCalc)
3300 DecimateModifierData *dmd = (DecimateModifierData*) md;
3301 DerivedMesh *dm = derivedData, *result = NULL;
3302 MVert *mvert;
3303 MFace *mface;
3304 LOD_Decimation_Info lod;
3305 int totvert, totface;
3306 int a, numTris;
3308 mvert = dm->getVertArray(dm);
3309 mface = dm->getFaceArray(dm);
3310 totvert = dm->getNumVerts(dm);
3311 totface = dm->getNumFaces(dm);
3313 numTris = 0;
3314 for (a=0; a<totface; a++) {
3315 MFace *mf = &mface[a];
3316 numTris++;
3317 if (mf->v4) numTris++;
3320 if(numTris<3) {
3321 modifier_setError(md,
3322 "There must be more than 3 input faces (triangles).");
3323 goto exit;
3326 lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
3327 lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
3328 lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
3329 lod.vertex_num= totvert;
3330 lod.face_num= numTris;
3332 for(a=0; a<totvert; a++) {
3333 MVert *mv = &mvert[a];
3334 float *vbCo = &lod.vertex_buffer[a*3];
3335 float *vbNo = &lod.vertex_normal_buffer[a*3];
3337 VECCOPY(vbCo, mv->co);
3339 vbNo[0] = mv->no[0]/32767.0f;
3340 vbNo[1] = mv->no[1]/32767.0f;
3341 vbNo[2] = mv->no[2]/32767.0f;
3344 numTris = 0;
3345 for(a=0; a<totface; a++) {
3346 MFace *mf = &mface[a];
3347 int *tri = &lod.triangle_index_buffer[3*numTris++];
3348 tri[0]= mf->v1;
3349 tri[1]= mf->v2;
3350 tri[2]= mf->v3;
3352 if(mf->v4) {
3353 tri = &lod.triangle_index_buffer[3*numTris++];
3354 tri[0]= mf->v1;
3355 tri[1]= mf->v3;
3356 tri[2]= mf->v4;
3360 dmd->faceCount = 0;
3361 if(LOD_LoadMesh(&lod) ) {
3362 if( LOD_PreprocessMesh(&lod) ) {
3363 /* we assume the decim_faces tells how much to reduce */
3365 while(lod.face_num > numTris*dmd->percent) {
3366 if( LOD_CollapseEdge(&lod)==0) break;
3369 if(lod.vertex_num>2) {
3370 result = CDDM_new(lod.vertex_num, 0, lod.face_num);
3371 dmd->faceCount = lod.face_num;
3373 else
3374 result = CDDM_new(lod.vertex_num, 0, 0);
3376 mvert = CDDM_get_verts(result);
3377 for(a=0; a<lod.vertex_num; a++) {
3378 MVert *mv = &mvert[a];
3379 float *vbCo = &lod.vertex_buffer[a*3];
3381 VECCOPY(mv->co, vbCo);
3384 if(lod.vertex_num>2) {
3385 mface = CDDM_get_faces(result);
3386 for(a=0; a<lod.face_num; a++) {
3387 MFace *mf = &mface[a];
3388 int *tri = &lod.triangle_index_buffer[a*3];
3389 mf->v1 = tri[0];
3390 mf->v2 = tri[1];
3391 mf->v3 = tri[2];
3392 test_index_face(mf, NULL, 0, 3);
3396 CDDM_calc_edges(result);
3397 CDDM_calc_normals(result);
3399 else
3400 modifier_setError(md, "Out of memory.");
3402 LOD_FreeDecimationData(&lod);
3404 else
3405 modifier_setError(md, "Non-manifold mesh as input.");
3407 MEM_freeN(lod.vertex_buffer);
3408 MEM_freeN(lod.vertex_normal_buffer);
3409 MEM_freeN(lod.triangle_index_buffer);
3411 exit:
3412 return result;
3415 /* Smooth */
3417 static void smoothModifier_initData(ModifierData *md)
3419 SmoothModifierData *smd = (SmoothModifierData*) md;
3421 smd->fac = 0.5f;
3422 smd->repeat = 1;
3423 smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
3424 smd->defgrp_name[0] = '\0';
3427 static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
3429 SmoothModifierData *smd = (SmoothModifierData*) md;
3430 SmoothModifierData *tsmd = (SmoothModifierData*) target;
3432 tsmd->fac = smd->fac;
3433 tsmd->repeat = smd->repeat;
3434 tsmd->flag = smd->flag;
3435 strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
3438 int smoothModifier_isDisabled(ModifierData *md)
3440 SmoothModifierData *smd = (SmoothModifierData*) md;
3441 short flag;
3443 flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
3445 /* disable if modifier is off for X, Y and Z or if factor is 0 */
3446 if((smd->fac == 0.0f) || flag == 0) return 1;
3448 return 0;
3451 CustomDataMask smoothModifier_requiredDataMask(ModifierData *md)
3453 SmoothModifierData *smd = (SmoothModifierData *)md;
3454 CustomDataMask dataMask = 0;
3456 /* ask for vertexgroups if we need them */
3457 if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
3459 return dataMask;
3462 static void smoothModifier_do(
3463 SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
3464 float (*vertexCos)[3], int numVerts)
3466 MDeformVert *dvert = NULL;
3467 MEdge *medges = NULL;
3469 int i, j, numDMEdges, defgrp_index;
3470 unsigned char *uctmp;
3471 float *ftmp, fac, facm;
3473 ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
3474 "smoothmodifier_f");
3475 if (!ftmp) return;
3476 uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
3477 "smoothmodifier_uc");
3478 if (!uctmp) {
3479 if (ftmp) MEM_freeN(ftmp);
3480 return;
3483 fac = smd->fac;
3484 facm = 1 - fac;
3486 medges = CDDM_get_edges(dm);
3487 numDMEdges = dm->getNumEdges(dm);
3489 defgrp_index = -1;
3491 if (smd->defgrp_name[0]) {
3492 bDeformGroup *def;
3494 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3495 if (!strcmp(def->name, smd->defgrp_name)) {
3496 defgrp_index = i;
3497 break;
3502 if (defgrp_index >= 0)
3503 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3505 /* NOTICE: this can be optimized a little bit by moving the
3506 * if (dvert) out of the loop, if needed */
3507 for (j = 0; j < smd->repeat; j++) {
3508 for (i = 0; i < numDMEdges; i++) {
3509 float fvec[3];
3510 float *v1, *v2;
3511 unsigned int idx1, idx2;
3513 idx1 = medges[i].v1;
3514 idx2 = medges[i].v2;
3516 v1 = vertexCos[idx1];
3517 v2 = vertexCos[idx2];
3519 fvec[0] = (v1[0] + v2[0]) / 2.0;
3520 fvec[1] = (v1[1] + v2[1]) / 2.0;
3521 fvec[2] = (v1[2] + v2[2]) / 2.0;
3523 v1 = &ftmp[idx1*3];
3524 v2 = &ftmp[idx2*3];
3526 if (uctmp[idx1] < 255) {
3527 uctmp[idx1]++;
3528 VecAddf(v1, v1, fvec);
3530 if (uctmp[idx2] < 255) {
3531 uctmp[idx2]++;
3532 VecAddf(v2, v2, fvec);
3536 if (dvert) {
3537 for (i = 0; i < numVerts; i++) {
3538 MDeformWeight *dw = NULL;
3539 float f, fm, facw, *fp, *v;
3540 int k;
3541 short flag = smd->flag;
3543 v = vertexCos[i];
3544 fp = &ftmp[i*3];
3546 for (k = 0; k < dvert[i].totweight; ++k) {
3547 if(dvert[i].dw[k].def_nr == defgrp_index) {
3548 dw = &dvert[i].dw[k];
3549 break;
3552 if (!dw) continue;
3554 f = fac * dw->weight;
3555 fm = 1.0f - f;
3557 /* fp is the sum of uctmp[i] verts, so must be averaged */
3558 facw = 0.0f;
3559 if (uctmp[i])
3560 facw = f / (float)uctmp[i];
3562 if (flag & MOD_SMOOTH_X)
3563 v[0] = fm * v[0] + facw * fp[0];
3564 if (flag & MOD_SMOOTH_Y)
3565 v[1] = fm * v[1] + facw * fp[1];
3566 if (flag & MOD_SMOOTH_Z)
3567 v[2] = fm * v[2] + facw * fp[2];
3570 else { /* no vertex group */
3571 for (i = 0; i < numVerts; i++) {
3572 float facw, *fp, *v;
3573 short flag = smd->flag;
3575 v = vertexCos[i];
3576 fp = &ftmp[i*3];
3578 /* fp is the sum of uctmp[i] verts, so must be averaged */
3579 facw = 0.0f;
3580 if (uctmp[i])
3581 facw = fac / (float)uctmp[i];
3583 if (flag & MOD_SMOOTH_X)
3584 v[0] = facm * v[0] + facw * fp[0];
3585 if (flag & MOD_SMOOTH_Y)
3586 v[1] = facm * v[1] + facw * fp[1];
3587 if (flag & MOD_SMOOTH_Z)
3588 v[2] = facm * v[2] + facw * fp[2];
3593 memset(ftmp, 0, 3*sizeof(float)*numVerts);
3594 memset(uctmp, 0, sizeof(unsigned char)*numVerts);
3597 MEM_freeN(ftmp);
3598 MEM_freeN(uctmp);
3601 static void smoothModifier_deformVerts(
3602 ModifierData *md, Object *ob, DerivedMesh *derivedData,
3603 float (*vertexCos)[3], int numVerts)
3605 DerivedMesh *dm;
3607 if(derivedData) dm = CDDM_copy(derivedData);
3608 else dm = CDDM_from_mesh(ob->data, ob);
3610 CDDM_apply_vert_coords(dm, vertexCos);
3611 CDDM_calc_normals(dm);
3613 smoothModifier_do((SmoothModifierData *)md, ob, dm,
3614 vertexCos, numVerts);
3616 dm->release(dm);
3619 static void smoothModifier_deformVertsEM(
3620 ModifierData *md, Object *ob, EditMesh *editData,
3621 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
3623 DerivedMesh *dm;
3625 if(derivedData) dm = CDDM_copy(derivedData);
3626 else dm = CDDM_from_editmesh(editData, ob->data);
3628 CDDM_apply_vert_coords(dm, vertexCos);
3629 CDDM_calc_normals(dm);
3631 smoothModifier_do((SmoothModifierData *)md, ob, dm,
3632 vertexCos, numVerts);
3634 dm->release(dm);
3637 /* Cast */
3639 static void castModifier_initData(ModifierData *md)
3641 CastModifierData *cmd = (CastModifierData*) md;
3643 cmd->fac = 0.5f;
3644 cmd->radius = 0.0f;
3645 cmd->size = 0.0f;
3646 cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
3647 | MOD_CAST_SIZE_FROM_RADIUS;
3648 cmd->type = MOD_CAST_TYPE_SPHERE;
3649 cmd->defgrp_name[0] = '\0';
3650 cmd->object = NULL;
3654 static void castModifier_copyData(ModifierData *md, ModifierData *target)
3656 CastModifierData *cmd = (CastModifierData*) md;
3657 CastModifierData *tcmd = (CastModifierData*) target;
3659 tcmd->fac = cmd->fac;
3660 tcmd->radius = cmd->radius;
3661 tcmd->size = cmd->size;
3662 tcmd->flag = cmd->flag;
3663 tcmd->type = cmd->type;
3664 tcmd->object = cmd->object;
3665 strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
3668 int castModifier_isDisabled(ModifierData *md)
3670 CastModifierData *cmd = (CastModifierData*) md;
3671 short flag;
3673 flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
3675 if((cmd->fac == 0.0f) || flag == 0) return 1;
3677 return 0;
3680 CustomDataMask castModifier_requiredDataMask(ModifierData *md)
3682 CastModifierData *cmd = (CastModifierData *)md;
3683 CustomDataMask dataMask = 0;
3685 /* ask for vertexgroups if we need them */
3686 if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
3688 return dataMask;
3691 static void castModifier_foreachObjectLink(
3692 ModifierData *md, Object *ob,
3693 void (*walk)(void *userData, Object *ob, Object **obpoin),
3694 void *userData)
3696 CastModifierData *cmd = (CastModifierData*) md;
3698 walk (userData, ob, &cmd->object);
3701 static void castModifier_updateDepgraph(
3702 ModifierData *md, DagForest *forest, Object *ob,
3703 DagNode *obNode)
3705 CastModifierData *cmd = (CastModifierData*) md;
3707 if (cmd->object) {
3708 DagNode *curNode = dag_get_node(forest, cmd->object);
3710 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
3714 static void castModifier_sphere_do(
3715 CastModifierData *cmd, Object *ob, DerivedMesh *dm,
3716 float (*vertexCos)[3], int numVerts)
3718 MDeformVert *dvert = NULL;
3720 Object *ctrl_ob = NULL;
3722 int i, defgrp_index = -1;
3723 int has_radius = 0;
3724 short flag, type;
3725 float fac, facm, len = 0.0f;
3726 float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
3727 float mat[4][4], imat[4][4];
3729 fac = cmd->fac;
3730 facm = 1.0f - fac;
3732 flag = cmd->flag;
3733 type = cmd->type; /* projection type: sphere or cylinder */
3735 if (type == MOD_CAST_TYPE_CYLINDER)
3736 flag &= ~MOD_CAST_Z;
3738 ctrl_ob = cmd->object;
3740 /* spherify's center is {0, 0, 0} (the ob's own center in its local
3741 * space), by default, but if the user defined a control object,
3742 * we use its location, transformed to ob's local space */
3743 if (ctrl_ob) {
3744 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3745 Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
3746 Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
3747 Mat4Invert(imat, mat);
3750 Mat4Invert(ob->imat, ob->obmat);
3751 VECCOPY(center, ctrl_ob->obmat[3]);
3752 Mat4MulVecfl(ob->imat, center);
3755 /* now we check which options the user wants */
3757 /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
3758 /* 2) cmd->radius > 0.0f: only the vertices within this radius from
3759 * the center of the effect should be deformed */
3760 if (cmd->radius > FLT_EPSILON) has_radius = 1;
3762 /* 3) if we were given a vertex group name,
3763 * only those vertices should be affected */
3764 if (cmd->defgrp_name[0]) {
3765 bDeformGroup *def;
3767 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3768 if (!strcmp(def->name, cmd->defgrp_name)) {
3769 defgrp_index = i;
3770 break;
3775 if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
3776 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3778 if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
3779 len = cmd->radius;
3781 else {
3782 len = cmd->size;
3785 if(len <= 0) {
3786 for (i = 0; i < numVerts; i++) {
3787 len += VecLenf(center, vertexCos[i]);
3789 len /= numVerts;
3791 if (len == 0.0f) len = 10.0f;
3794 /* ready to apply the effect, one vertex at a time;
3795 * tiny optimization: the code is separated (with parts repeated)
3796 * in two possible cases:
3797 * with or w/o a vgroup. With lots of if's in the code below,
3798 * further optimizations are possible, if needed */
3799 if (dvert) { /* with a vgroup */
3800 float fac_orig = fac;
3801 for (i = 0; i < numVerts; i++) {
3802 MDeformWeight *dw = NULL;
3803 int j;
3804 float tmp_co[3];
3806 VECCOPY(tmp_co, vertexCos[i]);
3807 if(ctrl_ob) {
3808 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3809 Mat4MulVecfl(mat, tmp_co);
3810 } else {
3811 VecSubf(tmp_co, tmp_co, center);
3815 VECCOPY(vec, tmp_co);
3817 if (type == MOD_CAST_TYPE_CYLINDER)
3818 vec[2] = 0.0f;
3820 if (has_radius) {
3821 if (VecLength(vec) > cmd->radius) continue;
3824 for (j = 0; j < dvert[i].totweight; ++j) {
3825 if(dvert[i].dw[j].def_nr == defgrp_index) {
3826 dw = &dvert[i].dw[j];
3827 break;
3830 if (!dw) continue;
3832 fac = fac_orig * dw->weight;
3833 facm = 1.0f - fac;
3835 Normalize(vec);
3837 if (flag & MOD_CAST_X)
3838 tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
3839 if (flag & MOD_CAST_Y)
3840 tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
3841 if (flag & MOD_CAST_Z)
3842 tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
3844 if(ctrl_ob) {
3845 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3846 Mat4MulVecfl(imat, tmp_co);
3847 } else {
3848 VecAddf(tmp_co, tmp_co, center);
3852 VECCOPY(vertexCos[i], tmp_co);
3854 return;
3857 /* no vgroup */
3858 for (i = 0; i < numVerts; i++) {
3859 float tmp_co[3];
3861 VECCOPY(tmp_co, vertexCos[i]);
3862 if(ctrl_ob) {
3863 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3864 Mat4MulVecfl(mat, tmp_co);
3865 } else {
3866 VecSubf(tmp_co, tmp_co, center);
3870 VECCOPY(vec, tmp_co);
3872 if (type == MOD_CAST_TYPE_CYLINDER)
3873 vec[2] = 0.0f;
3875 if (has_radius) {
3876 if (VecLength(vec) > cmd->radius) continue;
3879 Normalize(vec);
3881 if (flag & MOD_CAST_X)
3882 tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
3883 if (flag & MOD_CAST_Y)
3884 tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
3885 if (flag & MOD_CAST_Z)
3886 tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
3888 if(ctrl_ob) {
3889 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3890 Mat4MulVecfl(imat, tmp_co);
3891 } else {
3892 VecAddf(tmp_co, tmp_co, center);
3896 VECCOPY(vertexCos[i], tmp_co);
3900 static void castModifier_cuboid_do(
3901 CastModifierData *cmd, Object *ob, DerivedMesh *dm,
3902 float (*vertexCos)[3], int numVerts)
3904 MDeformVert *dvert = NULL;
3905 Object *ctrl_ob = NULL;
3907 int i, defgrp_index = -1;
3908 int has_radius = 0;
3909 short flag;
3910 float fac, facm;
3911 float min[3], max[3], bb[8][3];
3912 float center[3] = {0.0f, 0.0f, 0.0f};
3913 float mat[4][4], imat[4][4];
3915 fac = cmd->fac;
3916 facm = 1.0f - fac;
3918 flag = cmd->flag;
3920 ctrl_ob = cmd->object;
3922 /* now we check which options the user wants */
3924 /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
3925 /* 2) cmd->radius > 0.0f: only the vertices within this radius from
3926 * the center of the effect should be deformed */
3927 if (cmd->radius > FLT_EPSILON) has_radius = 1;
3929 /* 3) if we were given a vertex group name,
3930 * only those vertices should be affected */
3931 if (cmd->defgrp_name[0]) {
3932 bDeformGroup *def;
3934 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3935 if (!strcmp(def->name, cmd->defgrp_name)) {
3936 defgrp_index = i;
3937 break;
3942 if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
3943 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3945 if (ctrl_ob) {
3946 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3947 Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
3948 Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
3949 Mat4Invert(imat, mat);
3952 Mat4Invert(ob->imat, ob->obmat);
3953 VECCOPY(center, ctrl_ob->obmat[3]);
3954 Mat4MulVecfl(ob->imat, center);
3957 if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
3958 for(i = 0; i < 3; i++) {
3959 min[i] = -cmd->radius;
3960 max[i] = cmd->radius;
3962 } else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
3963 for(i = 0; i < 3; i++) {
3964 min[i] = -cmd->size;
3965 max[i] = cmd->size;
3967 } else {
3968 /* get bound box */
3969 /* We can't use the object's bound box because other modifiers
3970 * may have changed the vertex data. */
3971 INIT_MINMAX(min, max);
3973 /* Cast's center is the ob's own center in its local space,
3974 * by default, but if the user defined a control object, we use
3975 * its location, transformed to ob's local space. */
3976 if (ctrl_ob) {
3977 float vec[3];
3979 /* let the center of the ctrl_ob be part of the bound box: */
3980 DO_MINMAX(center, min, max);
3982 for (i = 0; i < numVerts; i++) {
3983 VecSubf(vec, vertexCos[i], center);
3984 DO_MINMAX(vec, min, max);
3987 else {
3988 for (i = 0; i < numVerts; i++) {
3989 DO_MINMAX(vertexCos[i], min, max);
3993 /* we want a symmetric bound box around the origin */
3994 if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]);
3995 if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]);
3996 if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
3997 min[0] = -max[0];
3998 min[1] = -max[1];
3999 min[2] = -max[2];
4002 /* building our custom bounding box */
4003 bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
4004 bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
4005 bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
4006 bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
4007 bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
4008 bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
4010 /* ready to apply the effect, one vertex at a time;
4011 * tiny optimization: the code is separated (with parts repeated)
4012 * in two possible cases:
4013 * with or w/o a vgroup. With lots of if's in the code below,
4014 * further optimizations are possible, if needed */
4015 if (dvert) { /* with a vgroup */
4016 float fac_orig = fac;
4017 for (i = 0; i < numVerts; i++) {
4018 MDeformWeight *dw = NULL;
4019 int j, octant, coord;
4020 float d[3], dmax, apex[3], fbb;
4021 float tmp_co[3];
4023 VECCOPY(tmp_co, vertexCos[i]);
4024 if(ctrl_ob) {
4025 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4026 Mat4MulVecfl(mat, tmp_co);
4027 } else {
4028 VecSubf(tmp_co, tmp_co, center);
4032 if (has_radius) {
4033 if (fabs(tmp_co[0]) > cmd->radius ||
4034 fabs(tmp_co[1]) > cmd->radius ||
4035 fabs(tmp_co[2]) > cmd->radius) continue;
4038 for (j = 0; j < dvert[i].totweight; ++j) {
4039 if(dvert[i].dw[j].def_nr == defgrp_index) {
4040 dw = &dvert[i].dw[j];
4041 break;
4044 if (!dw) continue;
4046 fac = fac_orig * dw->weight;
4047 facm = 1.0f - fac;
4049 /* The algo used to project the vertices to their
4050 * bounding box (bb) is pretty simple:
4051 * for each vertex v:
4052 * 1) find in which octant v is in;
4053 * 2) find which outer "wall" of that octant is closer to v;
4054 * 3) calculate factor (var fbb) to project v to that wall;
4055 * 4) project. */
4057 /* find in which octant this vertex is in */
4058 octant = 0;
4059 if (tmp_co[0] > 0.0f) octant += 1;
4060 if (tmp_co[1] > 0.0f) octant += 2;
4061 if (tmp_co[2] > 0.0f) octant += 4;
4063 /* apex is the bb's vertex at the chosen octant */
4064 VecCopyf(apex, bb[octant]);
4066 /* find which bb plane is closest to this vertex ... */
4067 d[0] = tmp_co[0] / apex[0];
4068 d[1] = tmp_co[1] / apex[1];
4069 d[2] = tmp_co[2] / apex[2];
4071 /* ... (the closest has the higher (closer to 1) d value) */
4072 dmax = d[0];
4073 coord = 0;
4074 if (d[1] > dmax) {
4075 dmax = d[1];
4076 coord = 1;
4078 if (d[2] > dmax) {
4079 /* dmax = d[2]; */ /* commented, we don't need it */
4080 coord = 2;
4083 /* ok, now we know which coordinate of the vertex to use */
4085 if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
4086 continue;
4088 /* finally, this is the factor we wanted, to project the vertex
4089 * to its bounding box (bb) */
4090 fbb = apex[coord] / tmp_co[coord];
4092 /* calculate the new vertex position */
4093 if (flag & MOD_CAST_X)
4094 tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
4095 if (flag & MOD_CAST_Y)
4096 tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
4097 if (flag & MOD_CAST_Z)
4098 tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
4100 if(ctrl_ob) {
4101 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4102 Mat4MulVecfl(imat, tmp_co);
4103 } else {
4104 VecAddf(tmp_co, tmp_co, center);
4108 VECCOPY(vertexCos[i], tmp_co);
4110 return;
4113 /* no vgroup (check previous case for comments about the code) */
4114 for (i = 0; i < numVerts; i++) {
4115 int octant, coord;
4116 float d[3], dmax, fbb, apex[3];
4117 float tmp_co[3];
4119 VECCOPY(tmp_co, vertexCos[i]);
4120 if(ctrl_ob) {
4121 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4122 Mat4MulVecfl(mat, tmp_co);
4123 } else {
4124 VecSubf(tmp_co, tmp_co, center);
4128 if (has_radius) {
4129 if (fabs(tmp_co[0]) > cmd->radius ||
4130 fabs(tmp_co[1]) > cmd->radius ||
4131 fabs(tmp_co[2]) > cmd->radius) continue;
4134 octant = 0;
4135 if (tmp_co[0] > 0.0f) octant += 1;
4136 if (tmp_co[1] > 0.0f) octant += 2;
4137 if (tmp_co[2] > 0.0f) octant += 4;
4139 VecCopyf(apex, bb[octant]);
4141 d[0] = tmp_co[0] / apex[0];
4142 d[1] = tmp_co[1] / apex[1];
4143 d[2] = tmp_co[2] / apex[2];
4145 dmax = d[0];
4146 coord = 0;
4147 if (d[1] > dmax) {
4148 dmax = d[1];
4149 coord = 1;
4151 if (d[2] > dmax) {
4152 /* dmax = d[2]; */ /* commented, we don't need it */
4153 coord = 2;
4156 if (fabs(tmp_co[coord]) < FLT_EPSILON)
4157 continue;
4159 fbb = apex[coord] / tmp_co[coord];
4161 if (flag & MOD_CAST_X)
4162 tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
4163 if (flag & MOD_CAST_Y)
4164 tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
4165 if (flag & MOD_CAST_Z)
4166 tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
4168 if(ctrl_ob) {
4169 if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4170 Mat4MulVecfl(imat, tmp_co);
4171 } else {
4172 VecAddf(tmp_co, tmp_co, center);
4176 VECCOPY(vertexCos[i], tmp_co);
4180 static void castModifier_deformVerts(
4181 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4182 float (*vertexCos)[3], int numVerts)
4184 DerivedMesh *dm = derivedData;
4185 CastModifierData *cmd = (CastModifierData *)md;
4187 if (!dm && ob->type == OB_MESH)
4188 dm = CDDM_from_mesh(ob->data, ob);
4190 if (cmd->type == MOD_CAST_TYPE_CUBOID) {
4191 castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
4192 } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
4193 castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
4196 if (!derivedData && dm) dm->release(dm);
4199 static void castModifier_deformVertsEM(
4200 ModifierData *md, Object *ob, EditMesh *editData,
4201 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
4203 DerivedMesh *dm = derivedData;
4204 CastModifierData *cmd = (CastModifierData *)md;
4206 if (!dm && ob->type == OB_MESH)
4207 dm = CDDM_from_editmesh(editData, ob->data);
4209 if (cmd->type == MOD_CAST_TYPE_CUBOID) {
4210 castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
4211 } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
4212 castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
4215 if (!derivedData && dm) dm->release(dm);
4218 /* Wave */
4220 static void waveModifier_initData(ModifierData *md)
4222 WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
4224 wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
4225 | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
4227 wmd->objectcenter = NULL;
4228 wmd->texture = NULL;
4229 wmd->map_object = NULL;
4230 wmd->height= 0.5f;
4231 wmd->width= 1.5f;
4232 wmd->speed= 0.5f;
4233 wmd->narrow= 1.5f;
4234 wmd->lifetime= 0.0f;
4235 wmd->damp= 10.0f;
4236 wmd->texmapping = MOD_WAV_MAP_LOCAL;
4237 wmd->defgrp_name[0] = 0;
4240 static void waveModifier_copyData(ModifierData *md, ModifierData *target)
4242 WaveModifierData *wmd = (WaveModifierData*) md;
4243 WaveModifierData *twmd = (WaveModifierData*) target;
4245 twmd->damp = wmd->damp;
4246 twmd->flag = wmd->flag;
4247 twmd->height = wmd->height;
4248 twmd->lifetime = wmd->lifetime;
4249 twmd->narrow = wmd->narrow;
4250 twmd->speed = wmd->speed;
4251 twmd->startx = wmd->startx;
4252 twmd->starty = wmd->starty;
4253 twmd->timeoffs = wmd->timeoffs;
4254 twmd->width = wmd->width;
4255 twmd->objectcenter = wmd->objectcenter;
4256 twmd->texture = wmd->texture;
4257 twmd->map_object = wmd->map_object;
4258 twmd->texmapping = wmd->texmapping;
4259 strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
4262 static int waveModifier_dependsOnTime(ModifierData *md)
4264 return 1;
4267 static void waveModifier_foreachObjectLink(
4268 ModifierData *md, Object *ob,
4269 ObjectWalkFunc walk, void *userData)
4271 WaveModifierData *wmd = (WaveModifierData*) md;
4273 walk(userData, ob, &wmd->objectcenter);
4274 walk(userData, ob, &wmd->map_object);
4277 static void waveModifier_foreachIDLink(ModifierData *md, Object *ob,
4278 IDWalkFunc walk, void *userData)
4280 WaveModifierData *wmd = (WaveModifierData*) md;
4282 walk(userData, ob, (ID **)&wmd->texture);
4284 waveModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
4287 static void waveModifier_updateDepgraph(
4288 ModifierData *md, DagForest *forest, Object *ob,
4289 DagNode *obNode)
4291 WaveModifierData *wmd = (WaveModifierData*) md;
4293 if(wmd->objectcenter) {
4294 DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
4296 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
4299 if(wmd->map_object) {
4300 DagNode *curNode = dag_get_node(forest, wmd->map_object);
4302 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
4306 CustomDataMask waveModifier_requiredDataMask(ModifierData *md)
4308 WaveModifierData *wmd = (WaveModifierData *)md;
4309 CustomDataMask dataMask = 0;
4312 /* ask for UV coordinates if we need them */
4313 if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
4314 dataMask |= (1 << CD_MTFACE);
4316 /* ask for vertexgroups if we need them */
4317 if(wmd->defgrp_name[0])
4318 dataMask |= (1 << CD_MDEFORMVERT);
4320 return dataMask;
4323 static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
4324 DerivedMesh *dm,
4325 float (*co)[3], float (*texco)[3],
4326 int numVerts)
4328 int i;
4329 int texmapping = wmd->texmapping;
4331 if(texmapping == MOD_WAV_MAP_OBJECT) {
4332 if(wmd->map_object)
4333 Mat4Invert(wmd->map_object->imat, wmd->map_object->obmat);
4334 else /* if there is no map object, default to local */
4335 texmapping = MOD_WAV_MAP_LOCAL;
4338 /* UVs need special handling, since they come from faces */
4339 if(texmapping == MOD_WAV_MAP_UV) {
4340 if(dm->getFaceDataArray(dm, CD_MTFACE)) {
4341 MFace *mface = dm->getFaceArray(dm);
4342 MFace *mf;
4343 char *done = MEM_callocN(sizeof(*done) * numVerts,
4344 "get_texture_coords done");
4345 int numFaces = dm->getNumFaces(dm);
4346 MTFace *tf;
4348 validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
4350 tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
4351 wmd->uvlayer_name);
4353 /* verts are given the UV from the first face that uses them */
4354 for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
4355 if(!done[mf->v1]) {
4356 texco[mf->v1][0] = tf->uv[0][0];
4357 texco[mf->v1][1] = tf->uv[0][1];
4358 texco[mf->v1][2] = 0;
4359 done[mf->v1] = 1;
4361 if(!done[mf->v2]) {
4362 texco[mf->v2][0] = tf->uv[1][0];
4363 texco[mf->v2][1] = tf->uv[1][1];
4364 texco[mf->v2][2] = 0;
4365 done[mf->v2] = 1;
4367 if(!done[mf->v3]) {
4368 texco[mf->v3][0] = tf->uv[2][0];
4369 texco[mf->v3][1] = tf->uv[2][1];
4370 texco[mf->v3][2] = 0;
4371 done[mf->v3] = 1;
4373 if(!done[mf->v4]) {
4374 texco[mf->v4][0] = tf->uv[3][0];
4375 texco[mf->v4][1] = tf->uv[3][1];
4376 texco[mf->v4][2] = 0;
4377 done[mf->v4] = 1;
4381 /* remap UVs from [0, 1] to [-1, 1] */
4382 for(i = 0; i < numVerts; ++i) {
4383 texco[i][0] = texco[i][0] * 2 - 1;
4384 texco[i][1] = texco[i][1] * 2 - 1;
4387 MEM_freeN(done);
4388 return;
4389 } else /* if there are no UVs, default to local */
4390 texmapping = MOD_WAV_MAP_LOCAL;
4393 for(i = 0; i < numVerts; ++i, ++co, ++texco) {
4394 switch(texmapping) {
4395 case MOD_WAV_MAP_LOCAL:
4396 VECCOPY(*texco, *co);
4397 break;
4398 case MOD_WAV_MAP_GLOBAL:
4399 VECCOPY(*texco, *co);
4400 Mat4MulVecfl(ob->obmat, *texco);
4401 break;
4402 case MOD_WAV_MAP_OBJECT:
4403 VECCOPY(*texco, *co);
4404 Mat4MulVecfl(ob->obmat, *texco);
4405 Mat4MulVecfl(wmd->map_object->imat, *texco);
4406 break;
4411 static void waveModifier_do(
4412 WaveModifierData *md, Object *ob, DerivedMesh *dm,
4413 float (*vertexCos)[3], int numVerts)
4415 WaveModifierData *wmd = (WaveModifierData*) md;
4416 MVert *mvert = NULL;
4417 MDeformVert *dvert = NULL;
4418 int defgrp_index;
4419 float ctime = bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
4420 float minfac =
4421 (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
4422 float lifefac = wmd->height;
4423 float (*tex_co)[3] = NULL;
4425 if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
4426 mvert = dm->getVertArray(dm);
4428 if(wmd->objectcenter){
4429 float mat[4][4];
4430 /* get the control object's location in local coordinates */
4431 Mat4Invert(ob->imat, ob->obmat);
4432 Mat4MulMat4(mat, wmd->objectcenter->obmat, ob->imat);
4434 wmd->startx = mat[3][0];
4435 wmd->starty = mat[3][1];
4438 /* get the index of the deform group */
4439 defgrp_index = -1;
4441 if(wmd->defgrp_name[0]) {
4442 int i;
4443 bDeformGroup *def;
4444 for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
4445 if(!strcmp(def->name, wmd->defgrp_name)) {
4446 defgrp_index = i;
4447 break;
4452 if(defgrp_index >= 0){
4453 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
4456 if(wmd->damp == 0) wmd->damp = 10.0f;
4458 if(wmd->lifetime != 0.0) {
4459 float x = ctime - wmd->timeoffs;
4461 if(x > wmd->lifetime) {
4462 lifefac = x - wmd->lifetime;
4464 if(lifefac > wmd->damp) lifefac = 0.0;
4465 else lifefac =
4466 (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
4470 if(wmd->texture) {
4471 tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
4472 "waveModifier_do tex_co");
4473 wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
4476 if(lifefac != 0.0) {
4477 int i;
4479 for(i = 0; i < numVerts; i++) {
4480 float *co = vertexCos[i];
4481 float x = co[0] - wmd->startx;
4482 float y = co[1] - wmd->starty;
4483 float amplit= 0.0f;
4484 TexResult texres;
4485 MDeformWeight *def_weight = NULL;
4487 /* get weights */
4488 if(dvert) {
4489 int j;
4490 for(j = 0; j < dvert[i].totweight; ++j) {
4491 if(dvert[i].dw[j].def_nr == defgrp_index) {
4492 def_weight = &dvert[i].dw[j];
4493 break;
4497 /* if this vert isn't in the vgroup, don't deform it */
4498 if(!def_weight) continue;
4501 if(wmd->texture) {
4502 texres.nor = NULL;
4503 get_texture_value(wmd->texture, tex_co[i], &texres);
4507 if(wmd->flag & MOD_WAVE_X) {
4508 if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
4509 else amplit = x;
4511 else if(wmd->flag & MOD_WAVE_Y)
4512 amplit= y;
4514 /* this way it makes nice circles */
4515 amplit -= (ctime - wmd->timeoffs) * wmd->speed;
4517 if(wmd->flag & MOD_WAVE_CYCL) {
4518 amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
4519 + wmd->width;
4522 /* GAUSSIAN */
4523 if(amplit > -wmd->width && amplit < wmd->width) {
4524 amplit = amplit * wmd->narrow;
4525 amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
4526 if(wmd->texture)
4527 amplit = amplit * texres.tin;
4529 if(def_weight)
4530 amplit = amplit * def_weight->weight;
4532 if(mvert) {
4533 /* move along normals */
4534 if(wmd->flag & MOD_WAVE_NORM_X) {
4535 co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
4537 if(wmd->flag & MOD_WAVE_NORM_Y) {
4538 co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
4540 if(wmd->flag & MOD_WAVE_NORM_Z) {
4541 co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
4544 else {
4545 /* move along local z axis */
4546 co[2] += lifefac * amplit;
4552 if(wmd->texture) MEM_freeN(tex_co);
4555 static void waveModifier_deformVerts(
4556 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4557 float (*vertexCos)[3], int numVerts)
4559 DerivedMesh *dm;
4560 WaveModifierData *wmd = (WaveModifierData *)md;
4562 if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
4563 dm = derivedData;
4564 else if(derivedData) dm = derivedData;
4565 else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
4566 else return;
4568 if(wmd->flag & MOD_WAVE_NORM) {
4569 CDDM_apply_vert_coords(dm, vertexCos);
4570 CDDM_calc_normals(dm);
4573 waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
4575 if(dm != derivedData) dm->release(dm);
4578 static void waveModifier_deformVertsEM(
4579 ModifierData *md, Object *ob, EditMesh *editData,
4580 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
4582 DerivedMesh *dm;
4583 WaveModifierData *wmd = (WaveModifierData *)md;
4585 if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
4586 dm = derivedData;
4587 else if(derivedData) dm = derivedData;
4588 else dm = CDDM_from_editmesh(editData, ob->data);
4590 if(wmd->flag & MOD_WAVE_NORM) {
4591 CDDM_apply_vert_coords(dm, vertexCos);
4592 CDDM_calc_normals(dm);
4595 waveModifier_do(wmd, ob, dm, vertexCos, numVerts);
4597 if(dm != derivedData) dm->release(dm);
4600 /* Armature */
4602 static void armatureModifier_initData(ModifierData *md)
4604 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4606 amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
4609 static void armatureModifier_copyData(ModifierData *md, ModifierData *target)
4611 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4612 ArmatureModifierData *tamd = (ArmatureModifierData*) target;
4614 tamd->object = amd->object;
4615 tamd->deformflag = amd->deformflag;
4616 strncpy(tamd->defgrp_name, amd->defgrp_name, 32);
4619 CustomDataMask armatureModifier_requiredDataMask(ModifierData *md)
4621 CustomDataMask dataMask = 0;
4623 /* ask for vertexgroups */
4624 dataMask |= (1 << CD_MDEFORMVERT);
4626 return dataMask;
4629 static int armatureModifier_isDisabled(ModifierData *md)
4631 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4633 return !amd->object;
4636 static void armatureModifier_foreachObjectLink(
4637 ModifierData *md, Object *ob,
4638 void (*walk)(void *userData, Object *ob, Object **obpoin),
4639 void *userData)
4641 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4643 walk(userData, ob, &amd->object);
4646 static void armatureModifier_updateDepgraph(
4647 ModifierData *md, DagForest *forest, Object *ob,
4648 DagNode *obNode)
4650 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4652 if (amd->object) {
4653 DagNode *curNode = dag_get_node(forest, amd->object);
4655 dag_add_relation(forest, curNode, obNode,
4656 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
4660 static void armatureModifier_deformVerts(
4661 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4662 float (*vertexCos)[3], int numVerts)
4664 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4666 armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
4667 numVerts, amd->deformflag, amd->defgrp_name);
4670 static void armatureModifier_deformVertsEM(
4671 ModifierData *md, Object *ob, EditMesh *editData,
4672 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
4674 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4675 DerivedMesh *dm = derivedData;
4677 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
4679 armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
4680 amd->deformflag, amd->defgrp_name);
4682 if(!derivedData) dm->release(dm);
4685 static void armatureModifier_deformMatricesEM(
4686 ModifierData *md, Object *ob, EditMesh *editData,
4687 DerivedMesh *derivedData, float (*vertexCos)[3],
4688 float (*defMats)[3][3], int numVerts)
4690 ArmatureModifierData *amd = (ArmatureModifierData*) md;
4691 DerivedMesh *dm = derivedData;
4693 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
4695 armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
4696 amd->deformflag, amd->defgrp_name);
4698 if(!derivedData) dm->release(dm);
4701 /* Hook */
4703 static void hookModifier_initData(ModifierData *md)
4705 HookModifierData *hmd = (HookModifierData*) md;
4707 hmd->force= 1.0;
4710 static void hookModifier_copyData(ModifierData *md, ModifierData *target)
4712 HookModifierData *hmd = (HookModifierData*) md;
4713 HookModifierData *thmd = (HookModifierData*) target;
4715 VECCOPY(thmd->cent, hmd->cent);
4716 thmd->falloff = hmd->falloff;
4717 thmd->force = hmd->force;
4718 thmd->object = hmd->object;
4719 thmd->totindex = hmd->totindex;
4720 thmd->indexar = MEM_dupallocN(hmd->indexar);
4721 memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
4722 strncpy(thmd->name, hmd->name, 32);
4725 CustomDataMask hookModifier_requiredDataMask(ModifierData *md)
4727 HookModifierData *hmd = (HookModifierData *)md;
4728 CustomDataMask dataMask = 0;
4730 /* ask for vertexgroups if we need them */
4731 if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
4733 return dataMask;
4736 static void hookModifier_freeData(ModifierData *md)
4738 HookModifierData *hmd = (HookModifierData*) md;
4740 if (hmd->indexar) MEM_freeN(hmd->indexar);
4743 static int hookModifier_isDisabled(ModifierData *md)
4745 HookModifierData *hmd = (HookModifierData*) md;
4747 return !hmd->object;
4750 static void hookModifier_foreachObjectLink(
4751 ModifierData *md, Object *ob,
4752 void (*walk)(void *userData, Object *ob, Object **obpoin),
4753 void *userData)
4755 HookModifierData *hmd = (HookModifierData*) md;
4757 walk(userData, ob, &hmd->object);
4760 static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest,
4761 Object *ob, DagNode *obNode)
4763 HookModifierData *hmd = (HookModifierData*) md;
4765 if (hmd->object) {
4766 DagNode *curNode = dag_get_node(forest, hmd->object);
4768 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
4772 static void hookModifier_deformVerts(
4773 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4774 float (*vertexCos)[3], int numVerts)
4776 HookModifierData *hmd = (HookModifierData*) md;
4777 float vec[3], mat[4][4];
4778 int i;
4779 DerivedMesh *dm = derivedData;
4781 Mat4Invert(ob->imat, ob->obmat);
4782 Mat4MulSerie(mat, ob->imat, hmd->object->obmat, hmd->parentinv,
4783 NULL, NULL, NULL, NULL, NULL);
4785 /* vertex indices? */
4786 if(hmd->indexar) {
4787 for(i = 0; i < hmd->totindex; i++) {
4788 int index = hmd->indexar[i];
4790 /* This should always be true and I don't generally like
4791 * "paranoid" style code like this, but old files can have
4792 * indices that are out of range because old blender did
4793 * not correct them on exit editmode. - zr
4795 if(index < numVerts) {
4796 float *co = vertexCos[index];
4797 float fac = hmd->force;
4799 /* if DerivedMesh is present and has original index data,
4800 * use it
4802 if(dm && dm->getVertData(dm, 0, CD_ORIGINDEX)) {
4803 int j;
4804 int orig_index;
4805 for(j = 0; j < numVerts; ++j) {
4806 fac = hmd->force;
4807 orig_index = *(int *)dm->getVertData(dm, j,
4808 CD_ORIGINDEX);
4809 if(orig_index == index) {
4810 co = vertexCos[j];
4811 if(hmd->falloff != 0.0) {
4812 float len = VecLenf(co, hmd->cent);
4813 if(len > hmd->falloff) fac = 0.0;
4814 else if(len > 0.0)
4815 fac *= sqrt(1.0 - len / hmd->falloff);
4818 if(fac != 0.0) {
4819 VecMat4MulVecfl(vec, mat, co);
4820 VecLerpf(co, co, vec, fac);
4824 } else {
4825 if(hmd->falloff != 0.0) {
4826 float len = VecLenf(co, hmd->cent);
4827 if(len > hmd->falloff) fac = 0.0;
4828 else if(len > 0.0)
4829 fac *= sqrt(1.0 - len / hmd->falloff);
4832 if(fac != 0.0) {
4833 VecMat4MulVecfl(vec, mat, co);
4834 VecLerpf(co, co, vec, fac);
4839 } else { /* vertex group hook */
4840 bDeformGroup *curdef;
4841 Mesh *me = ob->data;
4842 int index = 0;
4843 int use_dverts;
4844 int maxVerts = 0;
4846 /* find the group (weak loop-in-loop) */
4847 for(curdef = ob->defbase.first; curdef; curdef = curdef->next, index++)
4848 if(!strcmp(curdef->name, hmd->name)) break;
4850 if(dm)
4851 if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
4852 use_dverts = 1;
4853 maxVerts = dm->getNumVerts(dm);
4854 } else use_dverts = 0;
4855 else if(me->dvert) {
4856 use_dverts = 1;
4857 maxVerts = me->totvert;
4858 } else use_dverts = 0;
4860 if(curdef && use_dverts) {
4861 MDeformVert *dvert = me->dvert;
4862 int i, j;
4864 for(i = 0; i < maxVerts; i++, dvert++) {
4865 if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
4866 for(j = 0; j < dvert->totweight; j++) {
4867 if(dvert->dw[j].def_nr == index) {
4868 float fac = hmd->force*dvert->dw[j].weight;
4869 float *co = vertexCos[i];
4871 if(hmd->falloff != 0.0) {
4872 float len = VecLenf(co, hmd->cent);
4873 if(len > hmd->falloff) fac = 0.0;
4874 else if(len > 0.0)
4875 fac *= sqrt(1.0 - len / hmd->falloff);
4878 VecMat4MulVecfl(vec, mat, co);
4879 VecLerpf(co, co, vec, fac);
4887 static void hookModifier_deformVertsEM(
4888 ModifierData *md, Object *ob, EditMesh *editData,
4889 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
4891 DerivedMesh *dm = derivedData;
4893 if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
4895 hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts);
4897 if(!derivedData) dm->release(dm);
4900 /* Softbody */
4902 static void softbodyModifier_deformVerts(
4903 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4904 float (*vertexCos)[3], int numVerts)
4906 sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
4909 /* Boolean */
4911 static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
4913 BooleanModifierData *bmd = (BooleanModifierData*) md;
4914 BooleanModifierData *tbmd = (BooleanModifierData*) target;
4916 tbmd->object = bmd->object;
4917 tbmd->operation = bmd->operation;
4920 static int booleanModifier_isDisabled(ModifierData *md)
4922 BooleanModifierData *bmd = (BooleanModifierData*) md;
4924 return !bmd->object;
4927 static void booleanModifier_foreachObjectLink(
4928 ModifierData *md, Object *ob,
4929 void (*walk)(void *userData, Object *ob, Object **obpoin),
4930 void *userData)
4932 BooleanModifierData *bmd = (BooleanModifierData*) md;
4934 walk(userData, ob, &bmd->object);
4937 static void booleanModifier_updateDepgraph(
4938 ModifierData *md, DagForest *forest, Object *ob,
4939 DagNode *obNode)
4941 BooleanModifierData *bmd = (BooleanModifierData*) md;
4943 if(bmd->object) {
4944 DagNode *curNode = dag_get_node(forest, bmd->object);
4946 dag_add_relation(forest, curNode, obNode,
4947 DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
4951 static DerivedMesh *booleanModifier_applyModifier(
4952 ModifierData *md, Object *ob, DerivedMesh *derivedData,
4953 int useRenderParams, int isFinalCalc)
4955 // XXX doesn't handle derived data
4956 BooleanModifierData *bmd = (BooleanModifierData*) md;
4958 /* we do a quick sanity check */
4959 if(((Mesh *)ob->data)->totface > 3
4960 && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) {
4961 DerivedMesh *result = NewBooleanDerivedMesh(bmd->object, ob,
4962 1 + bmd->operation);
4964 /* if new mesh returned, return it; otherwise there was
4965 * an error, so delete the modifier object */
4966 if(result)
4967 return result;
4968 else
4969 bmd->object = NULL;
4972 return derivedData;
4975 /***/
4977 static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
4978 static int typeArrInit = 1;
4980 ModifierTypeInfo *modifierType_getInfo(ModifierType type)
4982 if (typeArrInit) {
4983 ModifierTypeInfo *mti;
4985 memset(typeArr, 0, sizeof(typeArr));
4987 /* Initialize and return the appropriate type info structure,
4988 * assumes that modifier has:
4989 * name == typeName,
4990 * structName == typeName + 'ModifierData'
4992 #define INIT_TYPE(typeName) \
4993 (strcpy(typeArr[eModifierType_##typeName].name, #typeName), \
4994 strcpy(typeArr[eModifierType_##typeName].structName, \
4995 #typeName "ModifierData"), \
4996 typeArr[eModifierType_##typeName].structSize = \
4997 sizeof(typeName##ModifierData), \
4998 &typeArr[eModifierType_##typeName])
5000 mti = &typeArr[eModifierType_None];
5001 strcpy(mti->name, "None");
5002 strcpy(mti->structName, "ModifierData");
5003 mti->structSize = sizeof(ModifierData);
5004 mti->type = eModifierType_None;
5005 mti->flags = eModifierTypeFlag_AcceptsMesh
5006 | eModifierTypeFlag_AcceptsCVs;
5007 mti->isDisabled = noneModifier_isDisabled;
5009 mti = INIT_TYPE(Curve);
5010 mti->type = eModifierTypeType_OnlyDeform;
5011 mti->flags = eModifierTypeFlag_AcceptsCVs
5012 | eModifierTypeFlag_SupportsEditmode;
5013 mti->initData = curveModifier_initData;
5014 mti->copyData = curveModifier_copyData;
5015 mti->requiredDataMask = curveModifier_requiredDataMask;
5016 mti->isDisabled = curveModifier_isDisabled;
5017 mti->foreachObjectLink = curveModifier_foreachObjectLink;
5018 mti->updateDepgraph = curveModifier_updateDepgraph;
5019 mti->deformVerts = curveModifier_deformVerts;
5020 mti->deformVertsEM = curveModifier_deformVertsEM;
5022 mti = INIT_TYPE(Lattice);
5023 mti->type = eModifierTypeType_OnlyDeform;
5024 mti->flags = eModifierTypeFlag_AcceptsCVs
5025 | eModifierTypeFlag_SupportsEditmode;
5026 mti->copyData = latticeModifier_copyData;
5027 mti->requiredDataMask = latticeModifier_requiredDataMask;
5028 mti->isDisabled = latticeModifier_isDisabled;
5029 mti->foreachObjectLink = latticeModifier_foreachObjectLink;
5030 mti->updateDepgraph = latticeModifier_updateDepgraph;
5031 mti->deformVerts = latticeModifier_deformVerts;
5032 mti->deformVertsEM = latticeModifier_deformVertsEM;
5034 mti = INIT_TYPE(Subsurf);
5035 mti->type = eModifierTypeType_Constructive;
5036 mti->flags = eModifierTypeFlag_AcceptsMesh
5037 | eModifierTypeFlag_SupportsMapping
5038 | eModifierTypeFlag_SupportsEditmode
5039 | eModifierTypeFlag_EnableInEditmode;
5040 mti->initData = subsurfModifier_initData;
5041 mti->copyData = subsurfModifier_copyData;
5042 mti->freeData = subsurfModifier_freeData;
5043 mti->applyModifier = subsurfModifier_applyModifier;
5044 mti->applyModifierEM = subsurfModifier_applyModifierEM;
5046 mti = INIT_TYPE(Build);
5047 mti->type = eModifierTypeType_Nonconstructive;
5048 mti->flags = eModifierTypeFlag_AcceptsMesh;
5049 mti->initData = buildModifier_initData;
5050 mti->copyData = buildModifier_copyData;
5051 mti->dependsOnTime = buildModifier_dependsOnTime;
5052 mti->applyModifier = buildModifier_applyModifier;
5054 mti = INIT_TYPE(Array);
5055 mti->type = eModifierTypeType_Constructive;
5056 mti->flags = eModifierTypeFlag_AcceptsMesh
5057 | eModifierTypeFlag_SupportsMapping
5058 | eModifierTypeFlag_SupportsEditmode
5059 | eModifierTypeFlag_EnableInEditmode;
5060 mti->initData = arrayModifier_initData;
5061 mti->copyData = arrayModifier_copyData;
5062 mti->foreachObjectLink = arrayModifier_foreachObjectLink;
5063 mti->updateDepgraph = arrayModifier_updateDepgraph;
5064 mti->applyModifier = arrayModifier_applyModifier;
5065 mti->applyModifierEM = arrayModifier_applyModifierEM;
5067 mti = INIT_TYPE(Mirror);
5068 mti->type = eModifierTypeType_Constructive;
5069 mti->flags = eModifierTypeFlag_AcceptsMesh
5070 | eModifierTypeFlag_SupportsMapping
5071 | eModifierTypeFlag_SupportsEditmode
5072 | eModifierTypeFlag_EnableInEditmode;
5073 mti->initData = mirrorModifier_initData;
5074 mti->copyData = mirrorModifier_copyData;
5075 mti->foreachObjectLink = mirrorModifier_foreachObjectLink;
5076 mti->updateDepgraph = mirrorModifier_updateDepgraph;
5077 mti->applyModifier = mirrorModifier_applyModifier;
5078 mti->applyModifierEM = mirrorModifier_applyModifierEM;
5080 mti = INIT_TYPE(EdgeSplit);
5081 mti->type = eModifierTypeType_Constructive;
5082 mti->flags = eModifierTypeFlag_AcceptsMesh
5083 | eModifierTypeFlag_SupportsMapping
5084 | eModifierTypeFlag_SupportsEditmode
5085 | eModifierTypeFlag_EnableInEditmode;
5086 mti->initData = edgesplitModifier_initData;
5087 mti->copyData = edgesplitModifier_copyData;
5088 mti->applyModifier = edgesplitModifier_applyModifier;
5089 mti->applyModifierEM = edgesplitModifier_applyModifierEM;
5091 mti = INIT_TYPE(Displace);
5092 mti->type = eModifierTypeType_OnlyDeform;
5093 mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsEditmode;
5094 mti->initData = displaceModifier_initData;
5095 mti->copyData = displaceModifier_copyData;
5096 mti->requiredDataMask = displaceModifier_requiredDataMask;
5097 mti->foreachObjectLink = displaceModifier_foreachObjectLink;
5098 mti->foreachIDLink = displaceModifier_foreachIDLink;
5099 mti->updateDepgraph = displaceModifier_updateDepgraph;
5100 mti->isDisabled = displaceModifier_isDisabled;
5101 mti->deformVerts = displaceModifier_deformVerts;
5102 mti->deformVertsEM = displaceModifier_deformVertsEM;
5104 mti = INIT_TYPE(UVProject);
5105 mti->type = eModifierTypeType_Nonconstructive;
5106 mti->flags = eModifierTypeFlag_AcceptsMesh
5107 | eModifierTypeFlag_SupportsMapping
5108 | eModifierTypeFlag_SupportsEditmode
5109 | eModifierTypeFlag_EnableInEditmode;
5110 mti->initData = uvprojectModifier_initData;
5111 mti->copyData = uvprojectModifier_copyData;
5112 mti->requiredDataMask = uvprojectModifier_requiredDataMask;
5113 mti->foreachObjectLink = uvprojectModifier_foreachObjectLink;
5114 mti->foreachIDLink = uvprojectModifier_foreachIDLink;
5115 mti->updateDepgraph = uvprojectModifier_updateDepgraph;
5116 mti->applyModifier = uvprojectModifier_applyModifier;
5117 mti->applyModifierEM = uvprojectModifier_applyModifierEM;
5119 mti = INIT_TYPE(Decimate);
5120 mti->type = eModifierTypeType_Nonconstructive;
5121 mti->flags = eModifierTypeFlag_AcceptsMesh;
5122 mti->initData = decimateModifier_initData;
5123 mti->copyData = decimateModifier_copyData;
5124 mti->applyModifier = decimateModifier_applyModifier;
5126 mti = INIT_TYPE(Smooth);
5127 mti->type = eModifierTypeType_OnlyDeform;
5128 mti->flags = eModifierTypeFlag_AcceptsMesh
5129 | eModifierTypeFlag_SupportsEditmode;
5130 mti->initData = smoothModifier_initData;
5131 mti->copyData = smoothModifier_copyData;
5132 mti->requiredDataMask = smoothModifier_requiredDataMask;
5133 mti->deformVerts = smoothModifier_deformVerts;
5134 mti->deformVertsEM = smoothModifier_deformVertsEM;
5136 mti = INIT_TYPE(Cast);
5137 mti->type = eModifierTypeType_OnlyDeform;
5138 mti->flags = eModifierTypeFlag_AcceptsCVs
5139 | eModifierTypeFlag_SupportsEditmode;
5140 mti->initData = castModifier_initData;
5141 mti->copyData = castModifier_copyData;
5142 mti->requiredDataMask = castModifier_requiredDataMask;
5143 mti->foreachObjectLink = castModifier_foreachObjectLink;
5144 mti->updateDepgraph = castModifier_updateDepgraph;
5145 mti->deformVerts = castModifier_deformVerts;
5146 mti->deformVertsEM = castModifier_deformVertsEM;
5148 mti = INIT_TYPE(Wave);
5149 mti->type = eModifierTypeType_OnlyDeform;
5150 mti->flags = eModifierTypeFlag_AcceptsCVs
5151 | eModifierTypeFlag_SupportsEditmode;
5152 mti->initData = waveModifier_initData;
5153 mti->copyData = waveModifier_copyData;
5154 mti->dependsOnTime = waveModifier_dependsOnTime;
5155 mti->requiredDataMask = waveModifier_requiredDataMask;
5156 mti->foreachObjectLink = waveModifier_foreachObjectLink;
5157 mti->foreachIDLink = waveModifier_foreachIDLink;
5158 mti->updateDepgraph = waveModifier_updateDepgraph;
5159 mti->deformVerts = waveModifier_deformVerts;
5160 mti->deformVertsEM = waveModifier_deformVertsEM;
5162 mti = INIT_TYPE(Armature);
5163 mti->type = eModifierTypeType_OnlyDeform;
5164 mti->flags = eModifierTypeFlag_AcceptsCVs
5165 | eModifierTypeFlag_SupportsEditmode;
5166 mti->initData = armatureModifier_initData;
5167 mti->copyData = armatureModifier_copyData;
5168 mti->requiredDataMask = armatureModifier_requiredDataMask;
5169 mti->isDisabled = armatureModifier_isDisabled;
5170 mti->foreachObjectLink = armatureModifier_foreachObjectLink;
5171 mti->updateDepgraph = armatureModifier_updateDepgraph;
5172 mti->deformVerts = armatureModifier_deformVerts;
5173 mti->deformVertsEM = armatureModifier_deformVertsEM;
5174 mti->deformMatricesEM = armatureModifier_deformMatricesEM;
5176 mti = INIT_TYPE(Hook);
5177 mti->type = eModifierTypeType_OnlyDeform;
5178 mti->flags = eModifierTypeFlag_AcceptsCVs
5179 | eModifierTypeFlag_SupportsEditmode;
5180 mti->initData = hookModifier_initData;
5181 mti->copyData = hookModifier_copyData;
5182 mti->requiredDataMask = hookModifier_requiredDataMask;
5183 mti->freeData = hookModifier_freeData;
5184 mti->isDisabled = hookModifier_isDisabled;
5185 mti->foreachObjectLink = hookModifier_foreachObjectLink;
5186 mti->updateDepgraph = hookModifier_updateDepgraph;
5187 mti->deformVerts = hookModifier_deformVerts;
5188 mti->deformVertsEM = hookModifier_deformVertsEM;
5190 mti = INIT_TYPE(Softbody);
5191 mti->type = eModifierTypeType_OnlyDeform;
5192 mti->flags = eModifierTypeFlag_AcceptsCVs
5193 | eModifierTypeFlag_RequiresOriginalData;
5194 mti->deformVerts = softbodyModifier_deformVerts;
5196 mti = INIT_TYPE(Boolean);
5197 mti->type = eModifierTypeType_Nonconstructive;
5198 mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
5199 mti->copyData = booleanModifier_copyData;
5200 mti->isDisabled = booleanModifier_isDisabled;
5201 mti->applyModifier = booleanModifier_applyModifier;
5202 mti->foreachObjectLink = booleanModifier_foreachObjectLink;
5203 mti->updateDepgraph = booleanModifier_updateDepgraph;
5205 typeArrInit = 0;
5206 #undef INIT_TYPE
5209 if (type>=0 && type<NUM_MODIFIER_TYPES && typeArr[type].name[0]!='\0') {
5210 return &typeArr[type];
5211 } else {
5212 return NULL;
5216 /***/
5218 ModifierData *modifier_new(int type)
5220 ModifierTypeInfo *mti = modifierType_getInfo(type);
5221 ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
5223 strcpy(md->name, mti->name);
5225 md->type = type;
5226 md->mode = eModifierMode_Realtime
5227 | eModifierMode_Render | eModifierMode_Expanded;
5229 if (mti->flags & eModifierTypeFlag_EnableInEditmode)
5230 md->mode |= eModifierMode_Editmode;
5232 if (mti->initData) mti->initData(md);
5234 return md;
5237 void modifier_free(ModifierData *md)
5239 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5241 if (mti->freeData) mti->freeData(md);
5242 if (md->error) MEM_freeN(md->error);
5244 MEM_freeN(md);
5247 int modifier_dependsOnTime(ModifierData *md)
5249 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5251 return mti->dependsOnTime && mti->dependsOnTime(md);
5254 int modifier_supportsMapping(ModifierData *md)
5256 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5258 return ( (mti->flags & eModifierTypeFlag_SupportsEditmode) &&
5259 ( (mti->type==eModifierTypeType_OnlyDeform ||
5260 (mti->flags & eModifierTypeFlag_SupportsMapping))) );
5263 ModifierData *modifiers_findByType(Object *ob, ModifierType type)
5265 ModifierData *md = ob->modifiers.first;
5267 for (; md; md=md->next)
5268 if (md->type==type)
5269 break;
5271 return md;
5274 void modifiers_clearErrors(Object *ob)
5276 ModifierData *md = ob->modifiers.first;
5277 int qRedraw = 0;
5279 for (; md; md=md->next) {
5280 if (md->error) {
5281 MEM_freeN(md->error);
5282 md->error = NULL;
5284 qRedraw = 1;
5288 if (qRedraw) allqueue(REDRAWBUTSEDIT, 0);
5291 void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
5292 void *userData)
5294 ModifierData *md = ob->modifiers.first;
5296 for (; md; md=md->next) {
5297 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5299 if (mti->foreachObjectLink)
5300 mti->foreachObjectLink(md, ob, walk, userData);
5304 void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
5306 ModifierData *md = ob->modifiers.first;
5308 for (; md; md=md->next) {
5309 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5311 if(mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
5312 else if(mti->foreachObjectLink) {
5313 /* each Object can masquerade as an ID, so this should be OK */
5314 ObjectWalkFunc fp = (ObjectWalkFunc)walk;
5315 mti->foreachObjectLink(md, ob, fp, userData);
5320 void modifier_copyData(ModifierData *md, ModifierData *target)
5322 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5324 target->mode = md->mode;
5326 if (mti->copyData)
5327 mti->copyData(md, target);
5330 int modifier_couldBeCage(ModifierData *md)
5332 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5334 return ( (md->mode & eModifierMode_Realtime) &&
5335 (md->mode & eModifierMode_Editmode) &&
5336 (!mti->isDisabled || !mti->isDisabled(md)) &&
5337 modifier_supportsMapping(md));
5340 void modifier_setError(ModifierData *md, char *format, ...)
5342 char buffer[2048];
5343 va_list ap;
5345 va_start(ap, format);
5346 vsprintf(buffer, format, ap);
5347 va_end(ap);
5349 if (md->error)
5350 MEM_freeN(md->error);
5352 md->error = BLI_strdup(buffer);
5354 allqueue(REDRAWBUTSEDIT, 0);
5357 /* used for buttons, to find out if the 'draw deformed in editmode' option is
5358 * there
5360 * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
5361 * then is NULL)
5363 int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
5365 ModifierData *md = ob->modifiers.first;
5366 int i, cageIndex = -1;
5368 /* Find the last modifier acting on the cage. */
5369 for (i=0; md; i++,md=md->next) {
5370 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5372 if (!(md->mode & eModifierMode_Realtime)) continue;
5373 if (!(md->mode & eModifierMode_Editmode)) continue;
5374 if (mti->isDisabled && mti->isDisabled(md)) continue;
5375 if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
5376 if (md->mode & eModifierMode_DisableTemporary) continue;
5378 if (!modifier_supportsMapping(md))
5379 break;
5381 if (lastPossibleCageIndex_r) *lastPossibleCageIndex_r = i;
5382 if (md->mode & eModifierMode_OnCage)
5383 cageIndex = i;
5386 return cageIndex;
5390 int modifiers_isSoftbodyEnabled(Object *ob)
5392 ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
5394 return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
5397 LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
5399 LinkNode *dataMasks = NULL;
5400 LinkNode *curr, *prev;
5402 /* build a list of modifier data requirements in reverse order */
5403 for(; md; md = md->next) {
5404 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
5405 CustomDataMask mask = 0;
5407 if(mti->requiredDataMask) mask = mti->requiredDataMask(md);
5409 BLI_linklist_prepend(&dataMasks, (void *)mask);
5412 /* build the list of required data masks - each mask in the list must
5413 * include all elements of the masks that follow it
5415 * note the list is currently in reverse order, so "masks that follow it"
5416 * actually means "masks that precede it" at the moment
5418 for(curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) {
5419 if(prev) {
5420 CustomDataMask prev_mask = (CustomDataMask)prev->link;
5421 CustomDataMask curr_mask = (CustomDataMask)curr->link;
5423 curr->link = (void *)(curr_mask | prev_mask);
5424 } else {
5425 CustomDataMask curr_mask = (CustomDataMask)curr->link;
5427 curr->link = (void *)(curr_mask | dataMask);
5431 /* reverse the list so it's in the correct order */
5432 BLI_linklist_reverse(&dataMasks);
5434 return dataMasks;
5437 ModifierData *modifiers_getVirtualModifierList(Object *ob)
5439 /* Kinda hacky, but should be fine since we are never
5440 * reentrant and avoid free hassles.
5442 static ArmatureModifierData amd;
5443 static CurveModifierData cmd;
5444 static LatticeModifierData lmd;
5445 static int init = 1;
5447 if (init) {
5448 ModifierData *md;
5450 md = modifier_new(eModifierType_Armature);
5451 amd = *((ArmatureModifierData*) md);
5452 modifier_free(md);
5454 md = modifier_new(eModifierType_Curve);
5455 cmd = *((CurveModifierData*) md);
5456 modifier_free(md);
5458 md = modifier_new(eModifierType_Lattice);
5459 lmd = *((LatticeModifierData*) md);
5460 modifier_free(md);
5462 amd.modifier.mode |= eModifierMode_Virtual;
5463 cmd.modifier.mode |= eModifierMode_Virtual;
5464 lmd.modifier.mode |= eModifierMode_Virtual;
5466 init = 0;
5469 if (ob->parent) {
5470 if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
5471 amd.object = ob->parent;
5472 amd.modifier.next = ob->modifiers.first;
5473 amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
5474 return &amd.modifier;
5475 } else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
5476 cmd.object = ob->parent;
5477 cmd.defaxis = ob->trackflag + 1;
5478 cmd.modifier.next = ob->modifiers.first;
5479 return &cmd.modifier;
5480 } else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
5481 lmd.object = ob->parent;
5482 lmd.modifier.next = ob->modifiers.first;
5483 return &lmd.modifier;
5487 return ob->modifiers.first;
5489 /* Takes an object and returns its first selected armature, else just its
5490 * armature
5491 * This should work for multiple armatures per object
5493 Object *modifiers_isDeformedByArmature(Object *ob)
5495 ModifierData *md = modifiers_getVirtualModifierList(ob);
5496 ArmatureModifierData *amd= NULL;
5498 /* return the first selected armature, this lets us use multiple armatures
5500 for (; md; md=md->next) {
5501 if (md->type==eModifierType_Armature) {
5502 amd = (ArmatureModifierData*) md;
5503 if (amd->object && (amd->object->flag & SELECT))
5504 return amd->object;
5508 if (amd) /* if were still here then return the last armature */
5509 return amd->object;
5511 return NULL;
5514 /* Takes an object and returns its first selected lattice, else just its
5515 * armature
5516 * This should work for multiple armatures per object
5518 Object *modifiers_isDeformedByLattice(Object *ob)
5520 ModifierData *md = modifiers_getVirtualModifierList(ob);
5521 LatticeModifierData *lmd= NULL;
5523 /* return the first selected armature, this lets us use multiple armatures
5525 for (; md; md=md->next) {
5526 if (md->type==eModifierType_Lattice) {
5527 lmd = (LatticeModifierData*) md;
5528 if (lmd->object && (lmd->object->flag & SELECT))
5529 return lmd->object;
5533 if (lmd) /* if were still here then return the last lattice */
5534 return lmd->object;
5536 return NULL;
5541 int modifiers_usesArmature(Object *ob, bArmature *arm)
5543 ModifierData *md = modifiers_getVirtualModifierList(ob);
5545 for (; md; md=md->next) {
5546 if (md->type==eModifierType_Armature) {
5547 ArmatureModifierData *amd = (ArmatureModifierData*) md;
5548 if (amd->object && amd->object->data==arm)
5549 return 1;
5553 return 0;
5556 int modifier_isDeformer(ModifierData *md)
5558 if (md->type==eModifierType_Armature)
5559 return 1;
5560 if (md->type==eModifierType_Curve)
5561 return 1;
5562 if (md->type==eModifierType_Lattice)
5563 return 1;
5565 return 0;
5568 int modifiers_isDeformed(Object *ob)
5570 ModifierData *md = modifiers_getVirtualModifierList(ob);
5572 for (; md; md=md->next) {
5573 if(ob==G.obedit && (md->mode & eModifierMode_Editmode)==0);
5574 else if(modifier_isDeformer(md))
5575 return 1;
5577 return 0;