technomage
18-02-2007, 10:02 PM
Hi people. this is not competition related. :)
I'm using Opengl to play with Normal mapping for the Alert figher project. I'm having problems calculating the Tanget and BinNormal vectors from the data have. Here is the code I came up with, can anyone see any problems (it's converted from C++, as always). Or even better has some code that works already :wink:.
function ROUNDOFF(d: Single): Single;
begin
//ROUNDOFF here is a macro that sets a value to 0.0f if the value is a very small
// value, such as > -0.001f and <0> -0.001) and (Result < 0.001) then Result := 0.0;
end;
procedure FindInvTBN(v0,v1,v2: TVector;t0,t1,t2:TTextureCoordinate;
var InvNormal: TVector; var InvBinormal: TVector; var InvTangent: TVector);
var v2v1, v3v1: TVector;
c2c1_T, c2c1_B: Single;
c3c1_T, c3c1_B: Single;
fDenominator, fScale1, fScale2: Single;
T,B,N: TVector;
begin
//Calculate the vectors from the current vertex
//to the two other vertices in the triangle
v2v1 := VectorSub(v0,v2);
v3v1 := VectorSub(v1,v0);
//Calculate the “direction” of the triangle based on texture coordinates.
c2c1_T := t0.u - t2.u;
c2c1_B := t0.v - t2.v;
c3c1_T := t1.u - t2.u;
c3c1_B := t1.v - t2.v;
//Look at the references for more explanation for this one.
fDenominator := c2c1_T * c3c1_B - c3c1_T * c2c1_B;
if ROUNDOFF(fDenominator) = 0.0 then
begin
//We won't risk a divide by zero, so set the tangent matrix to the
//identity matrix
InvTangent := NewVector(1.0, 0.0, 0.0);
InvBinormal := NewVector(0.0, 1.0, 0.0);
InvNormal := NewVector(0.0, 0.0, 1.0);
end
else
begin
fScale1 := 1.0 / fDenominator;
T := NewVector((c3c1_B * v2v1.x - c2c1_B * v3v1.x) * fscale1,
(c3c1_B * v2v1.y - c2c1_B * v3v1.y) * fScale1,
(c3c1_B * v2v1.z - c2c1_B * v3v1.z) * fScale1);
B := NewVector((-c3c1_T * v2v1.x + c2c1_T * v3v1.x) * fScale1,
(c3c1_T * v2v1.y + c2c1_T * v3v1.y) * fScale1,
(-c3c1_T * v2v1.z + c2c1_T * v3v1.z) * fScale1);
N := CrossProduct(T, B);
//This is where programmers should break up the function to smooth the tangent, binormal and
// normal values. */
//Look at “Derivation of the Tangent Space Matrix” for more information.
fScale2 := 1.0 / ((T.x * B.y * N.z - T.z * B.y * N.x) +
(B.x * N.y * T.z - B.z * N.y * T.x) +
(N.x * T.y * B.z - N.z * T.y * B.x));
InvTangent := NewVector(CrossProduct(B,N).x * fScale2,
CrossProduct((VectorScale(N, -1)),T).x * fScale2,
CrossProduct(T,B).x * fScale2 );
InvTangent := VectorNormalize(InvTangent);
InvBinormal := NewVector(CrossProduct(VectorScale(B, -1), N).y * fScale2,
CrossProduct(N,T).y * fScale2,
CrossProduct(VectorScale(T, -1), B).y * fScale2);
InvBinormal := VectorNormalize(InvBinormal);
InvNormal := NewVector(CrossProduct(B,N).z * fScale2,
CrossProduct(VectorScale(N, -1), T).z * fScale2,
CrossProduct(T,B).z * fScale2);
InvNormal := VectorNormalize(InvNormal);
end;
end;
I'm using Opengl to play with Normal mapping for the Alert figher project. I'm having problems calculating the Tanget and BinNormal vectors from the data have. Here is the code I came up with, can anyone see any problems (it's converted from C++, as always). Or even better has some code that works already :wink:.
function ROUNDOFF(d: Single): Single;
begin
//ROUNDOFF here is a macro that sets a value to 0.0f if the value is a very small
// value, such as > -0.001f and <0> -0.001) and (Result < 0.001) then Result := 0.0;
end;
procedure FindInvTBN(v0,v1,v2: TVector;t0,t1,t2:TTextureCoordinate;
var InvNormal: TVector; var InvBinormal: TVector; var InvTangent: TVector);
var v2v1, v3v1: TVector;
c2c1_T, c2c1_B: Single;
c3c1_T, c3c1_B: Single;
fDenominator, fScale1, fScale2: Single;
T,B,N: TVector;
begin
//Calculate the vectors from the current vertex
//to the two other vertices in the triangle
v2v1 := VectorSub(v0,v2);
v3v1 := VectorSub(v1,v0);
//Calculate the “direction” of the triangle based on texture coordinates.
c2c1_T := t0.u - t2.u;
c2c1_B := t0.v - t2.v;
c3c1_T := t1.u - t2.u;
c3c1_B := t1.v - t2.v;
//Look at the references for more explanation for this one.
fDenominator := c2c1_T * c3c1_B - c3c1_T * c2c1_B;
if ROUNDOFF(fDenominator) = 0.0 then
begin
//We won't risk a divide by zero, so set the tangent matrix to the
//identity matrix
InvTangent := NewVector(1.0, 0.0, 0.0);
InvBinormal := NewVector(0.0, 1.0, 0.0);
InvNormal := NewVector(0.0, 0.0, 1.0);
end
else
begin
fScale1 := 1.0 / fDenominator;
T := NewVector((c3c1_B * v2v1.x - c2c1_B * v3v1.x) * fscale1,
(c3c1_B * v2v1.y - c2c1_B * v3v1.y) * fScale1,
(c3c1_B * v2v1.z - c2c1_B * v3v1.z) * fScale1);
B := NewVector((-c3c1_T * v2v1.x + c2c1_T * v3v1.x) * fScale1,
(c3c1_T * v2v1.y + c2c1_T * v3v1.y) * fScale1,
(-c3c1_T * v2v1.z + c2c1_T * v3v1.z) * fScale1);
N := CrossProduct(T, B);
//This is where programmers should break up the function to smooth the tangent, binormal and
// normal values. */
//Look at “Derivation of the Tangent Space Matrix” for more information.
fScale2 := 1.0 / ((T.x * B.y * N.z - T.z * B.y * N.x) +
(B.x * N.y * T.z - B.z * N.y * T.x) +
(N.x * T.y * B.z - N.z * T.y * B.x));
InvTangent := NewVector(CrossProduct(B,N).x * fScale2,
CrossProduct((VectorScale(N, -1)),T).x * fScale2,
CrossProduct(T,B).x * fScale2 );
InvTangent := VectorNormalize(InvTangent);
InvBinormal := NewVector(CrossProduct(VectorScale(B, -1), N).y * fScale2,
CrossProduct(N,T).y * fScale2,
CrossProduct(VectorScale(T, -1), B).y * fScale2);
InvBinormal := VectorNormalize(InvBinormal);
InvNormal := NewVector(CrossProduct(B,N).z * fScale2,
CrossProduct(VectorScale(N, -1), T).z * fScale2,
CrossProduct(T,B).z * fScale2);
InvNormal := VectorNormalize(InvNormal);
end;
end;