void *BLI_memarena_alloc(MemArena *ma, size_t size) { void *ptr; /* ensure proper alignment by rounding * size up to multiple of 8 */ size = PADUP(size, ma->align); if (UNLIKELY(size > ma->cursize)) { if (size > ma->bufsize - (ma->align - 1)) { ma->cursize = PADUP(size + 1, ma->align); } else { ma->cursize = ma->bufsize; } ma->curbuf = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); memarena_curbuf_align(ma); } ptr = ma->curbuf; ma->curbuf += size; ma->cursize -= size; #ifdef WITH_MEM_VALGRIND VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); #endif return ptr; }
// be careful: implicit solver has to be resettet when using this one! // --> only for implicit handling of this spring! int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL; if(cloth) { // TODO: look if this spring is already there spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) return 0; spring->ij = indexA; spring->kl = indexB; spring->restlen = restlength; spring->type = spring_type; spring->flags = 0; spring->stiffness = 0; cloth->numsprings++; BLI_linklist_prepend ( &cloth->springs, spring ); return 1; } return 0; }
void *BLI_memarena_alloc(MemArena *ma, int size) { void *ptr; /* ensure proper alignment by rounding * size up to multiple of 8 */ size= PADUP(size, ma->align); if (size>ma->cursize) { unsigned char *tmp; if(size > ma->bufsize - (ma->align - 1)) { ma->cursize = PADUP(size+1, ma->align); } else ma->cursize = ma->bufsize; if(ma->use_calloc) ma->curbuf= MEM_callocN(ma->cursize, ma->name); else ma->curbuf= MEM_mallocN(ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); /* align alloc'ed memory (needed if align > 8) */ tmp = (unsigned char*)PADUP( (intptr_t) ma->curbuf, ma->align); ma->cursize -= (tmp - ma->curbuf); ma->curbuf = tmp; } ptr= ma->curbuf; ma->curbuf+= size; ma->cursize-= size; return ptr; }
static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys) { DerivedMesh *dm; bool dm_needsFree; if (ob->type == OB_MESH || ob->derivedFinal) { dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); dm_needsFree = false; } else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); dm_needsFree = true; } else { dm = NULL; } if (dm) { ListBase nurbslist = {NULL, NULL}; float projmat[4][4]; BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0); /* wire */ BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1); /* boundary */ ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat); if (nurbslist.first) { Nurb *nu; for (nu = nurbslist.first; nu; nu = nu->next) { if (nu->bp) { int a; BPoint *bp; bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0; float (*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__); for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) { ED_view3d_project_float_v2_m4(ar, bp->vec, mval[a], projmat); } if (is_cyclic) { copy_v2_v2(mval[a], mval[0]); } BLI_linklist_prepend(&polys, mval); } } } BKE_nurbList_free(&nurbslist); if (dm_needsFree) { dm->release(dm); } } return polys; }
void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type) { BVHCacheItem *item = NULL; assert(tree != NULL); assert(bvhcache_find(cache, type) == NULL); item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem"); assert(item != NULL); item->type = type; item->tree = tree; BLI_linklist_prepend(cache, item); }
/** * Reads the contents of a text file and returns the lines in a linked list. */ LinkNode *BLI_file_read_as_lines(const char *name) { FILE *fp = BLI_fopen(name, "r"); LinkNode *lines = NULL; char *buf; size_t size; if (!fp) return NULL; fseek(fp, 0, SEEK_END); size = (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); buf = MEM_mallocN(size, "file_as_lines"); if (buf) { size_t i, last = 0; /* * size = because on win32 reading * all the bytes in the file will return * less bytes because of crnl changes. */ size = fread(buf, 1, size, fp); for (i = 0; i <= size; i++) { if (i == size || buf[i] == '\n') { char *line = BLI_strdupn(&buf[last], i - last); BLI_linklist_prepend(&lines, line); /* faster to build singly-linked list in reverse order */ /* alternatively, could process buffer in reverse order so * list ends up right way round to start with */ last = i + 1; } } MEM_freeN(buf); } fclose(fp); /* get them the right way round */ BLI_linklist_reverse(&lines); return lines; }
LinkNode *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md, CustomDataMask dataMask, int required_mode) { LinkNode *dataMasks = NULL; LinkNode *curr, *prev; /* build a list of modifier data requirements in reverse order */ for(; md; md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); CustomDataMask mask = 0; if(modifier_isEnabled(scene, md, required_mode)) if(mti->requiredDataMask) mask = mti->requiredDataMask(ob, md); BLI_linklist_prepend(&dataMasks, SET_INT_IN_POINTER(mask)); } /* build the list of required data masks - each mask in the list must * include all elements of the masks that follow it * * note the list is currently in reverse order, so "masks that follow it" * actually means "masks that precede it" at the moment */ for(curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) { if(prev) { CustomDataMask prev_mask = (CustomDataMask)GET_INT_FROM_POINTER(prev->link); CustomDataMask curr_mask = (CustomDataMask)GET_INT_FROM_POINTER(curr->link); curr->link = SET_INT_IN_POINTER(curr_mask | prev_mask); } else { CustomDataMask curr_mask = (CustomDataMask)GET_INT_FROM_POINTER(curr->link); curr->link = SET_INT_IN_POINTER(curr_mask | dataMask); } } /* reverse the list so it's in the correct order */ BLI_linklist_reverse(&dataMasks); return dataMasks; }
LinkNode *BLI_file_read_as_lines(const char *name) { FILE *fp= BLI_fopen(name, "r"); LinkNode *lines= NULL; char *buf; size_t size; if (!fp) return NULL; fseek(fp, 0, SEEK_END); size= (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); buf= MEM_mallocN(size, "file_as_lines"); if (buf) { size_t i, last= 0; /* * size = because on win32 reading * all the bytes in the file will return * less bytes because of crnl changes. */ size= fread(buf, 1, size, fp); for (i=0; i<=size; i++) { if (i==size || buf[i]=='\n') { char *line= BLI_strdupn(&buf[last], i-last); BLI_linklist_prepend(&lines, line); last= i+1; } } MEM_freeN(buf); } fclose(fp); BLI_linklist_reverse(&lines); return lines; }
static void face_replace_edge(void *ptr, void *userdata) { SmoothFace *face = ptr; SmoothEdge *find = ((ReplaceData *)userdata)->find; SmoothEdge *replace = ((ReplaceData *)userdata)->replace; int i; #ifdef EDGESPLIT_DEBUG_3 printf("replacing edge %4d with %4d in face %4d", find->newIndex, replace->newIndex, face->newIndex); if(face->edges[3]) printf(": {%2d %2d %2d %2d}", face->edges[0]->newIndex, face->edges[1]->newIndex, face->edges[2]->newIndex, face->edges[3]->newIndex); else printf(": {%2d %2d %2d}", face->edges[0]->newIndex, face->edges[1]->newIndex, face->edges[2]->newIndex); #endif for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) { if(face->edges[i] == find) { linklist_remove_first(&face->edges[i]->faces, face, NULL); BLI_linklist_prepend(&replace->faces, face); face->edges[i] = replace; } } #ifdef EDGESPLIT_DEBUG_3 if(face->edges[3]) printf(" -> {%2d %2d %2d %2d}\n", face->edges[0]->newIndex, face->edges[1]->newIndex, face->edges[2]->newIndex, face->edges[3]->newIndex); else printf(" -> {%2d %2d %2d}\n", face->edges[0]->newIndex, face->edges[1]->newIndex, face->edges[2]->newIndex); #endif }
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; unsigned int i = 0; unsigned int numverts = (unsigned int)dm->getNumVerts ( dm ); unsigned int numedges = (unsigned int)dm->getNumEdges ( dm ); unsigned int numfaces = (unsigned int)dm->getNumFaces ( dm ); MEdge *medge = dm->getEdgeArray ( dm ); MFace *mface = dm->getFaceArray ( dm ); int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; // 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); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); 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.0f; 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.49f / ((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); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; 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); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); 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); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; 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; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; 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 */
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; unsigned int i = 0; unsigned int numverts = (unsigned int)dm->getNumVerts (dm); unsigned int numedges = (unsigned int)dm->getNumEdges (dm); unsigned int numfaces = (unsigned int)dm->getNumTessFaces (dm); float shrink_factor; MEdge *medge = dm->getEdgeArray (dm); MFace *mface = dm->getTessFaceArray (dm); int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeSet *edgeset = NULL; LinkNode *search = NULL, *search2 = NULL; // error handling if ( numedges==0 ) return 0; /* NOTE: handling ownership of springs and edgeset is quite sloppy * currently they are never initialized but assert just to be sure */ BLI_assert(cloth->springs == NULL); BLI_assert(cloth->edgeset == NULL); cloth->springs = NULL; cloth->edgeset = NULL; edgelist = MEM_callocN ( sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc" ); if (!edgelist) return 0; // structural springs for ( i = 0; i < numedges; i++ ) { spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if ( spring ) { spring_verts_ordered_set(spring, medge[i].v1, medge[i].v2); if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW && medge[i].flag & ME_LOOSEEDGE) { // handle sewing (loose edges will be pulled together) spring->restlen = 0.0f; spring->stiffness = 1.0f; spring->type = CLOTH_SPRING_TYPE_SEWING; } else { if (clmd->sim_parms->vgroup_shrink > 0) shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); else shrink_factor = 1.0f - clmd->sim_parms->shrink_min; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; } 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->flags = 0; struct_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } else { cloth_free_errorsprings(cloth, 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.49f / ((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, edgelist); return 0; } spring_verts_ordered_set(spring, mface[i].v1, mface[i].v3); if (clmd->sim_parms->vgroup_shrink > 0) shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); else shrink_factor = 1.0f - clmd->sim_parms->shrink_min; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; 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, edgelist); return 0; } spring_verts_ordered_set(spring, mface[i].v2, mface[i].v4); if (clmd->sim_parms->vgroup_shrink > 0) shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); else shrink_factor = 1.0f - clmd->sim_parms->shrink_min; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } edgeset = BLI_edgeset_new_ex(__func__, numedges); cloth->edgeset = edgeset; 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 ((index2 != tspring2->ij) && !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) { spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { cloth_free_errorsprings(cloth, edgelist); return 0; } spring_verts_ordered_set(spring, tspring2->ij, index2); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; BLI_edgeset_insert(edgeset, spring->ij, spring->kl); 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, edgelist); return 0; } spring->ij = tspring2->ij; spring->kl = tspring->kl; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } search = search->next; search2 = search2->next; } } /* note: the edges may already exist so run reinsert */ /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ for (i = 0; i < numedges; i++) { /* struct springs */ BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2); } for (i = 0; i < numfaces; i++) { /* edge springs */ if (mface[i].v4) { BLI_edgeset_add(edgeset, mface[i].v1, mface[i].v3); BLI_edgeset_add(edgeset, mface[i].v2, mface[i].v4); } } cloth->numsprings = struct_springs + shear_springs + bend_springs; cloth_free_edgelist(edgelist, numverts); #if 0 if (G.debug_value > 0) printf("avg_len: %f\n", clmd->sim_parms->avg_spring_len); #endif return 1; } /* cloth_build_springs */
/* finds another sharp edge which uses vert, by traversing faces around the * vert until it does one of the following: * - hits a loose edge (the edge is returned) * - hits a sharp edge (the edge is returned) * - returns to the start edge (NULL is returned) */ static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, LinkNode **visited_faces) { SmoothFace *face = NULL; SmoothEdge *edge2 = NULL; /* holds the edges we've seen so we can avoid looping indefinitely */ LinkNode *visited_edges = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif /* get a face on which to start */ if(edge->faces) face = edge->faces->link; else return NULL; /* record this edge as visited */ BLI_linklist_prepend(&visited_edges, edge); /* get the next edge */ edge2 = other_edge(face, vert, edge); /* record this face as visited */ if(visited_faces) BLI_linklist_prepend(visited_faces, face); /* search until we hit a loose edge or a sharp edge or an edge we've * seen before */ while(face && !edge_is_sharp(edge2) && !linklist_contains(visited_edges, edge2)) { #ifdef EDGESPLIT_DEBUG_3 printf("current face %4d; current edge %4d\n", face->newIndex, edge2->newIndex); #endif /* get the next face */ face = other_face(edge2, face); /* if face == NULL, edge2 is a loose edge */ if(face) { /* record this face as visited */ if(visited_faces) BLI_linklist_prepend(visited_faces, face); /* record this edge as visited */ BLI_linklist_prepend(&visited_edges, edge2); /* get the next edge */ edge2 = other_edge(face, vert, edge2); #ifdef EDGESPLIT_DEBUG_3 printf("next face %4d; next edge %4d\n", face->newIndex, edge2->newIndex); } else { printf("loose edge: %4d\n", edge2->newIndex); #endif } } /* either we came back to the start edge or we found a sharp/loose edge */ if(linklist_contains(visited_edges, edge2)) /* we came back to the start edge */ edge2 = NULL; BLI_linklist_free(visited_edges, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), " "returning edge %d\n", edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1); #endif return edge2; }
static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm) { SmoothMesh *mesh; EdgeHash *edges = BLI_edgehash_new(); int i; int totvert, totedge, totface; totvert = dm->getNumVerts(dm); totedge = dm->getNumEdges(dm); totface = dm->getNumFaces(dm); mesh = smoothmesh_new(totvert, totedge, totface, totvert, totedge, totface); mesh->dm = dm; for(i = 0; i < totvert; i++) { SmoothVert *vert = &mesh->verts[i]; vert->oldIndex = vert->newIndex = i; } for(i = 0; i < totedge; i++) { SmoothEdge *edge = &mesh->edges[i]; MEdge med; dm->getEdge(dm, i, &med); edge->verts[0] = &mesh->verts[med.v1]; edge->verts[1] = &mesh->verts[med.v2]; edge->oldIndex = edge->newIndex = i; edge->flag = med.flag; BLI_edgehash_insert(edges, med.v1, med.v2, edge); } for(i = 0; i < totface; i++) { SmoothFace *face = &mesh->faces[i]; MFace mf; MVert v1, v2, v3; int j; dm->getFace(dm, i, &mf); dm->getVert(dm, mf.v1, &v1); dm->getVert(dm, mf.v2, &v2); dm->getVert(dm, mf.v3, &v3); face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2); if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1; face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3); if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1; if(mf.v4) { MVert v4; dm->getVert(dm, mf.v4, &v4); face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4); if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1; face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1); if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1; normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co); } else { face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1); if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1; face->edges[3] = NULL; normal_tri_v3( face->normal,v1.co, v2.co, v3.co); } for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) { SmoothEdge *edge = face->edges[j]; BLI_linklist_prepend(&edge->faces, face); BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face); } face->oldIndex = face->newIndex = i; } BLI_edgehash_free(edges, NULL); return mesh; }