Beispiel #1
0
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated)
{
	Object *ob, *ob_iter;
	Base *base = NULL;
	DupliObject *dob;
	DerivedMesh *dm;
	Mesh *me= par->data;
	MTFace *mtface;
	MFace *mface;
	MVert *mvert;
	float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w;
	int lay, oblay, totface, a;
	Scene *sce = NULL;
	Group *group = NULL;
	GroupObject *go = NULL;
	EditMesh *em;
	float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
	
	/* simple preventing of too deep nested groups */
	if(level>MAX_DUPLI_RECUR) return;
	
	Mat4CpyMat4(pmat, par->obmat);
	
	em = BKE_mesh_get_editmesh(me);
	if(em) {
		int totvert;
		
		dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
		dm->copyFaceArray(dm, mface);
		totvert= dm->getNumVerts(dm);
		mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
		dm->copyVertArray(dm, mvert);

		BKE_mesh_end_editmesh(me, em);
	}
	else {
		dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= dm->getFaceArray(dm);
		mvert= dm->getVertArray(dm);
	}

	if(G.rendering) {

		orco= (float(*)[3])get_mesh_orco_verts(par);
		transform_mesh_orco_verts(me, orco, me->totvert, 0);
		mtface= me->mtface;
	}
	else {
		orco= NULL;
		mtface= NULL;
	}
	
	/* having to loop on scene OR group objects is NOT FUN */
	if (GS(id->name) == ID_SCE) {
		sce = (Scene *)id;
		lay= sce->lay;
		base= sce->base.first;
	} else {
		group = (Group *)id;
		lay= group->layer;
		go = group->gobject.first;
	}
	
	/* Start looping on Scene OR Group objects */
	while (base || go) { 
		if (sce) {
			ob_iter= base->object;
			oblay = base->lay;
		} else {
			ob_iter= go->ob;
			oblay = ob_iter->lay;
		}
		
		if (lay & oblay && scene->obedit!=ob_iter) {
			ob=ob_iter->parent;
			while(ob) {
				if(ob==par) {
					ob = ob_iter;
	/* End Scene/Group object loop, below is generic */
					
					/* par_space_mat - only used for groups so we can modify the space dupli's are in
					   when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
					*/
					if(par_space_mat)
						Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat);
					else
						Mat4CpyMat4(ob__obmat, ob->obmat);
					
					Mat3CpyMat4(imat, ob->parentinv);
						
					/* mballs have a different dupli handling */
					if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;	/* doesnt render */

					for(a=0; a<totface; a++) {
						int mv1 = mface[a].v1;
						int mv2 = mface[a].v2;
						int mv3 = mface[a].v3;
						int mv4 = mface[a].v4;
						float *v1= mvert[mv1].co;
						float *v2= mvert[mv2].co;
						float *v3= mvert[mv3].co;
						float *v4= (mv4)? mvert[mv4].co: NULL;
						float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];

						/* translation */
						if(v4)
							CalcCent4f(cent, v1, v2, v3, v4);
						else
							CalcCent3f(cent, v1, v2, v3);
						Mat4MulVecfl(pmat, cent);
						
						VecSubf(cent, cent, pmat[3]);
						VecAddf(cent, cent, ob__obmat[3]);
						
						Mat4CpyMat4(obmat, ob__obmat);
						
						VECCOPY(obmat[3], cent);
						
						/* rotation */
						triatoquat(v1, v2, v3, quat);
						QuatToMat3(quat, mat);
						
						/* scale */
						if(par->transflag & OB_DUPLIFACES_SCALE) {
							float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3);
							size= sqrt(size) * par->dupfacesca;
							Mat3MulFloat(mat[0], size);
						}
						
						Mat3CpyMat3(mat3, mat);
						Mat3MulMat3(mat, imat, mat3);
						
						Mat4CpyMat4(tmat, obmat);
						Mat4MulMat43(obmat, tmat, mat);
						
						dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated);
						if(G.rendering) {
							w= (mv4)? 0.25f: 1.0f/3.0f;

							if(orco) {
								VECADDFAC(dob->orco, dob->orco, orco[mv1], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv2], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv3], w);
								if(mv4)
									VECADDFAC(dob->orco, dob->orco, orco[mv4], w);
							}

							if(mtface) {
								dob->uv[0] += w*mtface[a].uv[0][0];
								dob->uv[1] += w*mtface[a].uv[0][1];
								dob->uv[0] += w*mtface[a].uv[1][0];
								dob->uv[1] += w*mtface[a].uv[1][1];
								dob->uv[0] += w*mtface[a].uv[2][0];
								dob->uv[1] += w*mtface[a].uv[2][1];

								if(mv4) {
									dob->uv[0] += w*mtface[a].uv[3][0];
									dob->uv[1] += w*mtface[a].uv[3][1];
								}
							}
						}
						
						if(ob->transflag & OB_DUPLI) {
							float tmpmat[4][4];
							Mat4CpyMat4(tmpmat, ob->obmat);
							Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated);
							Mat4CpyMat4(ob->obmat, tmpmat);
						}
					}
					
					break;
				}
				ob= ob->parent;
			}
		}
		if (sce)	base= base->next;	/* scene loop */
		else		go= go->next;		/* group loop */
	}
	
	if(par->mode & OB_MODE_EDIT) {
		MEM_freeN(mface);
		MEM_freeN(mvert);
	}

	if(orco)
		MEM_freeN(orco);
	
	dm->release(dm);
}
Beispiel #2
0
/**
 * This function populates an array of verts for the triangles of a mesh
 * Tangent and Normals are also stored
 */
static TriTessFace *mesh_calc_tri_tessface(
        Mesh *me, bool tangent, DerivedMesh *dm)
{
	int i;
	MVert *mvert;
	TSpace *tspace;
	float *precomputed_normals = NULL;
	bool calculate_normal;

	const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
	MLoopTri *looptri;
	TriTessFace *triangles;

	/* calculate normal for each polygon only once */
	unsigned int mpoly_prev = UINT_MAX;
	float no[3];

	mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
	looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
	triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);

	if (tangent) {
		DM_ensure_normals(dm);
		DM_calc_loop_tangents(dm);

		precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
		calculate_normal = precomputed_normals ? false : true;

		tspace = dm->getLoopDataArray(dm, CD_TANGENT);
		BLI_assert(tspace);
	}

	BKE_mesh_recalc_looptri(
	            me->mloop, me->mpoly,
	            me->mvert,
	            me->totloop, me->totpoly,
	            looptri);

	for (i = 0; i < tottri; i++) {
		MLoopTri *lt = &looptri[i];
		MPoly *mp = &me->mpoly[lt->poly];

		triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
		triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
		triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
		triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0;

		if (tangent) {
			triangles[i].tspace[0] = &tspace[lt->tri[0]];
			triangles[i].tspace[1] = &tspace[lt->tri[1]];
			triangles[i].tspace[2] = &tspace[lt->tri[2]];

			if (calculate_normal) {
				if (lt->poly != mpoly_prev) {
					const MPoly *mp = &me->mpoly[lt->poly];
					BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
					mpoly_prev = lt->poly;
				}
				copy_v3_v3(triangles[i].normal, no);
			}
			else {
				copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
			}
		}
	}

	MEM_freeN(looptri);

	return triangles;
}
Beispiel #3
0
void RE_bake_pixels_populate(
        Mesh *me, BakePixel pixel_array[],
        const size_t num_pixels, const BakeImages *bake_images, const char *uv_layer)
{
	BakeDataZSpan bd;
	size_t i;
	int a, p_id;

	const MLoopUV *mloopuv;
	const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
	MLoopTri *looptri;

	/* we can't bake in edit mode */
	if (me->edit_btmesh)
		return;

	bd.pixel_array = pixel_array;
	bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");

	/* initialize all pixel arrays so we know which ones are 'blank' */
	for (i = 0; i < num_pixels; i++) {
		pixel_array[i].primitive_id = -1;
	}

	for (i = 0; i < bake_images->size; i++) {
		zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height, R.clipcrop);
	}

	if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
		mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
	}
	else {
		int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
		mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
	}

	if (mloopuv == NULL)
		return;

	looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);

	BKE_mesh_recalc_looptri(
	        me->mloop, me->mpoly,
	        me->mvert,
	        me->totloop, me->totpoly,
	        looptri);

	p_id = -1;
	for (i = 0; i < tottri; i++) {
		const MLoopTri *lt = &looptri[i];
		const MPoly *mp = &me->mpoly[lt->poly];
		float vec[3][2];
		int mat_nr = mp->mat_nr;
		int image_id = bake_images->lookup[mat_nr];

		bd.bk_image = &bake_images->data[image_id];
		bd.primitive_id = ++p_id;

		for (a = 0; a < 3; a++) {
			const float *uv = mloopuv[lt->tri[a]].uv;

			/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
			 * where a pixel gets in between 2 faces or the middle of a quad,
			 * camera aligned quads also have this problem but they are less common.
			 * Add a small offset to the UVs, fixes bug #18685 - Campbell */
			vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
			vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
		}

		bake_differentials(&bd, vec[0], vec[1], vec[2]);
		zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
	}

	for (i = 0; i < bake_images->size; i++) {
		zbuf_free_span(&bd.zspan[i]);
	}

	MEM_freeN(looptri);
	MEM_freeN(bd.zspan);
}
Beispiel #4
0
static void waveModifier_do(WaveModifierData *md, 
                            Scene *scene, Object *ob, DerivedMesh *dm,
                            float (*vertexCos)[3], int numVerts)
{
	WaveModifierData *wmd = (WaveModifierData *) md;
	MVert *mvert = NULL;
	MDeformVert *dvert;
	int defgrp_index;
	float ctime = BKE_scene_frame_get(scene);
	float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
	float lifefac = wmd->height;
	float (*tex_co)[3] = NULL;
	const int wmd_axis = wmd->flag & (MOD_WAVE_X | MOD_WAVE_Y);
	const float falloff = wmd->falloff;
	float falloff_fac = 1.0f; /* when falloff == 0.0f this stays at 1.0f */

	if ((wmd->flag & MOD_WAVE_NORM) && (ob->type == OB_MESH))
		mvert = dm->getVertArray(dm);

	if (wmd->objectcenter) {
		float mat[4][4];
		/* get the control object's location in local coordinates */
		invert_m4_m4(ob->imat, ob->obmat);
		mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat);

		wmd->startx = mat[3][0];
		wmd->starty = mat[3][1];
	}

	/* get the index of the deform group */
	modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);

	if (wmd->damp == 0) wmd->damp = 10.0f;

	if (wmd->lifetime != 0.0f) {
		float x = ctime - wmd->timeoffs;

		if (x > wmd->lifetime) {
			lifefac = x - wmd->lifetime;

			if (lifefac > wmd->damp) lifefac = 0.0;
			else lifefac = (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp)));
		}
	}

	if (wmd->texture) {
		tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
		                     "waveModifier_do tex_co");
		get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);

		modifier_init_texture(wmd->modifier.scene, wmd->texture);
	}

	if (lifefac != 0.0f) {
		/* avoid divide by zero checks within the loop */
		float falloff_inv = falloff ? 1.0f / falloff : 1.0f;
		int i;

		for (i = 0; i < numVerts; i++) {
			float *co = vertexCos[i];
			float x = co[0] - wmd->startx;
			float y = co[1] - wmd->starty;
			float amplit = 0.0f;
			float def_weight = 1.0f;

			/* get weights */
			if (dvert) {
				def_weight = defvert_find_weight(&dvert[i], defgrp_index);

				/* if this vert isn't in the vgroup, don't deform it */
				if (def_weight == 0.0f) {
					continue;
				}
			}

			switch (wmd_axis) {
				case MOD_WAVE_X | MOD_WAVE_Y:
					amplit = sqrtf(x * x + y * y);
					break;
				case MOD_WAVE_X:
					amplit = x;
					break;
				case MOD_WAVE_Y:
					amplit = y;
					break;
			}

			/* this way it makes nice circles */
			amplit -= (ctime - wmd->timeoffs) * wmd->speed;

			if (wmd->flag & MOD_WAVE_CYCL) {
				amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width) +
				         wmd->width;
			}

			if (falloff != 0.0f) {
				float dist = 0.0f;

				switch (wmd_axis) {
					case MOD_WAVE_X | MOD_WAVE_Y:
						dist = sqrtf(x * x + y * y);
						break;
					case MOD_WAVE_X:
						dist = fabsf(x);
						break;
					case MOD_WAVE_Y:
						dist = fabsf(y);
						break;
				}

				falloff_fac = (1.0f - (dist * falloff_inv));
				CLAMP(falloff_fac, 0.0f, 1.0f);
			}

			/* GAUSSIAN */
			if ((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) {
				amplit = amplit * wmd->narrow;
				amplit = (float)(1.0f / expf(amplit * amplit) - minfac);

				/*apply texture*/
				if (wmd->texture) {
					TexResult texres;
					texres.nor = NULL;
					BKE_texture_get_value(wmd->modifier.scene, wmd->texture, tex_co[i], &texres, false);
					amplit *= texres.tin;
				}

				/*apply weight & falloff */
				amplit *= def_weight * falloff_fac;

				if (mvert) {
					/* move along normals */
					if (wmd->flag & MOD_WAVE_NORM_X) {
						co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
					}
					if (wmd->flag & MOD_WAVE_NORM_Y) {
						co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
					}
					if (wmd->flag & MOD_WAVE_NORM_Z) {
						co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
					}
				}
				else {
					/* move along local z axis */
					co[2] += lifefac * amplit;
				}
			}
		}
	}

	if (wmd->texture) MEM_freeN(tex_co);
}
Beispiel #5
0
BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
{
	BLI_mempool *pool = NULL;
	BLI_freenode *lasttail = NULL, *curnode = NULL;
	int i, j, maxchunks;
	char *addr;

	/* allocate the pool structure */
	if (flag & BLI_MEMPOOL_SYSMALLOC) {
		pool = malloc(sizeof(BLI_mempool));
	}
	else {
		pool = MEM_mallocN(sizeof(BLI_mempool), "memory pool");
	}

	/* set the elem size */
	if (esize < MEMPOOL_ELEM_SIZE_MIN) {
		esize = MEMPOOL_ELEM_SIZE_MIN;
	}

	if (flag & BLI_MEMPOOL_ALLOW_ITER) {
		pool->esize = MAX2(esize, (int)sizeof(BLI_freenode));
	}
	else {
		pool->esize = esize;
	}

	pool->flag = flag;
	pool->pchunk = pchunk;
	pool->csize = esize * pchunk;
	pool->chunks.first = pool->chunks.last = NULL;
	pool->totalloc = 0;
	pool->totused = 0;

	maxchunks = totelem / pchunk + 1;
	if (maxchunks == 0) {
		maxchunks = 1;
	}

	/* allocate the actual chunks */
	for (i = 0; i < maxchunks; i++) {
		BLI_mempool_chunk *mpchunk;

		if (flag & BLI_MEMPOOL_SYSMALLOC) {
			mpchunk = malloc(sizeof(BLI_mempool_chunk));
			mpchunk->data = malloc((size_t)pool->csize);
		}
		else {
			mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
			mpchunk->data = MEM_mallocN((size_t)pool->csize, "BLI Mempool Chunk Data");
		}

		mpchunk->next = mpchunk->prev = NULL;
		BLI_addtail(&(pool->chunks), mpchunk);

		if (i == 0) {
			pool->free = mpchunk->data; /* start of the list */
			if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
				pool->free->freeword = FREEWORD;
			}
		}

		/* loop through the allocated data, building the pointer structures */
		for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) {
			curnode = ((BLI_freenode *)addr);
			addr += pool->esize;
			curnode->next = (BLI_freenode *)addr;
			if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
				if (j != pool->pchunk - 1)
					curnode->next->freeword = FREEWORD;
				curnode->freeword = FREEWORD;
			}
		}
		/* final pointer in the previously allocated chunk is wrong */
		if (lasttail) {
			lasttail->next = mpchunk->data;
			if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
				lasttail->freeword = FREEWORD;
			}
		}

		/* set the end of this chunks memory to the new tail for next iteration */
		lasttail = curnode;
