// Copyright (C) 2013 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #include #include NzSubMesh::NzSubMesh(const NzMesh* parent) : NzResource(false), // Un SubMesh n'est pas persistant par défaut m_primitiveMode(nzPrimitiveMode_TriangleList), m_parent(parent), m_matIndex(0) { } NzSubMesh::~NzSubMesh() = default; void NzSubMesh::GenerateNormals() { NzVertexMapper mapper1(this); unsigned int vertexCount = mapper1.GetVertexCount(); for (unsigned int i = 0; i < vertexCount; ++i) mapper1.SetNormal(i, NzVector3f::Zero()); mapper1.Unmap(); NzTriangleIterator iterator(this); 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(this); for (unsigned int i = 0; i < vertexCount; ++i) mapper2.SetNormal(i, NzVector3f::Normalize(mapper2.GetNormal(i))); } void NzSubMesh::GenerateNormalsAndTangents() { NzVertexMapper mapper1(this); 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(this); do { NzVector3f pos0 = iterator.GetPosition(0); NzVector2f uv0 = iterator.GetTexCoord(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.GetTexCoord(1) - uv0; duv[1] = iterator.GetTexCoord(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(this); 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 NzSubMesh::GenerateTangents() { NzTriangleIterator iterator(this); do { NzVector3f pos0 = iterator.GetPosition(0); NzVector2f uv0 = iterator.GetTexCoord(0); NzVector3f dv[2]; dv[0] = iterator.GetPosition(1) - pos0; dv[1] = iterator.GetPosition(2) - pos0; NzVector2f duv[2]; duv[0] = iterator.GetTexCoord(1) - uv0; duv[1] = iterator.GetTexCoord(2) - uv0; float ds[2]; ds[0] = iterator.GetTexCoord(1).x - uv0.x; ds[1] = iterator.GetTexCoord(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 NzMesh* NzSubMesh::GetParent() const { return m_parent; } nzPrimitiveMode NzSubMesh::GetPrimitiveMode() const { return m_primitiveMode; } unsigned int NzSubMesh::GetTriangleCount() const { const NzIndexBuffer* indexBuffer = GetIndexBuffer(); unsigned int indexCount; if (indexBuffer) indexCount = indexBuffer->GetIndexCount(); else indexCount = GetVertexCount(); switch (m_primitiveMode) { case nzPrimitiveMode_LineList: case nzPrimitiveMode_LineStrip: case nzPrimitiveMode_PointList: return 0; case nzPrimitiveMode_TriangleFan: return (indexCount - 1) / 2; case nzPrimitiveMode_TriangleList: return indexCount / 3; case nzPrimitiveMode_TriangleStrip: return indexCount - 2; } NazaraError("Primitive mode not handled (0x" + NzString::Number(m_primitiveMode, 16) + ')'); return 0; } unsigned int NzSubMesh::GetMaterialIndex() const { return m_matIndex; } void NzSubMesh::SetPrimitiveMode(nzPrimitiveMode mode) { m_primitiveMode = mode; } void NzSubMesh::SetMaterialIndex(unsigned int matIndex) { m_matIndex = matIndex; }