OpenGL2: Store normals/tangents as int16_t[4].

This commit is contained in:
SmileTheory 2016-09-06 00:57:15 -07:00
parent 762f50757d
commit dfbaf50324
13 changed files with 288 additions and 1042 deletions

View file

@ -70,230 +70,11 @@ qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
/*
=============
R_CalcNormalForTriangle
R_CalcTexDirs
Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
=============
*/
void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2)
{
vec3_t udir, vdir;
// compute the face normal based on vertex points
VectorSubtract(v2, v0, udir);
VectorSubtract(v1, v0, vdir);
CrossProduct(udir, vdir, normal);
VectorNormalize(normal);
}
/*
=============
R_CalcTangentsForTriangle
http://members.rogers.com/deseric/tangentspace.htm
=============
*/
void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
const vec3_t v0, const vec3_t v1, const vec3_t v2,
const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
int i;
vec3_t planes[3];
vec3_t u, v;
for(i = 0; i < 3; i++)
{
VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
VectorNormalize(u);
VectorNormalize(v);
CrossProduct(u, v, planes[i]);
}
//So your tangent space will be defined by this :
//Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product,
// you have to make sure the normal points in the right direction)
//Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az )
//Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az )
// tangent...
tangent[0] = -planes[0][1] / planes[0][0];
tangent[1] = -planes[1][1] / planes[1][0];
tangent[2] = -planes[2][1] / planes[2][0];
VectorNormalize(tangent);
// bitangent...
bitangent[0] = -planes[0][2] / planes[0][0];
bitangent[1] = -planes[1][2] / planes[1][0];
bitangent[2] = -planes[2][2] / planes[2][0];
VectorNormalize(bitangent);
}
/*
=============
R_CalcTangentSpace
=============
*/
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalize(tangent);
VectorNormalize(bitangent);
// compute the face normal based on vertex points
if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
{
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
}
else
{
VectorCopy(normal, faceNormal);
}
VectorNormalize(faceNormal);
#if 1
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalize(tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
#else
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalize(normal);
if(DotProduct(normal, faceNormal) < 0)
{
//VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
// compute the cross product T=BxN
CrossProduct(bitangent, faceNormal, tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
}
#endif
VectorCopy(faceNormal, normal);
}
void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalizeFast(tangent);
VectorNormalizeFast(bitangent);
// compute the face normal based on vertex points
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
VectorNormalizeFast(faceNormal);
#if 0
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalizeFast(normal);
if(DotProduct(normal, faceNormal) < 0)
{
VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
CrossProduct(normal, tangent, bitangent);
}
VectorCopy(faceNormal, normal);
#else
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalizeFast(tangent);
#endif
VectorCopy(faceNormal, normal);
}
/*
http://www.terathon.com/code/tangent.html
*/
void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
{
@ -312,13 +93,21 @@ void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
t1 = w2[1] - w1[1];
t2 = w3[1] - w1[1];
r = 1.0f / (s1 * t2 - s2 * t1);
r = s1 * t2 - s2 * t1;
if (r) r = 1.0f / r;
VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
}
void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir)
/*
=============
R_CalcTangentSpace
Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
=============
*/
vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t normal, const vec3_t sdir, const vec3_t tdir)
{
vec3_t n_cross_t;
vec_t n_dot_t, handedness;
@ -332,113 +121,13 @@ void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t norm
CrossProduct(normal, sdir, n_cross_t);
handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
// Calculate bitangent
CrossProduct(normal, tangent, bitangent);
VectorScale(bitangent, handedness, bitangent);
// Calculate orthogonal bitangent, if necessary
if (bitangent)
CrossProduct(normal, tangent, bitangent);
return handedness;
}
void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
{
vec3_t v2v1;
vec3_t v3v1;
float c2c1_T;
float c2c1_B;
float c3c1_T;
float c3c1_B;
float denominator;
float scale1, scale2;
vec3_t T, B, N, C;
// Calculate the tangent basis for each vertex of the triangle
// UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has
// been removed as it was redundant (the entire TBN matrix was calculated three times
// instead of just one).
//
// Please note, that this function relies on the fact that the input geometry are triangles
// and the tangent basis for each vertex thus is identical!
//
// Calculate the vectors from the current vertex to the two other vertices in the triangle
VectorSubtract(v2, v1, v2v1);
VectorSubtract(v3, v1, v3v1);
// The equation presented in the article states that:
// c2c1_T = V2.texcoord.x - V1.texcoord.x
// c2c1_B = V2.texcoord.y - V1.texcoord.y
// c3c1_T = V3.texcoord.x - V1.texcoord.x
// c3c1_B = V3.texcoord.y - V1.texcoord.y
// Calculate c2c1_T and c2c1_B
c2c1_T = t2[0] - t1[0];
c2c1_B = t2[1] - t2[1];
// Calculate c3c1_T and c3c1_B
c3c1_T = t3[0] - t1[0];
c3c1_B = t3[1] - t1[1];
denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
//if(ROUNDOFF(fDenominator) == 0.0f)
if(denominator == 0.0f)
{
// We won't risk a divide by zero, so set the tangent matrix to the identity matrix
VectorSet(tangent, 1, 0, 0);
VectorSet(bitangent, 0, 1, 0);
VectorSet(normal, 0, 0, 1);
}
else
{
// Calculate the reciprocal value once and for all (to achieve speed)
scale1 = 1.0f / denominator;
// T and B are calculated just as the equation in the article states
VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
(c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1,
(c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1);
VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
(-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1,
(-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1);
// The normal N is calculated as the cross product between T and B
CrossProduct(T, B, N);
#if 0
VectorCopy(T, tangent);
VectorCopy(B, bitangent);
VectorCopy(N, normal);
#else
// Calculate the reciprocal value once and for all (to achieve speed)
scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
(B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) +
(N[0] * T[1] * B[2] - N[2] * T[1] * B[0]));
// Calculate the inverse if the TBN matrix using the formula described in the article.
// We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix
CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
VectorNormalize(tangent);
CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
VectorNormalize(bitangent);
CrossProduct(B, N, C); normal[0] = C[2] * scale2;
CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
CrossProduct(T, B, C); normal[2] = C[2] * scale2;
VectorNormalize(normal);
#endif
}
}
#ifdef USE_VERT_TANGENT_SPACE
qboolean R_CalcTangentVectors(srfVert_t * dv[3])
{
@ -455,7 +144,8 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
/* do each vertex */
for(i = 0; i < 3; i++)
{
vec3_t bitangent, nxt;
vec4_t tangent;
vec3_t normal, bitangent, nxt;
// calculate s tangent vector
s = dv[i]->st[0] + 10.0f;
@ -464,12 +154,12 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
VectorNormalize(dv[i]->tangent);
VectorSubtract(tangent, dv[i]->xyz, tangent);
VectorNormalize(tangent);
// calculate t tangent vector
s = dv[i]->st[0];
@ -486,8 +176,11 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
VectorNormalize(bitangent);
// store bitangent handedness
CrossProduct(dv[i]->normal, dv[i]->tangent, nxt);
dv[i]->tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
R_VaoUnpackNormal(normal, dv[i]->normal);
CrossProduct(normal, tangent, nxt);
tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
R_VaoPackTangent(dv[i]->tangent, tangent);
// debug code
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,