Example #1
0
static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2)
{
	MDefBoundIsect *isect;
	MeshDeformIsect isec;
	float (*cagecos)[3];
	MFace *mface;
	float vert[4][3], len, end[3];
	static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4};

	/* setup isec */
	memset(&isec, 0, sizeof(isec));
	isec.labda= 1e10f;

	VECADD(isec.start, co1, epsilon);
	VECADD(end, co2, epsilon);
	sub_v3_v3v3(isec.vec, end, isec.start);

	if(meshdeform_intersect(mdb, &isec)) {
		len= isec.labda;
		mface=(MFace*)isec.face;

		/* create MDefBoundIsect */
		isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect));

		/* compute intersection coordinate */
		isect->co[0]= co1[0] + isec.vec[0]*len;
		isect->co[1]= co1[1] + isec.vec[1]*len;
		isect->co[2]= co1[2] + isec.vec[2]*len;

		isect->len= len_v3v3(co1, isect->co);
		if(isect->len < MESHDEFORM_LEN_THRESHOLD)
			isect->len= MESHDEFORM_LEN_THRESHOLD;

		isect->v[0]= mface->v1;
		isect->v[1]= mface->v2;
		isect->v[2]= mface->v3;
		isect->v[3]= mface->v4;
		isect->nvert= (mface->v4)? 4: 3;

		isect->facing= isec.isect;

		/* compute mean value coordinates for interpolation */
		cagecos= mdb->cagecos;
		copy_v3_v3(vert[0], cagecos[mface->v1]);
		copy_v3_v3(vert[1], cagecos[mface->v2]);
		copy_v3_v3(vert[2], cagecos[mface->v3]);
		if(mface->v4) copy_v3_v3(vert[3], cagecos[mface->v4]);
		interp_weights_poly_v3( isect->uvw,vert, isect->nvert, isect->co);

		return isect;
	}

	return NULL;
}
Example #2
0
void BLI_polyfill_calc_arena(
        const float (*coords)[2],
        const unsigned int coords_tot,
        unsigned int (*r_tris)[3],

        struct MemArena *arena)
{
	unsigned int *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot);
	eSign *coords_sign = BLI_memarena_alloc(arena, sizeof(*coords_sign) * coords_tot);

	BLI_polyfill_calc_ex(
	        coords, coords_tot,
	        r_tris,
	        /* cache */

	        indices, coords_sign);

	/* indices & coords_sign are no longer needed,
	 * caller can clear arena */
}
Example #3
0
static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3)
{
	/* does not make edges */
	ScanFillFace *sf_tri;

	sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace));
	BLI_addtail(&sf_ctx->fillfacebase, sf_tri);
	
	sf_tri->v1 = v1;
	sf_tri->v2 = v2;
	sf_tri->v3 = v3;
}
void *BLI_memarena_calloc(MemArena *ma, size_t size)
{
	void *ptr;

	/* no need to use this function call if we're calloc'ing by default */
	BLI_assert(ma->use_calloc == false);

	ptr = BLI_memarena_alloc(ma, size);
	memset(ptr, 0, size);

	return ptr;
}
Example #5
0
static void imb_thread_cache_init(ImThreadTileCache *cache)
{
	ImThreadTile *ttile;
	int a;

	memset(cache, 0, sizeof(ImThreadTileCache));

	cache->tilehash= BLI_ghash_new(imb_thread_tile_hash, imb_thread_tile_cmp, "imb_thread_cache_init gh");

	/* pre-allocate all thread local tiles in unused list */
	for(a=0; a<IB_THREAD_CACHE_SIZE; a++) {
		ttile= BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImThreadTile));
		BLI_addtail(&cache->unused, ttile);
	}
}
Example #6
0
ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2)
{
	ScanFillEdge *sf_ed;

	sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge));
	BLI_addtail(&sf_ctx->filledgebase, sf_ed);
	
	sf_ed->v1 = v1;
	sf_ed->v2 = v2;

	/* just zero out the rest */
	sf_ed->poly_nr = sf_ctx->poly_nr;
	sf_ed->f = SF_EDGE_NEW;
	sf_ed->user_flag = 0;
	sf_ed->tmp.c = 0;

	return sf_ed;
}
Example #7
0
static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
{
	PropagateEdge *pedge = mesh->reusestack.first;

	if(pedge) {
		BLI_remlink(&mesh->reusestack, pedge);
	}
	else {
		if(!mesh->arena) {
			mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "edgesplit arena");
			BLI_memarena_use_calloc(mesh->arena);
		}

		pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
	}

	pedge->edge = edge;
	pedge->vert = vert;
	BLI_addhead(&mesh->propagatestack, pedge);
}
Example #8
0
ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
{
	ScanFillVert *sf_v;
	
	sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert));

	BLI_addtail(&sf_ctx->fillvertbase, sf_v);

	sf_v->tmp.p = NULL;
	copy_v3_v3(sf_v->co, vec);

	/* just zero out the rest */
	zero_v2(sf_v->xy);
	sf_v->keyindex = 0;
	sf_v->poly_nr = sf_ctx->poly_nr;
	sf_v->edge_tot = 0;
	sf_v->f = SF_VERT_NEW;
	sf_v->user_flag = 0;

	return sf_v;
}
/**
 * Inserts cube at lattice i, j, k into hash table, marking it as "done"
 */
