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
31 * ***** END GPL LICENSE BLOCK *****
33 * Modifier stack implementation.
35 * BKE_modifier.h contains the function prototypes for this file.
44 #include "BLI_blenlib.h"
46 #include "BLI_arithb.h"
47 #include "BLI_linklist.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_ghash.h"
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"
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"
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"
99 static int noneModifier_isDisabled(ModifierData
*md
)
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
);
134 static int curveModifier_isDisabled(ModifierData
*md
)
136 CurveModifierData
*cmd
= (CurveModifierData
*) md
;
141 static void curveModifier_foreachObjectLink(
142 ModifierData
*md
, Object
*ob
,
143 void (*walk
)(void *userData
, Object
*ob
, Object
**obpoin
),
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
;
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
);
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
);
210 static int latticeModifier_isDisabled(ModifierData
*md
)
212 LatticeModifierData
*lmd
= (LatticeModifierData
*) md
;
217 static void latticeModifier_foreachObjectLink(
218 ModifierData
*md
, Object
*ob
,
219 void (*walk
)(void *userData
, Object
*ob
, Object
**obpoin
),
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
;
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
);
265 static void subsurfModifier_initData(ModifierData
*md
)
267 SubsurfModifierData
*smd
= (SubsurfModifierData
*) md
;
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
;
290 ccgSubSurf_free(smd
->mCache
);
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
;
304 result
= subsurf_make_derived_from_derived(derivedData
, smd
,
305 useRenderParams
, NULL
,
311 static DerivedMesh
*subsurfModifier_applyModifierEM(
312 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
313 DerivedMesh
*derivedData
)
315 SubsurfModifierData
*smd
= (SubsurfModifierData
*) md
;
318 result
= subsurf_make_derived_from_derived(derivedData
, smd
, 0,
326 static void buildModifier_initData(ModifierData
*md
)
328 BuildModifierData
*bmd
= (BuildModifierData
*) md
;
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
)
350 static DerivedMesh
*buildModifier_applyModifier(ModifierData
*md
, Object
*ob
,
351 DerivedMesh
*derivedData
,
352 int useRenderParams
, int isFinalCalc
)
354 DerivedMesh
*dm
= derivedData
;
356 BuildModifierData
*bmd
= (BuildModifierData
*) md
;
358 int numFaces
, numEdges
;
359 int maxVerts
, maxEdges
, maxFaces
;
360 int *vertMap
, *edgeMap
, *faceMap
;
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
;
386 frac
= bsystem_time(ob
, 0, (float)G
.scene
->r
.cfra
,
387 bmd
->start
- 1.0f
) / bmd
->length
;
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 */
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
) {
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
) {
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
) {
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
) {
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
) {
462 dm
->getEdge(dm
, edgeMap
[i
], &me
);
464 BLI_ghash_insert(edgeHash
, (void *)BLI_ghash_size(edgeHash
),
468 int numVerts
= dm
->getNumVerts(dm
) * frac
;
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
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
)) {
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);
502 BLI_ghashIterator_free(hashIter
);
504 /* copy the edges across, remapping indices */
505 for(i
= 0; i
< BLI_ghash_size(edgeHash
); ++i
) {
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);
520 /* copy the faces across, remapping indices */
521 for(i
= 0; i
< numFaces
; ++i
) {
526 dm
->getFace(dm
, faceMap
[i
], &source
);
527 dest
= CDDM_get_face(result
, i
);
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
);
535 source
.v4
= (int)BLI_ghash_lookup(vertHash
, (void *)source
.v4
);
537 DM_copy_face_data(dm
, result
, faceMap
[i
], i
, 1);
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
);
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
;
568 amd
->offset
[0] = amd
->offset
[1] = amd
->offset
[2] = 0;
570 amd
->scale
[1] = amd
->scale
[2] = 0;
572 amd
->merge_dist
= 0.01;
573 amd
->fit_type
= MOD_ARR_FIXEDCOUNT
;
574 amd
->offset_type
= MOD_ARR_OFF_RELATIVE
;
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
),
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
);
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
);
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
)
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
];
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 */
663 /* -1 if this vert isn't merged, otherwise the old vert index it
664 * should be replaced with
667 /* 1 if this vert's first copy is merged with the last copy of its
668 * merge target, otherwise 0
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;
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
691 return indexMap
[oldIndex
].new;
693 return calc_mapping(indexMap
, indexMap
[oldIndex
].merge
,
698 static DerivedMesh
*arrayModifier_doArray(ArrayModifierData
*amd
,
699 Object
*ob
, DerivedMesh
*dm
,
705 float final_offset
[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
;
717 IndexMapEntry
*indexMap
;
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
);
729 indexMap
= MEM_callocN(sizeof(*indexMap
) * dm
->getNumVerts(dm
),
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
,
744 if((amd
->offset_type
& MOD_ARR_OFF_OBJ
) && (amd
->offset_ob
)) {
746 float result_mat
[4][4];
749 MTC_Mat4Invert(obinv
, ob
->obmat
);
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
;
763 cu
->flag
|= CU_PATH
; // needed for path & bevlist
764 makeDispListCurveTypes(amd
->curve_ob
, 0);
767 length
= cu
->path
->totdist
;
771 /* calculate the maximum number of copies which will fit within the
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
;
782 /* if the offset has no translation, just make one copy */
789 /* allocate memory for count duplicates (including original) plus
792 finalVerts
= dm
->getNumVerts(dm
) * count
;
793 finalEdges
= dm
->getNumEdges(dm
) * count
;
794 finalFaces
= dm
->getNumFaces(dm
) * count
;
796 finalVerts
+= start_cap
->getNumVerts(start_cap
);
797 finalEdges
+= start_cap
->getNumEdges(start_cap
);
798 finalFaces
+= start_cap
->getNumFaces(start_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
++) {
820 MVert
*mv
= &mvert
[numVerts
];
824 inMV
= &src_mvert
[i
];
826 DM_copy_vert_data(dm
, result
, i
, numVerts
, 1);
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 */
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
842 if((count
> 1) && (amd
->flags
& MOD_ARR_MERGE
)) {
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;
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);
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
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
++) {
898 dm
->getEdge(dm
, i
, &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
,
911 if(indexMap
[inMED
.v2
].merge_final
) {
912 med
.v2
= calc_mapping(indexMap
, indexMap
[inMED
.v2
].merge
,
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
;
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);
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
++) {
952 MFace
*mf
= &mface
[numFaces
];
954 dm
->getFace(dm
, i
, &inMF
);
956 DM_copy_face_data(dm
, result
, i
, numFaces
, 1);
959 mf
->v1
= indexMap
[inMF
.v1
].new;
960 mf
->v2
= indexMap
[inMF
.v2
].new;
961 mf
->v3
= indexMap
[inMF
.v3
].new;
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);
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
))) {
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);
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
);
997 mf2
->v4
= calc_mapping(indexMap
, inMF
.v4
, j
);
999 test_index_face(mf2
, &result
->faceData
, numFaces
, inMF
.v4
?4:3);
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
))) {
1005 DM_free_face_data(result
, numFaces
, 1);
1010 /* add start and end caps */
1012 float startoffset
[4][4];
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
];
1037 if(amd
->flags
& MOD_ARR_MERGE
) {
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);
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
;
1067 origindex
= result
->getEdgeDataArray(result
, CD_ORIGINDEX
);
1068 for(i
= 0; i
< capEdges
; i
++) {
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
;
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
;
1098 MEM_freeN(vert_map
);
1099 start_cap
->release(start_cap
);
1103 float endoffset
[4][4];
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
];
1128 if(amd
->flags
& MOD_ARR_MERGE
) {
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);
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
;
1158 origindex
= result
->getEdgeDataArray(result
, CD_ORIGINDEX
);
1159 for(i
= 0; i
< capEdges
; i
++) {
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
;
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
;
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
);
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
);
1217 static DerivedMesh
*arrayModifier_applyModifierEM(
1218 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
1219 DerivedMesh
*derivedData
)
1221 return arrayModifier_applyModifier(md
, ob
, derivedData
, 0, 1);
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
),
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
,
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
);
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
) {
1294 Mat4Invert(obinv
, mmd
->mirror_ob
->obmat
);
1295 Mat4MulMat4(mtx
, ob
->obmat
, obinv
);
1296 Mat4Invert(imtx
, mtx
);
1299 for(i
= 0; i
< maxVerts
; i
++) {
1301 MVert
*mv
= CDDM_get_vert(result
, numVerts
);
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);
1322 indexMap
[i
][0] = numVerts
- 1;
1323 indexMap
[i
][1] = !isShared
;
1327 if (mmd
->mirror_ob
) {
1328 VecMat4MulVecfl(co
, imtx
, co
);
1330 VecCopyf(mv
->co
, co
);
1332 mv
->flag
|= ME_VERT_MERGED
;
1334 MVert
*mv2
= CDDM_get_vert(result
, numVerts
);
1336 DM_copy_vert_data(dm
, result
, i
, numVerts
, 1);
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
++) {
1350 MEdge
*med
= CDDM_get_edge(result
, numEdges
);
1352 dm
->getEdge(dm
, i
, &inMED
);
1354 DM_copy_edge_data(dm
, result
, i
, numEdges
, 1);
1358 med
->v1
= indexMap
[inMED
.v1
][0];
1359 med
->v2
= indexMap
[inMED
.v2
][0];
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);
1370 med2
->v1
+= indexMap
[inMED
.v1
][1];
1371 med2
->v2
+= indexMap
[inMED
.v2
][1];
1375 for(i
= 0; i
< maxFaces
; i
++) {
1377 MFace
*mf
= CDDM_get_face(result
, numFaces
);
1379 dm
->getFace(dm
, i
, &inMF
);
1381 DM_copy_face_data(dm
, result
, i
, numFaces
, 1);
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);
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
);
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);
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
);
1437 static DerivedMesh
*mirrorModifier__doMirror(MirrorModifierData
*mmd
,
1438 Object
*ob
, DerivedMesh
*dm
,
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 */
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
);
1475 static DerivedMesh
*mirrorModifier_applyModifierEM(
1476 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
1477 DerivedMesh
*derivedData
)
1479 return mirrorModifier_applyModifier(md
, ob
, derivedData
, 0, 1);
1483 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
1484 * or edge angle (can be used to achieve autosmoothing)
1487 #define EDGESPLIT_DEBUG_3
1488 #define EDGESPLIT_DEBUG_2
1489 #define EDGESPLIT_DEBUG_1
1490 #define EDGESPLIT_DEBUG_0
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 */
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 */
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 */
1539 typedef struct SmoothMesh
{
1543 int num_verts
, num_edges
, num_faces
;
1544 int max_verts
, max_edges
, max_faces
;
1546 float threshold
; /* the cosine of the smoothing angle */
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");
1561 copy
->newIndex
= mesh
->num_verts
;
1564 #ifdef EDGESPLIT_DEBUG_2
1565 printf("copied vert %4d to vert %4d\n", vert
->newIndex
, copy
->newIndex
);
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");
1581 copy
->newIndex
= mesh
->num_edges
;
1584 #ifdef EDGESPLIT_DEBUG_2
1585 printf("copied edge %4d to edge %4d\n", edge
->newIndex
, copy
->newIndex
);
1590 static int smoothedge_has_vert(SmoothEdge
*edge
, SmoothVert
*vert
)
1593 for(i
= 0; i
< SMOOTHEDGE_NUM_VERTS
; i
++)
1594 if(edge
->verts
[i
] == vert
) return 1;
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
;
1621 static void smoothmesh_free(SmoothMesh
*mesh
)
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
);
1637 static void smoothmesh_resize_verts(SmoothMesh
*mesh
, int max_verts
)
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
) {
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
);
1660 mesh
->max_verts
= max_verts
;
1663 static void smoothmesh_resize_edges(SmoothMesh
*mesh
, int max_edges
)
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
) {
1677 SmoothFace
*face
= &mesh
->faces
[i
];
1679 for(j
= 0; j
< SMOOTHFACE_MAX_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
);
1687 mesh
->max_edges
= max_edges
;
1690 #ifdef EDGESPLIT_DEBUG_0
1691 static void smoothmesh_print(SmoothMesh
*mesh
)
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
];
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
);
1715 printf("\n--- Edges ---\n");
1716 for(i
= 0; i
< mesh
->num_edges
; i
++) {
1717 SmoothEdge
*edge
= &mesh
->edges
[i
];
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
);
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
++) {
1740 printf(" -%-2d", face
->edges
[j
]->newIndex
);
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
);
1753 static SmoothMesh
*smoothmesh_from_derivedmesh(DerivedMesh
*dm
)
1756 EdgeHash
*edges
= BLI_edgehash_new();
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
);
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
];
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
];
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;
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
);
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
);
1832 static DerivedMesh
*CDDM_from_smoothmesh(SmoothMesh
*mesh
)
1834 DerivedMesh
*result
= CDDM_from_template(mesh
->dm
,
1838 MVert
*new_verts
= CDDM_get_verts(result
);
1839 MEdge
*new_edges
= CDDM_get_edges(result
);
1840 MFace
*new_faces
= CDDM_get_faces(result
);
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
;
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
,
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)
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
)
1922 for(node
= edge
->faces
; node
!= NULL
; node
= node
->next
)
1923 if(node
->link
!= face
) return node
->link
;
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
;
1937 for(; source
; source
= source
->next
) {
1939 node
->next
= MEM_mallocN(sizeof(*node
->next
), "nlink_copy");
1942 node
= *target
= MEM_mallocN(sizeof(**target
), "nlink_copy");
1944 node
->link
= source
->link
;
1950 /* appends source to target if it's not already in target */
1951 static void linklist_append_unique(LinkNode
**target
, void *source
)
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");
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
)
1980 LinkNode
*node
= prepend
;
1981 while(node
->next
) node
= node
->next
;
1989 /* returns 1 if the linked list contains the given pointer, 0 otherwise
1991 static int linklist_contains(LinkNode
*list
, void *ptr
)
1995 for(node
= list
; node
; node
= node
->next
)
1996 if(node
->link
== ptr
) return 1;
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
))
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
);
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
) {
2040 prev
->next
= node
->next
;
2045 freefunc(node
->link
);
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
);
2078 typedef struct 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
;
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
);
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
);
2110 static void face_replace_vert(void *ptr
, void *userdata
)
2112 SmoothFace
*face
= ptr
;
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
;
2126 #ifdef EDGESPLIT_DEBUG_3
2127 printf("replacing edge %4d with %4d in face %4d",
2128 find
->newIndex
, replace
->newIndex
, face
->newIndex
);
2130 printf(": {%2d %2d %2d %2d}",
2131 face
->edges
[0]->newIndex
, face
->edges
[1]->newIndex
,
2132 face
->edges
[2]->newIndex
, face
->edges
[3]->newIndex
);
2134 printf(": {%2d %2d %2d}",
2135 face
->edges
[0]->newIndex
, face
->edges
[1]->newIndex
,
2136 face
->edges
[2]->newIndex
);
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
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
);
2153 printf(" -> {%2d %2d %2d}\n",
2154 face
->edges
[0]->newIndex
, face
->edges
[1]->newIndex
,
2155 face
->edges
[2]->newIndex
);
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
,
2167 #ifdef EDGESPLIT_DEBUG_1
2168 printf("edge %d: ", edge
->newIndex
);
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
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");
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
);
2207 /* get a face on which to start */
2208 if(edge
->faces
) face
= edge
->faces
->link
;
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 */
2219 BLI_linklist_prepend(visited_faces
, face
);
2221 /* search until we hit a loose edge or a sharp edge or an edge we've
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
,
2230 /* get the next face */
2231 face
= other_face(edge2
, face
);
2233 /* if face == NULL, edge2 is a loose edge */
2235 /* record this face as visited */
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
);
2248 printf("loose edge: %4d\n", edge2
->newIndex
);
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 */
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);
2268 static void split_single_vert(SmoothVert
*vert
, SmoothFace
*face
,
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
,
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
);
2293 edge2
= find_other_sharp_edge(vert
, edge
, &visited_faces
,
2294 mesh
->threshold
, mesh
->flags
);
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
);
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
)) {
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 */
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
);
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
);
2340 static void split_edge(SmoothEdge
*edge
, SmoothVert
*vert
, SmoothMesh
*mesh
)
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
);
2352 edge2
= find_other_sharp_edge(vert
, edge
, &visited_faces
,
2353 mesh
->threshold
, mesh
->flags
);
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
);
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
);
2393 /* edge2 is loose */
2394 SmoothEdge
*copy_edge
= smoothedge_copy(edge
, mesh
);
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
);
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);
2438 /* loop through edges, counting potential new ones */
2439 for(i
= 0; i
< mesh
->num_edges
; i
++) {
2440 SmoothEdge
*edge
= &mesh
->edges
[i
];
2443 /* treat all non-manifold edges (3 or more faces) as sharp */
2444 if(edge
->faces
&& edge
->faces
->next
&& edge
->faces
->next
->next
) {
2447 /* this edge is sharp */
2450 /* add an extra edge for every face beyond the first */
2452 for(node
= edge
->faces
->next
->next
->next
; node
; node
= node
->next
)
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 */
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
,
2472 if(edge_angle_cos
< threshold
) {
2473 /* this edge is sharp */
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
)
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
) {
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
2542 static void split_bridge_verts(SmoothMesh
*mesh
)
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
)
2578 DerivedMesh
*result
;
2579 int max_verts
, max_edges
;
2581 if(!(emd
->flags
& (MOD_EDGESPLIT_FROMANGLE
| MOD_EDGESPLIT_FROMFLAG
)))
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
);
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
);
2609 split_bridge_verts(mesh
);
2611 #ifdef EDGESPLIT_DEBUG_1
2612 printf("********** Post-vert-split **********\n");
2613 smoothmesh_print(mesh
);
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
);
2622 result
= CDDM_from_smoothmesh(mesh
);
2623 smoothmesh_free(mesh
);
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
);
2642 static DerivedMesh
*edgesplitModifier_applyModifierEM(
2643 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
2644 DerivedMesh
*derivedData
)
2646 return edgesplitModifier_applyModifier(md
, ob
, derivedData
, 0, 1);
2651 static void displaceModifier_initData(ModifierData
*md
)
2653 DisplaceModifierData
*dmd
= (DisplaceModifierData
*) md
;
2655 dmd
->texture
= NULL
;
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
);
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
)
2733 /* if a layer name was given, try to find that layer */
2735 index
= CustomData_get_named_layer_index(data
, CD_MTFACE
, name
);
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
,
2748 float (*co
)[3], float (*texco
)[3],
2752 int texmapping
= dmd
->texmapping
;
2754 if(texmapping
== MOD_DISP_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
);
2766 char *done
= MEM_callocN(sizeof(*done
) * numVerts
,
2767 "get_texture_coords done");
2768 int numFaces
= dm
->getNumFaces(dm
);
2771 validate_layer_name(&dm
->faceData
, CD_MTFACE
, dmd
->uvlayer_name
);
2773 tf
= CustomData_get_layer_named(&dm
->faceData
, CD_MTFACE
,
2776 /* verts are given the UV from the first face that uses them */
2777 for(i
= 0, mf
= mface
; i
< numFaces
; ++i
, ++mf
, ++tf
) {
2779 texco
[mf
->v1
][0] = tf
->uv
[0][0];
2780 texco
[mf
->v1
][1] = tf
->uv
[0][1];
2781 texco
[mf
->v1
][2] = 0;
2785 texco
[mf
->v2
][0] = tf
->uv
[1][0];
2786 texco
[mf
->v2
][1] = tf
->uv
[1][1];
2787 texco
[mf
->v2
][2] = 0;
2791 texco
[mf
->v3
][0] = tf
->uv
[2][0];
2792 texco
[mf
->v3
][1] = tf
->uv
[2][1];
2793 texco
[mf
->v3
][2] = 0;
2797 texco
[mf
->v4
][0] = tf
->uv
[3][0];
2798 texco
[mf
->v4
][1] = tf
->uv
[3][1];
2799 texco
[mf
->v4
][2] = 0;
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;
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
);
2821 case MOD_DISP_MAP_GLOBAL
:
2822 VECCOPY(*texco
, *co
);
2823 Mat4MulVecfl(ob
->obmat
, *texco
);
2825 case MOD_DISP_MAP_OBJECT
:
2826 VECCOPY(*texco
, *co
);
2827 Mat4MulVecfl(ob
->obmat
, *texco
);
2828 Mat4MulVecfl(dmd
->map_object
->imat
, *texco
);
2834 static void get_texture_value(Tex
*texture
, float *tex_co
, TexResult
*texres
)
2838 result_type
= multitex_ext(texture
, tex_co
, NULL
,
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
);
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
)
2859 MDeformVert
*dvert
= NULL
;
2863 if(!dmd
->texture
) return;
2867 if(dmd
->defgrp_name
[0]) {
2869 for(i
= 0, def
= ob
->defbase
.first
; def
; def
= def
->next
, i
++) {
2870 if(!strcmp(def
->name
, dmd
->defgrp_name
)) {
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
) {
2887 float delta
= 0, strength
= dmd
->strength
;
2888 MDeformWeight
*def_weight
= NULL
;
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
];
2898 if(!def_weight
) continue;
2902 get_texture_value(dmd
->texture
, tex_co
[i
], &texres
);
2904 delta
= texres
.tin
- dmd
->midlevel
;
2906 if(def_weight
) strength
*= def_weight
->weight
;
2910 switch(dmd
->direction
) {
2911 case MOD_DISP_DIR_X
:
2912 vertexCos
[i
][0] += delta
;
2914 case MOD_DISP_DIR_Y
:
2915 vertexCos
[i
][1] += delta
;
2917 case MOD_DISP_DIR_Z
:
2918 vertexCos
[i
][2] += delta
;
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
;
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
;
2936 static void displaceModifier_deformVerts(
2937 ModifierData
*md
, Object
*ob
, DerivedMesh
*derivedData
,
2938 float (*vertexCos
)[3], int numVerts
)
2942 if(derivedData
) dm
= CDDM_copy(derivedData
);
2943 else if(ob
->type
==OB_MESH
) dm
= CDDM_from_mesh(ob
->data
, ob
);
2946 CDDM_apply_vert_coords(dm
, vertexCos
);
2947 CDDM_calc_normals(dm
);
2949 displaceModifier_do((DisplaceModifierData
*)md
, ob
, dm
,
2950 vertexCos
, numVerts
);
2955 static void displaceModifier_deformVertsEM(
2956 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
2957 DerivedMesh
*derivedData
, float (*vertexCos
)[3], int numVerts
)
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
);
2974 /* UV Project modifier: Generates UVs projected from an object
2977 static void uvprojectModifier_initData(ModifierData
*md
)
2979 UVProjectModifierData
*umd
= (UVProjectModifierData
*) md
;
2982 for(i
= 0; i
< MOD_UVPROJECT_MAXPROJECTORS
; ++i
)
2983 umd
->projectors
[i
] = NULL
;
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
;
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
);
3015 static void uvprojectModifier_foreachObjectLink(ModifierData
*md
, Object
*ob
,
3016 ObjectWalkFunc walk
, void *userData
)
3018 UVProjectModifierData
*umd
= (UVProjectModifierData
*) md
;
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
,
3036 static void uvprojectModifier_updateDepgraph(ModifierData
*md
,
3037 DagForest
*forest
, Object
*ob
, DagNode
*obNode
)
3039 UVProjectModifierData
*umd
= (UVProjectModifierData
*) md
;
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 */
3058 static DerivedMesh
*uvprojectModifier_do(UVProjectModifierData
*umd
,
3059 Object
*ob
, DerivedMesh
*dm
)
3061 float (*coords
)[3], (*co
)[3];
3063 int i
, numVerts
, numFaces
;
3064 Image
*image
= umd
->image
;
3066 int override_image
= ((umd
->flags
& MOD_UVPROJECT_OVERRIDEIMAGE
) != 0);
3067 Projector projectors
[MOD_UVPROJECT_MAXPROJECTORS
];
3068 int num_projectors
= 0;
3071 if(umd
->aspecty
!= 0) aspect
= umd
->aspectx
/ umd
->aspecty
;
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
,
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
) {
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];
3117 float pixsize
= cam
->clipsta
* 32.0 / cam
->lens
;
3120 xmax
= 0.5f
* pixsize
;
3121 ymax
= xmax
/ aspect
;
3123 ymax
= 0.5f
* pixsize
;
3124 xmax
= ymax
* aspect
;
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];
3140 xmax
= 0.5f
* cam
->ortho_scale
;
3141 ymax
= xmax
/ aspect
;
3143 ymax
= 0.5f
* cam
->ortho_scale
;
3144 xmax
= ymax
* aspect
;
3149 i_ortho(xmin
, xmax
, ymin
, ymax
,
3150 cam
->clipsta
, cam
->clipend
, orthomat
);
3151 Mat4MulMat4(tmpmat
, projectors
[i
].projmat
, orthomat
);
3154 Mat4CpyMat4(tmpmat
, projectors
[i
].projmat
);
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];
3189 tface
->uv
[3][0] = coords
[mf
->v4
][0];
3190 tface
->uv
[3][1] = coords
[mf
->v4
][1];
3193 /* multiple projectors, select the closest to face normal
3196 float co1
[3], co2
[3], co3
[3], co4
[3];
3199 Projector
*best_projector
;
3202 VECCOPY(co1
, coords
[mf
->v1
]);
3203 VECCOPY(co2
, coords
[mf
->v2
]);
3204 VECCOPY(co3
, coords
[mf
->v3
]);
3206 /* get the untransformed face normal */
3208 VECCOPY(co4
, coords
[mf
->v4
]);
3209 CalcNormFloat4(co1
, co2
, co3
, co4
, face_no
);
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
,
3223 if(tmp_dot
> best_dot
) {
3225 best_projector
= &projectors
[j
];
3229 Mat4MulVec3Project(best_projector
->projmat
, co1
);
3230 Mat4MulVec3Project(best_projector
->projmat
, co2
);
3231 Mat4MulVec3Project(best_projector
->projmat
, co3
);
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];
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
;
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
);
3272 static DerivedMesh
*uvprojectModifier_applyModifierEM(
3273 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
3274 DerivedMesh
*derivedData
)
3276 return uvprojectModifier_applyModifier(md
, ob
, derivedData
, 0, 1);
3281 static void decimateModifier_initData(ModifierData
*md
)
3283 DecimateModifierData
*dmd
= (DecimateModifierData
*) md
;
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
;
3304 LOD_Decimation_Info lod
;
3305 int totvert
, totface
;
3308 mvert
= dm
->getVertArray(dm
);
3309 mface
= dm
->getFaceArray(dm
);
3310 totvert
= dm
->getNumVerts(dm
);
3311 totface
= dm
->getNumFaces(dm
);
3314 for (a
=0; a
<totface
; a
++) {
3315 MFace
*mf
= &mface
[a
];
3317 if (mf
->v4
) numTris
++;
3321 modifier_setError(md
,
3322 "There must be more than 3 input faces (triangles).");
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
;
3345 for(a
=0; a
<totface
; a
++) {
3346 MFace
*mf
= &mface
[a
];
3347 int *tri
= &lod
.triangle_index_buffer
[3*numTris
++];
3353 tri
= &lod
.triangle_index_buffer
[3*numTris
++];
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
;
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];
3392 test_index_face(mf
, NULL
, 0, 3);
3396 CDDM_calc_edges(result
);
3397 CDDM_calc_normals(result
);
3400 modifier_setError(md
, "Out of memory.");
3402 LOD_FreeDecimationData(&lod
);
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
);
3417 static void smoothModifier_initData(ModifierData
*md
)
3419 SmoothModifierData
*smd
= (SmoothModifierData
*) md
;
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
;
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;
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
);
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");
3476 uctmp
= (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts
,
3477 "smoothmodifier_uc");
3479 if (ftmp
) MEM_freeN(ftmp
);
3486 medges
= CDDM_get_edges(dm
);
3487 numDMEdges
= dm
->getNumEdges(dm
);
3491 if (smd
->defgrp_name
[0]) {
3494 for (i
= 0, def
= ob
->defbase
.first
; def
; def
= def
->next
, i
++) {
3495 if (!strcmp(def
->name
, smd
->defgrp_name
)) {
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
++) {
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;
3526 if (uctmp
[idx1
] < 255) {
3528 VecAddf(v1
, v1
, fvec
);
3530 if (uctmp
[idx2
] < 255) {
3532 VecAddf(v2
, v2
, fvec
);
3537 for (i
= 0; i
< numVerts
; i
++) {
3538 MDeformWeight
*dw
= NULL
;
3539 float f
, fm
, facw
, *fp
, *v
;
3541 short flag
= smd
->flag
;
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
];
3554 f
= fac
* dw
->weight
;
3557 /* fp is the sum of uctmp[i] verts, so must be averaged */
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
;
3578 /* fp is the sum of uctmp[i] verts, so must be averaged */
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
);
3601 static void smoothModifier_deformVerts(
3602 ModifierData
*md
, Object
*ob
, DerivedMesh
*derivedData
,
3603 float (*vertexCos
)[3], int numVerts
)
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
);
3619 static void smoothModifier_deformVertsEM(
3620 ModifierData
*md
, Object
*ob
, EditMesh
*editData
,
3621 DerivedMesh
*derivedData
, float (*vertexCos
)[3], int numVerts
)
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
);
3639 static void castModifier_initData(ModifierData
*md
)
3641 CastModifierData
*cmd
= (CastModifierData
*) md
;
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';
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
;
3673 flag
= cmd
->flag
& (MOD_CAST_X
|MOD_CAST_Y
|MOD_CAST_Z
);
3675 if((cmd
->fac
== 0.0f
) || flag
== 0) return 1;
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
);
3691 static void castModifier_foreachObjectLink(
3692 ModifierData
*md
, Object
*ob
,
3693 void (*walk
)(void *userData
, Object
*ob
, Object
**obpoin
),
3696 CastModifierData
*cmd
= (CastModifierData
*) md
;
3698 walk (userData
, ob
, &cmd
->object
);
3701 static void castModifier_updateDepgraph(
3702 ModifierData
*md
, DagForest
*forest
, Object
*ob
,
3705 CastModifierData
*cmd
= (CastModifierData
*) md
;
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;
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];
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 */
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]) {
3767 for (i
= 0, def
= ob
->defbase
.first
; def
; def
= def
->next
, i
++) {
3768 if (!strcmp(def
->name
, cmd
->defgrp_name
)) {
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
) {
3786 for (i
= 0; i
< numVerts
; i
++) {
3787 len
+= VecLenf(center
, vertexCos
[i
]);
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
;
3806 VECCOPY(tmp_co
, vertexCos
[i
]);
3808 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
3809 Mat4MulVecfl(mat
, tmp_co
);
3811 VecSubf(tmp_co
, tmp_co
, center
);
3815 VECCOPY(vec
, tmp_co
);
3817 if (type
== MOD_CAST_TYPE_CYLINDER
)
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
];
3832 fac
= fac_orig
* dw
->weight
;
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];
3845 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
3846 Mat4MulVecfl(imat
, tmp_co
);
3848 VecAddf(tmp_co
, tmp_co
, center
);
3852 VECCOPY(vertexCos
[i
], tmp_co
);
3858 for (i
= 0; i
< numVerts
; i
++) {
3861 VECCOPY(tmp_co
, vertexCos
[i
]);
3863 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
3864 Mat4MulVecfl(mat
, tmp_co
);
3866 VecSubf(tmp_co
, tmp_co
, center
);
3870 VECCOPY(vec
, tmp_co
);
3872 if (type
== MOD_CAST_TYPE_CYLINDER
)
3876 if (VecLength(vec
) > cmd
->radius
) continue;
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];
3889 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
3890 Mat4MulVecfl(imat
, tmp_co
);
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;
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];
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]) {
3934 for (i
= 0, def
= ob
->defbase
.first
; def
; def
= def
->next
, i
++) {
3935 if (!strcmp(def
->name
, cmd
->defgrp_name
)) {
3942 if ((ob
->type
== OB_MESH
) && dm
&& defgrp_index
>= 0)
3943 dvert
= dm
->getVertDataArray(dm
, CD_MDEFORMVERT
);
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
;
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. */
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
);
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]);
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
;
4023 VECCOPY(tmp_co
, vertexCos
[i
]);
4025 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
4026 Mat4MulVecfl(mat
, tmp_co
);
4028 VecSubf(tmp_co
, tmp_co
, center
);
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
];
4046 fac
= fac_orig
* dw
->weight
;
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;
4057 /* find in which octant this vertex is in */
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) */
4079 /* dmax = d[2]; */ /* commented, we don't need it */
4083 /* ok, now we know which coordinate of the vertex to use */
4085 if (fabs(tmp_co
[coord
]) < FLT_EPSILON
) /* avoid division by zero */
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
;
4101 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
4102 Mat4MulVecfl(imat
, tmp_co
);
4104 VecAddf(tmp_co
, tmp_co
, center
);
4108 VECCOPY(vertexCos
[i
], tmp_co
);
4113 /* no vgroup (check previous case for comments about the code) */
4114 for (i
= 0; i
< numVerts
; i
++) {
4116 float d
[3], dmax
, fbb
, apex
[3];
4119 VECCOPY(tmp_co
, vertexCos
[i
]);
4121 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
4122 Mat4MulVecfl(mat
, tmp_co
);
4124 VecSubf(tmp_co
, tmp_co
, center
);
4129 if (fabs(tmp_co
[0]) > cmd
->radius
||
4130 fabs(tmp_co
[1]) > cmd
->radius
||
4131 fabs(tmp_co
[2]) > cmd
->radius
) continue;
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];
4152 /* dmax = d[2]; */ /* commented, we don't need it */
4156 if (fabs(tmp_co
[coord
]) < FLT_EPSILON
)
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
;
4169 if(flag
& MOD_CAST_USE_OB_TRANSFORM
) {
4170 Mat4MulVecfl(imat
, tmp_co
);
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
);
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
;
4234 wmd
->lifetime
= 0.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
)
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
,
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
);
4323 static void wavemod_get_texture_coords(WaveModifierData
*wmd
, Object
*ob
,
4325 float (*co
)[3], float (*texco
)[3],
4329 int texmapping
= wmd
->texmapping
;
4331 if(texmapping
== MOD_WAV_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
);
4343 char *done
= MEM_callocN(sizeof(*done
) * numVerts
,
4344 "get_texture_coords done");
4345 int numFaces
= dm
->getNumFaces(dm
);
4348 validate_layer_name(&dm
->faceData
, CD_MTFACE
, wmd
->uvlayer_name
);
4350 tf
= CustomData_get_layer_named(&dm
->faceData
, CD_MTFACE
,
4353 /* verts are given the UV from the first face that uses them */
4354 for(i
= 0, mf
= mface
; i
< numFaces
; ++i
, ++mf
, ++tf
) {
4356 texco
[mf
->v1
][0] = tf
->uv
[0][0];
4357 texco
[mf
->v1
][1] = tf
->uv
[0][1];
4358 texco
[mf
->v1
][2] = 0;
4362 texco
[mf
->v2
][0] = tf
->uv
[1][0];
4363 texco
[mf
->v2
][1] = tf
->uv
[1][1];
4364 texco
[mf
->v2
][2] = 0;
4368 texco
[mf
->v3
][0] = tf
->uv
[2][0];
4369 texco
[mf
->v3
][1] = tf
->uv
[2][1];
4370 texco
[mf
->v3
][2] = 0;
4374 texco
[mf
->v4
][0] = tf
->uv
[3][0];
4375 texco
[mf
->v4
][1] = tf
->uv
[3][1];
4376 texco
[mf
->v4
][2] = 0;
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;
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
);
4398 case MOD_WAV_MAP_GLOBAL
:
4399 VECCOPY(*texco
, *co
);
4400 Mat4MulVecfl(ob
->obmat
, *texco
);
4402 case MOD_WAV_MAP_OBJECT
:
4403 VECCOPY(*texco
, *co
);
4404 Mat4MulVecfl(ob
->obmat
, *texco
);
4405 Mat4MulVecfl(wmd
->map_object
->imat
, *texco
);
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
;
4419 float ctime
= bsystem_time(ob
, 0, (float)G
.scene
->r
.cfra
, 0.0);
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
){
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 */
4441 if(wmd
->defgrp_name
[0]) {
4444 for(i
= 0, def
= ob
->defbase
.first
; def
; def
= def
->next
, i
++) {
4445 if(!strcmp(def
->name
, wmd
->defgrp_name
)) {
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;
4466 (float)(wmd
->height
* (1.0 - sqrt(lifefac
/ wmd
->damp
)));
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) {
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
;
4485 MDeformWeight
*def_weight
= NULL
;
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
];
4497 /* if this vert isn't in the vgroup, don't deform it */
4498 if(!def_weight
) continue;
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
);
4511 else if(wmd
->flag
& MOD_WAVE_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
)
4523 if(amplit
> -wmd
->width
&& amplit
< wmd
->width
) {
4524 amplit
= amplit
* wmd
->narrow
;
4525 amplit
= (float)(1.0 / exp(amplit
* amplit
) - minfac
);
4527 amplit
= amplit
* texres
.tin
;
4530 amplit
= amplit
* def_weight
->weight
;
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
;
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
)
4560 WaveModifierData
*wmd
= (WaveModifierData
*)md
;
4562 if(!wmd
->texture
&& !wmd
->defgrp_name
[0] && !(wmd
->flag
& MOD_WAVE_NORM
))
4564 else if(derivedData
) dm
= derivedData
;
4565 else if(ob
->type
== OB_MESH
) dm
= CDDM_from_mesh(ob
->data
, ob
);
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
)
4583 WaveModifierData
*wmd
= (WaveModifierData
*)md
;
4585 if(!wmd
->texture
&& !wmd
->defgrp_name
[0] && !(wmd
->flag
& MOD_WAVE_NORM
))
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
);
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
);
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
),
4641 ArmatureModifierData
*amd
= (ArmatureModifierData
*) md
;
4643 walk(userData
, ob
, &amd
->object
);
4646 static void armatureModifier_updateDepgraph(
4647 ModifierData
*md
, DagForest
*forest
, Object
*ob
,
4650 ArmatureModifierData
*amd
= (ArmatureModifierData
*) md
;
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
);
4703 static void hookModifier_initData(ModifierData
*md
)
4705 HookModifierData
*hmd
= (HookModifierData
*) md
;
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
);
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
),
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
;
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];
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? */
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,
4802 if(dm
&& dm
->getVertData(dm
, 0, CD_ORIGINDEX
)) {
4805 for(j
= 0; j
< numVerts
; ++j
) {
4807 orig_index
= *(int *)dm
->getVertData(dm
, j
,
4809 if(orig_index
== index
) {
4811 if(hmd
->falloff
!= 0.0) {
4812 float len
= VecLenf(co
, hmd
->cent
);
4813 if(len
> hmd
->falloff
) fac
= 0.0;
4815 fac
*= sqrt(1.0 - len
/ hmd
->falloff
);
4819 VecMat4MulVecfl(vec
, mat
, co
);
4820 VecLerpf(co
, co
, vec
, fac
);
4825 if(hmd
->falloff
!= 0.0) {
4826 float len
= VecLenf(co
, hmd
->cent
);
4827 if(len
> hmd
->falloff
) fac
= 0.0;
4829 fac
*= sqrt(1.0 - len
/ hmd
->falloff
);
4833 VecMat4MulVecfl(vec
, mat
, co
);
4834 VecLerpf(co
, co
, vec
, fac
);
4839 } else { /* vertex group hook */
4840 bDeformGroup
*curdef
;
4841 Mesh
*me
= ob
->data
;
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;
4851 if(dm
->getVertData(dm
, 0, CD_MDEFORMVERT
)) {
4853 maxVerts
= dm
->getNumVerts(dm
);
4854 } else use_dverts
= 0;
4855 else if(me
->dvert
) {
4857 maxVerts
= me
->totvert
;
4858 } else use_dverts
= 0;
4860 if(curdef
&& use_dverts
) {
4861 MDeformVert
*dvert
= me
->dvert
;
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;
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
);
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
);
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
),
4932 BooleanModifierData
*bmd
= (BooleanModifierData
*) md
;
4934 walk(userData
, ob
, &bmd
->object
);
4937 static void booleanModifier_updateDepgraph(
4938 ModifierData
*md
, DagForest
*forest
, Object
*ob
,
4941 BooleanModifierData
*bmd
= (BooleanModifierData
*) md
;
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 */
4977 static ModifierTypeInfo typeArr
[NUM_MODIFIER_TYPES
];
4978 static int typeArrInit
= 1;
4980 ModifierTypeInfo
*modifierType_getInfo(ModifierType type
)
4983 ModifierTypeInfo
*mti
;
4985 memset(typeArr
, 0, sizeof(typeArr
));
4987 /* Initialize and return the appropriate type info structure,
4988 * assumes that modifier has:
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
;
5209 if (type
>=0 && type
<NUM_MODIFIER_TYPES
&& typeArr
[type
].name
[0]!='\0') {
5210 return &typeArr
[type
];
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
);
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
);
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
);
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
)
5274 void modifiers_clearErrors(Object
*ob
)
5276 ModifierData
*md
= ob
->modifiers
.first
;
5279 for (; md
; md
=md
->next
) {
5281 MEM_freeN(md
->error
);
5288 if (qRedraw
) allqueue(REDRAWBUTSEDIT
, 0);
5291 void modifiers_foreachObjectLink(Object
*ob
, ObjectWalkFunc walk
,
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
;
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
, ...)
5345 va_start(ap
, format
);
5346 vsprintf(buffer
, format
, ap
);
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
5360 * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
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
))
5381 if (lastPossibleCageIndex_r
) *lastPossibleCageIndex_r
= i
;
5382 if (md
->mode
& eModifierMode_OnCage
)
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
) {
5420 CustomDataMask prev_mask
= (CustomDataMask
)prev
->link
;
5421 CustomDataMask curr_mask
= (CustomDataMask
)curr
->link
;
5423 curr
->link
= (void *)(curr_mask
| prev_mask
);
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
);
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;
5450 md
= modifier_new(eModifierType_Armature
);
5451 amd
= *((ArmatureModifierData
*) md
);
5454 md
= modifier_new(eModifierType_Curve
);
5455 cmd
= *((CurveModifierData
*) md
);
5458 md
= modifier_new(eModifierType_Lattice
);
5459 lmd
= *((LatticeModifierData
*) md
);
5462 amd
.modifier
.mode
|= eModifierMode_Virtual
;
5463 cmd
.modifier
.mode
|= eModifierMode_Virtual
;
5464 lmd
.modifier
.mode
|= eModifierMode_Virtual
;
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
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
))
5508 if (amd
) /* if were still here then return the last armature */
5514 /* Takes an object and returns its first selected lattice, else just its
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
))
5533 if (lmd
) /* if were still here then return the last lattice */
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
)
5556 int modifier_isDeformer(ModifierData
*md
)
5558 if (md
->type
==eModifierType_Armature
)
5560 if (md
->type
==eModifierType_Curve
)
5562 if (md
->type
==eModifierType_Lattice
)
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
))