Пример #1
0
static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData,
                             MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
{
	DerivedMesh *dm = bkr->lores_dm;
	const int lvl = bkr->lvl;
	const int tot_face = dm->getNumTessFaces(dm);

	if (tot_face > 0) {
		MultiresBakeThread *handles;
		MultiresBakeQueue queue;

		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
		MVert *mvert = dm->getVertArray(dm);
		MFace *mface = dm->getTessFaceArray(dm);
		MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
		float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
		float *pvtangent = NULL;

		ListBase threads;
		int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();

		void *bake_data = NULL;

		if (require_tangent) {
			if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
				DM_add_tangent_layer(dm);

			pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
		}

		/* all threads shares the same custom bake data */
		if (initBakeData)
			bake_data = initBakeData(bkr, ima);

		if (tot_thread > 1)
			BLI_init_threads(&threads, do_multires_bake_thread, tot_thread);

		handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");

		/* faces queue */
		queue.cur_face = 0;
		queue.tot_face = tot_face;
		BLI_spin_init(&queue.spin);

		/* fill in threads handles */
		for (i = 0; i < tot_thread; i++) {
			MultiresBakeThread *handle = &handles[i];

			handle->bkr = bkr;
			handle->image = ima;
			handle->queue = &queue;

			handle->data.mface = mface;
			handle->data.mvert = mvert;
			handle->data.mtface = mtface;
			handle->data.pvtangent = pvtangent;
			handle->data.precomputed_normals = precomputed_normals;  /* don't strictly need this */
			handle->data.w = ibuf->x;
			handle->data.h = ibuf->y;
			handle->data.lores_dm = dm;
			handle->data.hires_dm = bkr->hires_dm;
			handle->data.lvl = lvl;
			handle->data.pass_data = passKnownData;
			handle->data.bake_data = bake_data;
			handle->data.ibuf = ibuf;

			init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel);

			if (tot_thread > 1)
				BLI_insert_thread(&threads, handle);
		}

		/* run threads */
		if (tot_thread > 1)
			BLI_end_threads(&threads);
		else
			do_multires_bake_thread(&handles[0]);

		BLI_spin_end(&queue.spin);

		/* finalize baking */
		if (applyBakeData)
			applyBakeData(bake_data);

		if (freeBakeData)
			freeBakeData(bake_data);

		BKE_image_release_ibuf(ima, ibuf, NULL);
	}
}
Пример #2
0
/**
 * This function populates an array of verts for the triangles of a mesh
 * Tangent and Normals are also stored
 */
