コード例 #1
0
static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
{
	float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
	float *st0, *st1, *st2;
	float *tang0, *tang1, *tang2;
	float no0[3], no1[3], no2[3];
	float fUV[2], from_tang[3][3], to_tang[3][3];
	float u, v, w, sign;
	int r;

	const int i0 = data->i0;
	const int i1 = data->i1;
	const int i2 = data->i2;

	st0 = data->mtface[data->face_index].uv[i0];
	st1 = data->mtface[data->face_index].uv[i1];
	st2 = data->mtface[data->face_index].uv[i2];

	multiresbake_get_normal(data, no0, data->face_index, i0);   /* can optimize these 3 into one call */
	multiresbake_get_normal(data, no1, data->face_index, i1);
	multiresbake_get_normal(data, no2, data->face_index, i2);

	resolve_tri_uv(fUV, st, st0, st1, st2);

	u = fUV[0];
	v = fUV[1];
	w = 1 - u - v;

	if (data->pvtangent) {
		tang0 = data->pvtangent + data->face_index * 16 + i0 * 4;
		tang1 = data->pvtangent + data->face_index * 16 + i1 * 4;
		tang2 = data->pvtangent + data->face_index * 16 + i2 * 4;

		/* the sign is the same at all face vertices for any non degenerate face.
		 * Just in case we clamp the interpolated value though. */
		sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;

		/* this sequence of math is designed specifically as is with great care
		 * to be compatible with our shader. Please don't change without good reason. */
		for (r = 0; r < 3; r++) {
			from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
			from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
		}

		cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]);  /* B = sign * cross(N, T)  */
		mul_v3_fl(from_tang[1], sign);
		invert_m3_m3(to_tang, from_tang);
	}
	else {
		zero_m3(to_tang);
	}

	data->pass_data(data->lores_dm, data->hires_dm, data->bake_data,
	                data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
}
コード例 #2
0
ファイル: object_bake.c プロジェクト: BHCLL/blendocv
/* MultiresBake callback for normals' baking
   general idea:
     - find coord and normal of point with specified UV in hi-res mesh
     - multiply it by tangmat
     - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *UNUSED(bake_data),
                                   const int face_index, const int lvl, const float st[2],
                                   float tangmat[3][3], const int x, const int y)
{
	MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;
	Image *ima= mtface[face_index].tpage;
	ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
	float uv[2], *st0, *st1, *st2, *st3;
	int pixel= ibuf->x*y + x;
	float n[3], vec[3], tmp[3]= {0.5, 0.5, 0.5};

	lores_dm->getFace(lores_dm, face_index, &mface);

	st0= mtface[face_index].uv[0];
	st1= mtface[face_index].uv[1];
	st2= mtface[face_index].uv[2];

	if(mface.v4) {
		st3= mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	} else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm, lvl, face_index, uv[0], uv[1], NULL, n);

	mul_v3_m3v3(vec, tangmat, n);
	normalize_v3(vec);
	mul_v3_fl(vec, 0.5);
	add_v3_v3(vec, tmp);

	if(ibuf->rect_float) {
		float *rrgbf= ibuf->rect_float + pixel*4;
		rrgbf[0]= vec[0];
		rrgbf[1]= vec[1];
		rrgbf[2]= vec[2];
		rrgbf[3]= 1.0f;

		ibuf->userflags= IB_RECT_INVALID;
	} else {
		char *rrgb= (char*)ibuf->rect + pixel*4;
		rrgb[0]= FTOCHAR(vec[0]);
		rrgb[1]= FTOCHAR(vec[1]);
		rrgb[2]= FTOCHAR(vec[2]);
		rrgb[3]= 255;
	}
}
コード例 #3
0
/* MultiresBake callback for normals' baking
 * general idea:
 *   - find coord and normal of point with specified UV in hi-res mesh
 *   - multiply it by tangmat
 *   - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
                                   ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                   float tangmat[3][3], const int x, const int y)
{
	MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;
	MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
	float uv[2], *st0, *st1, *st2, *st3;
	int pixel = ibuf->x * y + x;
	float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5};

	lores_dm->getTessFace(lores_dm, face_index, &mface);

	st0 = mtface[face_index].uv[0];
	st1 = mtface[face_index].uv[1];
	st2 = mtface[face_index].uv[2];

	if (mface.v4) {
		st3 = mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	}
	else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm,
	               normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig,
	               lvl, face_index, uv[0], uv[1], NULL, n);

	mul_v3_m3v3(vec, tangmat, n);
	normalize_v3(vec);
	mul_v3_fl(vec, 0.5);
	add_v3_v3(vec, tmp);

	if (ibuf->rect_float) {
		float *rrgbf = ibuf->rect_float + pixel * 4;
		rrgbf[0] = vec[0];
		rrgbf[1] = vec[1];
		rrgbf[2] = vec[2];
		rrgbf[3] = 1.0f;
	}
	else {
		unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
		rgb_float_to_uchar(rrgb, vec);
		rrgb[3] = 255;
	}
}
コード例 #4
0
/* MultiresBake callback for heights baking
 * general idea:
 *   - find coord of point with specified UV in hi-res mesh (let's call it p1)
 *   - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
 *     mesh to make texture smoother) let's call this point p0 and n.
 *   - height wound be dot(n, p1-p0) */