static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k)
{
	int index;
	CENTERLIST *newc, *l, *q;

	index = HASH(i, j, k);
	q = table[index];

	for (l = q; l != NULL; l = l->next) {
		if (l->i == i && l->j == j && l->k == k) return 1;
	}

	newc = BLI_memarena_alloc(process->pgn_elements, sizeof(CENTERLIST));
	newc->i = i;
	newc->j = j;
	newc->k = k;
	newc->next = q;
	table[index] = newc;

	return 0;
}
/**
 * Adds cube at given lattice position to cube stack of process.
 */
static void add_cube(PROCESS *process, int i, int j, int k)
{
	CUBES *ncube;
	int n;

	/* test if cube has been found before */
	if (setcenter(process, process->centers, i, j, k) == 0) {
		/* push cube on stack: */
		ncube = BLI_memarena_alloc(process->pgn_elements, sizeof(CUBES));
		ncube->next = process->cubes;
		process->cubes = ncube;

		ncube->cube.i = i;
		ncube->cube.j = j;
		ncube->cube.k = k;

		/* set corners of initial cube: */
		for (n = 0; n < 8; n++)
			ncube->cube.corners[n] = setcorner(process, i + MB_BIT(n, 2), j + MB_BIT(n, 1), k + MB_BIT(n, 0));
	}
}
Example #11
0
void scatter_tree_build(ScatterTree *tree)
{
	ScatterPoint *newpoints, **tmppoints;
	float mid[3], size[3];
	int totpoint= tree->totpoint;

	newpoints = MEM_callocN(sizeof(ScatterPoint) * totpoint, "ScatterPoints");
	tmppoints = MEM_callocN(sizeof(ScatterPoint *) * totpoint, "ScatterTmpPoints");
	tree->tmppoints= tmppoints;

	tree->arena= BLI_memarena_new(0x8000 * sizeof(ScatterNode), "sss tree arena");
	BLI_memarena_use_calloc(tree->arena);

	/* build tree */
	tree->root= BLI_memarena_alloc(tree->arena, sizeof(ScatterNode));
	tree->root->points= newpoints;
	tree->root->totpoint= totpoint;

	mid[0]= (tree->min[0]+tree->max[0])*0.5f;
	mid[1]= (tree->min[1]+tree->max[1])*0.5f;
	mid[2]= (tree->min[2]+tree->max[2])*0.5f;

	size[0]= (tree->max[0]-tree->min[0])*0.5f;
	size[1]= (tree->max[1]-tree->min[1])*0.5f;
	size[2]= (tree->max[2]-tree->min[2])*0.5f;

	create_octree_node(tree, tree->root, mid, size, tree->refpoints, 0);

	MEM_freeN(tree->points);
	MEM_freeN(tree->refpoints);
	MEM_freeN(tree->tmppoints);
	tree->refpoints= NULL;
	tree->tmppoints= NULL;
	tree->points= newpoints;
	
	/* sum radiance at nodes */
	sum_radiance(tree, tree->root);
}
Example #12
0
void BKE_mesh_loop_islands_add(
        MeshIslandStore *island_store, const int item_num, int *items_indices,
        const int num_island_items, int *island_item_indices,
        const int num_innercut_items, int *innercut_item_indices)
{
	MemArena *mem = island_store->mem;

	MeshElemMap *isld, *innrcut;
	const int curr_island_idx = island_store->islands_num++;
	const size_t curr_num_islands = (size_t)island_store->islands_num;
	int i = item_num;

	island_store->items_to_islands_num = item_num;
	while (i--) {
		island_store->items_to_islands[items_indices[i]] = curr_island_idx;
	}

	if (UNLIKELY(curr_num_islands > island_store->islands_num_alloc)) {
		MeshElemMap **islds, **innrcuts;

		island_store->islands_num_alloc *= 2;
		islds = BLI_memarena_alloc(mem, sizeof(*islds) * island_store->islands_num_alloc);
		memcpy(islds, island_store->islands, sizeof(*islds) * (curr_num_islands - 1));
		island_store->islands = islds;

		innrcuts = BLI_memarena_alloc(mem, sizeof(*innrcuts) * island_store->islands_num_alloc);
		memcpy(innrcuts, island_store->innercuts, sizeof(*innrcuts) * (curr_num_islands - 1));
		island_store->innercuts = innrcuts;
	}

	island_store->islands[curr_island_idx] = isld = BLI_memarena_alloc(mem, sizeof(*isld));
	isld->count = num_island_items;
	isld->indices = BLI_memarena_alloc(mem, sizeof(*isld->indices) * (size_t)num_island_items);
	memcpy(isld->indices, island_item_indices, sizeof(*isld->indices) * (size_t)num_island_items);

	island_store->innercuts[curr_island_idx] = innrcut = BLI_memarena_alloc(mem, sizeof(*innrcut));
	innrcut->count = num_innercut_items;
	innrcut->indices = BLI_memarena_alloc(mem, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
	memcpy(innrcut->indices, innercut_item_indices, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
}
Example #13
0
static void meshdeform_matrix_solve(MeshDeformBind *mdb)
{
	NLContext *context;
	float vec[3], gridvec[3];
	int a, b, x, y, z, totvar;
	char message[1024];

	/* setup variable indices */
	mdb->varidx= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformDSvaridx");
	for(a=0, totvar=0; a<mdb->size3; a++)
		mdb->varidx[a]= (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)? -1: totvar++;

	if(totvar == 0) {
		MEM_freeN(mdb->varidx);
		return;
	}

	progress_bar(0, "Starting mesh deform solve");

	/* setup opennl solver */
	nlNewContext();
	context= nlGetCurrent();

	nlSolverParameteri(NL_NB_VARIABLES, totvar);
	nlSolverParameteri(NL_NB_ROWS, totvar);
	nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 1);

	nlBegin(NL_SYSTEM);
	nlBegin(NL_MATRIX);

	/* build matrix */
	for(z=0; z<mdb->size; z++)
		for(y=0; y<mdb->size; y++)
			for(x=0; x<mdb->size; x++)
				meshdeform_matrix_add_cell(mdb, x, y, z);

	/* solve for each cage vert */
	for(a=0; a<mdb->totcagevert; a++) {
		if(a != 0) {
			nlBegin(NL_SYSTEM);
			nlBegin(NL_MATRIX);
		}

		/* fill in right hand side and solve */
		for(z=0; z<mdb->size; z++)
			for(y=0; y<mdb->size; y++)
				for(x=0; x<mdb->size; x++)
					meshdeform_matrix_add_rhs(mdb, x, y, z, a);

		nlEnd(NL_MATRIX);
		nlEnd(NL_SYSTEM);

#if 0
		nlPrintMatrix();
#endif

		if(nlSolveAdvanced(NULL, NL_TRUE)) {
			for(z=0; z<mdb->size; z++)
				for(y=0; y<mdb->size; y++)
					for(x=0; x<mdb->size; x++)
						meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);

			for(z=0; z<mdb->size; z++)
				for(y=0; y<mdb->size; y++)
					for(x=0; x<mdb->size; x++)
						meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);

			for(b=0; b<mdb->size3; b++) {
				if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
					mdb->phi[b]= nlGetVariable(0, mdb->varidx[b]);
				mdb->totalphi[b] += mdb->phi[b];
			}

			if(mdb->weights) {
				/* static bind : compute weights for each vertex */
				for(b=0; b<mdb->totvert; b++) {
					if(mdb->inside[b]) {
						copy_v3_v3(vec, mdb->vertexcos[b]);
						gridvec[0]= (vec[0] - mdb->min[0] - mdb->halfwidth[0])/mdb->width[0];
						gridvec[1]= (vec[1] - mdb->min[1] - mdb->halfwidth[1])/mdb->width[1];
						gridvec[2]= (vec[2] - mdb->min[2] - mdb->halfwidth[2])/mdb->width[2];

						mdb->weights[b*mdb->totcagevert + a]= meshdeform_interp_w(mdb, gridvec, vec, a);
					}
				}
			}
			else {
				MDefBindInfluence *inf;

				/* dynamic bind */
				for(b=0; b<mdb->size3; b++) {
					if(mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
						inf= BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
						inf->vertex= a;
						inf->weight= mdb->phi[b];
						inf->next= mdb->dyngrid[b];
						mdb->dyngrid[b]= inf;
					}
				}
			}
		}
		else {
			error("Mesh Deform: failed to find solution.");
			break;
		}

		sprintf(message, "Mesh deform solve %d / %d       |||", a+1, mdb->totcagevert);
		progress_bar((float)(a+1)/(float)(mdb->totcagevert), message);
	}

