屏幕截图:http://1drv.ms/1C9fgyl 请注意,正常缓冲区非常奇怪。我在此链接中使用方法:http://www.terathon.com/code/tangent.html
织物切线在左半侧和右半侧之间非常不同。 我不知道发生了什么。
我测试了另一个两个人的场景并把它们放在其他使用相同方法来计算TBN的人身上并得到同样的问题。 我的algrithom中的错误是什么?
bool OBJModel_Loader::BuildTangent(std::vector<OBJModel* >& Objects)
{
for (OBJModel* actor : Objects)
{
PracEngLogf("BuildTangent For Model: %s! \n", actor->Name.c_str());
int cnt = actor->VertexBuffer.size();
PEVector3* tan1 = new PEVector3[cnt * 2];
PEVector3* tan2 = tan1 + cnt;
ZeroMemory(tan1, cnt*sizeof(PEVector3) * 2);
for (size_t i = 0; i < actor->FaceInfos.size(); i+=3)
{
int Idx1 = actor->FaceInfos[i].VertexIdx;
int Idx2 = actor->FaceInfos[i + 1].VertexIdx;
int Idx3 = actor->FaceInfos[i + 2].VertexIdx;
const PEFloat3& v1 = actor->VertexBuffer[Idx1];
const PEFloat3& v2 = actor->VertexBuffer[Idx2];
const PEFloat3& v3 = actor->VertexBuffer[Idx3];
const PEFloat2& w1 = actor->UVs[actor->FaceInfos[i].UVIdx];
const PEFloat2& w2 = actor->UVs[actor->FaceInfos[i+1].UVIdx];
const PEFloat2& w3 = actor->UVs[actor->FaceInfos[i+2].UVIdx];
PEVector3 E1(v2.X - v1.X, v2.Y - v1.Y, v2.Z - v1.Z);
PEVector3 E2(v3.X - v1.X, v3.Y - v1.Y, v3.Z - v1.Z);
PEFloat2 St1 ( w2.X - w1.X, w2.Y - w1.Y );
PEFloat2 St2 ( w3.X - w1.X, w3.Y - w1.Y );
PEVector3 sDir;
PEVector3 tDir;
float r = St1.X*St2.Y - St2.X*St1.Y;
if (fabs(r) < 1e-6f)
{
sDir = PEVector3(1.0f, .0f, .0f);
tDir = PEVector3(.0f, 1.0f, .0f);
}
else
{
r = 1.0f / r;
sDir = PEVector3((St2.Y*E1.x - St1.Y*E2.x)*r, (St2.Y*E1.y - St1.Y*E2.y)*r, (St2.Y*E1.z - St1.Y*E2.z)*r);
tDir = PEVector3((St1.X*E2.x - St2.X*E1.x)*r, (St1.X*E2.y - St2.X*E1.y)*r, (St1.X*E2.z - St2.X*E1.z)*r);
}
tan1[Idx1] += sDir;
tan1[Idx2] += sDir;
tan1[Idx3] += sDir;
tan2[Idx1] += tDir;
tan2[Idx2] += tDir;
tan2[Idx3] += tDir;
}
for (size_t i = 0; i < actor->FaceInfos.size(); i++)
{
int Idx = actor->FaceInfos[i].VertexIdx;
const PEVector3& N = actor->VertexNormal[actor->FaceInfos[i].NormalIdx];
const PEVector3& T = tan1[Idx];
PEVector3 adjTangent = T - N * PEVector3::Dot(N, T);
adjTangent.Normalize();
actor->VertexTangent[Idx] = adjTangent;
actor->VertexTangent[Idx].w = PEVector3::Dot(N.Cross(T), tan2[Idx]) < .0f ? -1.0f : 1.0f;
}
delete[] tan1;
}
return true;
}