Fix mesh tangent and bitangent vectors generation with OpenFBX backend by using MikkTSpace

This commit is contained in:
Wojtek Figat
2021-11-11 13:23:30 +01:00
parent ac347f0029
commit 6f16195b08
9 changed files with 2218 additions and 46 deletions

View File

@@ -17,6 +17,7 @@ void MeshData::Clear()
UVs.Clear();
Normals.Clear();
Tangents.Clear();
BitangentSigns.Clear();
LightmapUVs.Clear();
Colors.Clear();
BlendIndices.Clear();
@@ -44,6 +45,7 @@ void MeshData::SwapBuffers(MeshData& other)
UVs.Swap(other.UVs);
Normals.Swap(other.Normals);
Tangents.Swap(other.Tangents);
BitangentSigns.Swap(other.BitangentSigns);
LightmapUVs.Swap(other.LightmapUVs);
Colors.Swap(other.Colors);
BlendIndices.Swap(other.BlendIndices);
@@ -59,6 +61,7 @@ void MeshData::Release()
UVs.Resize(0);
Normals.Resize(0);
Tangents.Resize(0);
BitangentSigns.Resize(0);
LightmapUVs.Resize(0);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -72,6 +75,7 @@ void MeshData::InitFromModelVertices(ModelVertex19* vertices, uint32 verticesCou
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(verticesCount, false);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -97,6 +101,7 @@ void MeshData::InitFromModelVertices(ModelVertex18* vertices, uint32 verticesCou
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(verticesCount, false);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -121,6 +126,7 @@ void MeshData::InitFromModelVertices(ModelVertex15* vertices, uint32 verticesCou
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(0);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -144,6 +150,7 @@ void MeshData::InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(verticesCount, false);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -169,6 +176,7 @@ void MeshData::InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(verticesCount, false);
if (vb2)
{
@@ -206,6 +214,7 @@ void MeshData::InitFromModelVertices(VB0ElementType15* vb0, VB1ElementType15* vb
UVs.Resize(verticesCount, false);
Normals.Resize(verticesCount, false);
Tangents.Resize(verticesCount, false);
BitangentSigns.Resize(0);
LightmapUVs.Resize(0, false);
Colors.Resize(0);
BlendIndices.Resize(0);
@@ -283,6 +292,12 @@ bool MeshData::Pack2Model(WriteStream* stream) const
LOG(Error, "Invalid size of {0} stream.", TEXT("Tangents"));
return true;
}
bool hasBitangentSigns = BitangentSigns.HasItems();
if (hasBitangentSigns && BitangentSigns.Count() != verticiecCount)
{
LOG(Error, "Invalid size of {0} stream.", TEXT("BitangentSigns"));
return true;
}
bool hasLightmapUVs = LightmapUVs.HasItems();
if (hasLightmapUVs && LightmapUVs.Count() != verticiecCount)
{
@@ -314,15 +329,12 @@ bool MeshData::Pack2Model(WriteStream* stream) const
Vector3 normal = hasNormals ? Normals[i] : Vector3::UnitZ;
Vector3 tangent = hasTangents ? Tangents[i] : Vector3::UnitX;
Vector2 lightmapUV = hasLightmapUVs ? LightmapUVs[i] : Vector2::Zero;
// Calculate bitangent sign
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
Vector3 bitangentSign = hasBitangentSigns ? BitangentSigns[i] : Vector3::Dot(Vector3::Cross(Vector3::Normalize(Vector3::Cross(normal, tangent)), normal), tangent);
// Write vertex
vb1.TexCoord = Half2(uv);
vb1.Normal = Float1010102(normal * 0.5f + 0.5f, 0);
vb1.Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
vb1.Tangent = Float1010102(tangent * 0.5f + 0.5f, static_cast<byte>(bitangentSign < 0 ? 1 : 0));
vb1.LightmapUVs = Half2(lightmapUV);
stream->Write(&vb1);
@@ -405,6 +417,12 @@ bool MeshData::Pack2SkinnedModel(WriteStream* stream) const
LOG(Error, "Invalid size of {0} stream.", TEXT("Tangents"));
return true;
}
bool hasBitangentSigns = BitangentSigns.HasItems();
if (hasBitangentSigns && BitangentSigns.Count() != verticiecCount)
{
LOG(Error, "Invalid size of {0} stream.", TEXT("BitangentSigns"));
return true;
}
if (BlendIndices.Count() != verticiecCount)
{
LOG(Error, "Invalid size of {0} stream.", TEXT("BlendIndices"));
@@ -441,18 +459,15 @@ bool MeshData::Pack2SkinnedModel(WriteStream* stream) const
Vector2 uv = hasUVs ? UVs[i] : Vector2::Zero;
Vector3 normal = hasNormals ? Normals[i] : Vector3::UnitZ;
Vector3 tangent = hasTangents ? Tangents[i] : Vector3::UnitX;
Vector3 bitangentSign = hasBitangentSigns ? BitangentSigns[i] : Vector3::Dot(Vector3::Cross(Vector3::Normalize(Vector3::Cross(normal, tangent)), normal), tangent);
Int4 blendIndices = BlendIndices[i];
Vector4 blendWeights = BlendWeights[i];
// Calculate bitangent sign
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
// Write vertex
vb.Position = Positions[i];
vb.TexCoord = Half2(uv);
vb.Normal = Float1010102(normal * 0.5f + 0.5f, 0);
vb.Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
vb.Tangent = Float1010102(tangent * 0.5f + 0.5f, static_cast<byte>(bitangentSign < 0 ? 1 : 0));
vb.BlendIndices = Color32(blendIndices.X, blendIndices.Y, blendIndices.Z, blendIndices.W);
vb.BlendWeights = Half4(blendWeights);
stream->Write(&vb);
@@ -522,6 +537,7 @@ void MeshData::Merge(MeshData& other)
MERGE(UVs, Vector2::Zero);
MERGE(Normals, Vector3::Forward);
MERGE(Tangents, Vector3::Right);
MERGE(BitangentSigns, 1.0f);
MERGE(LightmapUVs, Vector2::Zero);
MERGE(Colors, Color::Black);
MERGE(BlendIndices, Int4::Zero);