#if 0
	/* sanity check */
	for(b=0; b<mdb->size3; b++)
		if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
			if(fabs(mdb->totalphi[b] - 1.0f) > 1e-4)
				printf("totalphi deficiency [%s|%d] %d: %.10f\n",
					(mdb->tag[b] == MESHDEFORM_TAG_INTERIOR)? "interior": "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
#endif
	
	/* free */
	MEM_freeN(mdb->varidx);

	nlDeleteContext(context);
}
Example #14
0
static void create_octree_node(ScatterTree *tree, ScatterNode *node, float *mid, float *size, ScatterPoint **refpoints, int depth)
{
	ScatterNode *subnode;
	ScatterPoint **subrefpoints, **tmppoints= tree->tmppoints;
	int index, nsize[8], noffset[8], i, subco, used_nodes, usedi;
	float submid[3], subsize[3];

	/* stopping condition */
	if (node->totpoint <= MAX_OCTREE_NODE_POINTS || depth == MAX_OCTREE_DEPTH) {
		for (i=0; i<node->totpoint; i++)
			node->points[i]= *(refpoints[i]);

		return;
	}

	subsize[0]= size[0]*0.5f;
	subsize[1]= size[1]*0.5f;
	subsize[2]= size[2]*0.5f;

	node->split[0]= mid[0];
	node->split[1]= mid[1];
	node->split[2]= mid[2];

	memset(nsize, 0, sizeof(nsize));
	memset(noffset, 0, sizeof(noffset));

	/* count points in subnodes */
	for (i=0; i<node->totpoint; i++) {
		index= SUBNODE_INDEX(refpoints[i]->co, node->split);
		tmppoints[i]= refpoints[i];
		nsize[index]++;
	}

	/* here we check if only one subnode is used. if this is the case, we don't
	 * create a new node, but rather call this function again, with different
	 * size and middle position for the same node. */
	for (usedi=0, used_nodes=0, i=0; i<8; i++) {
		if (nsize[i]) {
			used_nodes++;
			usedi = i;
		}
		if (i != 0)
			noffset[i]= noffset[i-1]+nsize[i-1];
	}
	
	if (used_nodes <= 1) {
		subnode_middle(usedi, mid, subsize, submid);
		create_octree_node(tree, node, submid, subsize, refpoints, depth+1);
		return;
	}

	/* reorder refpoints by subnode */
	for (i=0; i<node->totpoint; i++) {
		index= SUBNODE_INDEX(tmppoints[i]->co, node->split);
		refpoints[noffset[index]]= tmppoints[i];
		noffset[index]++;
	}

	/* create subnodes */
	for (subco=0, i=0; i<8; subco+=nsize[i], i++) {
		if (nsize[i] > 0) {
			subnode= BLI_memarena_alloc(tree->arena, sizeof(ScatterNode));
			node->child[i]= subnode;
			subnode->points= node->points + subco;
			subnode->totpoint= nsize[i];
			subrefpoints= refpoints + subco;

			subnode_middle(i, mid, subsize, submid);

			create_octree_node(tree, subnode, submid, subsize, subrefpoints,
				depth+1);
		}
		else
			node->child[i]= NULL;
	}

	node->points= NULL;
	node->totpoint= 0;
}
/**
 * Iterates over ALL objects in the scene and all of its sets, including
 * making all duplis(not only metas). Copies metas to mainb array.
 * Computes bounding boxes for building BVH. */