#ifdef USE_TOTALLOC
		pool->totalloc += pool->pchunk;
#endif
	}
	/* terminate the list */
	curnode->next = NULL;
	return pool;
}
Beispiel #6
0
void render_view3d_draw(RenderEngine *engine, const bContext *C)
{
	Render *re = engine->re;
	RenderResult rres;
	char name[32];
	
	render_view3d_do(engine, C);
	
	if (re == NULL) {
		sprintf(name, "View3dPreview %p", (void *)CTX_wm_region(C));
		re = RE_GetRender(name);
	
		if (re == NULL) return;
	}
	
	RE_AcquireResultImage(re, &rres);
	
	if (rres.rectf) {
		Scene *scene = CTX_data_scene(C);
		bool force_fallback = false;
		bool need_fallback = true;
		float dither = scene->r.dither_intensity;

		/* Dithering is not supported on GLSL yet */
		force_fallback |= dither != 0.0f;

		/* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
		force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);

		/* Try using GLSL display transform. */
		if (force_fallback == false) {
			if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) {
				glEnable(GL_BLEND);
				glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
				glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
				                 GL_LINEAR, rres.rectf);
				glDisable(GL_BLEND);

				IMB_colormanagement_finish_glsl_draw();
				need_fallback = false;
			}
		}

		/* If GLSL failed, use old-school CPU-based transform. */
		if (need_fallback) {
			unsigned char *display_buffer = MEM_mallocN(4 * rres.rectx * rres.recty * sizeof(char),
			                                            "render_view3d_draw");

			IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty,
			                                              4, dither, NULL, &scene->display_settings);

			glEnable(GL_BLEND);
			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
			glaDrawPixelsAuto(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE,
			                  GL_LINEAR, display_buffer);
			glDisable(GL_BLEND);

			MEM_freeN(display_buffer);
		}
	}

	RE_ReleaseResultImage(re);
}
Beispiel #7
0
/**
 * Main boxpacking function accessed from other functions
 * This sets boxes x,y to positive values, sorting from 0,0 outwards.
 * There is no limit to the space boxes may take, only that they will be packed
 * tightly into the lower left hand corner (0,0)
 *
 * \param boxarray: a pre allocated array of boxes.
 *      only the 'box->x' and 'box->y' are set, 'box->w' and 'box->h' are used,
 *      'box->index' is not used at all, the only reason its there
 *          is that the box array is sorted by area and programs need to be able
 *          to have some way of writing the boxes back to the original data.
 * \param len: the number of boxes in the array.
 * \param r_tot_x, r_tot_y: set so you can normalize the data.
 *  */
void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r_tot_y)
{
	uint box_index, verts_pack_len, i, j, k;
	uint *vertex_pack_indices;  /* an array of indices used for sorting verts */
	bool isect;
	float tot_x = 0.0f, tot_y = 0.0f;

	BoxPack *box, *box_test; /*current box and another for intersection tests*/
	BoxVert *vert; /* the current vert */

	struct VertSortContext vs_ctx;

	if (!len) {
		*r_tot_x = tot_x;
		*r_tot_y = tot_y;
		return;
	}

	/* Sort boxes, biggest first */
	qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);

	/* add verts to the boxes, these are only used internally  */
	vert = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts");
	vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices");

	vs_ctx.vertarray = vert;

	for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) {

		vert->blb = vert->brb = vert->tlb =
		            vert->isect_cache[0] = vert->isect_cache[1] =
		            vert->isect_cache[2] = vert->isect_cache[3] = NULL;
		vert->free = CORNERFLAGS & ~TRF;
		vert->trb = box;
		vert->used = false;
		vert->index = i++;
		box->v[BL] = vert++;

		vert->trb = vert->brb = vert->tlb =
		            vert->isect_cache[0] = vert->isect_cache[1] =
		            vert->isect_cache[2] = vert->isect_cache[3] = NULL;
		vert->free = CORNERFLAGS & ~BLF;
		vert->blb = box;
		vert->used = false;
		vert->index = i++;
		box->v[TR] = vert++;

		vert->trb = vert->blb = vert->tlb =
		            vert->isect_cache[0] = vert->isect_cache[1] =
		            vert->isect_cache[2] = vert->isect_cache[3] = NULL;
		vert->free = CORNERFLAGS & ~BRF;
		vert->brb = box;
		vert->used = false;
		vert->index = i++;
		box->v[TL] = vert++;

		vert->trb = vert->blb = vert->brb =
		            vert->isect_cache[0] = vert->isect_cache[1] =
		            vert->isect_cache[2] = vert->isect_cache[3] = NULL;
		vert->free = CORNERFLAGS & ~TLF;
		vert->tlb = box;
		vert->used = false;
		vert->index = i++;
		box->v[BR] = vert++;
	}
	vert = NULL;

	/* Pack the First box!
	 * then enter the main box-packing loop */

	box = boxarray; /* get the first box  */
	/* First time, no boxes packed */
	box->v[BL]->free = 0; /* Can't use any if these */
	box->v[BR]->free &= ~(BLF | BRF);
	box->v[TL]->free &= ~(BLF | TLF);

	tot_x = box->w;
	tot_y = box->h;

	/* This sets all the vertex locations */
	box_xmin_set(box, 0.0f);
	box_ymin_set(box, 0.0f);
	box->x = box->y = 0.0f;

	for (i = 0; i < 4; i++) {
		box->v[i]->used = true;
#ifdef USE_PACK_BIAS
		vert_bias_update(box->v[i]);
#endif
	}

	for (i = 0; i < 3; i++)
		vertex_pack_indices[i] = box->v[i + 1]->index;
	verts_pack_len = 3;
	box++; /* next box, needed for the loop below */
	/* ...done packing the first box */

	/* Main boxpacking loop */
	for (box_index = 1; box_index < len; box_index++, box++) {

		/* These floats are used for sorting re-sorting */
		vs_ctx.box_width = box->w;
		vs_ctx.box_height = box->h;

		qsort_r(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort, &vs_ctx);

#ifdef USE_FREE_STRIP
		/* strip free vertices */
		i = verts_pack_len - 1;
		while ((i != 0) && vs_ctx.vertarray[vertex_pack_indices[i]].free == 0) {
			i--;
		}
		verts_pack_len = i + 1;
#endif

		/* Pack the box in with the others */
		/* sort the verts */
		isect = true;

		for (i = 0; i < verts_pack_len && isect; i++) {
			vert = &vs_ctx.vertarray[vertex_pack_indices[i]];
			/* printf("\ttesting vert %i %i %i %f %f\n", i,
			 *        vert->free, verts_pack_len, vert->x, vert->y); */

			/* This vert has a free quadrant
			 * Test if we can place the box here
			 * vert->free & quad_flags[j] - Checks
			 * */

			for (j = 0; (j < 4) && isect; j++) {
				if (vert->free & quad_flag(j)) {
					switch (j) {
						case BL:
							box_xmax_set(box, vert->x);
							box_ymax_set(box, vert->y);
							break;
						case TR:
							box_xmin_set(box, vert->x);
							box_ymin_set(box, vert->y);
							break;
						case TL:
							box_xmax_set(box, vert->x);
							box_ymin_set(box, vert->y);
							break;
						case BR:
							box_xmin_set(box, vert->x);
							box_ymax_set(box, vert->y);
							break;
					}

					/* Now we need to check that the box intersects
					 * with any other boxes
					 * Assume no intersection... */
					isect = false;

					if ( /* Constrain boxes to positive X/Y values */
					    box_xmin_get(box) < 0.0f || box_ymin_get(box) < 0.0f ||
					    /* check for last intersected */
					    (vert->isect_cache[j] &&
					     box_isect(box, vert->isect_cache[j])))
					{
						/* Here we check that the last intersected
						 * box will intersect with this one using
						 * isect_cache that can store a pointer to a
						 * box for each quadrant
						 * big speedup */
						isect = true;
					}
					else {
						/* do a full search for colliding box
						 * this is really slow, some spatially divided
						 * data-structure would be better */
						for (box_test = boxarray; box_test != box; box_test++) {
							if (box_isect(box, box_test)) {
								/* Store the last intersecting here as cache
								 * for faster checking next time around */
								vert->isect_cache[j] = box_test;
								isect = true;
								break;
							}
						}
					}

					if (!isect) {

						/* maintain the total width and height */
						tot_x = max_ff(box_xmax_get(box), tot_x);
						tot_y = max_ff(box_ymax_get(box), tot_y);

						/* Place the box */
						vert->free &= (signed char)(~quad_flag(j));

						switch (j) {
							case TR:
								box->v[BL] = vert;
								vert->trb = box;
								break;
							case TL:
								box->v[BR] = vert;
								vert->tlb = box;
								break;
							case BR:
								box->v[TL] = vert;
								vert->brb = box;
								break;
							case BL:
								box->v[TR] = vert;
								vert->blb = box;
								break;
						}

						/* Mask free flags for verts that are
						 * on the bottom or side so we don't get
						 * boxes outside the given rectangle ares
						 *
						 * We can do an else/if here because only the first
						 * box can be at the very bottom left corner */
						if (box_xmin_get(box) <= 0) {
							box->v[TL]->free &= ~(TLF | BLF);
							box->v[BL]->free &= ~(TLF | BLF);
						}
						else if (box_ymin_get(box) <= 0) {
							box->v[BL]->free &= ~(BRF | BLF);
							box->v[BR]->free &= ~(BRF | BLF);
						}

						/* The following block of code does a logical
						 * check with 2 adjacent boxes, its possible to
						 * flag verts on one or both of the boxes
						 * as being used by checking the width or
						 * height of both boxes */
						if (vert->tlb && vert->trb && (box == vert->tlb || box == vert->trb)) {
							if (UNLIKELY(fabsf(vert->tlb->h - vert->trb->h) < EPSILON_MERGE)) {
#ifdef USE_MERGE
#  define A (vert->trb->v[TL])
#  define B (vert->tlb->v[TR])
#  define MASK (BLF | BRF)
								BLI_assert(A->used != B->used);
								if (A->used) {
									A->free &= B->free & ~MASK;
									B = A;
								}
								else {
									B->free &= A->free & ~MASK;
									A = B;
								}
								BLI_assert((A->free & MASK) == 0);
#  undef A
#  undef B
#  undef MASK
#else
								vert->tlb->v[TR]->free &= ~BLF;
								vert->trb->v[TL]->free &= ~BRF;
#endif
							}
							else if (vert->tlb->h > vert->trb->h) {
								vert->trb->v[TL]->free &= ~(TLF | BLF);
							}
							else /* if (vert->tlb->h < vert->trb->h) */ {
								vert->tlb->v[TR]->free &= ~(TRF | BRF);
							}
						}
						else if (vert->blb && vert->brb && (box == vert->blb || box == vert->brb)) {
							if (UNLIKELY(fabsf(vert->blb->h - vert->brb->h) < EPSILON_MERGE)) {
#ifdef USE_MERGE
#  define A (vert->blb->v[BR])
#  define B (vert->brb->v[BL])
#  define MASK (TRF | TLF)
								BLI_assert(A->used != B->used);
								if (A->used) {
									A->free &= B->free & ~MASK;
									B = A;
								}
								else {
									B->free &= A->free & ~MASK;
									A = B;
								}
								BLI_assert((A->free & MASK) == 0);
#  undef A
#  undef B
#  undef MASK
#else
								vert->blb->v[BR]->free &= ~TRF;
								vert->brb->v[BL]->free &= ~TLF;
#endif
							}
							else if (vert->blb->h > vert->brb->h) {
								vert->brb->v[BL]->free &= ~(TLF | BLF);
							}
							else /* if (vert->blb->h < vert->brb->h) */ {
								vert->blb->v[BR]->free &= ~(TRF | BRF);
							}
						}
						/* Horizontal */
						if (vert->tlb && vert->blb && (box == vert->tlb || box == vert->blb)) {
							if (UNLIKELY(fabsf(vert->tlb->w - vert->blb->w) < EPSILON_MERGE)) {
#ifdef USE_MERGE
#  define A (vert->blb->v[TL])
#  define B (vert->tlb->v[BL])
#  define MASK (TRF | BRF)
								BLI_assert(A->used != B->used);
								if (A->used) {
									A->free &= B->free & ~MASK;
									B = A;
								}
								else {
									B->free &= A->free & ~MASK;
									A = B;
								}
								BLI_assert((A->free & MASK) == 0);
#  undef A
#  undef B
#  undef MASK
#else
								vert->blb->v[TL]->free &= ~TRF;
								vert->tlb->v[BL]->free &= ~BRF;
#endif
							}
							else if (vert->tlb->w > vert->blb->w) {
								vert->blb->v[TL]->free &= ~(TLF | TRF);
							}
							else /* if (vert->tlb->w < vert->blb->w) */ {
								vert->tlb->v[BL]->free &= ~(BLF | BRF);
							}
						}
						else if (vert->trb && vert->brb && (box == vert->trb || box == vert->brb)) {
							if (UNLIKELY(fabsf(vert->trb->w - vert->brb->w) < EPSILON_MERGE)) {

#ifdef USE_MERGE
#  define A (vert->brb->v[TR])
#  define B (vert->trb->v[BR])
#  define MASK (TLF | BLF)
								BLI_assert(A->used != B->used);
								if (A->used) {
									A->free &= B->free & ~MASK;
									B = A;
								}
								else {
									B->free &= A->free & ~MASK;
									A = B;
								}
								BLI_assert((A->free & MASK) == 0);
#  undef A
#  undef B
#  undef MASK
#else
								vert->brb->v[TR]->free &= ~TLF;
								vert->trb->v[BR]->free &= ~BLF;
#endif
							}
							else if (vert->trb->w > vert->brb->w) {
								vert->brb->v[TR]->free &= ~(TLF | TRF);
							}
							else /* if (vert->trb->w < vert->brb->w) */ {
								vert->trb->v[BR]->free &= ~(BLF | BRF);
							}
						}
						/* End logical check */

						for (k = 0; k < 4; k++) {
							if (box->v[k]->used == false) {
								box->v[k]->used = true;
#ifdef USE_PACK_BIAS
								vert_bias_update(box->v[k]);
#endif
								vertex_pack_indices[verts_pack_len] = box->v[k]->index;
								verts_pack_len++;
							}
						}
						/* The Box verts are only used internally
						 * Update the box x and y since thats what external
						 * functions will see */
						box->x = box_xmin_get(box);
						box->y = box_ymin_get(box);
					}
				}
			}
		}
	}

	*r_tot_x = tot_x;
	*r_tot_y = tot_y;

	/* free all the verts, not really needed because they shouldn't be
	 * touched anymore but accessing the pointers would crash blender */
	for (box_index = 0; box_index < len; box_index++) {
		box = boxarray + box_index;
		box->v[0] = box->v[1] = box->v[2] = box->v[3] = NULL;
	}
	MEM_freeN(vertex_pack_indices);
	MEM_freeN(vs_ctx.vertarray);
}
Beispiel #8
0
/* get a GPUBuffer of at least `size' bytes; uses one from the buffer
   pool if possible, otherwise creates a new one */