static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
                                   ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                   float UNUSED(tangmat[3][3]), const int x, const int y)
{
	MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;
	MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
	float uv[2], *st0, *st1, *st2, *st3;
	int pixel = ibuf->x * y + x;
	float vec[3], p0[3], p1[3], n[3], len;

	lores_dm->getTessFace(lores_dm, face_index, &mface);

	st0 = mtface[face_index].uv[0];
	st1 = mtface[face_index].uv[1];
	st2 = mtface[face_index].uv[2];

	if (mface.v4) {
		st3 = mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	}
	else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm,
	               height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly,
	               lvl, face_index, uv[0], uv[1], p1, 0);

	if (height_data->ssdm) {
		get_ccgdm_data(lores_dm, height_data->ssdm,
		               height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly,
		               0, face_index, uv[0], uv[1], p0, n);
	}
	else {
		lores_dm->getTessFace(lores_dm, face_index, &mface);

		if (mface.v4) {
			interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
			interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
		}
		else {
			interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
			interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
		}
	}

	sub_v3_v3v3(vec, p1, p0);
	len = dot_v3v3(n, vec);

	height_data->heights[pixel] = len;
	if (len < height_data->height_min) height_data->height_min = len;
	if (len > height_data->height_max) height_data->height_max = len;

	if (ibuf->rect_float) {
		float *rrgbf = ibuf->rect_float + pixel * 4;
		rrgbf[3] = 1.0f;
	}
	else {
		char *rrgb = (char *)ibuf->rect + pixel * 4;
		rrgb[3] = 255;
	}
}
コード例 #5
0
static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
                              ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                              float UNUSED(tangmat[3][3]), const int x, const int y)
{
	MAOBakeData *ao_data = (MAOBakeData *) bake_data;
	MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;

	int i, k, perm_offs;
	float pos[3], nrm[3];
	float cen[3];
	float axisX[3], axisY[3], axisZ[3];
	float shadow = 0;
	float value;
	int pixel = ibuf->x * y + x;
	float uv[2], *st0, *st1, *st2, *st3;

	lores_dm->getTessFace(lores_dm, face_index, &mface);

	st0 = mtface[face_index].uv[0];
	st1 = mtface[face_index].uv[1];
	st2 = mtface[face_index].uv[2];

	if (mface.v4) {
		st3 = mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	}
	else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm,
	               ao_data->orig_index_mf_to_mpoly, ao_data->orig_index_mp_to_orig,
	               lvl, face_index, uv[0], uv[1], pos, nrm);

	/* offset ray origin by user bias along normal */
	for (i = 0; i < 3; i++)
		cen[i] = pos[i] + ao_data->bias * nrm[i];

	/* build tangent frame */
	for (i = 0; i < 3; i++)
		axisZ[i] = nrm[i];

	build_coordinate_frame(axisX, axisY, axisZ);

	/* static noise */
	perm_offs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);

	/* importance sample shadow rays (cosine weighted) */
	for (i = 0; i < ao_data->number_of_rays; i++) {
		int hit_something;

		/* use N-Rooks to distribute our N ray samples across
		 * a multi-dimensional domain (2D)
		 */
		const unsigned short I = ao_data->permutation_table_1[(i + perm_offs) % ao_data->number_of_rays];
		const unsigned short J = ao_data->permutation_table_2[i];

		const float JitPh = (get_ao_random2(I + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
		const float JitTh = (get_ao_random1(J + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
		const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
		const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);

		/* this gives results identical to the so-called cosine
		 * weighted distribution relative to the north pole.
		 */
		float SiPhi = sqrt(SiSqPhi);
		float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
		float CoThe = cos(Theta);
		float SiThe = sin(Theta);

		const float dx = CoThe * CoPhi;
		const float dy = SiThe * CoPhi;
		const float dz = SiPhi;

		/* transform ray direction out of tangent frame */
		float dv[3];
		for (k = 0; k < 3; k++)
			dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;

		hit_something = trace_ao_ray(ao_data, cen, dv);

		if (hit_something != 0)
			shadow += 1;
	}

	value = 1.0f - (shadow / ao_data->number_of_rays);

	if (ibuf->rect_float) {
		float *rrgbf = ibuf->rect_float + pixel * 4;
		rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
		rrgbf[3] = 1.0f;
	}
	else {
		unsigned char *rrgb = (unsigned char *) ibuf->rect + pixel * 4;
		rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(value);
		rrgb[3] = 255;
	}
}