diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 3c759f90d..ab8960b35 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -55,6 +55,10 @@ class NAZARA_API NzMesh : public NzResource, NzResourceListener bool CreateStatic(); void Destroy(); + void GenerateNormals(); + void GenerateNormalsAndTangents(); + void GenerateTangents(); + const NzAxisAlignedBox& GetAABB() const; NzString GetAnimation() const; nzAnimationType GetAnimationType() const; diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 67143849b..fde4963af 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -262,6 +264,159 @@ void NzMesh::Destroy() } } +void NzMesh::GenerateNormals() +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + #endif + + for (NzSubMesh* subMesh : m_impl->subMeshes) + { + NzVertexMapper mapper1(subMesh); + unsigned int vertexCount = mapper1.GetVertexCount(); + for (unsigned int i = 0; i < vertexCount; ++i) + mapper1.SetNormal(i, NzVector3f::Zero()); + + mapper1.Unmap(); + + NzTriangleIterator iterator(subMesh); + do + { + NzVector3f pos0 = iterator.GetPosition(0); + + NzVector3f dv[2]; + dv[0] = iterator.GetPosition(1) - pos0; + dv[1] = iterator.GetPosition(2) - pos0; + + NzVector3f normal = dv[0].CrossProduct(dv[1]); + + for (unsigned int i = 0; i < 3; ++i) + iterator.SetNormal(i, iterator.GetNormal(i) + normal); + } + while (iterator.Advance()); + + NzVertexMapper mapper2(subMesh); + for (unsigned int i = 0; i < vertexCount; ++i) + mapper2.SetNormal(i, NzVector3f::Normalize(mapper2.GetNormal(i))); + } +} + +void NzMesh::GenerateNormalsAndTangents() +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + #endif + + for (NzSubMesh* subMesh : m_impl->subMeshes) + { + NzVertexMapper mapper1(subMesh); + unsigned int vertexCount = mapper1.GetVertexCount(); + for (unsigned int i = 0; i < vertexCount; ++i) + { + mapper1.SetNormal(i, NzVector3f::Zero()); + mapper1.SetTangent(i, NzVector3f::Zero()); + } + + mapper1.Unmap(); + + NzTriangleIterator iterator(subMesh); + do + { + NzVector3f pos0 = iterator.GetPosition(0); + NzVector2f uv0 = iterator.GetTexCoords(0); + + NzVector3f dv[2]; + dv[0] = iterator.GetPosition(1) - pos0; + dv[1] = iterator.GetPosition(2) - pos0; + + NzVector3f normal = dv[0].CrossProduct(dv[1]); + + NzVector2f duv[2]; + duv[0] = iterator.GetTexCoords(1) - uv0; + duv[1] = iterator.GetTexCoords(2) - uv0; + + float coef = 1.f / (duv[0].x*duv[1].y - duv[1].x*duv[0].y); + + NzVector3f tangent; + tangent.x = coef * (dv[0].x*duv[1].y + dv[1].x*(-duv[0].y)); + tangent.y = coef * (dv[0].y*duv[1].y + dv[1].y*(-duv[0].y)); + tangent.z = coef * (dv[0].z*duv[1].y + dv[1].z*(-duv[0].y)); + + for (unsigned int i = 0; i < 3; ++i) + { + iterator.SetNormal(i, iterator.GetNormal(i) + normal); + iterator.SetTangent(i, iterator.GetTangent(i) + tangent); + } + } + while (iterator.Advance()); + + NzVertexMapper mapper2(subMesh); + for (unsigned int i = 0; i < vertexCount; ++i) + { + mapper2.SetNormal(i, NzVector3f::Normalize(mapper2.GetNormal(i))); + mapper2.SetTangent(i, NzVector3f::Normalize(mapper2.GetTangent(i))); + } + } +} + +void NzMesh::GenerateTangents() +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + #endif + + for (NzSubMesh* subMesh : m_impl->subMeshes) + { + NzTriangleIterator iterator(subMesh); + do + { + NzVector3f pos0 = iterator.GetPosition(0); + NzVector2f uv0 = iterator.GetTexCoords(0); + + NzVector3f dv[2]; + dv[0] = iterator.GetPosition(1) - pos0; + dv[1] = iterator.GetPosition(2) - pos0; + + NzVector2f duv[2]; + duv[0] = iterator.GetTexCoords(1) - uv0; + duv[1] = iterator.GetTexCoords(2) - uv0; + + float ds[2]; + ds[0] = iterator.GetTexCoords(1).x - uv0.x; + ds[1] = iterator.GetTexCoords(2).x - uv0.x; + + NzVector3f ppt; + ppt.x = ds[0]*dv[1].x - dv[0].x*ds[1]; + ppt.y = ds[0]*dv[1].y - dv[0].y*ds[1]; + ppt.z = ds[0]*dv[1].z - dv[0].z*ds[1]; + ppt.Normalize(); + + for (unsigned int i = 0; i < 3; ++i) + { + NzVector3f normal = iterator.GetNormal(i); + float d = ppt.DotProduct(normal); + + NzVector3f tangent = ppt - (d * normal); + + iterator.SetTangent(i, tangent); + } + } + while (iterator.Advance()); + } +} + const NzAxisAlignedBox& NzMesh::GetAABB() const { #if NAZARA_UTILITY_SAFE