GPUBuffer *GPU_buffer_alloc(int size)
{
	GPUBufferPool *pool;
	GPUBuffer *buf;
	int i, bufsize, bestfit = -1;

	pool = gpu_get_global_buffer_pool();

	/* not sure if this buffer pool code has been profiled much,
	   seems to me that the graphics driver and system memory
	   management might do this stuff anyway. --nicholas
	*/

	/* check the global buffer pool for a recently-deleted buffer
	   that is at least as big as the request, but not more than
	   twice as big */
	for(i = 0; i < pool->totbuf; i++) {
		bufsize = pool->buffers[i]->size;

		/* check for an exact size match */
		if(bufsize == size) {
			bestfit = i;
			break;
		}
		/* smaller buffers won't fit data and buffers at least
		   twice as big are a waste of memory */
		else if(bufsize > size && size > (bufsize / 2)) {
			/* is it closer to the required size than the
			   last appropriate buffer found. try to save
			   memory */
			if(bestfit == -1 || pool->buffers[bestfit]->size > bufsize) {
				bestfit = i;
			}
		}
	}

	/* if an acceptable buffer was found in the pool, remove it
	   from the pool and return it */
	if(bestfit != -1) {
		buf = pool->buffers[bestfit];
		gpu_buffer_pool_remove_index(pool, bestfit);
		return buf;
	}

	/* no acceptable buffer found in the pool, create a new one */
	buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
	buf->size = size;

	if(useVBOs == 1) {
		/* create a new VBO and initialize it to the requested
		   size */
		glGenBuffersARB(1, &buf->id);
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf->id);
		glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB);
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
	}
	else {
		buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
		
		/* purpose of this seems to be dealing with
		   out-of-memory errors? looks a bit iffy to me
		   though, at least on Linux I expect malloc() would
		   just overcommit. --nicholas */
		while(!buf->pointer && pool->totbuf > 0) {
			gpu_buffer_pool_delete_last(pool);
			buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
		}
		if(!buf->pointer)
			return NULL;
	}

	return buf;
}
Beispiel #9
0
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
				   int vector_size, int size, GLenum target,
				   void *user, GPUBufferCopyFunc copy_f)
{
	GPUBufferPool *pool;
	GPUBuffer *buffer;
	float *varray;
	int mat_orig_to_new[MAX_MATERIALS];
	int *cur_index_per_mat;
	int i;
	int success;
	GLboolean uploaded;

	pool = gpu_get_global_buffer_pool();

	/* alloc a GPUBuffer; fall back to legacy mode on failure */
	if(!(buffer = GPU_buffer_alloc(size)))
		dm->drawObject->legacy = 1;

	/* nothing to do for legacy mode */
	if(dm->drawObject->legacy)
		return 0;

	cur_index_per_mat = MEM_mallocN(sizeof(int)*object->totmaterial,
					"GPU_buffer_setup.cur_index_per_mat");
	for(i = 0; i < object->totmaterial; i++) {
		/* for each material, the current index to copy data to */
		cur_index_per_mat[i] = object->materials[i].start * vector_size;

		/* map from original material index to new
		   GPUBufferMaterial index */
		mat_orig_to_new[object->materials[i].mat_nr] = i;
	}

	if(useVBOs) {
		success = 0;

		while(!success) {
			/* bind the buffer and discard previous data,
			   avoids stalling gpu */
			glBindBufferARB(target, buffer->id);
			glBufferDataARB(target, buffer->size, 0, GL_STATIC_DRAW_ARB);

			/* attempt to map the buffer */
			if(!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
				/* failed to map the buffer; delete it */
				GPU_buffer_free(buffer);
				gpu_buffer_pool_delete_last(pool);
				buffer= NULL;

				/* try freeing an entry from the pool
				   and reallocating the buffer */
				if(pool->totbuf > 0) {
					gpu_buffer_pool_delete_last(pool);
					buffer = GPU_buffer_alloc(size);
				}

				/* allocation still failed; fall back
				   to legacy mode */
				if(!buffer) {
					dm->drawObject->legacy = 1;
					success = 1;
				}
			}
			else {
				success = 1;
			}
		}

		/* check legacy fallback didn't happen */
		if(dm->drawObject->legacy == 0) {
			uploaded = GL_FALSE;
			/* attempt to upload the data to the VBO */
			while(uploaded == GL_FALSE) {
				(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
				/* glUnmapBuffer returns GL_FALSE if
				   the data store is corrupted; retry
				   in that case */
				uploaded = glUnmapBufferARB(target);
			}
		}
		glBindBufferARB(target, 0);
	}
	else {
		/* VBO not supported, use vertex array fallback */
		if(buffer->pointer) {
			varray = buffer->pointer;
			(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
		}
		else {
			dm->drawObject->legacy = 1;
		}
	}

	MEM_freeN(cur_index_per_mat);

	return buffer;
}
Beispiel #10
0
/* screen can be NULL */
static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
{
	/* will be scaled down, but gives some nice oversampling */
	ImBuf *ibuf;
	int *thumb;
	char err_out[256] = "unknown";

	/* screen if no camera found */
	ScrArea *sa = NULL;
	ARegion *ar = NULL;
	View3D *v3d = NULL;

	*thumb_pt = NULL;

	/* scene can be NULL if running a script at startup and calling the save operator */
	if (G.background || scene == NULL)
		return NULL;

	if ((scene->camera == NULL) && (screen != NULL)) {
		sa = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
		ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
		if (ar) {
			v3d = sa->spacedata.first;
		}
	}

	if (scene->camera == NULL && v3d == NULL) {
		return NULL;
	}

	/* gets scaled to BLEN_THUMB_SIZE */
	if (scene->camera) {
		ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
		                                             BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
		                                             IB_rect, OB_SOLID, FALSE, FALSE, R_ADDSKY, err_out);
	}
	else {
		ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
		                                      IB_rect, FALSE, R_ADDSKY, err_out);
	}

	if (ibuf) {
		float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);

		/* dirty oversampling */
		IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE);

		/* add pretty overlay */
		IMB_overlayblend_thumb(ibuf->rect, ibuf->x, ibuf->y, aspect);
		
		/* first write into thumb buffer */
		thumb = MEM_mallocN(((2 + (BLEN_THUMB_SIZE * BLEN_THUMB_SIZE))) * sizeof(int), "write_file thumb");

		thumb[0] = BLEN_THUMB_SIZE;
		thumb[1] = BLEN_THUMB_SIZE;

		memcpy(thumb + 2, ibuf->rect, BLEN_THUMB_SIZE * BLEN_THUMB_SIZE * sizeof(int));
	}
	else {
		/* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */
		fprintf(stderr, "blend_file_thumb failed to create thumbnail: %s\n", err_out);
		thumb = NULL;
	}
	
	/* must be freed by caller */
	*thumb_pt = thumb;
	
	return ibuf;
}
Beispiel #11
0
static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
		int subdiv, float dia, float depth, int ext, int fill)
{
	/*
	 * type - for the type of shape
	 * dia - the radius for cone,sphere cylinder etc.
	 * depth - 
	 * ext - extrude
	 * fill - end capping, and option to fill in circle
	 * cent[3] - center of the data. 
	 * */
	EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
	EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
	float phi, phid, vec[3];
	float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
	short a, b;
	
	EM_clear_flag_all(em, SELECT);

	phid= 2.0f*(float)M_PI/tot;
	phi= .25f*(float)M_PI;

	switch(type) {
	case PRIM_GRID: /*  grid */
		/* clear flags */
		eve= em->verts.first;
		while(eve) {
			eve->f= 0;
			eve= eve->next;
		}
		
		/* one segment first: the X axis */		
		phi = (2*dia)/(float)(tot-1);
		phid = (2*dia)/(float)(seg-1);
		for(a=tot-1;a>=0;a--) {
			vec[0] = (phi*a) - dia;
			vec[1]= - dia;
			vec[2]= 0.0f;
			eve= addvertlist(em, vec, NULL);
			eve->f= 1+2+4;
			if(a < tot -1) addedgelist(em, eve->prev, eve, NULL);
		}
		/* extrude and translate */
		vec[0]= vec[2]= 0.0;
		vec[1]= phid;
		
		for(a=0;a<seg-1;a++) {
			extrudeflag_vert(obedit, em, 2, nor, 0);	// nor unused
			translateflag(em, 2, vec);
		}
			
		/* and now do imat */
		eve= em->verts.first;
		while(eve) {
			if(eve->f & SELECT) {
				mul_m4_v3(mat,eve->co);
			}
			eve= eve->next;
		}
		recalc_editnormals(em);
		break;
			
	case PRIM_UVSPHERE: /*  UVsphere */
		
		/* clear all flags */
		eve= em->verts.first;
		while(eve) {
			eve->f= 0;
			eve= eve->next;
		}
		
		/* one segment first */
		phi= 0; 
		phid/=2;
		for(a=0; a<=tot; a++) {
			vec[0]= dia*sinf(phi);
			vec[1]= 0.0;
			vec[2]= dia*cosf(phi);
			eve= addvertlist(em, vec, NULL);
			eve->f= 1+2+4;
			if(a==0) v1= eve;
			else addedgelist(em, eve, eve->prev, NULL);
			phi+= phid;
		}
		
		/* extrude and rotate */
		phi= M_PI/seg;
		q[0]= cos(phi);
		q[3]= sin(phi);
		q[1]=q[2]= 0;
		quat_to_mat3( cmat,q);
		
		for(a=0; a<seg; a++) {
			extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused
			rotateflag(em, 2, v1->co, cmat);
		}

		removedoublesflag(em, 4, 0, 0.0001);

		/* and now do imat */
		eve= em->verts.first;
		while(eve) {
			if(eve->f & SELECT) {
				mul_m4_v3(mat,eve->co);
			}
			eve= eve->next;
		}
		recalc_editnormals(em);
		break;
	case PRIM_ICOSPHERE: /* Icosphere */
		{
			EditVert *eva[12];
			EditEdge *eed;
			
			/* clear all flags */
			eve= em->verts.first;
			while(eve) {
				eve->f= 0;
				eve= eve->next;
			}
			dia/=200;
			for(a=0;a<12;a++) {
				vec[0]= dia*icovert[a][0];
				vec[1]= dia*icovert[a][1];
				vec[2]= dia*icovert[a][2];
				eva[a]= addvertlist(em, vec, NULL);
				eva[a]->f= 1+2;
			}
			for(a=0;a<20;a++) {
				EditFace *evtemp;
				v1= eva[ icoface[a][0] ];
				v2= eva[ icoface[a][1] ];
				v3= eva[ icoface[a][2] ];
				evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
				evtemp->e1->f = 1+2;
				evtemp->e2->f = 1+2;
				evtemp->e3->f = 1+2;
			}

			dia*=200;
			for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0);
			/* and now do imat */
			eve= em->verts.first;
			while(eve) {
				if(eve->f & 2) {
					mul_m4_v3(mat,eve->co);
				}
				eve= eve->next;
			}
			
			// Clear the flag 2 from the edges
			for(eed=em->edges.first;eed;eed=eed->next){
				if(eed->f & 2){
					   eed->f &= !2;
				}   
			}
		}
		break;
	case PRIM_MONKEY: /* Monkey */
		{
			//extern int monkeyo, monkeynv, monkeynf;
			//extern signed char monkeyf[][4];
			//extern signed char monkeyv[][3];
			EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
			int i;

			for (i=0; i<monkeynv; i++) {
				float v[3];
				v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
				tv[i]= addvertlist(em, v, NULL);
				tv[i]->f |= SELECT;
				tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
				tv[monkeynv+i]->f |= SELECT;
			}
			for (i=0; i<monkeynf; i++) {
				addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
				addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
			}

			MEM_freeN(tv);

			/* and now do imat */
			for(eve= em->verts.first; eve; eve= eve->next) {
				if(eve->f & SELECT) {
					mul_m4_v3(mat,eve->co);
				}
			}
			recalc_editnormals(em);
		}
		break;
	default: /* all types except grid, sphere... */
		if(type==PRIM_CONE);
		else if(ext==0) 
			depth= 0.0f;
	
		/* first vertex at 0° for circular objects */
		if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) )
			phi = 0.0f;
			
		vtop= vdown= v1= v2= 0;
		for(b=0; b<=ext; b++) {
			for(a=0; a<tot; a++) {
				
				vec[0]= dia*sinf(phi);
				vec[1]= dia*cosf(phi);
				vec[2]= b?depth:-depth;
				
				mul_m4_v3(mat, vec);
				eve= addvertlist(em, vec, NULL);
				eve->f= SELECT;
				if(a==0) {
					if(b==0) v1= eve;
					else v2= eve;
				}
				phi+=phid;
			}
		}
			
		/* center vertices */
		/* type PRIM_CONE can only have 1 one side filled
		 * if the cone has no capping, dont add vtop */
		if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) {
			vec[0]= vec[1]= 0.0f;
			vec[2]= type==PRIM_CONE ? depth : -depth;
			mul_m4_v3(mat, vec);
			vdown= addvertlist(em, vec, NULL);
			if((ext || type==PRIM_CONE) && fill) {
				vec[0]= vec[1]= 0.0f;
				vec[2]= type==PRIM_CONE ? -depth : depth;
				mul_m4_v3(mat,vec);
				vtop= addvertlist(em, vec, NULL);
			}
		} else {
			vdown= v1;
			vtop= v2;
		}
		if(vtop) vtop->f= SELECT;
		if(vdown) vdown->f= SELECT;
	
		/* top and bottom face */
		if(fill || type==PRIM_CONE) {
			if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
				v3= v1->next->next;
				if(ext) v4= v2->next->next;
				
				addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
				if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
				
			}
			else {
				v3= v1;
				v4= v2;
				for(a=1; a<tot; a++) {
					addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
					v3= v3->next;
					if(ext && fill) {
						addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
						v4= v4->next;
					}
				}
				if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
					addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
					if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
				}
			}
		}
		else if(type==PRIM_CIRCLE) {  /* we need edges for a circle */
			v3= v1;
			for(a=1;a<tot;a++) {
				addedgelist(em, v3, v3->next, NULL);
				v3= v3->next;
			}
			addedgelist(em, v3, v1, NULL);
		}
		/* side faces */
		if(ext) {
			v3= v1;
			v4= v2;
			for(a=1; a<tot; a++) {
				addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
				v3= v3->next;
				v4= v4->next;
			}
			addfacelist(em, v3, v1, v2, v4, NULL, NULL);
		}
		else if(fill && type==PRIM_CONE) {
			/* add the bottom flat area of the cone
			 * if capping is disabled dont bother */
			v3= v1;
			for(a=1; a<tot; a++) {
				addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
				v3= v3->next;
			}
			addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
		}
	}
	
	EM_stats_update(em);
	/* simple selection flush OK, based on fact it's a single model */
	EM_select_flush(em); /* flushes vertex -> edge -> face selection */

	if(!ELEM5(type, PRIM_GRID, PRIM_PLANE, PRIM_ICOSPHERE, PRIM_UVSPHERE, PRIM_MONKEY))
		EM_recalc_normal_direction(em, FALSE, TRUE);	/* otherwise monkey has eyes in wrong direction */

	BKE_mesh_end_editmesh(obedit->data, em);
}
Beispiel #12
0
/* Object Surface Area Heuristic splitter */
int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
{
	int size = rtbuild_size(b);
	assert(nchilds == 2);
	assert(size > 1);
	int baxis = -1, boffset = 0;

	if (size > nchilds) {
		float bcost = FLT_MAX;
		baxis = -1, boffset = size / 2;

		SweepCost *sweep = (SweepCost *)MEM_mallocN(sizeof(SweepCost) * size, "RTBuilder.HeuristicSweep");
		
		for (int axis = 0; axis < 3; axis++) {
			SweepCost sweep_left;

			RTBuilder::Object **obj = b->sorted_begin[axis];
			
//			float right_cost = 0;
			for (int i = size - 1; i >= 0; i--) {
				if (i == size - 1) {
					copy_v3_v3(sweep[i].bb, obj[i]->bb);
					copy_v3_v3(sweep[i].bb + 3, obj[i]->bb + 3);
					sweep[i].cost = obj[i]->cost;
				}
				else {
					sweep[i].bb[0] = min_ff(obj[i]->bb[0], sweep[i + 1].bb[0]);
					sweep[i].bb[1] = min_ff(obj[i]->bb[1], sweep[i + 1].bb[1]);
					sweep[i].bb[2] = min_ff(obj[i]->bb[2], sweep[i + 1].bb[2]);
					sweep[i].bb[3] = max_ff(obj[i]->bb[3], sweep[i + 1].bb[3]);
					sweep[i].bb[4] = max_ff(obj[i]->bb[4], sweep[i + 1].bb[4]);
					sweep[i].bb[5] = max_ff(obj[i]->bb[5], sweep[i + 1].bb[5]);
					sweep[i].cost  = obj[i]->cost + sweep[i + 1].cost;
				}
//				right_cost += obj[i]->cost;
			}
			
			sweep_left.bb[0] = obj[0]->bb[0];
			sweep_left.bb[1] = obj[0]->bb[1];
			sweep_left.bb[2] = obj[0]->bb[2];
			sweep_left.bb[3] = obj[0]->bb[3];
			sweep_left.bb[4] = obj[0]->bb[4];
			sweep_left.bb[5] = obj[0]->bb[5];
			sweep_left.cost  = obj[0]->cost;
			
//			right_cost -= obj[0]->cost;	if (right_cost < 0) right_cost = 0;

			for (int i = 1; i < size; i++) {
				//Worst case heuristic (cost of each child is linear)
				float hcost, left_side, right_side;
				
				// not using log seems to have no impact on raytracing perf, but
				// makes tree construction quicker, left out for now to test (brecht)
				// left_side  = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost + logf((float)i));
				// right_side = bb_area(sweep[i].bb,   sweep[i].bb   + 3) * (sweep[i].cost   + logf((float)size - i));
				left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost);
				right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost);
				hcost = left_side + right_side;

				assert(left_side >= 0);
				assert(right_side >= 0);
				
				if (left_side > bcost) break;   //No way we can find a better heuristic in this axis

				assert(hcost >= 0);
				// this makes sure the tree built is the same whatever is the order of the sorting axis
				if (hcost < bcost || (hcost == bcost && axis < baxis)) {
					bcost = hcost;
					baxis = axis;
					boffset = i;
				}
				DO_MIN(obj[i]->bb,   sweep_left.bb);
				DO_MAX(obj[i]->bb + 3, sweep_left.bb + 3);

				sweep_left.cost += obj[i]->cost;
//				right_cost -= obj[i]->cost; if (right_cost < 0) right_cost = 0;
			}
			
			//assert(baxis >= 0 && baxis < 3);
			if (!(baxis >= 0 && baxis < 3))
				baxis = 0;
		}
			
		
		MEM_freeN(sweep);
	}
	else if (size == 2) {
		baxis = 0;
		boffset = 1;
	}
	else if (size == 1) {
		b->child_offset[0] = 0;
		b->child_offset[1] = 1;
		return 1;
	}
		
	b->child_offset[0] = 0;
	b->child_offset[1] = boffset;
	b->child_offset[2] = size;
	

	/* Adjust sorted arrays for childs */
	for (int i = 0; i < boffset; i++) b->sorted_begin[baxis][i]->selected = true;
	for (int i = boffset; i < size; i++) b->sorted_begin[baxis][i]->selected = false;
	for (int i = 0; i < 3; i++)
		std::stable_partition(b->sorted_begin[i], b->sorted_end[i], selected_node);

	return nchilds;
}
Beispiel #13
0
size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
	unsigned int c;
	GlyphBLF *g, *g_prev = NULL;
	FT_Vector delta;
	int pen_x = 0;
	size_t i = 0, i_prev;
	GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
	const int width_i = (int)width + 1;
	int width_new;

	bool is_malloc;
	int (*width_accum)[2];
	int width_accum_ofs = 0;

	BLF_KERNING_VARS(font, has_kerning, kern_mode);

	/* skip allocs in simple cases */
	len = BLI_strnlen(str, len);
	if (width_i <= 1 || len == 0) {
		if (r_width) {
			*r_width = 0.0f;
		}
		return len;
	}

	if (len < 2048) {
		width_accum = BLI_array_alloca(width_accum, len);
		is_malloc = false;
	}
	else {
		width_accum = MEM_mallocN(sizeof(*width_accum) * len, __func__);
		is_malloc = true;
	}

	blf_font_ensure_ascii_table(font);

	while ((i < len) && str[i]) {
		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);

		if (UNLIKELY(c == BLI_UTF8_ERR))
			break;
		if (UNLIKELY(g == NULL))
			continue;
		if (has_kerning)
			BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);

		pen_x += g->advance_i;

		width_accum[width_accum_ofs][0] = (int)i;
		width_accum[width_accum_ofs][1] = pen_x;
		width_accum_ofs++;

		g_prev = g;
	}

	if (pen_x > width_i && width_accum_ofs != 0) {
		const int min_x = pen_x - width_i;

		/* search backwards */
		width_new = pen_x;
		while (width_accum_ofs-- > 0) {
			if (min_x > width_accum[width_accum_ofs][1]) {
				break;
			}
		}
		width_accum_ofs++;
		width_new = pen_x - width_accum[width_accum_ofs][1];
		i_prev = (size_t)width_accum[width_accum_ofs][0];
	}
	else {
		width_new = pen_x;
		i_prev = 0;
	}

	if (is_malloc) {
		MEM_freeN(width_accum);
	}

	if (r_width) {
		*r_width = (float)width_new;
	}

	return i_prev;
}
Beispiel #14
0
void calc_curvepath(Object *ob)
{
	BevList *bl;
	BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
	PathPoint *pp;
	Curve *cu;
	Nurb *nu;
	Path *path;
	float *fp, *dist, *maxdist, xyz[3];
	float fac, d=0, fac1, fac2;
	int a, tot, cycl=0;
	

	/* in a path vertices are with equal differences: path->len = number of verts */
	/* NOW WITH BEVELCURVE!!! */
	
	if(ob==NULL || ob->type != OB_CURVE) return;
	cu= ob->data;
	if(cu->editnurb) 
		nu= cu->editnurb->first;
	else 
		nu= cu->nurb.first;
	
	if(cu->path) free_path(cu->path);
	cu->path= NULL;
	
	bl= cu->bev.first;
	if(bl==NULL || !bl->nr) return;

	cu->path=path= MEM_callocN(sizeof(Path), "path");
	
	/* if POLY: last vertice != first vertice */
	cycl= (bl->poly!= -1);
	
	if(cycl) tot= bl->nr;
	else tot= bl->nr-1;
	
	path->len= tot+1;
	/* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */
	if(path->len<nu->resolu*SEGMENTSU(nu)) path->len= nu->resolu*SEGMENTSU(nu);
	
	dist= (float *)MEM_mallocN((tot+1)*4, "calcpathdist");

		/* all lengths in *dist */
	bevp= bevpfirst= (BevPoint *)(bl+1);
	fp= dist;
	*fp= 0;
	for(a=0; a<tot; a++) {
		fp++;
		if(cycl && a==tot-1)
			VecSubf(xyz, bevpfirst->vec, bevp->vec);
		else
			VecSubf(xyz, (bevp+1)->vec, bevp->vec);
		
		*fp= *(fp-1)+VecLength(xyz);
		bevp++;
	}
	
	path->totdist= *fp;

		/* the path verts  in path->data */
		/* now also with TILT value */
	pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*4*path->len, "pathdata"); // XXX - why *4? - in 2.4x each element was 4 and the size was 16, so better leave for now - Campbell
	
	bevp= bevpfirst;
	bevpn= bevp+1;
	bevplast= bevpfirst + (bl->nr-1);
	fp= dist+1;
	maxdist= dist+tot;
	fac= 1.0f/((float)path->len-1.0f);
        fac = fac * path->totdist;

	for(a=0; a<path->len; a++) {
		
		d= ((float)a)*fac;
		
		/* we're looking for location (distance) 'd' in the array */
		while((d>= *fp) && fp<maxdist) {
			fp++;
			if(bevp<bevplast) bevp++;
			bevpn= bevp+1;
			if(bevpn>bevplast) {
				if(cycl) bevpn= bevpfirst;
				else bevpn= bevplast;
			}
		}
		
		fac1= *(fp)- *(fp-1);
		fac2= *(fp)-d;
		fac1= fac2/fac1;
		fac2= 1.0f-fac1;

		VecLerpf(pp->vec, bevp->vec, bevpn->vec, fac2);
		pp->vec[3]= fac1*bevp->alfa + fac2*bevpn->alfa;
		pp->radius= fac1*bevp->radius + fac2*bevpn->radius;
		QuatInterpol(pp->quat, bevp->quat, bevpn->quat, fac2);
		NormalQuat(pp->quat);
		
		pp++;
	}
	
	MEM_freeN(dist);
}
Beispiel #15
0
static void warpModifier_do(WarpModifierData *wmd, Object *ob,
                            DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
	float obinv[4][4];
	float mat_from[4][4];
	float mat_from_inv[4][4];
	float mat_to[4][4];
	float mat_unit[4][4];
	float mat_final[4][4];

	float tmat[4][4];

	float strength = wmd->strength;
	float fac = 1.0f, weight;
	int i;
	int defgrp_index;
	MDeformVert *dvert, *dv = NULL;

	float (*tex_co)[3] = NULL;

	if (!(wmd->object_from && wmd->object_to))
		return;

	modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);

	if (wmd->curfalloff == NULL) /* should never happen, but bad lib linking could cause it */
		wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);

	if (wmd->curfalloff) {
		curvemapping_initialize(wmd->curfalloff);
	}

	invert_m4_m4(obinv, ob->obmat);

	mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat);
	mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat);

	invert_m4_m4(tmat, mat_from); // swap?
	mul_m4_m4m4(mat_final, tmat, mat_to);

	invert_m4_m4(mat_from_inv, mat_from);

	unit_m4(mat_unit);

	if (strength < 0.0f) {
		float loc[3];
		strength = -strength;

		/* inverted location is not useful, just use the negative */
		copy_v3_v3(loc, mat_final[3]);
		invert_m4(mat_final);
		negate_v3_v3(mat_final[3], loc);

	}
	weight = strength;

	if (wmd->texture) {
		tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co");
		get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);

		modifier_init_texture(wmd->modifier.scene, wmd->texture);
	}

	for (i = 0; i < numVerts; i++) {
		float *co = vertexCos[i];

		if (wmd->falloff_type == eWarp_Falloff_None ||
		    ((fac = len_v3v3(co, mat_from[3])) < wmd->falloff_radius &&
		     (fac = (wmd->falloff_radius - fac) / wmd->falloff_radius)))
		{
			/* skip if no vert group found */
			if (dvert && defgrp_index != -1) {
				dv = &dvert[i];

				if (dv) {
					weight = defvert_find_weight(dv, defgrp_index) * strength;
					if (weight <= 0.0f) /* Should never occure... */
						continue;
				}
			}


			/* closely match PROP_SMOOTH and similar */
			switch (wmd->falloff_type) {
				case eWarp_Falloff_None:
					fac = 1.0f;
					break;
				case eWarp_Falloff_Curve:
					fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac);
					break;
				case eWarp_Falloff_Sharp:
					fac = fac * fac;
					break;
				case eWarp_Falloff_Smooth:
					fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
					break;
				case eWarp_Falloff_Root:
					fac = (float)sqrt(fac);
					break;
				case eWarp_Falloff_Linear:
					/* pass */
					break;
				case eWarp_Falloff_Const:
					fac = 1.0f;
					break;
				case eWarp_Falloff_Sphere:
					fac = (float)sqrt(2 * fac - fac * fac);
					break;
			}

			fac *= weight;

			if (tex_co) {
				TexResult texres;
				texres.nor = NULL;
				BKE_texture_get_value(wmd->modifier.scene, wmd->texture, tex_co[i], &texres, false);
				fac *= texres.tin;
			}

			/* into the 'from' objects space */
			mul_m4_v3(mat_from_inv, co);

			if (fac >= 1.0f) {
				mul_m4_v3(mat_final, co);
			}
			else if (fac > 0.0f) {
				if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
					/* interpolate the matrix for nicer locations */
					blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
					mul_m4_v3(tmat, co);
				}
				else {
					float tvec[3];
					mul_v3_m4v3(tvec, mat_final, co);
					interp_v3_v3v3(co, co, tvec, fac);
				}
			}

			/* out of the 'from' objects space */
			mul_m4_v3(mat_from, co);
		}
	}

	if (tex_co)
		MEM_freeN(tex_co);

}
Beispiel #16
0
/**
 * Take as inputs two sets of verts, to be processed for detection of doubles and mapping.
 * Each set of verts is defined by its start within mverts array and its num_verts;
 * It builds a mapping for all vertices within source, to vertices within target, or -1 if no double found
 * The int doubles_map[num_verts_source] array must have been allocated by caller.
 */
