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;
}
Example #2
0
// 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;
}
Example #3
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;
}
Example #5
0
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);
}
Example #6
0
/**
 * 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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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
}
Example #10
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 */
Example #11
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->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 */
Example #12
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;
}
Example #13
0
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;
}