Beispiel #1
0
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 );
}
Beispiel #2
0
/* 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;
	}
}
Beispiel #3
0
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
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
	}
}
Beispiel #6
0
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 */
}
Beispiel #8
0
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;
}
Beispiel #10
0
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;
	}
}
Beispiel #11
0
void BLI_memarena_free(MemArena *ma)
{
	BLI_linklist_free(ma->bufs, (void (*)(void *))MEM_freeN);
	MEM_freeN(ma);
}
Beispiel #12
0
void BLI_file_free_lines(LinkNode *lines)
{
	BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN);
}
Beispiel #13
0
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;
}
Beispiel #14
0
void bvhcache_free(BVHCache *cache)
{
	BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free);
	*cache = NULL;
}
Beispiel #15
0
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);
}
Beispiel #16
0
/* 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;
	}
}
Beispiel #17
0
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 */
Beispiel #18
0
/* 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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
/* 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;
}
Beispiel #21
0
/* 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;
}
Beispiel #22
0
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
}