static void dm_mvert_map_doubles(
        int *doubles_map,
        const MVert *mverts,
        const int target_start,
        const int target_num_verts,
        const int source_start,
        const int source_num_verts,
        const float dist,
        const bool with_follow)
{
	const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist;   /* Just above sqrt(3) */
	int i_source, i_target, i_target_low_bound, target_end, source_end;
	SortVertsElem *sorted_verts_target, *sorted_verts_source;
	SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
	bool target_scan_completed;

	target_end = target_start + target_num_verts;
	source_end = source_start + source_num_verts;

	/* build array of MVerts to be tested for merging */
	sorted_verts_target = MEM_mallocN(sizeof(SortVertsElem) * target_num_verts, __func__);
	sorted_verts_source = MEM_mallocN(sizeof(SortVertsElem) * source_num_verts, __func__);

	/* Copy target vertices index and cos into SortVertsElem array */
	svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end);

	/* Copy source vertices index and cos into SortVertsElem array */
	svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end);

	/* sort arrays according to sum of vertex coordinates (sumco) */
	qsort(sorted_verts_target, target_num_verts, sizeof(SortVertsElem), svert_sum_cmp);
	qsort(sorted_verts_source, source_num_verts, sizeof(SortVertsElem), svert_sum_cmp);

	sve_target_low_bound = sorted_verts_target;
	i_target_low_bound = 0;
	target_scan_completed = false;

	/* Scan source vertices, in SortVertsElem sorted array, */
	/* all the while maintaining the lower bound of possible doubles in target vertices */
	for (i_source = 0, sve_source = sorted_verts_source;
	     i_source < source_num_verts;
	     i_source++, sve_source++)
	{
		bool double_found;
		float sve_source_sumco;

		/* If source has already been assigned to a target (in an earlier call, with other chunks) */
		if (doubles_map[sve_source->vertex_num] != -1) {
			continue;
		}

		/* If target fully scanned already, then all remaining source vertices cannot have a double */
		if (target_scan_completed) {
			doubles_map[sve_source->vertex_num] = -1;
			continue;
		}

		sve_source_sumco = sum_v3(sve_source->co);

		/* Skip all target vertices that are more than dist3 lower in terms of sumco */
		/* and advance the overall lower bound, applicable to all remaining vertices as well. */
		while ((i_target_low_bound < target_num_verts) &&
		       (sve_target_low_bound->sum_co < sve_source_sumco - dist3))
		{
			i_target_low_bound++;
			sve_target_low_bound++;
		}
		/* If end of target list reached, then no more possible doubles */
		if (i_target_low_bound >= target_num_verts) {
			doubles_map[sve_source->vertex_num] = -1;
			target_scan_completed = true;
			continue;
		}
		/* Test target candidates starting at the low bound of possible doubles, ordered in terms of sumco */
		i_target = i_target_low_bound;
		sve_target = sve_target_low_bound;

		/* i_target will scan vertices in the [v_source_sumco - dist3;  v_source_sumco + dist3] range */

		double_found = false;
		while ((i_target < target_num_verts) &&
		       (sve_target->sum_co <= sve_source_sumco + dist3))
		{
			/* Testing distance for candidate double in target */
			/* v_target is within dist3 of v_source in terms of sumco;  check real distance */
			if (compare_len_v3v3(sve_source->co, sve_target->co, dist)) {
				/* Double found */
				/* If double target is itself already mapped to other vertex,
				 * behavior depends on with_follow option */
				int target_vertex = sve_target->vertex_num;
				if (doubles_map[target_vertex] != -1) {
					if (with_follow) { /* with_follow option:  map to initial target */
						target_vertex = doubles_map[target_vertex];
					}
					else {
						/* not with_follow: if target is mapped, then we do not map source, and stop searching  */
						break;
					}
				}
				doubles_map[sve_source->vertex_num] = target_vertex;
				double_found = true;
				break;
			}
			i_target++;
			sve_target++;
		}
		/* End of candidate scan: if none found then no doubles */
		if (!double_found) {
			doubles_map[sve_source->vertex_num] = -1;
		}
	}

	MEM_freeN(sorted_verts_source);
	MEM_freeN(sorted_verts_target);
}
Beispiel #17
0
static struct ImageUI_Data *ui_imageuser_data_copy(const struct ImageUI_Data *rnd_pt_src)
{
  struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__);
  memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src));
  return rnd_pt_dst;
}
Beispiel #18
0
static DerivedMesh *arrayModifier_doArray(
        ArrayModifierData *amd,
        Scene *scene, Object *ob, DerivedMesh *dm,
        ModifierApplyFlag flag)
{
	const float eps = 1e-6f;
	const MVert *src_mvert;
	MVert *mv, *mv_prev, *result_dm_verts;

	MEdge *me;
	MLoop *ml;
	MPoly *mp;
	int i, j, c, count;
	float length = amd->length;
	/* offset matrix */
	float offset[4][4];
	float scale[3];
	bool offset_has_scale;
	float current_offset[4][4];
	float final_offset[4][4];
	int *full_doubles_map = NULL;
	int tot_doubles;

	const bool use_merge = (amd->flags & MOD_ARR_MERGE) != 0;
	const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge;
	const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob);
	/* allow pole vertices to be used by many faces */
	const bool with_follow = use_offset_ob;

	int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
	int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
	int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0;
	int chunk_nverts, chunk_nedges, chunk_nloops, chunk_npolys;
	int first_chunk_start, first_chunk_nverts, last_chunk_start, last_chunk_nverts;

	DerivedMesh *result, *start_cap_dm = NULL, *end_cap_dm = NULL;

	chunk_nverts = dm->getNumVerts(dm);
	chunk_nedges = dm->getNumEdges(dm);
	chunk_nloops = dm->getNumLoops(dm);
	chunk_npolys = dm->getNumPolys(dm);

	count = amd->count;

	if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH) {
		start_cap_dm = get_dm_for_modifier(amd->start_cap, flag);
		if (start_cap_dm) {
			start_cap_nverts = start_cap_dm->getNumVerts(start_cap_dm);
			start_cap_nedges = start_cap_dm->getNumEdges(start_cap_dm);
			start_cap_nloops = start_cap_dm->getNumLoops(start_cap_dm);
			start_cap_npolys = start_cap_dm->getNumPolys(start_cap_dm);
		}
	}
	if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH) {
		end_cap_dm = get_dm_for_modifier(amd->end_cap, flag);
		if (end_cap_dm) {
			end_cap_nverts = end_cap_dm->getNumVerts(end_cap_dm);
			end_cap_nedges = end_cap_dm->getNumEdges(end_cap_dm);
			end_cap_nloops = end_cap_dm->getNumLoops(end_cap_dm);
			end_cap_npolys = end_cap_dm->getNumPolys(end_cap_dm);
		}
	}

	/* Build up offset array, cumulating all settings options */

	unit_m4(offset);
	src_mvert = dm->getVertArray(dm);

	if (amd->offset_type & MOD_ARR_OFF_CONST)
		add_v3_v3v3(offset[3], offset[3], amd->offset);

	if (amd->offset_type & MOD_ARR_OFF_RELATIVE) {
		for (j = 0; j < 3; j++)
			offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
	}

	if (use_offset_ob) {
		float obinv[4][4];
		float result_mat[4][4];

		if (ob)
			invert_m4_m4(obinv, ob->obmat);
		else
			unit_m4(obinv);

		mul_m4_series(result_mat, offset,
		              obinv, amd->offset_ob->obmat);
		copy_m4_m4(offset, result_mat);
	}

	/* Check if there is some scaling.  If scaling, then we will not translate mapping */
	mat4_to_size(scale, offset);
	offset_has_scale = !is_one_v3(scale);

	if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
		Curve *cu = amd->curve_ob->data;
		if (cu) {
#ifdef CYCLIC_DEPENDENCY_WORKAROUND
			if (amd->curve_ob->curve_cache == NULL) {
				BKE_displist_make_curveTypes(scene, amd->curve_ob, false);
			}
#endif

			if (amd->curve_ob->curve_cache && amd->curve_ob->curve_cache->path) {
				float scale = mat4_to_scale(amd->curve_ob->obmat);
				length = scale * amd->curve_ob->curve_cache->path->totdist;
			}
		}
	}

	/* calculate the maximum number of copies which will fit within the
	 * prescribed length */
	if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) {
		float dist = len_v3(offset[3]);

		if (dist > eps) {
			/* this gives length = first copy start to last copy end
			 * add a tiny offset for floating point rounding errors */
			count = (length + eps) / dist;
		}
		else {
			/* if the offset has no translation, just make one copy */
			count = 1;
		}
	}

	if (count < 1)
		count = 1;

	/* The number of verts, edges, loops, polys, before eventually merging doubles */
	result_nverts = chunk_nverts * count + start_cap_nverts + end_cap_nverts;
	result_nedges = chunk_nedges * count + start_cap_nedges + end_cap_nedges;
	result_nloops = chunk_nloops * count + start_cap_nloops + end_cap_nloops;
	result_npolys = chunk_npolys * count + start_cap_npolys + end_cap_npolys;

	/* Initialize a result dm */
	result = CDDM_from_template(dm, result_nverts, result_nedges, 0, result_nloops, result_npolys);
	result_dm_verts = CDDM_get_verts(result);

	if (use_merge) {
		/* Will need full_doubles_map for handling merge */
		full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map");
		fill_vn_i(full_doubles_map, result_nverts, -1);
	}

	/* copy customdata to original geometry */
	DM_copy_vert_data(dm, result, 0, 0, chunk_nverts);
	DM_copy_edge_data(dm, result, 0, 0, chunk_nedges);
	DM_copy_loop_data(dm, result, 0, 0, chunk_nloops);
	DM_copy_poly_data(dm, result, 0, 0, chunk_npolys);

	/* subsurf for eg wont have mesh data in the
	 * now add mvert/medge/mface layers */

	if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) {
		dm->copyVertArray(dm, result_dm_verts);
	}
	if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) {
		dm->copyEdgeArray(dm, CDDM_get_edges(result));
	}
	if (!CustomData_has_layer(&dm->polyData, CD_MPOLY)) {
		dm->copyLoopArray(dm, CDDM_get_loops(result));
		dm->copyPolyArray(dm, CDDM_get_polys(result));
	}

	/* Remember first chunk, in case of cap merge */
	first_chunk_start = 0;
	first_chunk_nverts = chunk_nverts;

	unit_m4(current_offset);
	for (c = 1; c < count; c++) {
		/* copy customdata to new geometry */
		DM_copy_vert_data(result, result, 0, c * chunk_nverts, chunk_nverts);
		DM_copy_edge_data(result, result, 0, c * chunk_nedges, chunk_nedges);
		DM_copy_loop_data(result, result, 0, c * chunk_nloops, chunk_nloops);
		DM_copy_poly_data(result, result, 0, c * chunk_npolys, chunk_npolys);

		mv_prev = result_dm_verts;
		mv = mv_prev + c * chunk_nverts;

		/* recalculate cumulative offset here */
		mul_m4_m4m4(current_offset, current_offset, offset);

		/* apply offset to all new verts */
		for (i = 0; i < chunk_nverts; i++, mv++, mv_prev++) {
			mul_m4_v3(current_offset, mv->co);

			/* We have to correct normals too, if we do not tag them as dirty! */
			if (!use_recalc_normals) {
				float no[3];
				normal_short_to_float_v3(no, mv->no);
				mul_mat3_m4_v3(current_offset, no);
				normalize_v3(no);
				normal_float_to_short_v3(mv->no, no);
			}
		}

		/* adjust edge vertex indices */
		me = CDDM_get_edges(result) + c * chunk_nedges;
		for (i = 0; i < chunk_nedges; i++, me++) {
			me->v1 += c * chunk_nverts;
			me->v2 += c * chunk_nverts;
		}

		mp = CDDM_get_polys(result) + c * chunk_npolys;
		for (i = 0; i < chunk_npolys; i++, mp++) {
			mp->loopstart += c * chunk_nloops;
		}

		/* adjust loop vertex and edge indices */
		ml = CDDM_get_loops(result) + c * chunk_nloops;
		for (i = 0; i < chunk_nloops; i++, ml++) {
			ml->v += c * chunk_nverts;
			ml->e += c * chunk_nedges;
		}

		/* Handle merge between chunk n and n-1 */
		if (use_merge && (c >= 1)) {
			if (!offset_has_scale && (c >= 2)) {
				/* Mapping chunk 3 to chunk 2 is a translation of mapping 2 to 1
				 * ... that is except if scaling makes the distance grow */
				int k;
				int this_chunk_index = c * chunk_nverts;
				int prev_chunk_index = (c - 1) * chunk_nverts;
				for (k = 0; k < chunk_nverts; k++, this_chunk_index++, prev_chunk_index++) {
					int target = full_doubles_map[prev_chunk_index];
					if (target != -1) {
						target += chunk_nverts; /* translate mapping */
						if (full_doubles_map[target] != -1) {
							if (with_follow) {
								target = full_doubles_map[target];
							}
							else {
								/* The rule here is to not follow mapping to chunk N-2, which could be too far
								 * so if target vertex was itself mapped, then this vertex is not mapped */
								target = -1;
							}
						}
					}
					full_doubles_map[this_chunk_index] = target;
				}
			}
			else {
				dm_mvert_map_doubles(
				        full_doubles_map,
				        result_dm_verts,
				        (c - 1) * chunk_nverts,
				        chunk_nverts,
				        c * chunk_nverts,
				        chunk_nverts,
				        amd->merge_dist,
				        with_follow);
			}
		}
	}

	last_chunk_start = (count - 1) * chunk_nverts;
	last_chunk_nverts = chunk_nverts;

	copy_m4_m4(final_offset, current_offset);

	if (use_merge && (amd->flags & MOD_ARR_MERGEFINAL) && (count > 1)) {
		/* Merge first and last copies */
		dm_mvert_map_doubles(
		        full_doubles_map,
		        result_dm_verts,
		        last_chunk_start,
		        last_chunk_nverts,
		        first_chunk_start,
		        first_chunk_nverts,
		        amd->merge_dist,
		        with_follow);
	}

	/* start capping */
	if (start_cap_dm) {
		float start_offset[4][4];
		int start_cap_start = result_nverts - start_cap_nverts - end_cap_nverts;
		invert_m4_m4(start_offset, offset);
		dm_merge_transform(
		        result, start_cap_dm, start_offset,
		        result_nverts - start_cap_nverts - end_cap_nverts,
		        result_nedges - start_cap_nedges - end_cap_nedges,
		        result_nloops - start_cap_nloops - end_cap_nloops,
		        result_npolys - start_cap_npolys - end_cap_npolys,
		        start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys);
		/* Identify doubles with first chunk */
		if (use_merge) {
			dm_mvert_map_doubles(
			        full_doubles_map,
			        result_dm_verts,
			        first_chunk_start,
			        first_chunk_nverts,
			        start_cap_start,
			        start_cap_nverts,
			        amd->merge_dist,
			        false);
		}
	}

	if (end_cap_dm) {
		float end_offset[4][4];
		int end_cap_start = result_nverts - end_cap_nverts;
		mul_m4_m4m4(end_offset, current_offset, offset);
		dm_merge_transform(
		        result, end_cap_dm, end_offset,
		        result_nverts - end_cap_nverts,
		        result_nedges - end_cap_nedges,
		        result_nloops - end_cap_nloops,
		        result_npolys - end_cap_npolys,
		        end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys);
		/* Identify doubles with last chunk */
		if (use_merge) {
			dm_mvert_map_doubles(
			        full_doubles_map,
			        result_dm_verts,
			        last_chunk_start,
			        last_chunk_nverts,
			        end_cap_start,
			        end_cap_nverts,
			        amd->merge_dist,
			        false);
		}
	}
	/* done capping */

	/* Handle merging */
	tot_doubles = 0;
	if (use_merge) {
		for (i = 0; i < result_nverts; i++) {
			if (full_doubles_map[i] != -1) {
				if (i == full_doubles_map[i]) {
					full_doubles_map[i] = -1;
				}
				else {
					tot_doubles++;
				}
			}
		}
		if (tot_doubles > 0) {
			result = CDDM_merge_verts(result, full_doubles_map, tot_doubles, CDDM_MERGE_VERTS_DUMP_IF_EQUAL);
		}
		MEM_freeN(full_doubles_map);
	}

	/* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm!
	 * TODO: we may need to set other dirty flags as well?
	 */
	if (use_recalc_normals) {
		result->dirty |= DM_DIRTY_NORMALS;
	}

	return result;
}
Beispiel #19
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;
}
Beispiel #20
0
static int preprocess_include(char *maindata, int len)
{
	int a, newlen, comment = 0;
	char *cp, *temp, *md;
	
	/* note: len + 1, last character is a dummy to prevent
	 * comparisons using uninitialized memory */
	temp = MEM_mallocN(len + 1, "preprocess_include");
	temp[len] = ' ';

	memcpy(temp, maindata, len);
	
	/* remove all c++ comments */
	/* replace all enters/tabs/etc with spaces */
	cp = temp;
	a = len;
	comment = 0;
	while (a--) {
		if (cp[0] == '/' && cp[1] == '/') {
			comment = 1;
		}
		else if (*cp < 32) {
			comment = 0;
		}
		if (comment || *cp < 32 || *cp > 128) *cp = 32;
		cp++;
	}
	

	/* data from temp copy to maindata, remove comments and double spaces */
	cp = temp;
	md = maindata;
	newlen = 0;
	comment = 0;
	a = len;
	while (a--) {
		
		if (cp[0] == '/' && cp[1] == '*') {
			comment = 1;
			cp[0] = cp[1] = 32;
		}
		if (cp[0] == '*' && cp[1] == '/') {
			comment = 0;
			cp[0] = cp[1] = 32;
		}

		/* do not copy when: */
		if (comment) {
			/* pass */
		}
		else if (cp[0] == ' ' && cp[1] == ' ') {
			/* pass */
		}
		else if (cp[-1] == '*' && cp[0] == ' ') {
			/* pointers with a space */
		}	/* skip special keywords */
		else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) {
			/* single values are skipped already, so decrement 1 less */
			a -= 13;
			cp += 13;
		}
		else {
			md[0] = cp[0];
			md++;
			newlen++;
		}
		cp++;
	}
	
	MEM_freeN(temp);
	return newlen;
}
Beispiel #21
0
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm = derivedData;
	DerivedMesh *result;
	BuildModifierData *bmd = (BuildModifierData *) md;
	int i, j, k;
	int numFaces_dst, numEdges_dst, numLoops_dst = 0;
	int *vertMap, *edgeMap, *faceMap;
	float frac;
	MPoly *mpoly_dst;
	MLoop *ml_dst, *ml_src /*, *mloop_dst */;
	GHashIterator *hashIter;
	/* maps vert indices in old mesh to indices in new mesh */
	GHash *vertHash = BLI_ghash_int_new("build ve apply gh");
	/* maps edge indices in new mesh to indices in old mesh */
	GHash *edgeHash = BLI_ghash_int_new("build ed apply gh");
	GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh");

	const int numVert_src = dm->getNumVerts(dm);
	const int numEdge_src = dm->getNumEdges(dm);
	const int numPoly_src = dm->getNumPolys(dm);
	MPoly *mpoly_src = dm->getPolyArray(dm);
	MLoop *mloop_src = dm->getLoopArray(dm);
	MEdge *medge_src = dm->getEdgeArray(dm);
	MVert *mvert_src = dm->getVertArray(dm);


	vertMap = MEM_mallocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap");
	edgeMap = MEM_mallocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap");
	faceMap = MEM_mallocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap");

#pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= DM_OMP_LIMIT)
	{
#pragma omp section
		{ range_vn_i(vertMap, numVert_src, 0); }
#pragma omp section
		{ range_vn_i(edgeMap, numEdge_src, 0); }
#pragma omp section
		{ range_vn_i(faceMap, numPoly_src, 0); }
	}

	frac = (BKE_scene_frame_get(md->scene) - bmd->start) / bmd->length;
	CLAMP(frac, 0.0f, 1.0f);

	numFaces_dst = numPoly_src * frac;
	numEdges_dst = numEdge_src * frac;

	/* if there's at least one face, build based on faces */
	if (numFaces_dst) {
		MPoly *mpoly, *mp;
		MLoop *ml, *mloop;
		MEdge *medge;
		
		if (bmd->randomize) {
			BLI_array_randomize(faceMap, sizeof(*faceMap),
			                    numPoly_src, bmd->seed);
		}

		/* get the set of all vert indices that will be in the final mesh,
		 * mapped to the new indices
		 */
		mpoly = mpoly_src;
		mloop = mloop_src;
		for (i = 0; i < numFaces_dst; i++) {
			mp = mpoly + faceMap[i];
			ml = mloop + mp->loopstart;

			for (j = 0; j < mp->totloop; j++, ml++) {
				if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v)))
					BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v),
					                 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
			}
			
			numLoops_dst += mp->totloop;
		}

		/* get the set of edges that will be in the new mesh (i.e. all edges
		 * that have both verts in the new mesh)
		 */
		medge = medge_src;
		for (i = 0; i < numEdge_src; i++) {
			MEdge *me = medge + i;

			if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
			    BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
			{
				j = BLI_ghash_size(edgeHash);
				
				BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
				                 SET_INT_IN_POINTER(i));
				BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i),
				                 SET_INT_IN_POINTER(j));
			}
		}
	}
	else if (numEdges_dst) {
		MEdge *medge, *me;

		if (bmd->randomize)
			BLI_array_randomize(edgeMap, sizeof(*edgeMap),
			                    numEdge_src, bmd->seed);

		/* get the set of all vert indices that will be in the final mesh,
		 * mapped to the new indices
		 */
		medge = medge_src;
		for (i = 0; i < numEdges_dst; i++) {
			me = medge + edgeMap[i];

			if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))) {
				BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1),
				                 SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
			}
			if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) {
				BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
			}
		}

		/* get the set of edges that will be in the new mesh */
		for (i = 0; i < numEdges_dst; i++) {
			j = BLI_ghash_size(edgeHash);
			
			BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
			                 SET_INT_IN_POINTER(edgeMap[i]));
			BLI_ghash_insert(edgeHash2,  SET_INT_IN_POINTER(edgeMap[i]),
			                 SET_INT_IN_POINTER(j));
		}
	}
	else {
		int numVerts = numVert_src * frac;

		if (bmd->randomize) {
			BLI_array_randomize(vertMap, sizeof(*vertMap),
			                    numVert_src, bmd->seed);
		}

		/* get the set of all vert indices that will be in the final mesh,
		 * mapped to the new indices
		 */
		for (i = 0; i < numVerts; i++) {
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
		}
	}

	/* now we know the number of verts, edges and faces, we can create
	 * the mesh
	 */
	result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
	                            BLI_ghash_size(edgeHash), 0, numLoops_dst, numFaces_dst);

	/* copy the vertices across */
	for (hashIter = BLI_ghashIterator_new(vertHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter)
	     )
	{
		MVert source;
		MVert *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));

		source = mvert_src[oldIndex];
		dest = CDDM_get_vert(result, newIndex);

		DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
		*dest = source;
	}
	BLI_ghashIterator_free(hashIter);
	
	/* copy the edges across, remapping indices */
	for (i = 0; i < BLI_ghash_size(edgeHash); i++) {
		MEdge source;
		MEdge *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
		
		source = medge_src[oldIndex];
		dest = CDDM_get_edge(result, i);
		
		source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
		source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
		
		DM_copy_edge_data(dm, result, oldIndex, i, 1);
		*dest = source;
	}

	mpoly_dst = CDDM_get_polys(result);
	/* mloop_dst = */ ml_dst = CDDM_get_loops(result);
	
	/* copy the faces across, remapping indices */
	k = 0;
	for (i = 0; i < numFaces_dst; i++) {
		MPoly *source;
		MPoly *dest;
		
		source = mpoly_src + faceMap[i];
		dest = mpoly_dst + i;
		DM_copy_poly_data(dm, result, faceMap[i], i, 1);
		
		*dest = *source;
		dest->loopstart = k;
		
		DM_copy_loop_data(dm, result, source->loopstart, dest->loopstart, dest->totloop);

		ml_src = mloop_src + source->loopstart;
		for (j = 0; j < source->totloop; j++, k++, ml_src++, ml_dst++) {
			ml_dst->v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(ml_src->v)));
			ml_dst->e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash2, SET_INT_IN_POINTER(ml_src->e)));
		}
	}

	BLI_ghash_free(vertHash, NULL, NULL);
	BLI_ghash_free(edgeHash, NULL, NULL);
	BLI_ghash_free(edgeHash2, NULL, NULL);
	
	MEM_freeN(vertMap);
	MEM_freeN(edgeMap);
	MEM_freeN(faceMap);

	return result;
}
Beispiel #22
0
void *BKE_frameserver_context_create(void)
{
    FrameserverContext *context = MEM_mallocN(sizeof(FrameserverContext), "Frameserver Context");
    return context;
}
Beispiel #23
0
/**
 * Allocate an array from the mempool.
 */
void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
{
	void *data = MEM_mallocN((size_t)(BLI_mempool_count(pool) * pool->esize), allocstr);
	BLI_mempool_as_array(pool, data);
	return data;
}
Beispiel #24
0
static void build_pict_list(PlayState *ps, char *first, int totframes, int fstep, int fontid)
{
	char *mem, filepath[FILE_MAX];
//	short val;
	PlayAnimPict *picture = NULL;
	struct ImBuf *ibuf = NULL;
	char str[32 + FILE_MAX];
	struct anim *anim;

	if (IMB_isanim(first)) {
		/* OCIO_TODO: support different input color space */
		anim = IMB_open_anim(first, IB_rect, 0, NULL);
		if (anim) {
			int pic;
			ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
			if (ibuf) {
				playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
				IMB_freeImBuf(ibuf);
			}

			for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) {
				picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict");
				picture->anim = anim;
				picture->frame = pic;
				picture->IB_flags = IB_rect;
				BLI_snprintf(str, sizeof(str), "%s : %4.d", first, pic + 1);
				picture->name = strdup(str);
				BLI_addtail(&picsbase, picture);
			}
		}
		else {
			printf("couldn't open anim %s\n", first);
		}
	}
	else {
		int count = 0;

		BLI_strncpy(filepath, first, sizeof(filepath));

		pupdate_time();
		ptottime = 1.0;

		/* O_DIRECT
		 *
		 * If set, all reads and writes on the resulting file descriptor will
		 * be performed directly to or from the user program buffer, provided
		 * appropriate size and alignment restrictions are met.  Refer to the
		 * F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for
		 * information about how to determine the alignment constraints.
		 * O_DIRECT is a Silicon Graphics extension and is only supported on
		 * local EFS and XFS file systems.
		 */

		while (IMB_ispic(filepath) && totframes) {
			size_t size;
			int file;

			file = open(filepath, O_BINARY | O_RDONLY, 0);
			if (file < 0) {
				/* print errno? */
				return;
			}

			picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
			if (picture == NULL) {
				printf("Not enough memory for pict struct '%s'\n", filepath);
				close(file);
				return;
			}
			size = BLI_file_descriptor_size(file);

			if (size < 1) {
				close(file);
				MEM_freeN(picture);
				return;
			}

			picture->size = size;
			picture->IB_flags = IB_rect;

			if (fromdisk == FALSE) {
				mem = (char *)MEM_mallocN(size, "build pic list");
				if (mem == NULL) {
					printf("Couldn't get memory\n");
					close(file);
					MEM_freeN(picture);
					return;
				}

				if (read(file, mem, size) != size) {
					printf("Error while reading %s\n", filepath);
					close(file);
					MEM_freeN(picture);
					MEM_freeN(mem);
					return;
				}
			}
			else {
				mem = NULL;
			}

			picture->mem = mem;
			picture->name = strdup(filepath);
			close(file);
			BLI_addtail(&picsbase, picture);
			count++;

			pupdate_time();

			if (ptottime > 1.0) {
				/* OCIO_TODO: support different input color space */
				if (picture->mem) {
					ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size,
					                             picture->IB_flags, NULL, picture->name);
				}
				else {
					ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL);
				}
				if (ibuf) {
					playanim_toscreen(ps, picture, ibuf, fontid, fstep);
					IMB_freeImBuf(ibuf);
				}
				pupdate_time();
				ptottime = 0.0;
			}

			BLI_newname(filepath, +fstep);

