Skip to content

Commit

Permalink
Fix locked normal indices being ignored for NiTriShapeData
Browse files Browse the repository at this point in the history
Only BSTriShape's version of RecalcNormals respected the NiIntegersExtraData for locked normal indices.
  • Loading branch information
ousnius committed Sep 18, 2024
1 parent 9dfe61e commit 6a0e9a3
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
12 changes: 9 additions & 3 deletions include/Geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,9 @@ class NiGeometryData : public NiCloneableStreamable<NiGeometryData, NiObject> {
const std::vector<Triangle>* tris,
const std::vector<Vector2>* uvs,
const std::vector<Vector3>* 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<uint32_t>* lockedIndices = nullptr);
virtual void CalcTangentSpace();
};

Expand Down Expand Up @@ -769,7 +771,9 @@ class NiTriShapeData : public NiCloneableStreamable<NiTriShapeData, NiTriBasedGe
bool GetTriangles(std::vector<Triangle>& tris) const override;
void SetTriangles(const std::vector<Triangle>& 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<uint32_t>* lockedIndices = nullptr) override;
void CalcTangentSpace() override;
};

Expand Down Expand Up @@ -809,7 +813,9 @@ class NiTriStripsData : public NiCloneableStreamable<NiTriStripsData, NiTriBased
void SetTriangles(const std::vector<Triangle>& tris) override;
std::vector<Triangle> 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<uint32_t>* lockedIndices = nullptr) override;
void CalcTangentSpace() override;
};

Expand Down
36 changes: 26 additions & 10 deletions src/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ void NiGeometryData::notifyVerticesDelete(const std::vector<uint16_t>& vertIndic
EraseVectorIndices(uvSet, vertIndices);
}

void NiGeometryData::RecalcNormals(const bool, const float) {
void NiGeometryData::RecalcNormals(const bool, const float, std::unordered_set<uint32_t>*) {
SetNormals(true);
}

Expand Down Expand Up @@ -889,11 +889,11 @@ void BSTriShape::SetEyeData(const std::vector<float>& in) {

static void CalculateNormals(const std::vector<Vector3>& verts,
const std::vector<Triangle>& tris,
std::vector<Vector3>& norms,
std::vector<Vector3>& outNorms,
const bool smooth,
float smoothThresh) {
// Zero norms
norms.clear();
float smoothThresh,
std::unordered_set<uint32_t>* lockedIndices = nullptr) {
std::vector<Vector3> norms;
norms.resize(verts.size());

// Face normals
Expand Down Expand Up @@ -932,6 +932,18 @@ static void CalculateNormals(const std::vector<Vector3>& 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<uint32_t>(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,
Expand All @@ -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) {
Expand Down Expand Up @@ -1966,13 +1978,15 @@ void NiTriShapeData::SetTriangles(const std::vector<Triangle>& 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<uint32_t>* lockedIndices) {
if (!HasNormals())
return;

NiTriBasedGeomData::RecalcNormals();

CalculateNormals(vertices, triangles, normals, smooth, smoothThresh);
CalculateNormals(vertices, triangles, normals, smooth, smoothThresh, lockedIndices);
}

void NiTriShapeData::CalcTangentSpace() {
Expand Down Expand Up @@ -2133,15 +2147,17 @@ std::vector<Triangle> 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<uint32_t>* lockedIndices) {
if (!HasNormals())
return;

NiTriBasedGeomData::RecalcNormals();

std::vector<Triangle> tris = StripsToTris();

CalculateNormals(vertices, tris, normals, smooth, smoothThresh);
CalculateNormals(vertices, tris, normals, smooth, smoothThresh, lockedIndices);
}

void NiTriStripsData::CalcTangentSpace() {
Expand Down
4 changes: 2 additions & 2 deletions src/NifFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<BSTriShape>()) {
auto bsTriShape = dynamic_cast<BSTriShape*>(shape);
if (bsTriShape)
bsTriShape->RecalcNormals(smooth, smoothThresh, &lockedIndices);
bsTriShape->RecalcNormals(smooth, smoothThresh, lockedIndices.empty() ? nullptr : &lockedIndices);
}
}

Expand Down

0 comments on commit 6a0e9a3

Please sign in to comment.