static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) { unsigned int i = 0; if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while(search) { ClothSpring *spring = search->link; MEM_freeN ( spring ); search = search->next; } BLI_linklist_free(cloth->springs, NULL); cloth->springs = NULL; } if(edgelist) { for ( i = 0; i < cloth->numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); } MEM_freeN ( edgelist ); } if(cloth->edgehash) BLI_edgehash_free ( cloth->edgehash, NULL ); }
/* frees all */ void cloth_free_modifier(ClothModifierData *clmd ) { Cloth *cloth = NULL; if ( !clmd ) return; cloth = clmd->clothObject; if ( cloth ) { BPH_cloth_solver_free(clmd); // Free the verts. if ( cloth->verts != NULL ) MEM_freeN ( cloth->verts ); cloth->verts = NULL; cloth->mvert_num = 0; // Free the springs. if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while (search) { ClothSpring *spring = search->link; MEM_freeN ( spring ); search = search->next; } BLI_linklist_free(cloth->springs, NULL); cloth->springs = NULL; } cloth->springs = NULL; cloth->numsprings = 0; // free BVH collision tree if ( cloth->bvhtree ) BLI_bvhtree_free ( cloth->bvhtree ); if ( cloth->bvhselftree ) BLI_bvhtree_free ( cloth->bvhselftree ); // we save our faces for collision objects if (cloth->tri) MEM_freeN(cloth->tri); if (cloth->edgeset) BLI_edgeset_free(cloth->edgeset); /* if (clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); */ MEM_freeN ( cloth ); clmd->clothObject = NULL; } }
static void propagate_split(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) { SmoothEdge *edge2; LinkNode *visited_faces = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === propagate_split(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces); if(!edge2) { /* didn't find a sharp or loose edge, so we've hit a dead end */ } else if(!edge_is_loose(edge2)) { /* edge2 is not loose, so it must be sharp */ if(edge_is_loose(edge)) { /* edge is loose, so we can split edge2 at this vert */ split_edge(edge2, vert, mesh); } else if(edge_is_sharp(edge)) { /* both edges are sharp, so we can split the pair at vert */ split_edge(edge, vert, mesh); } else { /* edge is not sharp, so try to split edge2 at its other vert */ split_edge(edge2, other_vert(edge2, vert), mesh); } } else { /* edge2 is loose */ if(edge_is_loose(edge)) { SmoothVert *vert2; ReplaceData repdata; /* can't split edge, what should we do with vert? */ if(linklist_subset(vert->faces, visited_faces)) { /* vert has only one fan of faces attached; don't split it */ } else { /* vert has more than one fan of faces attached; split it */ vert2 = smoothvert_copy(vert, mesh); /* fails in rare cases, see [#26993] */ if(vert2) { /* replace vert with its copy in visited_faces */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); } } } else { /* edge is not loose, so it must be sharp; split it */ split_edge(edge, vert, mesh); } } BLI_linklist_free(visited_faces, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === propagate_split(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif }
static void smoothmesh_free(SmoothMesh *mesh) { int i; for(i = 0; i < mesh->num_verts; ++i) BLI_linklist_free(mesh->verts[i].faces, NULL); for(i = 0; i < mesh->num_edges; ++i) BLI_linklist_free(mesh->edges[i].faces, NULL); if(mesh->arena) BLI_memarena_free(mesh->arena); MEM_freeN(mesh->verts); MEM_freeN(mesh->edges); MEM_freeN(mesh->faces); MEM_freeN(mesh); }
static void cloth_free_edgelist(LinkNode **edgelist, unsigned int numverts) { if (edgelist) { unsigned int i; for (i = 0; i < numverts; i++) { BLI_linklist_free(edgelist[i], NULL); } MEM_freeN(edgelist); } }
static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num) { if (edgelist) { unsigned int i; for (i = 0; i < mvert_num; i++) { BLI_linklist_free(edgelist[i].list, NULL); } MEM_freeN(edgelist); } }
static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) { LinkNode *names = NULL; int totnames_dummy; names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); int i = 0; LinkNode *n = names; while (n) { BLO_library_link_named_part(main_tmp, &bpy_openlib, idcode, (char *)n->link); n = (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ }
static int create_navmesh_exec(bContext *C, wmOperator *op) { Scene* scene= CTX_data_scene(C); LinkNode* obs= NULL; Base* navmeshBase= NULL; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if (base->object->type == OB_MESH) { if (base->object->body_type==OB_BODY_TYPE_NAVMESH) { if (!navmeshBase || base == scene->basact) { navmeshBase= base; } } else { BLI_linklist_append(&obs, (void*)base->object); } } } CTX_DATA_END; if (obs) { struct recast_polyMesh *pmesh= NULL; struct recast_polyMeshDetail *dmesh= NULL; int nverts= 0, ntris= 0; int *tris= 0; float *verts= NULL; createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris); BLI_linklist_free(obs, NULL); buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh); createRepresentation(C, pmesh, dmesh, navmeshBase); MEM_freeN(verts); MEM_freeN(tris); return OPERATOR_FINISHED; } else { BKE_report(op->reports, RPT_ERROR, "No mesh objects found"); return OPERATOR_CANCELLED; } }
static PyObject *_bpy_names(BPy_Library *self, int blocktype) { PyObject *list; LinkNode *l, *names; int totnames; names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); list = PyList_New(totnames); if (names) { int counter = 0; for (l = names; l; l = l->next) { PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ } return list; }
static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist) { if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while (search) { ClothSpring *spring = search->link; MEM_freeN ( spring ); search = search->next; } BLI_linklist_free(cloth->springs, NULL); cloth->springs = NULL; } cloth_free_edgelist(edgelist, cloth->numverts); if (cloth->edgeset) { BLI_edgeset_free(cloth->edgeset); cloth->edgeset = NULL; } }
void BLI_memarena_free(MemArena *ma) { BLI_linklist_free(ma->bufs, (void (*)(void *))MEM_freeN); MEM_freeN(ma); }
void BLI_file_free_lines(LinkNode *lines) { BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN); }
bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; int idcode= BKE_idcode_from_name(group); short flag= 0; /* don't need any special options */ ReportList reports; static char err_local[255]; /* only scene and mesh supported right now */ if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); *err_str= err_local; BLO_blendhandle_close(bpy_openlib); return false; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); *err_str= err_local; BLO_blendhandle_close(bpy_openlib); return false; } if (bpy_openlib==NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); *err_str= err_local; return false; } main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain"); BKE_reports_init(&reports, RPT_STORE); /* here appending/linking starts */ main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); int i=0; LinkNode *n= names; while(n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); n= (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy); int i=0; LinkNode *n= names; while(n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, ID_AC); n= (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag); } BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); /* done linking */ /* needed for lookups*/ GetMainDynamic().push_back(main_newlib); strncpy(main_newlib->name, path, sizeof(main_newlib->name)); if (idcode==ID_ME) { /* Convert all new meshes into BGE meshes */ ID* mesh; for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) printf("MeshName: %s\n", mesh->name+2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this); scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); } } else if (idcode==ID_AC) { /* Convert all actions */ ID *action; for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name+2); scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); } } else if (idcode==ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) printf("SceneName: %s\n", scene->name+2); /* merge into the base scene */ KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene delete other; } /* Now handle all the actions */ if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name+2); scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); } } } return true; }
void bvhcache_free(BVHCache *cache) { BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free); *cache = NULL; }
void filelist_from_library(struct FileList* filelist) { LinkNode *l, *names, *previews; struct ImBuf* ima; int ok, i, nprevs, nnames, idcode; char filename[FILE_MAX]; char dir[FILE_MAX], group[GROUP_MAX]; /* name test */ ok= filelist_islibrary(filelist, dir, group); if (!ok) { /* free */ if (filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); filelist->libfiledata= NULL; return; } BLI_strncpy(filename, G.main->name, sizeof(filename)); /* there we go */ /* for the time being only read filedata when libfiledata==0 */ if (filelist->libfiledata == NULL) { filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); if (filelist->libfiledata == NULL) return; } idcode= groupname_to_code(group); /* memory for strings is passed into filelist[i].relname * and freed in freefilelist */ if (idcode) { previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode, &nprevs); names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode, &nnames); /* ugh, no rewind, need to reopen */ BLO_blendhandle_close(filelist->libfiledata); filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); } else { previews= NULL; nprevs= 0; names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata); nnames= BLI_linklist_length(names); } filelist->numfiles= nnames + 1; filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist)); memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist)); filelist->filelist[0].relname= BLI_strdup(".."); filelist->filelist[0].type |= S_IFDIR; for (i=0, l= names; i<nnames; i++, l= l->next) { char *blockname= l->link; filelist->filelist[i + 1].relname= BLI_strdup(blockname); if (idcode) { filelist->filelist[i + 1].type |= S_IFREG; } else { filelist->filelist[i + 1].type |= S_IFDIR; } } if (previews && (nnames != nprevs)) { printf("filelist_from_library: error, found %d items, %d previews\n", nnames, nprevs); } else if (previews) { for (i=0, l= previews; i<nnames; i++, l= l->next) { PreviewImage *img= l->link; if (img) { unsigned int w = img->w[ICON_SIZE_PREVIEW]; unsigned int h = img->h[ICON_SIZE_PREVIEW]; unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; /* first allocate imbuf for copying preview into it */ if (w > 0 && h > 0 && rect) { ima = IMB_allocImBuf(w, h, 32, IB_rect); memcpy(ima->rect, rect, w*h*sizeof(unsigned int)); filelist->filelist[i + 1].image = ima; filelist->filelist[i + 1].flags = IMAGEFILE; } } } } BLI_linklist_free(names, free); if (previews) BLI_linklist_free(previews, BKE_previewimg_freefunc); filelist_sort(filelist, FILE_SORT_ALPHA); BLI_strncpy(G.main->name, filename, sizeof(filename)); // prevent G.main->name to change filelist->filter = 0; filelist_filter(filelist); }
/* frees all */ void cloth_free_modifier_extern ( ClothModifierData *clmd ) { Cloth *cloth = NULL; if(G.rt > 0) printf("cloth_free_modifier_extern\n"); if ( !clmd ) return; cloth = clmd->clothObject; if ( cloth ) { if(G.rt > 0) printf("cloth_free_modifier_extern in\n"); // If our solver provides a free function, call it if ( solvers [clmd->sim_parms->solver_type].free ) { solvers [clmd->sim_parms->solver_type].free ( clmd ); } // Free the verts. if ( cloth->verts != NULL ) MEM_freeN ( cloth->verts ); cloth->verts = NULL; cloth->numverts = 0; // Free the springs. if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while(search) { ClothSpring *spring = search->link; MEM_freeN ( spring ); search = search->next; } BLI_linklist_free(cloth->springs, NULL); cloth->springs = NULL; } cloth->springs = NULL; cloth->numsprings = 0; // free BVH collision tree if ( cloth->bvhtree ) BLI_bvhtree_free ( cloth->bvhtree ); if ( cloth->bvhselftree ) BLI_bvhtree_free ( cloth->bvhselftree ); // we save our faces for collision objects if ( cloth->mfaces ) MEM_freeN ( cloth->mfaces ); if(cloth->edgehash) BLI_edgehash_free ( cloth->edgehash, NULL ); /* if(clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); */ MEM_freeN ( cloth ); clmd->clothObject = NULL; } }
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 */
/* Does not fix anything, but checks that all linked data-blocks are still valid (i.e. pointing to the right library). */ bool BLO_main_validate_libraries(struct Main *bmain, struct ReportList *reports) { ListBase mainlist; bool is_valid = true; BKE_main_lock(bmain); blo_split_main(&mainlist, bmain); ListBase *lbarray[MAX_LIBARRAY]; int i = set_listbasepointers(bmain, lbarray); while (i--) { for (ID *id = lbarray[i]->first; id != NULL; id = id->next) { if (id->lib != NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s is in local database while being linked from library %s!\n", id->name, id->lib->name); } } } for (Main *curmain = bmain->next; curmain != NULL; curmain = curmain->next) { Library *curlib = curmain->curlib; if (curlib == NULL) { BKE_reportf(reports, RPT_ERROR, "Library database with NULL library datablock!\n"); continue; } BKE_library_filepath_set(bmain, curlib, curlib->name); BlendHandle *bh = BLO_blendhandle_from_file(curlib->filepath, reports); if (bh == NULL) { BKE_reportf(reports, RPT_ERROR, "Library ID %s not found at expected path %s!\n", curlib->id.name, curlib->filepath); continue; } i = set_listbasepointers(curmain, lbarray); while (i--) { ID *id = lbarray[i]->first; if (id == NULL) { continue; } if (GS(id->name) == ID_LI) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "Library ID %s in library %s, this should not happen!\n", id->name, curlib->name); continue; } int totnames = 0; LinkNode *names = BLO_blendhandle_get_datablock_names(bh, GS(id->name), &totnames); for (; id != NULL; id = id->next) { if (id->lib == NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s has NULL lib pointer while being in library %s!\n", id->name, curlib->name); continue; } if (id->lib != curlib) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s has mismatched lib pointer!\n", id->name); continue; } LinkNode *name = names; for (; name; name = name->next) { char *str_name = (char *)name->link; if (id->name[2] == str_name[0] && STREQ(str_name, id->name + 2)) { break; } } if (name == NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s not found in library %s anymore!\n", id->name, id->lib->name); continue; } } BLI_linklist_free(names, free); } BLO_blendhandle_close(bh); } blo_join_main(&mainlist); BLI_assert(BLI_listbase_is_single(&mainlist)); BLI_assert(mainlist.first == (void *)bmain); BKE_main_unlock(bmain); return is_valid; }
static void createVertsTrisData(bContext *C, LinkNode* obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r) { MVert *mvert; int nfaces= 0, *tri, i, curnverts, basenverts, curnfaces; MFace *mface; float co[3], wco[3]; Object *ob; LinkNode *oblink, *dmlink; DerivedMesh *dm; Scene* scene= CTX_data_scene(C); LinkNode* dms= NULL; int nverts, ntris, *tris; float *verts; nverts= 0; ntris= 0; /* calculate number of verts and tris */ for(oblink= obs; oblink; oblink= oblink->next) { ob= (Object*) oblink->link; dm= mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); BLI_linklist_append(&dms, (void*)dm); nverts+= dm->getNumVerts(dm); nfaces= dm->getNumFaces(dm); ntris+= nfaces; /* resolve quad faces */ mface= dm->getFaceArray(dm); for(i= 0; i<nfaces; i++) { MFace* mf= &mface[i]; if(mf->v4) ntris+=1; } } /* create data */ verts= MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts"); tris= MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces"); basenverts= 0; tri= tris; for(oblink= obs, dmlink= dms; oblink && dmlink; oblink= oblink->next, dmlink= dmlink->next) { ob= (Object*) oblink->link; dm= (DerivedMesh*) dmlink->link; curnverts= dm->getNumVerts(dm); mvert= dm->getVertArray(dm); /* copy verts */ for(i= 0; i<curnverts; i++) { MVert *v= &mvert[i]; copy_v3_v3(co, v->co); mul_v3_m4v3(wco, ob->obmat, co); verts[3*(basenverts+i)+0]= wco[0]; verts[3*(basenverts+i)+1]= wco[2]; verts[3*(basenverts+i)+2]= wco[1]; } /* create tris */ curnfaces= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); for(i= 0; i<curnfaces; i++) { MFace* mf= &mface[i]; tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v3; tri[2]= basenverts + mf->v2; tri += 3; if(mf->v4) { tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v4; tri[2]= basenverts + mf->v3; tri += 3; } } basenverts+= curnverts; } /* release derived mesh */ for(dmlink= dms; dmlink; dmlink= dmlink->next) { dm= (DerivedMesh*) dmlink->link; dm->release(dm); } BLI_linklist_free(dms, NULL); *nverts_r= nverts; *verts_r= verts; *ntris_r= ntris; *tris_r= tris; }
/* empties the linked list * frees pointers with freefunc if freefunc is not NULL */ static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc) { BLI_linklist_free(*list, freefunc); *list = NULL; }
/* 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 void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) { SmoothEdge *edge2; SmoothVert *vert2; ReplaceData repdata; /* the list of faces traversed while looking for a sharp edge */ LinkNode *visited_faces = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === split_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces); if(!edge2) { /* didn't find a sharp or loose edge, so try the other vert */ vert2 = other_vert(edge, vert); push_propagate_stack(edge, vert2, mesh); } else if(!edge_is_loose(edge2)) { /* edge2 is not loose, so it must be sharp */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh); SmoothVert *vert2; /* replace edge with its copy in visited_faces */ repdata.find = edge; repdata.replace = copy_edge; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); /* replace edge2 with its copy in visited_faces */ repdata.find = edge2; repdata.replace = copy_edge2; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); vert2 = smoothvert_copy(vert, mesh); /* replace vert with its copy in visited_faces (must be done after * edge replacement so edges have correct vertices) */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); /* all copying and replacing is done; the mesh should be consistent. * now propagate the split to the vertices at either end */ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh); if(smoothedge_has_vert(edge, vert)) push_propagate_stack(edge, vert, mesh); } else { /* edge2 is loose */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); SmoothVert *vert2; /* replace edge with its copy in visited_faces */ repdata.find = edge; repdata.replace = copy_edge; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); vert2 = smoothvert_copy(vert, mesh); /* bug [#29205] which is caused by exactly the same reason as [#26316] this check will only prevent crash without fixing actual issue and some vertices can stay unsplitted when they should (sergey) */ if(vert2) { /* replace vert with its copy in visited_faces (must be done after * edge replacement so edges have correct vertices) */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); } /* copying and replacing is done; the mesh should be consistent. * now propagate the split to the vertex at the other end */ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); if(smoothedge_has_vert(edge, vert)) push_propagate_stack(edge, vert, mesh); } BLI_linklist_free(visited_faces, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === split_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif }