// Copyright (C) 2015 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) : NzRefCounted(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 mapper(this); unsigned int vertexCount = GetVertexCount(); NzSparsePtr normals = mapper.GetComponentPtr(nzVertexComponent_Normal); NzSparsePtr positions = mapper.GetComponentPtr(nzVertexComponent_Position); for (unsigned int i = 0; i < vertexCount; ++i) normals[i].MakeZero(); NzTriangleIterator iterator(this); do { NzVector3f pos0 = positions[iterator[0]]; NzVector3f dv[2]; dv[0] = positions[iterator[1]] - pos0; dv[1] = positions[iterator[2]] - pos0; NzVector3f normal = dv[0].CrossProduct(dv[1]); for (unsigned int i = 0; i < 3; ++i) normals[iterator[i]] += normal; } while (iterator.Advance()); for (unsigned int i = 0; i < vertexCount; ++i) normals[i].Normalize(); } void NzSubMesh::GenerateNormalsAndTangents() { NzVertexMapper mapper(this); unsigned int vertexCount = GetVertexCount(); NzSparsePtr normals = mapper.GetComponentPtr(nzVertexComponent_Normal); NzSparsePtr positions = mapper.GetComponentPtr(nzVertexComponent_Position); NzSparsePtr tangents = mapper.GetComponentPtr(nzVertexComponent_Tangent); NzSparsePtr texCoords = mapper.GetComponentPtr(nzVertexComponent_TexCoord); for (unsigned int i = 0; i < vertexCount; ++i) { normals[i].MakeZero(); tangents[i].MakeZero(); } NzTriangleIterator iterator(this); do { NzVector3f pos0 = positions[iterator[0]]; NzVector3f dv[2]; dv[0] = positions[iterator[1]] - pos0; dv[1] = positions[iterator[2]] - pos0; NzVector3f normal = dv[0].CrossProduct(dv[1]); NzVector2f uv0 = texCoords[iterator[0]]; NzVector2f duv[2]; duv[0] = texCoords[iterator[1]] - uv0; duv[1] = texCoords[iterator[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) { nzUInt32 index = iterator[i]; normals[index] += normal; tangents[index] += tangent; } } while (iterator.Advance()); for (unsigned int i = 0; i < vertexCount; ++i) { normals[i].Normalize(); tangents[i].Normalize(); } } void NzSubMesh::GenerateTangents() { NzVertexMapper mapper(this); NzSparsePtr normals = mapper.GetComponentPtr(nzVertexComponent_Normal); NzSparsePtr positions = mapper.GetComponentPtr(nzVertexComponent_Position); NzSparsePtr tangents = mapper.GetComponentPtr(nzVertexComponent_Tangent); NzSparsePtr texCoords = mapper.GetComponentPtr(nzVertexComponent_TexCoord); NzTriangleIterator iterator(this); do { NzVector3f pos0 = positions[iterator[0]]; NzVector2f uv0 = texCoords[iterator[0]]; NzVector2f uv1 = texCoords[iterator[1]]; NzVector2f uv2 = texCoords[iterator[2]]; NzVector3f dv[2]; dv[0] = positions[iterator[1]] - pos0; dv[1] = positions[iterator[2]] - pos0; NzVector2f duv[2]; duv[0] = uv1 - uv0; duv[1] = uv2 - uv0; float ds[2]; ds[0] = uv1.x - uv0.x; ds[1] = uv2.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 = normals[iterator[i]]; float d = ppt.DotProduct(normal); tangents[iterator[i]] = ppt - (d * normal); } } 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; }