static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh) { DerivedMesh *result = CDDM_from_template(mesh->dm, mesh->num_verts, mesh->num_edges, mesh->num_faces); MVert *new_verts = CDDM_get_verts(result); MEdge *new_edges = CDDM_get_edges(result); MFace *new_faces = CDDM_get_faces(result); int i; for(i = 0; i < mesh->num_verts; ++i) { SmoothVert *vert = &mesh->verts[i]; MVert *newMV = &new_verts[vert->newIndex]; DM_copy_vert_data(mesh->dm, result, vert->oldIndex, vert->newIndex, 1); mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV); } for(i = 0; i < mesh->num_edges; ++i) { SmoothEdge *edge = &mesh->edges[i]; MEdge *newME = &new_edges[edge->newIndex]; DM_copy_edge_data(mesh->dm, result, edge->oldIndex, edge->newIndex, 1); mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME); newME->v1 = edge->verts[0]->newIndex; newME->v2 = edge->verts[1]->newIndex; } for(i = 0; i < mesh->num_faces; ++i) { SmoothFace *face = &mesh->faces[i]; MFace *newMF = &new_faces[face->newIndex]; DM_copy_face_data(mesh->dm, result, face->oldIndex, face->newIndex, 1); mesh->dm->getFace(mesh->dm, face->oldIndex, newMF); newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex; newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex; newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex; if(face->edges[3]) { newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex; } else { newMF->v4 = 0; } } return result; }
static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); MFace *mface = CDDM_get_faces(dm); unsigned int i = 0; /* Allocate our vertices. */ clmd->clothObject->numverts = numverts; clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); if ( clmd->clothObject->verts == NULL ) { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } // save face information clmd->clothObject->numfaces = numfaces; clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); if ( clmd->clothObject->mfaces == NULL ) { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); printf("cloth_free_modifier clmd->clothObject->mfaces\n"); return; } for ( i = 0; i < numfaces; i++ ) memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) ); /* Free the springs since they can't be correct if the vertices * changed. */ if ( clmd->clothObject->springs != NULL ) MEM_freeN ( clmd->clothObject->springs ); }
/* read .bobj.gz file into a fluidsimDerivedMesh struct */ static DerivedMesh *fluidsim_read_obj(const char *filename) { int wri = 0,i; int gotBytes; gzFile gzf; int numverts = 0, numfaces = 0; DerivedMesh *dm = NULL; MFace *mf; MVert *mv; short *normals, *no_s; float no[3]; // ------------------------------------------------ // get numverts + numfaces first // ------------------------------------------------ gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); numverts = wri; // skip verts gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1; // read number of normals if(gotBytes) gotBytes = gzread(gzf, &wri, sizeof(wri)); // skip normals gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1; /* get no. of triangles */ if(gotBytes) gotBytes = gzread(gzf, &wri, sizeof(wri)); numfaces = wri; gzclose( gzf ); // ------------------------------------------------ if(!numfaces || !numverts || !gotBytes) return NULL; gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } dm = CDDM_new(numverts, 0, numfaces); if(!dm) { gzclose( gzf ); return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); // read vertex position from file mv = CDDM_get_verts(dm); for(i=0; i<numverts; i++, mv++) gotBytes = gzread(gzf, mv->co, sizeof(float) * 3); // should be the same as numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri != numverts) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" ); if(!normals) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } // read normals from file (but don't save them yet) for(i=numverts, no_s= normals; i>0; i--, no_s += 3) { gotBytes = gzread(gzf, no, sizeof(float) * 3); normal_float_to_short_v3(no_s, no); } /* read no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri!=numfaces) { printf("Fluidsim: error in reading data from file.\n"); if(dm) dm->release(dm); gzclose( gzf ); MEM_freeN(normals); return NULL; } // read triangles from file mf = CDDM_get_faces(dm); for(i=numfaces; i>0; i--, mf++) { int face[3]; gotBytes = gzread(gzf, face, sizeof(int) * 3); // check if 3rd vertex has index 0 (not allowed in blender) if(face[2]) { mf->v1 = face[0]; mf->v2 = face[1]; mf->v3 = face[2]; } else { mf->v1 = face[1]; mf->v2 = face[2]; mf->v3 = face[0]; } mf->v4 = 0; test_index_face(mf, NULL, 0, 3); } gzclose( gzf ); CDDM_calc_edges(dm); CDDM_apply_vert_normals(dm, (short (*)[3])normals); MEM_freeN(normals); // CDDM_calc_normals(result); return dm; }
DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) { MFace *mface, *mf; MEdge *medge, *me; MVert *mvert, *mv; int *origindex; int totface,totedge,totvert,i,bmeshok,len, numTex, numCol; BME_Vert *v1=NULL; BME_Edge *e=NULL, *oe=NULL; BME_Poly *f=NULL; DerivedMesh *result; EdgeHash *edge_hash = BLI_edgehash_new(); totvert = BLI_countlist(&(bm->verts)); totedge = 0; /*we cannot have double edges in a derived mesh!*/ for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i; for(e=bm->edges.first; e; e=e->next){ oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1); if(!oe){ totedge++; BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e); e->tflag2 = 1; } else{ e->tflag2 = 0; } } /*count quads and tris*/ totface = 0; bmeshok = 1; for(f=bm->polys.first;f;f=f->next){ len = BME_cycle_length(f->loopbase); if(len == 3 || len == 4) totface++; } /*convert back to mesh*/ result = CDDM_from_template(dm,totvert,totedge,totface); CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert); CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge); CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface); CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface); numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); /*Make Verts*/ mvert = CDDM_get_verts(result); origindex = result->getVertDataArray(result, CD_ORIGINDEX); for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){ VECCOPY(mv->co,v1->co); mv->flag = (unsigned char)v1->flag; mv->bweight = (char)(255.0*v1->bweight); CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i); origindex[i] = ORIGINDEX_NONE; } medge = CDDM_get_edges(result); origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); i=0; for(e=bm->edges.first,me=medge;e;e=e->next){ if(e->tflag2){ if(e->v1->tflag1 < e->v2->tflag1){ me->v1 = e->v1->tflag1; me->v2 = e->v2->tflag1; } else{ me->v1 = e->v2->tflag1; me->v2 = e->v1->tflag1; } me->crease = (char)(255.0*e->crease); me->bweight = (char)(255.0*e->bweight); me->flag = e->flag; CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i); origindex[i] = ORIGINDEX_NONE; me++; i++; } } if(totface){ mface = CDDM_get_faces(result); origindex = result->getFaceDataArray(result, CD_ORIGINDEX); /*make faces*/ for(i=0,f=bm->polys.first;f;f=f->next){ mf = &mface[i]; len = BME_cycle_length(f->loopbase); if(len==3 || len==4){ mf->v1 = f->loopbase->v->tflag1; mf->v2 = f->loopbase->next->v->tflag1; mf->v3 = f->loopbase->next->next->v->tflag1; if(len == 4){ mf->v4 = f->loopbase->prev->v->tflag1; } /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */ if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){ test_index_face(mf, NULL, i, len); } mf->mat_nr = (unsigned char)f->mat_nr; mf->flag = (unsigned char)f->flag; CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i); BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex); origindex[i] = ORIGINDEX_NONE; i++; } } } BLI_edgehash_free(edge_hash, NULL); return result; }
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; int i = 0; int numverts = dm->getNumVerts ( dm ); int numedges = dm->getNumEdges ( dm ); int numfaces = dm->getNumFaces ( dm ); MEdge *medge = CDDM_get_edges ( dm ); MFace *mface = CDDM_get_faces ( dm ); int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; float temp[3]; // error handling if ( numedges==0 ) return 0; cloth->springs = NULL; edgelist = MEM_callocN ( sizeof ( LinkNode * ) * numverts, "cloth_edgelist_alloc" ); if(!edgelist) return 0; for ( i = 0; i < numverts; i++ ) { edgelist[i] = NULL; } if ( cloth->springs ) MEM_freeN ( cloth->springs ); // create spring network hash edgehash = BLI_edgehash_new(); // structural springs for ( i = 0; i < numedges; i++ ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if ( spring ) { spring->ij = MIN2(medge[i].v1, medge[i].v2); spring->kl = MAX2(medge[i].v2, medge[i].v1); VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); clmd->sim_parms->avg_spring_len += spring->restlen; cloth->verts[spring->ij].avg_spring_len += spring->restlen; cloth->verts[spring->kl].avg_spring_len += spring->restlen; cloth->verts[spring->ij].spring_count++; cloth->verts[spring->kl].spring_count++; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0; struct_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } else { cloth_free_errorsprings(cloth, edgehash, edgelist); return 0; } } if(struct_springs > 0) clmd->sim_parms->avg_spring_len /= struct_springs; for(i = 0; i < numverts; i++) { cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49 / ((float)cloth->verts[i].spring_count); } // shear springs for ( i = 0; i < numfaces; i++ ) { // triangle faces already have shear springs due to structural geometry if ( !mface[i].v4 ) continue; spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) { cloth_free_errorsprings(cloth, edgehash, edgelist); return 0; } spring->ij = MIN2(mface[i].v1, mface[i].v3); spring->kl = MAX2(mface[i].v3, mface[i].v1); VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0; BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); // if ( mface[i].v4 ) --> Quad face spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) { cloth_free_errorsprings(cloth, edgehash, edgelist); return 0; } spring->ij = MIN2(mface[i].v2, mface[i].v4); spring->kl = MAX2(mface[i].v4, mface[i].v2); VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0; BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } if(numfaces) { // bending springs search2 = cloth->springs; for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) { if ( !search2 ) break; tspring2 = search2->link; search = edgelist[tspring2->kl]; while ( search ) { tspring = search->link; index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); // check for existing spring // check also if startpoint is equal to endpoint if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) && ( index2!=tspring2->ij ) ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) { cloth_free_errorsprings(cloth, edgehash, edgelist); return 0; } spring->ij = MIN2(tspring2->ij, index2); spring->kl = MAX2(tspring2->ij, index2); VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } search = search->next; } search2 = search2->next; } } else if(struct_springs > 2) { /* bending springs for hair strands */ /* The current algorightm only goes through the edges in order of the mesh edges list */ /* and makes springs between the outer vert of edges sharing a vertice. This works just */ /* fine for hair, but not for user generated string meshes. This could/should be later */ /* extended to work with non-ordered edges so that it can be used for general "rope */ /* dynamics" without the need for the vertices or edges to be ordered through the length*/ /* of the strands. -jahka */ search = cloth->springs; search2 = search->next; while(search && search2) { tspring = search->link; tspring2 = search2->link; if(tspring->ij == tspring2->kl) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) { cloth_free_errorsprings(cloth, edgehash, edgelist); return 0; } spring->ij = tspring2->ij; spring->kl = tspring->kl; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } search = search->next; search2 = search2->next; } } /* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */ for ( i = 0; i < numedges; i++ ) // struct springs BLI_edgehash_insert ( edgehash, MIN2(medge[i].v1, medge[i].v2), MAX2(medge[i].v2, medge[i].v1), NULL ); for ( i = 0; i < numfaces; i++ ) // edge springs { if(mface[i].v4) { BLI_edgehash_insert ( edgehash, MIN2(mface[i].v1, mface[i].v3), MAX2(mface[i].v3, mface[i].v1), NULL ); BLI_edgehash_insert ( edgehash, MIN2(mface[i].v2, mface[i].v4), MAX2(mface[i].v2, mface[i].v4), NULL ); } } cloth->numsprings = struct_springs + shear_springs + bend_springs; if ( edgelist ) { for ( i = 0; i < numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); } MEM_freeN ( edgelist ); } cloth->edgehash = edgehash; if(G.rt>0) printf("avg_len: %f\n",clmd->sim_parms->avg_spring_len); return 1; } /* cloth_build_springs */
/* read .bobj.gz file into a fluidsimDerivedMesh struct */ static DerivedMesh *fluidsim_read_obj(char *filename) { int wri,i,j; float wrf; int gotBytes; gzFile gzf; int numverts = 0, numfaces = 0; DerivedMesh *dm = NULL; MFace *mface; MVert *mvert; short *normals; // ------------------------------------------------ // get numverts + numfaces first // ------------------------------------------------ gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); numverts = wri; // skip verts for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); } // read number of normals gotBytes = gzread(gzf, &wri, sizeof(wri)); // skip normals for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); } /* get no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); numfaces = wri; gzclose( gzf ); // ------------------------------------------------ if(!numfaces || !numverts) return NULL; gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } dm = CDDM_new(numverts, 0, numfaces); if(!dm) { gzclose( gzf ); return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); // read vertex position from file mvert = CDDM_get_verts(dm); for(i=0; i<numverts; i++) { MVert *mv = &mvert[i]; for(j=0; j<3; j++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); mv->co[j] = wrf; } } // should be the same as numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri != numverts) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" ); if(!normals) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } // read normals from file (but don't save them yet) for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); normals[i] = (short)(wrf*32767.0f); } /* read no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri!=numfaces) printf("Fluidsim: error in reading data from file.\n"); // read triangles from file mface = CDDM_get_faces(dm); for(i=0; i<numfaces; i++) { int face[4]; MFace *mf = &mface[i]; gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); face[3] = 0; // check if 3rd vertex has index 0 (not allowed in blender) if(face[2]) { mf->v1 = face[0]; mf->v2 = face[1]; mf->v3 = face[2]; } else { mf->v1 = face[1]; mf->v2 = face[2]; mf->v3 = face[0]; } mf->v4 = face[3]; test_index_face(mf, NULL, 0, 3); } gzclose( gzf ); CDDM_calc_edges(dm); CDDM_apply_vert_normals(dm, (short (*)[3])normals); MEM_freeN(normals); // CDDM_calc_normals(result); return dm; }