From 6a0e9a3e8292550c5131e8548bd64046c2cb3abb Mon Sep 17 00:00:00 2001 From: ousnius Date: Wed, 18 Sep 2024 21:56:48 +0200 Subject: [PATCH] Fix locked normal indices being ignored for NiTriShapeData Only BSTriShape's version of RecalcNormals respected the NiIntegersExtraData for locked normal indices. --- include/Geometry.hpp | 12 +++++++++--- src/Geometry.cpp | 36 ++++++++++++++++++++++++++---------- src/NifFile.cpp | 4 ++-- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/include/Geometry.hpp b/include/Geometry.hpp index fc00cf6..c2fb0ca 100644 --- a/include/Geometry.hpp +++ b/include/Geometry.hpp @@ -204,7 +204,9 @@ class NiGeometryData : public NiCloneableStreamable { const std::vector* tris, const std::vector* uvs, const std::vector* norms); - virtual void RecalcNormals(const bool smooth = true, const float smoothThres = 60.0f); + virtual void RecalcNormals(const bool smooth = true, + const float smoothThres = 60.0f, + std::unordered_set* lockedIndices = nullptr); virtual void CalcTangentSpace(); }; @@ -769,7 +771,9 @@ class NiTriShapeData : public NiCloneableStreamable& tris) const override; void SetTriangles(const std::vector& tris) override; - void RecalcNormals(const bool smooth = true, const float smoothThres = 60.0f) override; + void RecalcNormals(const bool smooth = true, + const float smoothThres = 60.0f, + std::unordered_set* lockedIndices = nullptr) override; void CalcTangentSpace() override; }; @@ -809,7 +813,9 @@ class NiTriStripsData : public NiCloneableStreamable& tris) override; std::vector StripsToTris() const; - void RecalcNormals(const bool smooth = true, const float smoothThres = 60.0f) override; + void RecalcNormals(const bool smooth = true, + const float smoothThres = 60.0f, + std::unordered_set* lockedIndices = nullptr) override; void CalcTangentSpace() override; }; diff --git a/src/Geometry.cpp b/src/Geometry.cpp index ccf810c..c9d22f0 100644 --- a/src/Geometry.cpp +++ b/src/Geometry.cpp @@ -254,7 +254,7 @@ void NiGeometryData::notifyVerticesDelete(const std::vector& vertIndic EraseVectorIndices(uvSet, vertIndices); } -void NiGeometryData::RecalcNormals(const bool, const float) { +void NiGeometryData::RecalcNormals(const bool, const float, std::unordered_set*) { SetNormals(true); } @@ -889,11 +889,11 @@ void BSTriShape::SetEyeData(const std::vector& in) { static void CalculateNormals(const std::vector& verts, const std::vector& tris, - std::vector& norms, + std::vector& outNorms, const bool smooth, - float smoothThresh) { - // Zero norms - norms.clear(); + float smoothThresh, + std::unordered_set* lockedIndices = nullptr) { + std::vector norms; norms.resize(verts.size()); // Face normals @@ -932,6 +932,18 @@ static void CalculateNormals(const std::vector& verts, norms[matchset[j]] = seamNorms[j]; } } + + if (lockedIndices) { + outNorms.resize(norms.size()); + + // Move normals of indices that aren't locked only + for (uint32_t i = 0; i < static_cast(norms.size()); i++) { + if (lockedIndices->find(i) == lockedIndices->end()) + outNorms[i] = std::move(norms[i]); + } + } + else + outNorms = std::move(norms); } void BSTriShape::RecalcNormals(const bool smooth, @@ -940,7 +952,7 @@ void BSTriShape::RecalcNormals(const bool smooth, UpdateRawVertices(); SetNormals(true); - CalculateNormals(rawVertices, triangles, rawNormals, smooth, smoothThresh); + CalculateNormals(rawVertices, triangles, rawNormals, smooth, smoothThresh, lockedIndices); for (uint16_t i = 0; i < numVertices; i++) { if (lockedIndices) { @@ -1966,13 +1978,15 @@ void NiTriShapeData::SetTriangles(const std::vector& tris) { numTrianglePoints = numTriangles * 3; } -void NiTriShapeData::RecalcNormals(const bool smooth, const float smoothThresh) { +void NiTriShapeData::RecalcNormals(const bool smooth, + const float smoothThresh, + std::unordered_set* lockedIndices) { if (!HasNormals()) return; NiTriBasedGeomData::RecalcNormals(); - CalculateNormals(vertices, triangles, normals, smooth, smoothThresh); + CalculateNormals(vertices, triangles, normals, smooth, smoothThresh, lockedIndices); } void NiTriShapeData::CalcTangentSpace() { @@ -2133,7 +2147,9 @@ std::vector NiTriStripsData::StripsToTris() const { return GenerateTrianglesFromStrips(stripsInfo.points); } -void NiTriStripsData::RecalcNormals(const bool smooth, const float smoothThresh) { +void NiTriStripsData::RecalcNormals(const bool smooth, + const float smoothThresh, + std::unordered_set* lockedIndices) { if (!HasNormals()) return; @@ -2141,7 +2157,7 @@ void NiTriStripsData::RecalcNormals(const bool smooth, const float smoothThresh) std::vector tris = StripsToTris(); - CalculateNormals(vertices, tris, normals, smooth, smoothThresh); + CalculateNormals(vertices, tris, normals, smooth, smoothThresh, lockedIndices); } void NiTriStripsData::CalcTangentSpace() { diff --git a/src/NifFile.cpp b/src/NifFile.cpp index fdafbef..fe02638 100644 --- a/src/NifFile.cpp +++ b/src/NifFile.cpp @@ -3695,12 +3695,12 @@ void NifFile::CalcNormalsForShape(NiShape* shape, if (auto geomData = GetGeometryData(shape)) { if (geomData) - geomData->RecalcNormals(smooth, smoothThresh); + geomData->RecalcNormals(smooth, smoothThresh, lockedIndices.empty() ? nullptr : &lockedIndices); } else if (shape->HasType()) { auto bsTriShape = dynamic_cast(shape); if (bsTriShape) - bsTriShape->RecalcNormals(smooth, smoothThresh, &lockedIndices); + bsTriShape->RecalcNormals(smooth, smoothThresh, lockedIndices.empty() ? nullptr : &lockedIndices); } }