#if 0 // XXX25
			while (qtest()) {
				switch (qreadN(&val)) {
					case ESCKEY:
						if (val) return;
						break;
				}
			}
#endif
			totframes--;
		}
	}
	return;
}
Beispiel #25
0
/**
 * This function populates pixel_array and returns TRUE if things are correct
 */
static bool cast_ray_highpoly(
        BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
        const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
        const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
{
	int i;
	int primitive_id = -1;
	float uv[2];
	int hit_mesh = -1;
	float hit_distance = FLT_MAX;

	BVHTreeRayHit *hits;
	hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays");

	for (i = 0; i < tot_highpoly; i++) {
		float co_high[3], dir_high[3];

		hits[i].index = -1;
		/* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
		hits[i].dist = 10000.0f;

		/* transform the ray from the world space to the highpoly space */
		mul_v3_m4v3(co_high, highpoly[i].imat, co);

		/* rotates */
		mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
		normalize_v3(dir_high);

		/* cast ray */
		if (treeData[i].tree) {
			BLI_bvhtree_ray_cast(treeData[i].tree, co_high, dir_high, 0.0f, &hits[i], treeData[i].raycast_callback, &treeData[i]);
		}

		if (hits[i].index != -1) {
			/* cull backface */
			const float dot = dot_v3v3(dir_high, hits[i].no);
			if (dot < 0.0f) {
				float distance;
				float hit_world[3];

				/* distance comparison in world space */
				mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co);
				distance = len_squared_v3v3(hit_world, co);

				if (distance < hit_distance) {
					hit_mesh = i;
					hit_distance = distance;
				}
			}
		}
	}

	if (hit_mesh != -1) {
		calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
		pixel_array[pixel_id].primitive_id = primitive_id;
		pixel_array[pixel_id].object_id = hit_mesh;
		copy_v2_v2(pixel_array[pixel_id].uv, uv);

		/* the differentials are relative to the UV/image space, so the highpoly differentials
		 * are the same as the low poly differentials */
		pixel_array[pixel_id].du_dx = du_dx;
		pixel_array[pixel_id].du_dy = du_dy;
		pixel_array[pixel_id].dv_dx = dv_dx;
		pixel_array[pixel_id].dv_dy = dv_dy;
	}
	else {
		pixel_array[pixel_id].primitive_id = -1;
		pixel_array[pixel_id].object_id = -1;
	}

	MEM_freeN(hits);
	return hit_mesh != -1;
}
Beispiel #26
0
static void meshcache_do(
        MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm),
        float (*vertexCos_Real)[3], int numVerts)
{
	const bool use_factor = mcmd->factor < 1.0f;
	float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ?
	                              MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL;
	float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;

	Scene *scene = mcmd->modifier.scene;
	const float fps = FPS;

	char filepath[FILE_MAX];
	const char *err_str = NULL;
	bool ok;

	float time;


	/* -------------------------------------------------------------------- */
	/* Interpret Time (the reading functions also do some of this ) */
	if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
		const float cfra = BKE_scene_frame_get(scene);

		switch (mcmd->time_mode) {
			case MOD_MESHCACHE_TIME_FRAME:
			{
				time = cfra;
				break;
			}
			case MOD_MESHCACHE_TIME_SECONDS:
			{
				time = cfra / fps;
				break;
			}
			case MOD_MESHCACHE_TIME_FACTOR:
			default:
			{
				time = cfra / fps;
				break;
			}
		}

		/* apply offset and scale */
		time = (mcmd->frame_scale * time) - mcmd->frame_start;
	}
	else {  /*  if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */
		switch (mcmd->time_mode) {
			case MOD_MESHCACHE_TIME_FRAME:
			{
				time = mcmd->eval_frame;
				break;
			}
			case MOD_MESHCACHE_TIME_SECONDS:
			{
				time = mcmd->eval_time;
				break;
			}
			case MOD_MESHCACHE_TIME_FACTOR:
			default:
			{
				time = mcmd->eval_factor;
				break;
			}
		}
	}


	/* -------------------------------------------------------------------- */
	/* Read the File (or error out when the file is bad) */

	/* would be nice if we could avoid doing this _every_ frame */
	BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath));
	BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob));

	switch (mcmd->type) {
		case MOD_MESHCACHE_TYPE_MDD:
			ok = MOD_meshcache_read_mdd_times(filepath, vertexCos, numVerts,
			                                  mcmd->interp, time, fps, mcmd->time_mode, &err_str);
			break;
		case MOD_MESHCACHE_TYPE_PC2:
			ok = MOD_meshcache_read_pc2_times(filepath, vertexCos, numVerts,
			                                  mcmd->interp, time, fps, mcmd->time_mode, &err_str);
			break;
		default:
			ok = false;
			break;
	}


	/* -------------------------------------------------------------------- */
	/* tricky shape key integration (slow!) */
	if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) {
		Mesh *me = ob->data;

		/* we could support any object type */
		if (UNLIKELY(ob->type != OB_MESH)) {
			modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects");
		}
		else if (UNLIKELY(me->totvert != numVerts)) {
			modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch");
		}
		else if (UNLIKELY(me->totpoly == 0)) {
			modifier_setError(&mcmd->modifier, "'Integrate' requires faces");
		}
		else {
			/* the moons align! */
			int i;

			float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__);
			float (*vertexCos_New)[3]    = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__);
			MVert *mv = me->mvert;

			for (i = 0; i < numVerts; i++, mv++) {
				copy_v3_v3(vertexCos_Source[i], mv->co);
			}

			BKE_mesh_calc_relative_deform(
			        me->mpoly, me->totpoly,
			        me->mloop, me->totvert,

			        (const float (*)[3])vertexCos_Source,   /* from the original Mesh*/
			        (const float (*)[3])vertexCos_Real,     /* the input we've been given (shape keys!) */

			        (const float (*)[3])vertexCos,          /* the result of this modifier */
			        vertexCos_New                           /* the result of this function */
			        );

			/* write the corrected locations back into the result */
			memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts);

			MEM_freeN(vertexCos_Source);
			MEM_freeN(vertexCos_New);
		}
	}


	/* -------------------------------------------------------------------- */
	/* Apply the transformation matrix (if needed) */
	if (UNLIKELY(err_str)) {
		modifier_setError(&mcmd->modifier, "%s", err_str);
	}
	else if (ok) {
		bool use_matrix = false;
		float mat[3][3];
		unit_m3(mat);

		if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) {
			use_matrix = true;
		}

		if (mcmd->flip_axis) {
			float tmat[3][3];
			unit_m3(tmat);
			if (mcmd->flip_axis & (1 << 0)) tmat[0][0] = -1.0f;
			if (mcmd->flip_axis & (1 << 1)) tmat[1][1] = -1.0f;
			if (mcmd->flip_axis & (1 << 2)) tmat[2][2] = -1.0f;
			mul_m3_m3m3(mat, tmat, mat);

			use_matrix = true;
		}

		if (use_matrix) {
			int i;
			for (i = 0; i < numVerts; i++) {
				mul_m3_v3(mat, vertexCos[i]);
			}
		}
	}

	if (vertexCos_Store) {
		if (ok) {
			if (use_factor) {
				interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
			}
			else {
				memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts);
			}
		}

		MEM_freeN(vertexCos_Store);
	}
}
Beispiel #27
0
bool RE_bake_pixels_populate_from_objects(
        struct Mesh *me_low, BakePixel pixel_array_from[],  BakePixel pixel_array_to[],
        BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
        const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
{
	size_t i;
	int primitive_id;
	float u, v;
	float imat_low[4][4];
	bool is_cage = me_cage != NULL;
	bool result = true;

	DerivedMesh *dm_low = NULL;
	DerivedMesh **dm_highpoly;
	BVHTreeFromMesh *treeData;

	/* Note: all coordinates are in local space */
	TriTessFace *tris_low = NULL;
	TriTessFace *tris_cage = NULL;
	TriTessFace **tris_high;

	/* assume all lowpoly tessfaces can be quads */
	tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");

	/* assume all highpoly tessfaces are triangles */
	dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes");
	treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");

	if (!is_cage) {
		dm_low = CDDM_from_mesh(me_low);
		tris_low = mesh_calc_tri_tessface(me_low, true, dm_low);
	}
	else if (is_custom_cage) {
		tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
		tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
	}
	else {
		tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
	}

	invert_m4_m4(imat_low, mat_low);

	for (i = 0; i < tot_highpoly; i++) {
		tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);

		dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
		DM_ensure_tessface(dm_highpoly[i]);

		if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) {
			/* Create a bvh-tree for each highpoly object */
			bvhtree_from_mesh_faces(&treeData[i], dm_highpoly[i], 0.0, 2, 6);

			if (treeData[i].tree == NULL) {
				printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2);
				result = false;
				goto cleanup;
			}
		}
	}

	for (i = 0; i < num_pixels; i++) {
		float co[3];
		float dir[3];

		primitive_id = pixel_array_from[i].primitive_id;

		if (primitive_id == -1) {
			pixel_array_to[i].primitive_id = -1;
			continue;
		}

		u = pixel_array_from[i].uv[0];
		v = pixel_array_from[i].uv[1];

		/* calculate from low poly mesh cage */
		if (is_custom_cage) {
			calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir);
		}
		else if (is_cage) {
			calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true);
		}
		else {
			calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false);
		}

		/* cast ray */
		if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
		                       pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
		                       pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
			/* if it fails mask out the original pixel array */
			pixel_array_from[i].primitive_id = -1;
		}
	}


	/* garbage collection */