static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
	Scene *sce_iter = scene;
	Base *base;
	Object *bob;
	MetaBall *mb;
	const MetaElem *ml;
	float obinv[4][4], obmat[4][4];
	unsigned int i;
	int obnr, zero_size = 0;
	char obname[MAX_ID_NAME];
	SceneBaseIter iter;

	copy_m4_m4(obmat, ob->obmat);   /* to cope with duplicators from BKE_scene_base_iter_next */
	invert_m4_m4(obinv, ob->obmat);

	BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');

	/* make main array */
	BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
	while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
		if (bob->type == OB_MBALL) {
			zero_size = 0;
			ml = NULL;

			if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
				mb = ob->data;

				if (mb->editelems) ml = mb->editelems->first;
				else ml = mb->elems.first;
			}
			else {
				char name[MAX_ID_NAME];
				int nr;

				BLI_split_name_num(name, &nr, bob->id.name + 2, '.');
				if (STREQ(obname, name)) {
					mb = bob->data;

					if (mb->editelems) ml = mb->editelems->first;
					else ml = mb->elems.first;
				}
			}

			/* when metaball object has zero scale, then MetaElem to this MetaBall
			 * will not be put to mainb array */
			if (has_zero_axis_m4(bob->obmat)) {
				zero_size = 1;
			}
			else if (bob->parent) {
				struct Object *pob = bob->parent;
				while (pob) {
					if (has_zero_axis_m4(pob->obmat)) {
						zero_size = 1;
						break;
					}
					pob = pob->parent;
				}
			}

			if (zero_size) {
				while (ml) {
					ml = ml->next;
				}
			}
			else {
				while (ml) {
					if (!(ml->flag & MB_HIDE)) {
						float pos[4][4], rot[4][4];
						float expx, expy, expz;
						float tempmin[3], tempmax[3];

						MetaElem *new_ml;

						/* make a copy because of duplicates */
						new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem));
						*(new_ml) = *ml;
						new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox));
						new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
						new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));

						/* too big stiffness seems only ugly due to linear interpolation
						* no need to have possibility for too big stiffness */
						if (ml->s > 10.0f) new_ml->s = 10.0f;
						else new_ml->s = ml->s;

						/* if metaball is negative, set stiffness negative */
						if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s;

						/* Translation of MetaElem */
						unit_m4(pos);
						pos[3][0] = ml->x;
						pos[3][1] = ml->y;
						pos[3][2] = ml->z;

						/* Rotation of MetaElem is stored in quat */
						quat_to_mat4(rot, ml->quat);

						/* basis object space -> world -> ml object space -> position -> rotation -> ml local space */
						mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot);
						/* ml local space -> basis object space */
						invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);

						/* rad2 is inverse of squared radius */
						new_ml->rad2 = 1 / (ml->rad * ml->rad);

						/* initial dimensions = radius */
						expx = ml->rad;
						expy = ml->rad;
						expz = ml->rad;

						switch (ml->type) {
							case MB_BALL:
								break;
							case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
								expz += ml->expz;
								/* fall through */
							case MB_PLANE: /* plane is "expanded" by expy and expx */
								expy += ml->expy;
								/* fall through */
							case MB_TUBE: /* tube is "expanded" by expx */
								expx += ml->expx;
								break;
							case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
								expx *= ml->expx;
								expy *= ml->expy;
								expz *= ml->expz;
								break;
						}

						/* untransformed Bounding Box of MetaElem */
						/* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
						copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz);  /* 0 */
						copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz);  /* 1 */
						copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz);  /* 2 */
						copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz);  /* 3 */
						copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz);  /* 4 */
						copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz);  /* 5 */
						copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz);  /* 6 */
						copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz);  /* 7 */

						/* transformation of Metalem bb */
						for (i = 0; i < 8; i++)
							mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);

						/* find max and min of transformed bb */
						INIT_MINMAX(tempmin, tempmax);
						for (i = 0; i < 8; i++) {
							DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax);
						}

						/* set only point 0 and 6 - AABB of Metaelem */
						copy_v3_v3(new_ml->bb->vec[0], tempmin);
						copy_v3_v3(new_ml->bb->vec[6], tempmax);

						/* add new_ml to mainb[] */
						if (UNLIKELY(process->totelem == process->mem)) {
							process->mem = process->mem * 2 + 10;
							process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem);
						}
						process->mainb[process->totelem++] = new_ml;
					}
					ml = ml->next;
				}
			}
		}
	}

	/* compute AABB of all Metaelems */
	if (process->totelem > 0) {
		copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
		copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
		for (i = 1; i < process->totelem; i++)
			make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
	}
}
static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const float co1[3], const float co2[3])
{
	BVHTreeRayHit hit;
	MeshDeformIsect isect_mdef;
	struct MeshRayCallbackData data = {
		mdb,
		&isect_mdef,
	};
	float end[3], vec_normal[3];

	/* happens binding when a cage has no faces */
	if (UNLIKELY(mdb->bvhtree == NULL))
		return NULL;

	/* setup isec */
	memset(&isect_mdef, 0, sizeof(isect_mdef));
	isect_mdef.lambda = 1e10f;

	copy_v3_v3(isect_mdef.start, co1);
	copy_v3_v3(end, co2);
	sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
	isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);

	hit.index = -1;
	hit.dist = BVH_RAYCAST_DIST_MAX;
	if (BLI_bvhtree_ray_cast(mdb->bvhtree, isect_mdef.start, vec_normal,
	                         0.0, &hit, harmonic_ray_callback, &data) != -1)
	{
		const MLoop *mloop = mdb->cagedm_cache.mloop;
		const MLoopTri *lt = &mdb->cagedm_cache.looptri[hit.index];
		const MPoly *mp = &mdb->cagedm_cache.mpoly[lt->poly];
		const float (*cagecos)[3] = mdb->cagecos;
		const float len = isect_mdef.lambda;
		MDefBoundIsect *isect;

		float (*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
		int i;

		/* create MDefBoundIsect, and extra for 'poly_weights[]' */
		isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));

		/* compute intersection coordinate */
		madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);

		isect->facing = isect_mdef.isect;

		isect->poly_index = lt->poly;

		isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);

		/* compute mean value coordinates for interpolation */
		for (i = 0; i < mp->totloop; i++) {
			copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
		}

		interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);

		return isect;
	}

	return NULL;
}
Example #17
0
static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth)
{
	ListBase threads;
	OcclusionBuildThread othreads[BLENDER_MAX_THREADS];
	OccNode *child, tmpnode;
	/* OccFace *face; */
	int a, b, totthread = 0, offset[TOTCHILD], count[TOTCHILD];

	/* add a new node */
	node->occlusion = 1.0f;

	/* leaf node with only children */
	if (end - begin <= TOTCHILD) {
		for (a = begin, b = 0; a < end; a++, b++) {
			/* face= &tree->face[a]; */
			node->child[b].face = a;
			node->childflag |= (1 << b);
		}
	}
	else {
		/* order faces */
		occ_build_8_split(tree, begin, end, offset, count);

		if (depth == 1 && tree->dothreadedbuild)
			BLI_init_threads(&threads, exec_occ_build, tree->totbuildthread);

		for (b = 0; b < TOTCHILD; b++) {
			if (count[b] == 0) {
				node->child[b].node = NULL;
			}
			else if (count[b] == 1) {
				/* face= &tree->face[offset[b]]; */
				node->child[b].face = offset[b];
				node->childflag |= (1 << b);
			}
			else {
				if (tree->dothreadedbuild)
					BLI_lock_thread(LOCK_CUSTOM1);

				child = BLI_memarena_alloc(tree->arena, sizeof(OccNode));
				node->child[b].node = child;

				/* keep track of maximum depth for stack */
				if (depth >= tree->maxdepth)
					tree->maxdepth = depth + 1;

				if (tree->dothreadedbuild)
					BLI_unlock_thread(LOCK_CUSTOM1);

				if (depth == 1 && tree->dothreadedbuild) {
					othreads[totthread].tree = tree;
					othreads[totthread].node = child;
					othreads[totthread].begin = offset[b];
					othreads[totthread].end = offset[b] + count[b];
					othreads[totthread].depth = depth + 1;
					BLI_insert_thread(&threads, &othreads[totthread]);
					totthread++;
				}
				else
					occ_build_recursive(tree, child, offset[b], offset[b] + count[b], depth + 1);
			}
		}

		if (depth == 1 && tree->dothreadedbuild)
			BLI_end_threads(&threads);
	}

	/* combine area, position and sh */
	for (b = 0; b < TOTCHILD; b++) {
		if (node->childflag & (1 << b)) {
			child = &tmpnode;
			occ_node_from_face(tree->face + node->child[b].face, &tmpnode);
		}
		else {
			child = node->child[b].node;
		}

		if (child) {
			node->area += child->area;
			sh_add(node->sh, node->sh, child->sh);
			madd_v3_v3fl(node->co, child->co, child->area);
		}
	}

	if (node->area != 0.0f)
		mul_v3_fl(node->co, 1.0f / node->area);

	/* compute maximum distance from center */
	node->dco = 0.0f;
	if (node->area > 0.0f)
		occ_build_dco(tree, node, node->co, &node->dco);
}
Example #18
0
/* render call to fill in strands */
int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBase *apsmbase, unsigned int lay, int UNUSED(negzmask), float winmat[][4], int winx, int winy, int UNUSED(sample), float (*jit)[2], float clipcrop, int shadow, StrandShadeCache *cache)
{
	ObjectRen *obr;
	ObjectInstanceRen *obi;
	ZSpan zspan;
	StrandRen *strand=0;
	StrandVert *svert;
	StrandBound *sbound;
	StrandPart spart;
	StrandSegment sseg;
	StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg;
	MemArena *memarena;
	float z[4], bounds[4], obwinmat[4][4];
	int a, b, c, i, totsegment, clip[4];

	if (re->test_break(re->tbh))
		return 0;
	if (re->totstrand == 0)
		return 0;

	/* setup StrandPart */
	memset(&spart, 0, sizeof(spart));

	spart.re= re;
	spart.rectx= pa->rectx;
	spart.recty= pa->recty;
	spart.apixbuf= apixbuf;
	spart.zspan= &zspan;
	spart.rectdaps= pa->rectdaps;
	spart.rectz= pa->rectz;
	spart.rectmask= pa->rectmask;
	spart.cache= cache;
	spart.shadow= shadow;
	spart.jit= jit;

	zbuf_alloc_span(&zspan, pa->rectx, pa->recty, clipcrop);

	/* needed for transform from hoco to zbuffer co */
	zspan.zmulx= ((float)winx)/2.0f;
	zspan.zmuly= ((float)winy)/2.0f;
	
	zspan.zofsx= -pa->disprect.xmin;
	zspan.zofsy= -pa->disprect.ymin;

	/* to center the sample position */
	if (!shadow) {
		zspan.zofsx -= 0.5f;
		zspan.zofsy -= 0.5f;
	}

	zspan.apsmbase= apsmbase;

	/* clipping setup */
	bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx;
	bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx;
	bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy;
	bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy;

	memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "strand sort arena");
	firstseg= NULL;
	totsegment= 0;

	/* for all object instances */
	for (obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) {
		Material *ma;
		float widthx, widthy;

		obr= obi->obr;

		if (!obr->strandbuf || !(obr->strandbuf->lay & lay))
			continue;

		/* compute matrix and try clipping whole object */
		if (obi->flag & R_TRANSFORMED)
			mult_m4_m4m4(obwinmat, winmat, obi->mat);
		else
			copy_m4_m4(obwinmat, winmat);

		/* test if we should skip it */
		ma = obr->strandbuf->ma;

		if (shadow && !(ma->mode & MA_SHADBUF))
			continue;
		else if (!shadow && (ma->mode & MA_ONLYCAST))
			continue;

		if (clip_render_object(obi->obr->boundbox, bounds, obwinmat))
			continue;
		
		widthx= obr->strandbuf->maxwidth*obwinmat[0][0];
		widthy= obr->strandbuf->maxwidth*obwinmat[1][1];

		/* for each bounding box containing a number of strands */
		sbound= obr->strandbuf->bound;
		for (c=0; c<obr->strandbuf->totbound; c++, sbound++) {
			if (clip_render_object(sbound->boundbox, bounds, obwinmat))
				continue;

			/* for each strand in this bounding box */
			for (a=sbound->start; a<sbound->end; a++) {
				strand= RE_findOrAddStrand(obr, a);
				svert= strand->vert;

				/* keep clipping and z depth for 4 control points */
				clip[1]= strand_test_clip(obwinmat, &zspan, bounds, svert->co, &z[1], widthx, widthy);
				clip[2]= strand_test_clip(obwinmat, &zspan, bounds, (svert+1)->co, &z[2], widthx, widthy);
				clip[0]= clip[1]; z[0]= z[1];

				for (b=0; b<strand->totvert-1; b++, svert++) {
					/* compute 4th point clipping and z depth */
					if (b < strand->totvert-2) {
						clip[3]= strand_test_clip(obwinmat, &zspan, bounds, (svert+2)->co, &z[3], widthx, widthy);
					}
					else {
						clip[3]= clip[2]; z[3]= z[2];
					}

					/* check clipping and add to sortsegments buffer */
					if (!(clip[0] & clip[1] & clip[2] & clip[3])) {
						sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment));
						sortseg->obi= i;
						sortseg->strand= strand->index;
						sortseg->segment= b;

						sortseg->z= 0.5f*(z[1] + z[2]);

						sortseg->next= firstseg;
						firstseg= sortseg;
						totsegment++;
					}

					/* shift clipping and z depth */
					clip[0]= clip[1]; z[0]= z[1];
					clip[1]= clip[2]; z[1]= z[2];
					clip[2]= clip[3]; z[2]= z[3];
				}
			}
		}
	}

	if (!re->test_break(re->tbh)) {
		/* convert list to array and sort */
		sortsegments= MEM_mallocN(sizeof(StrandSortSegment)*totsegment, "StrandSortSegment");
		for (a=0, sortseg=firstseg; a<totsegment; a++, sortseg=sortseg->next)
			sortsegments[a]= *sortseg;
		qsort(sortsegments, totsegment, sizeof(StrandSortSegment), compare_strand_segment);
	}

	BLI_memarena_free(memarena);

	spart.totapixbuf= MEM_callocN(sizeof(int)*pa->rectx*pa->recty, "totapixbuf");

	if (!re->test_break(re->tbh)) {
		/* render segments in sorted order */
		sortseg= sortsegments;
		for (a=0; a<totsegment; a++, sortseg++) {
			if (re->test_break(re->tbh))
				break;

			obi= &re->objectinstance[sortseg->obi];
			obr= obi->obr;

			sseg.obi= obi;
			sseg.strand= RE_findOrAddStrand(obr, sortseg->strand);
			sseg.buffer= sseg.strand->buffer;
			sseg.sqadaptcos= sseg.buffer->adaptcos;
			sseg.sqadaptcos *= sseg.sqadaptcos;

			svert= sseg.strand->vert + sortseg->segment;
			sseg.v[0]= (sortseg->segment > 0)? (svert-1): svert;
			sseg.v[1]= svert;
			sseg.v[2]= svert+1;
			sseg.v[3]= (sortseg->segment < sseg.strand->totvert-2)? svert+2: svert+1;
			sseg.shaded= 0;

			spart.segment= &sseg;

			render_strand_segment(re, winmat, &spart, &zspan, 1, &sseg);
		}
	}

	if (sortsegments)
		MEM_freeN(sortsegments);
	MEM_freeN(spart.totapixbuf);
	
	zbuf_free_span(&zspan);

	return totsegment;
}
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
	LinearSolver *context;
	float vec[3], gridvec[3];
	int a, b, x, y, z, totvar;
	char message[256];

	/* setup variable indices */
	mdb->varidx = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformDSvaridx");
	for (a = 0, totvar = 0; a < mdb->size3; a++)
		mdb->varidx[a] = (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) ? -1 : totvar++;

	if (totvar == 0) {
		MEM_freeN(mdb->varidx);
		return;
	}

	progress_bar(0, "Starting mesh deform solve");

	/* setup linear solver */
	context = EIG_linear_solver_new(totvar, totvar, 1);

	/* build matrix */
	for (z = 0; z < mdb->size; z++)
		for (y = 0; y < mdb->size; y++)
			for (x = 0; x < mdb->size; x++)
				meshdeform_matrix_add_cell(mdb, context, x, y, z);

	/* solve for each cage vert */
	for (a = 0; a < mdb->totcagevert; a++) {
		/* fill in right hand side and solve */
		for (z = 0; z < mdb->size; z++)
			for (y = 0; y < mdb->size; y++)
				for (x = 0; x < mdb->size; x++)
					meshdeform_matrix_add_rhs(mdb, context, x, y, z, a);

		if (EIG_linear_solver_solve(context)) {
			for (z = 0; z < mdb->size; z++)
				for (y = 0; y < mdb->size; y++)
					for (x = 0; x < mdb->size; x++)
						meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);

			for (z = 0; z < mdb->size; z++)
				for (y = 0; y < mdb->size; y++)
					for (x = 0; x < mdb->size; x++)
						meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);

			for (b = 0; b < mdb->size3; b++) {
				if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
					mdb->phi[b] = EIG_linear_solver_variable_get(context, 0, mdb->varidx[b]);
				mdb->totalphi[b] += mdb->phi[b];
			}

			if (mdb->weights) {
				/* static bind : compute weights for each vertex */
				for (b = 0; b < mdb->totvert; b++) {
					if (mdb->inside[b]) {
						copy_v3_v3(vec, mdb->vertexcos[b]);
						gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
						gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
						gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];

						mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
					}
				}
			}
			else {
				MDefBindInfluence *inf;

				/* dynamic bind */
				for (b = 0; b < mdb->size3; b++) {
					if (mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
						inf = BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
						inf->vertex = a;
						inf->weight = mdb->phi[b];
						inf->next = mdb->dyngrid[b];
						mdb->dyngrid[b] = inf;
					}
				}
			}
		}
		else {
			modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
			error("Mesh Deform: failed to find bind solution.");
			break;
		}

		BLI_snprintf(message, sizeof(message), "Mesh deform solve %d / %d       |||", a + 1, mdb->totcagevert);
		progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
	}

