Blender  V2.59
MOD_build.c
Go to the documentation of this file.
00001 /*
00002 * $Id: MOD_build.c 36276 2011-04-21 15:53:30Z campbellbarton $
00003 *
00004 * ***** BEGIN GPL LICENSE BLOCK *****
00005 *
00006 * This program is free software; you can redistribute it and/or
00007 * modify it under the terms of the GNU General Public License
00008 * as published by the Free Software Foundation; either version 2
00009 * of the License, or (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software  Foundation,
00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *
00020 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00021 * All rights reserved.
00022 *
00023 * Contributor(s): Daniel Dunbar
00024 *                 Ton Roosendaal,
00025 *                 Ben Batt,
00026 *                 Brecht Van Lommel,
00027 *                 Campbell Barton
00028 *
00029 * ***** END GPL LICENSE BLOCK *****
00030 *
00031 */
00032 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "BLI_utildefines.h"
00041 #include "BLI_rand.h"
00042 #include "BLI_ghash.h"
00043 
00044 #include "DNA_scene_types.h"
00045 #include "DNA_meshdata_types.h"
00046 
00047 #include "BKE_cdderivedmesh.h"
00048 #include "BKE_mesh.h"
00049 #include "BKE_modifier.h"
00050 #include "BKE_object.h"
00051 #include "BKE_particle.h"
00052 #include "BKE_scene.h"
00053 
00054 #include "MOD_util.h"
00055 
00056 static void initData(ModifierData *md)
00057 {
00058         BuildModifierData *bmd = (BuildModifierData*) md;
00059 
00060         bmd->start = 1.0;
00061         bmd->length = 100.0;
00062 }
00063 
00064 static void copyData(ModifierData *md, ModifierData *target)
00065 {
00066         BuildModifierData *bmd = (BuildModifierData*) md;
00067         BuildModifierData *tbmd = (BuildModifierData*) target;
00068 
00069         tbmd->start = bmd->start;
00070         tbmd->length = bmd->length;
00071         tbmd->randomize = bmd->randomize;
00072         tbmd->seed = bmd->seed;
00073 }
00074 
00075 static int dependsOnTime(ModifierData *UNUSED(md))
00076 {
00077         return 1;
00078 }
00079 
00080 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
00081                                                 DerivedMesh *derivedData,
00082                                                 int UNUSED(useRenderParams),
00083                                                 int UNUSED(isFinalCalc))
00084 {
00085         DerivedMesh *dm = derivedData;
00086         DerivedMesh *result;
00087         BuildModifierData *bmd = (BuildModifierData*) md;
00088         int i;
00089         int numFaces, numEdges;
00090         int *vertMap, *edgeMap, *faceMap;
00091         float frac;
00092         GHashIterator *hashIter;
00093         /* maps vert indices in old mesh to indices in new mesh */
00094         GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
00095                                         BLI_ghashutil_intcmp, "build ve apply gh");
00096         /* maps edge indices in new mesh to indices in old mesh */
00097         GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
00098                                         BLI_ghashutil_intcmp, "build ed apply gh");
00099 
00100         const int maxVerts= dm->getNumVerts(dm);
00101         const int maxEdges= dm->getNumEdges(dm);
00102         const int maxFaces= dm->getNumFaces(dm);
00103 
00104         vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts, "build modifier vertMap");
00105         for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
00106         edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges, "build modifier edgeMap");
00107         for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
00108         faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces, "build modifier faceMap");
00109         for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
00110 
00111         if (ob) {
00112                 frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
00113                                         bmd->start - 1.0f) / bmd->length;
00114         } else {
00115                 frac = BKE_curframe(md->scene) - bmd->start / bmd->length;
00116         }
00117         CLAMP(frac, 0.0f, 1.0f);
00118 
00119         numFaces = dm->getNumFaces(dm) * frac;
00120         numEdges = dm->getNumEdges(dm) * frac;
00121 
00122         /* if there's at least one face, build based on faces */
00123         if(numFaces) {
00124                 if(bmd->randomize)
00125                         BLI_array_randomize(faceMap, sizeof(*faceMap),
00126                                                 maxFaces, bmd->seed);
00127 
00128                 /* get the set of all vert indices that will be in the final mesh,
00129                 * mapped to the new indices
00130                 */
00131                 for(i = 0; i < numFaces; ++i) {
00132                         MFace mf;
00133                         dm->getFace(dm, faceMap[i], &mf);
00134 
00135                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
00136                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
00137                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00138                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
00139                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
00140                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00141                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
00142                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
00143                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00144                         if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
00145                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
00146                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00147                 }
00148 
00149                 /* get the set of edges that will be in the new mesh (i.e. all edges
00150                 * that have both verts in the new mesh)
00151                 */
00152                 for(i = 0; i < maxEdges; ++i) {
00153                         MEdge me;
00154                         dm->getEdge(dm, i, &me);
00155 
00156                         if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
00157                                                 && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
00158                                 BLI_ghash_insert(edgeHash,
00159                                         SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
00160                 }
00161         } else if(numEdges) {
00162                 if(bmd->randomize)
00163                         BLI_array_randomize(edgeMap, sizeof(*edgeMap),
00164                                                 maxEdges, bmd->seed);
00165 
00166                 /* get the set of all vert indices that will be in the final mesh,
00167                 * mapped to the new indices
00168                 */
00169                 for(i = 0; i < numEdges; ++i) {
00170                         MEdge me;
00171                         dm->getEdge(dm, edgeMap[i], &me);
00172 
00173                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
00174                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
00175                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00176                         if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
00177                                 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
00178                                         SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
00179                 }
00180 
00181                 /* get the set of edges that will be in the new mesh
00182                 */
00183                 for(i = 0; i < numEdges; ++i) {
00184                         MEdge me;
00185                         dm->getEdge(dm, edgeMap[i], &me);
00186 
00187                         BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
00188                                          SET_INT_IN_POINTER(edgeMap[i]));
00189                 }
00190         } else {
00191                 int numVerts = dm->getNumVerts(dm) * frac;
00192 
00193                 if(bmd->randomize)
00194                         BLI_array_randomize(vertMap, sizeof(*vertMap),
00195                                                 maxVerts, bmd->seed);
00196 
00197                 /* get the set of all vert indices that will be in the final mesh,
00198                 * mapped to the new indices
00199                 */
00200                 for(i = 0; i < numVerts; ++i)
00201                         BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
00202         }
00203 
00204         /* now we know the number of verts, edges and faces, we can create
00205         * the mesh
00206         */
00207         result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
00208                                         BLI_ghash_size(edgeHash), numFaces);
00209 
00210         /* copy the vertices across */
00211         for(    hashIter = BLI_ghashIterator_new(vertHash);
00212                         !BLI_ghashIterator_isDone(hashIter);
00213                         BLI_ghashIterator_step(hashIter)
00214         ) {
00215                 MVert source;
00216                 MVert *dest;
00217                 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
00218                 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
00219 
00220                 dm->getVert(dm, oldIndex, &source);
00221                 dest = CDDM_get_vert(result, newIndex);
00222 
00223                 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
00224                 *dest = source;
00225         }
00226         BLI_ghashIterator_free(hashIter);
00227         
00228         /* copy the edges across, remapping indices */
00229         for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
00230                 MEdge source;
00231                 MEdge *dest;
00232                 int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
00233                 
00234                 dm->getEdge(dm, oldIndex, &source);
00235                 dest = CDDM_get_edge(result, i);
00236                 
00237                 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
00238                 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
00239                 
00240                 DM_copy_edge_data(dm, result, oldIndex, i, 1);
00241                 *dest = source;
00242         }
00243 
00244         /* copy the faces across, remapping indices */
00245         for(i = 0; i < numFaces; ++i) {
00246                 MFace source;
00247                 MFace *dest;
00248                 int orig_v4;
00249                 
00250                 dm->getFace(dm, faceMap[i], &source);
00251                 dest = CDDM_get_face(result, i);
00252                 
00253                 orig_v4 = source.v4;
00254                 
00255                 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
00256                 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
00257                 source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
00258                 if(source.v4)
00259                         source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
00260                 
00261                 DM_copy_face_data(dm, result, faceMap[i], i, 1);
00262                 *dest = source;
00263                 
00264                 test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
00265         }
00266 
00267         CDDM_calc_normals(result);
00268         
00269         BLI_ghash_free(vertHash, NULL, NULL);
00270         BLI_ghash_free(edgeHash, NULL, NULL);
00271         
00272         MEM_freeN(vertMap);
00273         MEM_freeN(edgeMap);
00274         MEM_freeN(faceMap);
00275         
00276         return result;
00277 }
00278 
00279 
00280 ModifierTypeInfo modifierType_Build = {
00281         /* name */              "Build",
00282         /* structName */        "BuildModifierData",
00283         /* structSize */        sizeof(BuildModifierData),
00284         /* type */              eModifierTypeType_Nonconstructive,
00285         /* flags */             eModifierTypeFlag_AcceptsMesh
00286                                                         | eModifierTypeFlag_AcceptsCVs,
00287         /* copyData */          copyData,
00288         /* deformVerts */       NULL,
00289         /* deformMatrices */    NULL,
00290         /* deformVertsEM */     NULL,
00291         /* deformMatricesEM */  NULL,
00292         /* applyModifier */     applyModifier,
00293         /* applyModifierEM */   NULL,
00294         /* initData */          initData,
00295         /* requiredDataMask */  NULL,
00296         /* freeData */          NULL,
00297         /* isDisabled */        NULL,
00298         /* updateDepgraph */    NULL,
00299         /* dependsOnTime */     dependsOnTime,
00300         /* dependsOnNormals */  NULL,
00301         /* foreachObjectLink */ NULL,
00302         /* foreachIDLink */     NULL
00303 };