cleanup:
	for (i = 0; i < tot_highpoly; i++) {
		free_bvhtree_from_mesh(&treeData[i]);

		if (dm_highpoly[i]) {
			dm_highpoly[i]->release(dm_highpoly[i]);
		}

		if (tris_high[i]) {
			MEM_freeN(tris_high[i]);
		}
	}

	MEM_freeN(tris_high);
	MEM_freeN(treeData);
	MEM_freeN(dm_highpoly);

	if (dm_low) {
		dm_low->release(dm_low);
	}
	if (tris_low) {
		MEM_freeN(tris_low);
	}
	if (tris_cage) {
		MEM_freeN(tris_cage);
	}

	return result;
}
Beispiel #28
0
/**
 * Checks if name is a fully qualified filename to an executable.
 * If not it searches $PATH for the file. On Windows it also
 * adds the correct extension (.com .exe etc) from
 * $PATHEXT if necessary. Also on Windows it translates
 * the name to its 8.3 version to prevent problems with
 * spaces and stuff. Final result is returned in fullname.
 *
 * \param fullname The full path and full name of the executable
 * (must be FILE_MAX minimum)
 * \param name The name of the executable (usually argv[0]) to be checked
 */
static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
{
	char filename[FILE_MAX];
	const char *path = NULL, *temp;

#ifdef _WIN32
	const char *separator = ";";
#else
	const char *separator = ":";
#endif

	
#ifdef WITH_BINRELOC
	/* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
	path = br_find_exe(NULL);
	if (path) {
		BLI_strncpy(fullname, path, maxlen);
		free((void *)path);
		return;
	}
#endif

#ifdef _WIN32
	wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
	if (GetModuleFileNameW(0, fullname_16, maxlen)) {
		conv_utf_16_to_8(fullname_16, fullname, maxlen);
		if (!BLI_exists(fullname)) {
			printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
			MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
		}
		MEM_freeN(fullname_16);
		return;
	}

	MEM_freeN(fullname_16);
#endif

	/* unix and non linux */
	if (name && name[0]) {

		BLI_strncpy(fullname, name, maxlen);
		if (name[0] == '.') {
			char wdir[FILE_MAX] = "";
			BLI_current_working_dir(wdir, sizeof(wdir));     /* backup cwd to restore after */

			// not needed but avoids annoying /./ in name
			if (name[1] == SEP)
				BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
			else
				BLI_join_dirfile(fullname, maxlen, wdir, name);

			add_win32_extension(fullname); /* XXX, doesnt respect length */
		}
		else if (BLI_last_slash(name)) {
			// full path
			BLI_strncpy(fullname, name, maxlen);
			add_win32_extension(fullname);
		}
		else {
			// search for binary in $PATH
			path = getenv("PATH");
			if (path) {
				do {
					temp = strstr(path, separator);
					if (temp) {
						strncpy(filename, path, temp - path);
						filename[temp - path] = 0;
						path = temp + 1;
					}
					else {
						strncpy(filename, path, sizeof(filename));
					}
					BLI_path_append(fullname, maxlen, name);
					if (add_win32_extension(filename)) {
						BLI_strncpy(fullname, filename, maxlen);
						break;
					}
				} while (temp);
			}
		}
#if defined(DEBUG)
		if (!STREQ(name, fullname)) {
			printf("guessing '%s' == '%s'\n", name, fullname);
		}
#endif
	}
}
Beispiel #29
0
Datei: sss.c Projekt: jinjoh/NOOR
static void sss_create_tree_mat(Render *re, Material *mat)
{
	SSSPoints *p;
	RenderResult *rr;
	ListBase points;
	float (*co)[3] = NULL, (*color)[3] = NULL, *area = NULL;
	int totpoint = 0, osa, osaflag, partsdone;

	if(re->test_break(re->tbh))
		return;
	
	points.first= points.last= NULL;

	/* TODO: this is getting a bit ugly, copying all those variables and
	   setting them back, maybe we need to create our own Render? */

	/* do SSS preprocessing render */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	rr= re->result;
	osa= re->osa;
	osaflag= re->r.mode & R_OSA;
	partsdone= re->i.partsdone;

	re->osa= 0;
	re->r.mode &= ~R_OSA;
	re->sss_points= &points;
	re->sss_mat= mat;
	re->i.partsdone= 0;

	if(!(re->r.scemode & R_PREVIEWBUTS))
		re->result= NULL;
	BLI_rw_mutex_unlock(&re->resultmutex);

	RE_TileProcessor(re, 0, 1);
	
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if(!(re->r.scemode & R_PREVIEWBUTS)) {
		RE_FreeRenderResult(re->result);
		re->result= rr;
	}
	BLI_rw_mutex_unlock(&re->resultmutex);

	re->i.partsdone= partsdone;
	re->sss_mat= NULL;
	re->sss_points= NULL;
	re->osa= osa;
	if (osaflag) re->r.mode |= R_OSA;

	/* no points? no tree */
	if(!points.first)
		return;

	/* merge points together into a single buffer */
	if(!re->test_break(re->tbh)) {
		for(totpoint=0, p=points.first; p; p=p->next)
			totpoint += p->totpoint;
		
		co= MEM_mallocN(sizeof(*co)*totpoint, "SSSCo");
		color= MEM_mallocN(sizeof(*color)*totpoint, "SSSColor");
		area= MEM_mallocN(sizeof(*area)*totpoint, "SSSArea");

		for(totpoint=0, p=points.first; p; p=p->next) {
			memcpy(co+totpoint, p->co, sizeof(*co)*p->totpoint);
			memcpy(color+totpoint, p->color, sizeof(*color)*p->totpoint);
			memcpy(area+totpoint, p->area, sizeof(*area)*p->totpoint);
			totpoint += p->totpoint;
		}
	}

	/* free points */
	for(p=points.first; p; p=p->next) {
		MEM_freeN(p->co);
		MEM_freeN(p->color);
		MEM_freeN(p->area);
	}
	BLI_freelistN(&points);

	/* build tree */
	if(!re->test_break(re->tbh)) {
		SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData");
		float ior= mat->sss_ior, cfac= mat->sss_colfac;
		float col[3], *radius= mat->sss_radius;
		float fw= mat->sss_front, bw= mat->sss_back;
		float error = mat->sss_error;

		error= get_render_aosss_error(&re->r, error);
		if((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f)
			error= 0.5f;

		if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(col, mat->sss_col);
		else VECCOPY(col, mat->sss_col);
		
		sss->ss[0]= scatter_settings_new(col[0], radius[0], ior, cfac, fw, bw);
		sss->ss[1]= scatter_settings_new(col[1], radius[1], ior, cfac, fw, bw);
		sss->ss[2]= scatter_settings_new(col[2], radius[2], ior, cfac, fw, bw);
		sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error,
			co, color, area, totpoint);

		MEM_freeN(co);
		MEM_freeN(color);
		MEM_freeN(area);

		scatter_tree_build(sss->tree);

		BLI_ghash_insert(re->sss_hash, mat, sss);
	}
	else {
		if (co) MEM_freeN(co);
		if (color) MEM_freeN(color);
		if (area) MEM_freeN(area);
	}
}
Beispiel #30
0
/* Adds the geometry found in dm to bm
  */
BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
{
	
	BME_Mesh *bm;
	int allocsize[4] = {512,512,2048,512};
	MVert *mvert, *mv;
	MEdge *medge, *me;
	MFace *mface, *mf;
	int totface,totedge,totvert,i,len, numTex, numCol;
	BME_Vert *v1=NULL,*v2=NULL, **vert_array;
	BME_Edge *e=NULL;
	BME_Poly *f=NULL;
	
	EdgeHash *edge_hash = BLI_edgehash_new();

	bm = BME_make_mesh(allocsize);
	/*copy custom data layout*/
	CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	/*copy face corner data*/
	CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
	/*initialize memory pools*/
	CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
	CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
	CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
	CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
	/*needed later*/
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);

	totvert = dm->getNumVerts(dm);
	totedge = dm->getNumEdges(dm);
	totface = dm->getNumFaces(dm);
	mvert = dm->getVertArray(dm);
	medge = dm->getEdgeArray(dm);
	mface = dm->getFaceArray(dm);

	vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");

	BME_model_begin(bm);
	/*add verts*/
	for(i=0,mv = mvert; i < totvert;i++,mv++){
		v1 = BME_MV(bm,mv->co);
		vert_array[i] = v1;
		v1->flag = mv->flag;
		v1->bweight = mv->bweight/255.0f;
		CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data);
	}
	/*add edges*/
	for(i=0,me = medge; i < totedge;i++,me++){
		v1 = vert_array[me->v1];
		v2 = vert_array[me->v2];
		e = BME_ME(bm, v1, v2);
		e->crease = me->crease/255.0f;
		e->bweight = me->bweight/255.0f;
		e->flag = (unsigned char)me->flag;
		BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
		CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data);
	}
	/*add faces.*/
	for(i=0,mf = mface; i < totface;i++,mf++){
		BME_Edge *edar[4];
		if(mf->v4) len = 4;
		else len = 3;
		
		edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
		edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
		if(len == 4){
			edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
			edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
		}
		else
			edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
		
		/*find v1 and v2*/
		v1 = vert_array[mf->v1];
		v2 = vert_array[mf->v2];
		
		f = BME_MF(bm,v1,v2,edar,len);
		f->mat_nr = mf->mat_nr;
		f->flag = mf->flag;
		CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data);
		BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex);
	}
	
	BME_model_end(bm);
	BLI_edgehash_free(edge_hash, NULL);
	MEM_freeN(vert_array);
	return bm;
}