#if 0
	/* sanity check */
	for (b = 0; b < mdb->size3; b++)
		if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
			if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
				printf("totalphi deficiency [%s|%d] %d: %.10f\n",
				       (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
#endif
	
	/* free */
	MEM_freeN(mdb->varidx);

	EIG_linear_solver_delete(context);
}
Example #20
0
static ImGlobalTile *imb_global_cache_get_tile(ImBuf *ibuf, int tx, int ty, ImGlobalTile *replacetile)
{
	ImGlobalTile *gtile, lookuptile;

	BLI_mutex_lock(&GLOBAL_CACHE.mutex);

	if(replacetile)
		replacetile->refcount--;

	/* find tile in global cache */
	lookuptile.ibuf = ibuf;
	lookuptile.tx = tx;
	lookuptile.ty = ty;
	gtile= BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile);
	
	if(gtile) {
		/* found tile. however it may be in the process of being loaded
		   by another thread, in that case we do stupid busy loop waiting
		   for the other thread to load the tile */
		gtile->refcount++;

		BLI_mutex_unlock(&GLOBAL_CACHE.mutex);

		while(gtile->loading)
			;
	}
	else {
		/* not found, let's load it from disk */

		/* first check if we hit the memory limit */
		if(GLOBAL_CACHE.maxmem && GLOBAL_CACHE.totmem > GLOBAL_CACHE.maxmem) {
			/* find an existing tile to unload */
			for(gtile=GLOBAL_CACHE.tiles.last; gtile; gtile=gtile->prev)
				if(gtile->refcount == 0 && gtile->loading == 0)
					break;
		}

		if(gtile) {
			/* found a tile to unload */
			imb_global_cache_tile_unload(gtile);
			BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL);
			BLI_remlink(&GLOBAL_CACHE.tiles, gtile);
		}
		else {
			/* allocate a new tile or reuse unused */
			if(GLOBAL_CACHE.unused.first) {
				gtile= GLOBAL_CACHE.unused.first;
				BLI_remlink(&GLOBAL_CACHE.unused, gtile);
			}
			else
				gtile= BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile));
		}

		/* setup new tile */
		gtile->ibuf= ibuf;
		gtile->tx= tx;
		gtile->ty= ty;
		gtile->refcount= 1;
		gtile->loading= 1;

		BLI_ghash_insert(GLOBAL_CACHE.tilehash, gtile, gtile);
		BLI_addhead(&GLOBAL_CACHE.tiles, gtile);

		/* mark as being loaded and unlock to allow other threads to load too */
		GLOBAL_CACHE.totmem += sizeof(unsigned int)*ibuf->tilex*ibuf->tiley;

		BLI_mutex_unlock(&GLOBAL_CACHE.mutex);

		/* load from disk */
		imb_global_cache_tile_load(gtile);

		/* mark as done loading */
		gtile->loading= 0;
	}

	return gtile;
}
/**
 * The intention is that this calculates the output of #BLI_polyfill_calc
 *
 *
 * \note assumes the \a coords form a boundary,
 * so any edges running along contiguous (wrapped) indices,
 * are ignored since the edges wont share 2 faces.
 */
