converted more mixed tab/space indentations to tabs. only whitespace changes.
[blender.git] / source / blender / modifiers / intern / MOD_build.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
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.
10 *
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.
15 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 /** \file blender/modifiers/intern/MOD_build.c
34  *  \ingroup modifiers
35  */
36
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_utildefines.h"
41 #include "BLI_rand.h"
42 #include "BLI_ghash.h"
43
44 #include "DNA_scene_types.h"
45 #include "DNA_meshdata_types.h"
46
47 #include "BKE_cdderivedmesh.h"
48 #include "BKE_mesh.h"
49 #include "BKE_modifier.h"
50 #include "BKE_object.h"
51 #include "BKE_particle.h"
52 #include "BKE_scene.h"
53
54 #include "MOD_util.h"
55
56 static void initData(ModifierData *md)
57 {
58         BuildModifierData *bmd = (BuildModifierData*) md;
59
60         bmd->start = 1.0;
61         bmd->length = 100.0;
62 }
63
64 static void copyData(ModifierData *md, ModifierData *target)
65 {
66         BuildModifierData *bmd = (BuildModifierData*) md;
67         BuildModifierData *tbmd = (BuildModifierData*) target;
68
69         tbmd->start = bmd->start;
70         tbmd->length = bmd->length;
71         tbmd->randomize = bmd->randomize;
72         tbmd->seed = bmd->seed;
73 }
74
75 static int dependsOnTime(ModifierData *UNUSED(md))
76 {
77         return 1;
78 }
79
80 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
81                                                 DerivedMesh *derivedData,
82                                                 int UNUSED(useRenderParams),
83                                                 int UNUSED(isFinalCalc))
84 {
85         DerivedMesh *dm = derivedData;
86         DerivedMesh *result;
87         BuildModifierData *bmd = (BuildModifierData*) md;
88         int i;
89         int numFaces, numEdges;
90         int *vertMap, *edgeMap, *faceMap;
91         float frac;
92         GHashIterator *hashIter;
93         /* maps vert indices in old mesh to indices in new mesh */
94         GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
95                                         BLI_ghashutil_intcmp, "build ve apply gh");
96         /* maps edge indices in new mesh to indices in old mesh */
97         GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
98                                         BLI_ghashutil_intcmp, "build ed apply gh");
99
100         const int maxVerts= dm->getNumVerts(dm);
101         const int maxEdges= dm->getNumEdges(dm);
102         const int maxFaces= dm->getNumFaces(dm);
103
104         vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts, "build modifier vertMap");
105         for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
106         edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges, "build modifier edgeMap");
107         for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
108         faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces, "build modifier faceMap");
109         for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
110
111         if (ob) {
112                 frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
113                                         bmd->start - 1.0f) / bmd->length;
114         } else {
115                 frac = BKE_curframe(md->scene) - bmd->start / bmd->length;
116         }
117         CLAMP(frac, 0.0f, 1.0f);
118
119         numFaces = dm->getNumFaces(dm) * frac;
120         numEdges = dm->getNumEdges(dm) * frac;
121
122         /* if there's at least one face, build based on faces */
123         if(numFaces) {
124                 if(bmd->randomize)
125                         BLI_array_randomize(faceMap, sizeof(*faceMap),
126                                                 maxFaces, bmd->seed);
127
128                 /* get the set of all vert indices that will be in the final mesh,
129                 * mapped to the new indices
130                 */
131                 for(i = 0; i < numFaces; ++i) {
132                         MFace mf;
133                         dm->getFace(dm, faceMap[i], &mf);
134
135                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
136                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
137                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
138                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
139                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
140                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
141                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
142                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
143                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
144                         if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
145                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
146                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
147                 }
148
149                 /* get the set of edges that will be in the new mesh (i.e. all edges
150                 * that have both verts in the new mesh)
151                 */
152                 for(i = 0; i < maxEdges; ++i) {
153                         MEdge me;
154                         dm->getEdge(dm, i, &me);
155
156                         if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
157                                                 && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
158                                 BLI_ghash_insert(edgeHash,
159                                         SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
160                 }
161         } else if(numEdges) {
162                 if(bmd->randomize)
163                         BLI_array_randomize(edgeMap, sizeof(*edgeMap),
164                                                 maxEdges, bmd->seed);
165
166                 /* get the set of all vert indices that will be in the final mesh,
167                 * mapped to the new indices
168                 */
169                 for(i = 0; i < numEdges; ++i) {
170                         MEdge me;
171                         dm->getEdge(dm, edgeMap[i], &me);
172
173                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
174                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
175                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
176                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
177                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
178                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
179                 }
180
181                 /* get the set of edges that will be in the new mesh
182                 */
183                 for(i = 0; i < numEdges; ++i) {
184                         MEdge me;
185                         dm->getEdge(dm, edgeMap[i], &me);
186
187                         BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
188                                          SET_INT_IN_POINTER(edgeMap[i]));
189                 }
190         } else {
191                 int numVerts = dm->getNumVerts(dm) * frac;
192
193                 if(bmd->randomize)
194                         BLI_array_randomize(vertMap, sizeof(*vertMap),
195                                                 maxVerts, bmd->seed);
196
197                 /* get the set of all vert indices that will be in the final mesh,
198                 * mapped to the new indices
199                 */
200                 for(i = 0; i < numVerts; ++i)
201                         BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
202         }
203
204         /* now we know the number of verts, edges and faces, we can create
205         * the mesh
206         */
207         result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
208                                         BLI_ghash_size(edgeHash), numFaces);
209
210         /* copy the vertices across */
211         for(    hashIter = BLI_ghashIterator_new(vertHash);
212                         !BLI_ghashIterator_isDone(hashIter);
213                         BLI_ghashIterator_step(hashIter)
214         ) {
215                 MVert source;
216                 MVert *dest;
217                 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
218                 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
219
220                 dm->getVert(dm, oldIndex, &source);
221                 dest = CDDM_get_vert(result, newIndex);
222
223                 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
224                 *dest = source;
225         }
226         BLI_ghashIterator_free(hashIter);
227         
228         /* copy the edges across, remapping indices */
229         for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
230                 MEdge source;
231                 MEdge *dest;
232                 int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
233                 
234                 dm->getEdge(dm, oldIndex, &source);
235                 dest = CDDM_get_edge(result, i);
236                 
237                 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
238                 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
239                 
240                 DM_copy_edge_data(dm, result, oldIndex, i, 1);
241                 *dest = source;
242         }
243
244         /* copy the faces across, remapping indices */
245         for(i = 0; i < numFaces; ++i) {
246                 MFace source;
247                 MFace *dest;
248                 int orig_v4;
249                 
250                 dm->getFace(dm, faceMap[i], &source);
251                 dest = CDDM_get_face(result, i);
252                 
253                 orig_v4 = source.v4;
254                 
255                 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
256                 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
257                 source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
258                 if(source.v4)
259                         source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
260                 
261                 DM_copy_face_data(dm, result, faceMap[i], i, 1);
262                 *dest = source;
263                 
264                 test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
265         }
266
267         CDDM_calc_normals(result);
268         
269         BLI_ghash_free(vertHash, NULL, NULL);
270         BLI_ghash_free(edgeHash, NULL, NULL);
271         
272         MEM_freeN(vertMap);
273         MEM_freeN(edgeMap);
274         MEM_freeN(faceMap);
275         
276         return result;
277 }
278
279
280 ModifierTypeInfo modifierType_Build = {
281         /* name */              "Build",
282         /* structName */        "BuildModifierData",
283         /* structSize */        sizeof(BuildModifierData),
284         /* type */              eModifierTypeType_Nonconstructive,
285         /* flags */             eModifierTypeFlag_AcceptsMesh
286                                                         | eModifierTypeFlag_AcceptsCVs,
287         /* copyData */          copyData,
288         /* deformVerts */       NULL,
289         /* deformMatrices */    NULL,
290         /* deformVertsEM */     NULL,
291         /* deformMatricesEM */  NULL,
292         /* applyModifier */     applyModifier,
293         /* applyModifierEM */   NULL,
294         /* initData */          initData,
295         /* requiredDataMask */  NULL,
296         /* freeData */          NULL,
297         /* isDisabled */        NULL,
298         /* updateDepgraph */    NULL,
299         /* dependsOnTime */     dependsOnTime,
300         /* dependsOnNormals */  NULL,
301         /* foreachObjectLink */ NULL,
302         /* foreachIDLink */     NULL
303 };