summaryrefslogtreecommitdiff
path: root/Runtime/Geometry/TangentSpaceCalculation.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Geometry/TangentSpaceCalculation.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Geometry/TangentSpaceCalculation.cpp')
-rw-r--r--Runtime/Geometry/TangentSpaceCalculation.cpp534
1 files changed, 534 insertions, 0 deletions
diff --git a/Runtime/Geometry/TangentSpaceCalculation.cpp b/Runtime/Geometry/TangentSpaceCalculation.cpp
new file mode 100644
index 0000000..f7b17f1
--- /dev/null
+++ b/Runtime/Geometry/TangentSpaceCalculation.cpp
@@ -0,0 +1,534 @@
+#include "UnityPrefix.h"
+#include "TangentSpaceCalculation.h"
+#include "Runtime/Math/Matrix3x3.h"
+#include "Runtime/Math/Vector2.h"
+#include "Plane.h"
+#include <vector>
+
+using std::vector;
+/*
+void CreateTangentSpaceTangents(const Vector3f* vertex, const Vector2f* texcoord, const Vector3f* normals, Matrix3x3f* avgOrthonormalBases, int vertexCount, const UInt16* indices, int triangleCount)
+{
+ Vector3f *tan1 = new Vector3f[vertexCount * 2];
+ Vector3f *tan2 = tan1 + vertexCount;
+ memset(tan1, 0, vertexCount * sizeof(Vector3f) * 2);
+
+ for (int a = 0; a < triangleCount; a++)
+ {
+ int i1 = indices[0];
+ int i2 = indices[1];
+ int i3 = indices[2];
+
+ const Vector3f& v1 = vertex[i1];
+ const Vector3f& v2 = vertex[i2];
+ const Vector3f& v3 = vertex[i3];
+
+ const Vector2f& w1 = texcoord[i1];
+ const Vector2f& w2 = texcoord[i2];
+ const Vector2f& w3 = texcoord[i3];
+
+ float x1 = v2.x - v1.x;
+ float x2 = v3.x - v1.x;
+ float y1 = v2.y - v1.y;
+ float y2 = v3.y - v1.y;
+ float z1 = v2.z - v1.z;
+ float z2 = v3.z - v1.z;
+
+ float s1 = w2.x - w1.x;
+ float s2 = w3.x - w1.x;
+ float t1 = w2.y - w1.y;
+ float t2 = w3.y - w1.y;
+
+ float r = 1.0F / (s1 * t2 - s2 * t1);
+ Vector3f sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
+ Vector3f tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
+
+ tan1[i1] += sdir;
+ tan1[i2] += sdir;
+ tan1[i3] += sdir;
+
+ tan2[i1] += tdir;
+ tan2[i2] += tdir;
+ tan2[i3] += tdir;
+
+ indices += 3;
+ }
+
+
+ for (long a = 0; a < vertexCount; a++)
+ {
+ Vector3f normal = normals[a];
+ Vector3f tangent = tan1[a];
+
+
+ // Gram-Schmidt orthogonalize
+ (tangent - normal * (normal * tangent)));
+
+ // Calculate handedness
+ //tangent[a].w = (normal % tangent * tan2[a] < 0.0F) ? -1.0F : 1.0F;
+
+ avgOrthonormalBases[a].SetOrthoNormalBasis (tangent, Cross (normal, tangent), normal);
+ }
+
+ delete[] tan1;
+}*/
+
+/*
+void CreateTangentSpaceTangents (const Vector3f* pPositions, const Vector2f* tex, const Vector3f* normals, Matrix3x3f* avgOrthonormalBases, int vertexCount, const UInt16* indices, int faceCount)
+{
+ vector<Vector3f> sVector, tVector;
+ vector<Vector3f> avgS, avgT;
+
+ avgS.resize (vertexCount);
+ avgT.resize (vertexCount);
+
+ sVector.reserve (faceCount * 3);
+ tVector.reserve (faceCount * 3);
+
+ // for each face, calculate its S,T & SxT vector, & store its edges
+ for (int f = 0; f < faceCount * 3; f += 3 )
+ {
+ Vector3f edge0;
+ Vector3f edge1;
+ Vector3f s;
+ Vector3f t;
+
+ // create an edge out of x, s and t
+ edge0.x = pPositions[ indices[ f + 1 ] ].x - pPositions[ indices[ f ] ].x;
+ edge0.y = tex[ indices[ f + 1 ] ].x - tex[ indices[ f ] ].x;
+ edge0.z = tex[ indices[ f + 1 ] ].y - tex[ indices[ f ] ].y;
+
+ // create an edge out of x, s and t
+ edge1.x = pPositions[ indices[ f + 2 ] ].x - pPositions[ indices[ f ] ].x;
+ edge1.y = tex[ indices[ f + 2 ] ].x - tex[ indices[ f ] ].x;
+ edge1.z = tex[ indices[ f + 2 ] ].y - tex[ indices[ f ] ].y;
+
+ Vector3f sxt = Cross (edge0, edge1);
+
+ float a = sxt.x;
+ float b = sxt.y;
+ float c = sxt.z;
+
+ float ds_dx = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ ds_dx = -b / a;
+
+ float dt_dx = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ dt_dx = -c / a;
+
+ // create an edge out of y, s and t
+ edge0.x = pPositions[ indices[ f + 1 ] ].y - pPositions[ indices[ f ] ].y;
+ // create an edge out of y, s and t
+ edge1.x = pPositions[ indices[ f + 2 ] ].y - pPositions[ indices[ f ] ].y;
+
+ sxt = Cross (edge0, edge1);
+
+ a = sxt.x;
+ b = sxt.y;
+ c = sxt.z;
+
+ float ds_dy = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ ds_dy = -b / a;
+
+ float dt_dy = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ dt_dy = -c / a;
+
+ // create an edge out of z, s and t
+ edge0.x = pPositions[ indices[ f + 1 ] ].z - pPositions[ indices[ f ] ].z;
+ // create an edge out of z, s and t
+ edge1.x = pPositions[ indices[ f + 2 ] ].z - pPositions[ indices[ f ] ].z;
+
+ sxt = Cross (edge0, edge1);
+
+ a = sxt.x;
+ b = sxt.y;
+ c = sxt.z;
+
+ float ds_dz = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ ds_dz = -b / a;
+
+ float dt_dz = 0.0F;
+ if ( Abs( a ) > Vector3f::epsilon )
+ dt_dz = -c / a;
+
+ // generate coordinate frame from the gradients
+ s = Vector3f( ds_dx, ds_dy, ds_dz );
+ t = Vector3f( dt_dx, dt_dy, dt_dz );
+
+ s = NormalizeSafe (s);
+ t = NormalizeSafe (t);
+
+ // save vectors for this face
+ sVector.push_back( s );
+ tVector.push_back( t );
+ }
+
+
+ for ( int p = 0; p < vertexCount; p ++ )
+ {
+ avgS[p] = Vector3f::zero;
+ avgT[p] = Vector3f::zero;
+ }
+
+ // go through faces and add up the bases for each vertex
+ for ( int face = 0; face < faceCount; ++face )
+ {
+ // sum bases, so we smooth the tangent space across edges
+ avgS[ indices[ face * 3 ] ] += sVector[ face ];
+ avgT[ indices[ face * 3 ] ] += tVector[ face ];
+
+ avgS[ indices[ face * 3 + 1 ] ] += sVector[ face ];
+ avgT[ indices[ face * 3 + 1 ] ] += tVector[ face ];
+
+ avgS[ indices[ face * 3 + 2 ] ] += sVector[ face ];
+ avgT[ indices[ face * 3 + 2 ] ] += tVector[ face ];
+ }
+
+ // now renormalize
+ for ( int p = 0; p < vertexCount; p ++ )
+ {
+ Vector3f normal = normals[p];
+
+
+ //OrthoNormalize (&normal, &avgS[p], &avgT[p]);
+
+ avgOrthonormalBases[p].SetOrthoNormalBasis (avgS[p], avgT[p], normal);
+
+ #if DEBUGMODE
+ float det = avgOrthonormalBases[p].GetDeterminant ();
+ AssertIf (!CompareApproximately (det, 1.0F,0.001) && !CompareApproximately (det, -1.0F,0.001));
+ #endif
+// AssertIf (!CompareApproximately (avgOrthonormalBases[p].MultiplyPoint3Transpose (Vector3f (0,0,1)), normal));
+ }
+}*/
+
+/*
+void CreateTangentSpaceTangents (const Vector3f* pPositions, const Vector2f* tex, const Vector3f* normals, Matrix3x3f* avgOrthonormalBases, int vertexCount, const UInt16* indices, int faceCount)
+{
+
+
+ Vector3f v0,v1,v2, tanu, tanv;
+
+ Vector3f p0,p1,p2;
+
+ Vector3f d1,d2;
+
+ float uv[3][2],det,u,v,l1,l2;
+
+ int i,j,k;
+ vector<Vector3f> sVector, tVector;
+ vector<Vector3f> avgS, avgT;
+
+ avgS.resize (vertexCount);
+ avgT.resize (vertexCount);
+
+ sVector.reserve (faceCount * 3);
+ tVector.reserve (faceCount * 3);
+
+ for( i=0;i<vertexCount;i++ )
+
+ {
+
+ sVector[i]=Vector3f(0.0, 0.0, 0.0);
+
+ tVector[i]=Vector3f(0.0, 0.0, 0.0);
+
+ }
+
+ k=0;
+ for( i=0;i<faceCount;i++,k+=3 )
+
+ {
+
+ v0=*((Vector3f *)&pPositions[indices[k]]);
+
+ v1=*((Vector3f *)&pPositions[indices[k+1]])-v0;
+
+ v2=*((Vector3f *)&pPositions[indices[k+2]])-v0;
+
+ uv[0][0]=-tex[indices[k]].x;
+
+ uv[0][1]=tex[indices[k]].y;
+
+ uv[1][0]=-tex[indices[k+1]].x-uv[0][0];
+
+ uv[1][1]=tex[indices[k+1]].y-uv[0][1];
+
+ uv[2][0]=-tex[indices[k+2]].x-uv[0][0];
+
+ uv[2][1]=tex[indices[k+2]].y-uv[0][1];
+
+ det=(uv[1][0]*uv[2][1])-(uv[2][0]*uv[1][1]);
+
+
+
+ if (fabsf(det)<0.000000001f){
+ continue;
+ }
+
+ u=0; v=0;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p0=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ u=1; v=0;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p1=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ u=0; v=1;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p2=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ d1=p2-p0;
+
+ d2=p1-p0;
+
+ l1=Magnitude(d1);
+
+ l2=Magnitude(d2);
+
+ d1*=1.0f/l1;
+
+ d2*=1.0f/l2;
+
+
+
+ j=indices[k];
+
+ sVector[j].x+=d1.x; sVector[j].y+=d1.y; sVector[j].z+=d1.z;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+
+
+ j=indices[k+1];
+
+ sVector[j].x+=d1.x; sVector[j].y+=d1.y; sVector[j].z+=d1.z;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+
+
+ j=indices[k+2];
+
+ sVector[j].x+=d1.x; sVector[j].y+=d1.y; sVector[j].z+=d1.z;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+ }
+
+
+
+ for( i=0;i<vertexCount;i++ )
+
+ {
+
+ //v0.vec(vert[i].tanu[0],vert[i].tanu[1],vert[i].tanu[2]);
+ v0 = Vector3f(sVector[i].x,sVector[i].y,sVector[i].z);
+ //v0.normalize();
+ v0 = NormalizeRobust(v0);
+
+ //v1.vec(vert[i].tanv[0],vert[i].tanv[1],vert[i].tanv[2]);
+ v1 = Vector3f(tVector[i].x,tVector[i].y,tVector[i].z);
+ //v1 = NormalizeRobust(v1);
+
+ Vector3f n(normals[i].x,normals[i].y,normals[i].z);
+
+ if (SqrMagnitude(v1)<0.0001f)
+ {
+ v1 = Cross(n,v0);
+ }
+
+ v1 = NormalizeRobust(v1);
+
+
+ sVector[i].x=v0.x;
+
+ sVector[i].y=v0.y;
+
+ sVector[i].z=v0.z;
+
+ tVector[i].x=v1.x;
+
+ tVector[i].y=v1.y;
+
+ tVector[i].z=v1.z;
+
+ avgOrthonormalBases[i].SetOrthoNormalBasis (tVector[i], sVector[i], n);
+ }
+
+}*/
+
+void CreateTangentSpaceTangents (const Vector3f* pPositions, const Vector2f* tex, const Vector3f* normals, Matrix3x3f* avgOrthonormalBases, int vertexCount, const int* indices, int faceCount)
+{
+
+
+ Vector3f v0,v1,v2, tanu, tanv;
+
+ Vector3f p0,p1,p2;
+
+ Vector3f d1,d2;
+
+ float uv[3][2],det,u,v,l1,l2;
+
+ int i,j,k;
+ vector<Vector3f> sVector, tVector;
+ vector<Vector3f> avgS, avgT;
+
+ avgS.resize (vertexCount);
+ avgT.resize (vertexCount);
+
+ sVector.reserve (faceCount * 3);
+ tVector.reserve (faceCount * 3);
+
+ for( i=0;i<vertexCount;i++ )
+
+ {
+
+ sVector[i]=Vector3f(0.0, 0.0, 0.0);
+
+ tVector[i]=Vector3f(0.0, 0.0, 0.0);
+
+ }
+
+ k=0;
+ for( i=0;i<faceCount;i++,k+=3 )
+
+ {
+
+ v0=*((Vector3f *)&pPositions[indices[k]]);
+
+ v1=*((Vector3f *)&pPositions[indices[k+1]])-v0;
+
+ v2=*((Vector3f *)&pPositions[indices[k+2]])-v0;
+
+ uv[0][0]=tex[indices[k]].x;
+
+ uv[0][1]=tex[indices[k]].y;
+
+ uv[1][0]=tex[indices[k+1]].x-uv[0][0];
+
+ uv[1][1]=tex[indices[k+1]].y-uv[0][1];
+
+ uv[2][0]=tex[indices[k+2]].x-uv[0][0];
+
+ uv[2][1]=tex[indices[k+2]].y-uv[0][1];
+
+ det=(uv[1][0]*uv[2][1])-(uv[2][0]*uv[1][1]);
+
+
+
+ if (fabsf(det)<0.000001f){
+ continue;
+ }
+
+ u=0; v=0;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p0=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ u=1; v=0;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p1=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ u=0; v=1;
+
+ u-=uv[0][0]; v-=uv[0][1];
+
+ p2=v0+v1*((u*uv[2][1]-uv[2][0]*v)/det)+v2*((uv[1][0]*v-u*uv[1][1])/det);
+
+
+
+ d1=p2-p0;
+
+ d2=p1-p0;
+
+ l1=Magnitude(d1);
+
+ l2=Magnitude(d2);
+
+ d1*=1.0f/l1;
+
+ d2*=1.0f/l2;
+
+
+
+ j=indices[k];
+
+ sVector[j] += d1;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+
+
+ j=indices[k+1];
+
+ sVector[j].x+=d1.x; sVector[j].y+=d1.y; sVector[j].z+=d1.z;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+
+
+ j=indices[k+2];
+
+ sVector[j].x+=d1.x; sVector[j].y+=d1.y; sVector[j].z+=d1.z;
+
+ tVector[j].x+=d2.x; tVector[j].y+=d2.y; tVector[j].z+=d2.z;
+
+ }
+
+
+
+ for( i=0;i<vertexCount;i++ )
+
+ {
+
+ v0 = Vector3f(sVector[i].x,sVector[i].y,sVector[i].z);
+ v0 = NormalizeRobust(v0);
+
+ v1 = Vector3f(tVector[i].x,tVector[i].y,tVector[i].z);
+
+ Vector3f n(normals[i].x,normals[i].y,normals[i].z);
+
+ if (SqrMagnitude(v1)<0.0001f)
+ {
+ v1 = Cross(v0,n);
+ }
+ v1 = NormalizeRobust(v1);
+
+
+ sVector[i]=v0;
+
+ tVector[i].x=v1.x;
+
+ tVector[i].y=v1.y;
+
+ tVector[i].z=v1.z;
+
+ avgOrthonormalBases[i].SetOrthoNormalBasis (tVector[i], sVector[i], n);
+ }
+
+}
+