void BLI_polyfill_beautify(
    const float (*coords)[2],
    const unsigned int coords_tot,
    unsigned int (*tris)[3],

    /* structs for reuse */
    MemArena *arena, Heap *eheap, EdgeHash *ehash)
{
    const unsigned int coord_last = coords_tot - 1;
    const unsigned int tris_tot = coords_tot - 2;
    /* internal edges only (between 2 tris) */
    const unsigned int edges_tot = tris_tot - 1;
    unsigned int edges_tot_used = 0;
    unsigned int i;

    HeapNode **eheap_table;

    struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges));

    BLI_assert(BLI_heap_size(eheap) == 0);
    BLI_assert(BLI_edgehash_size(ehash) == 0);

    /* first build edges */
    for (i = 0; i < tris_tot; i++) {
        unsigned int j_prev, j_curr, j_next;
        j_prev = 2;
        j_next = 1;
        for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) {
            int e_index;

            unsigned int e_pair[2] = {
                tris[i][j_prev],
                tris[i][j_curr],
            };

            if (e_pair[0] > e_pair[1]) {
                SWAP(unsigned int, e_pair[0], e_pair[1]);
                e_index = 1;
            }
            else {
                e_index = 0;
            }

            if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) {
                struct PolyEdge *e;
                void **val_p;

                if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) {
                    e = &edges[edges_tot_used++];
                    *val_p = e;
                    memcpy(e->verts, e_pair, sizeof(e->verts));
#ifndef NDEBUG
                    e->faces[!e_index] = (unsigned int)-1;
#endif
                }
                else {
                    e = *val_p;
                    /* ensure each edge only ever has 2x users */
#ifndef NDEBUG
                    BLI_assert(e->faces[e_index] == (unsigned int)-1);
                    BLI_assert((e->verts[0] == e_pair[0]) &&
                               (e->verts[1] == e_pair[1]));
#endif
                }

                e->faces[e_index] = i;
                e->faces_other_v[e_index] = j_next;
            }
        }
    }

    /* now perform iterative rotations */
    eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot);

    // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); }

    /* build heap */
    for (i = 0; i < edges_tot; i++) {
        struct PolyEdge *e = &edges[i];
        const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e);
        if (cost < 0.0f) {
            eheap_table[i] = BLI_heap_insert(eheap, cost, e);
        }
        else {
            eheap_table[i] = NULL;
        }
    }

    while (BLI_heap_is_empty(eheap) == false) {
        struct PolyEdge *e = BLI_heap_popmin(eheap);
        i = (unsigned int)(e - edges);
        eheap_table[i] = NULL;

        polyedge_rotate(tris, e, ehash);

        /* recalculate faces connected on the heap */
        polyedge_beauty_cost_update(
            coords, (const unsigned int (*)[3])tris, edges,
            e,
            eheap, eheap_table, ehash);
    }

    BLI_heap_clear(eheap, NULL);
    BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);

    /* MEM_freeN(eheap_table); */  /* arena */
}
/* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */
float *BME_new_transdata_float(BME_TransData_Head *td) {
	return BLI_memarena_alloc(td->ma, sizeof(float));
}