static void mesh_calc_tri_tessface(
        TriTessFace *triangles, 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;
	/* 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__);

	if (tangent) {
		DM_ensure_normals(dm);
		DM_add_tangent_layer(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);
}
Пример #3
0
static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData,
                             MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
{
	DerivedMesh *dm= bkr->lores_dm;
	ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
	const int lvl= bkr->lvl;
	const int tot_face= dm->getNumFaces(dm);
	MVert *mvert= dm->getVertArray(dm);
	MFace *mface= dm->getFaceArray(dm);
	MTFace *mtface= dm->getFaceDataArray(dm, CD_MTFACE);
	float *pvtangent= NULL;

	if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
		DM_add_tangent_layer(dm);

	pvtangent= DM_get_face_data_layer(dm, CD_TANGENT);

	if(tot_face > 0) {  /* sanity check */
		int f= 0;
		MBakeRast bake_rast;
		MResolvePixelData data={NULL};

		data.mface= mface;
		data.mvert= mvert;
		data.mtface= mtface;
		data.pvtangent= pvtangent;
		data.precomputed_normals= dm->getFaceDataArray(dm, CD_NORMAL);	/* don't strictly need this */
		data.w= ibuf->x;
		data.h= ibuf->y;
		data.lores_dm= dm;
		data.hires_dm= bkr->hires_dm;
		data.lvl= lvl;
		data.pass_data= passKnownData;

		if(initBakeData)
			data.bake_data= initBakeData(bkr, ima);

		init_bake_rast(&bake_rast, ibuf, &data, flush_pixel);

		for(f= 0; f<tot_face; f++) {
			MTFace *mtfate= &mtface[f];
			int verts[3][2], nr_tris, t;

			if(multiresbake_test_break(bkr))
				break;

			if(mtfate->tpage!=ima)
				continue;

			data.face_index= f;

			/* might support other forms of diagonal splits later on such as
			   split by shortest diagonal.*/
			verts[0][0]=0;
			verts[1][0]=1;
			verts[2][0]=2;

			verts[0][1]=0;
			verts[1][1]=2;
			verts[2][1]=3;

			nr_tris= mface[f].v4!=0 ? 2 : 1;
			for(t= 0; t<nr_tris; t++) {
				data.i0= verts[0][t];
				data.i1= verts[1][t];
				data.i2 =verts[2][t];

				bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]);
			}

			bkr->baked_faces++;

			if(bkr->do_update)
				*bkr->do_update= 1;

			if(bkr->progress)
				*bkr->progress= ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj;
		}

		if(applyBakeData)
			applyBakeData(data.bake_data);

		if(freeBakeData)
			freeBakeData(data.bake_data);
	}
}
Пример #4
0
/**
 * This function populates an array of verts for the triangles of a mesh
 * Tangent and Normals are also stored
 */
static void mesh_calc_tri_tessface(
        TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm)
{
	int i;
	int p_id;
	MFace *mface;
	MVert *mvert;
	TSpace *tspace;
	float *precomputed_normals = NULL;
	bool calculate_normal;

	mface = CustomData_get_layer(&me->fdata, CD_MFACE);
	mvert = CustomData_get_layer(&me->vdata, CD_MVERT);

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

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

		//mface = dm->getTessFaceArray(dm);
		//mvert = dm->getVertArray(dm);

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

	p_id = -1;
	for (i = 0; i < me->totface; i++) {
		MFace *mf = &mface[i];
		TSpace *ts = tangent ? &tspace[i * 4] : NULL;

		p_id++;

		triangles[p_id].mverts[0] = &mvert[mf->v1];
		triangles[p_id].mverts[1] = &mvert[mf->v2];
		triangles[p_id].mverts[2] = &mvert[mf->v3];
		triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;

		if (tangent) {
			triangles[p_id].tspace[0] = &ts[0];
			triangles[p_id].tspace[1] = &ts[1];
			triangles[p_id].tspace[2] = &ts[2];

			if (calculate_normal) {
				if (mf->v4 != 0) {
					normal_quad_v3(triangles[p_id].normal,
					               mvert[mf->v1].co,
					               mvert[mf->v2].co,
					               mvert[mf->v3].co,
					               mvert[mf->v4].co);
				}
				else {
					normal_tri_v3(triangles[p_id].normal,
					              triangles[p_id].mverts[0]->co,
					              triangles[p_id].mverts[1]->co,
					              triangles[p_id].mverts[2]->co);
				}
			}
			else {
				copy_v3_v3(triangles[p_id].normal, &precomputed_normals[3 * i]);
			}
		}

		/* 4 vertices in the face */
		if (mf->v4 != 0) {
			p_id++;

			triangles[p_id].mverts[0] = &mvert[mf->v1];
			triangles[p_id].mverts[1] = &mvert[mf->v3];
			triangles[p_id].mverts[2] = &mvert[mf->v4];
			triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;

			if (tangent) {
				triangles[p_id].tspace[0] = &ts[0];
				triangles[p_id].tspace[1] = &ts[2];
				triangles[p_id].tspace[2] = &ts[3];

				/* same normal as the other "triangle" */
				copy_v3_v3(triangles[p_id].normal, triangles[p_id - 1].normal);
			}
		}
	}

	BLI_assert(p_id < me->totface * 2);
}