Skip to content

Commit

Permalink
Fix UV generation on deformed chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
SirLynix committed Nov 6, 2024
1 parent 524b2b9 commit 1e9b4fa
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 20 deletions.
6 changes: 5 additions & 1 deletion include/CommonLib/Chunk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ namespace tsom
virtual void BuildMesh(std::vector<Nz::UInt32>& indices, const Nz::Vector3f& center, const Nz::FunctionRef<VertexAttributes(Nz::UInt32 count)>& addVertices) const;

virtual std::optional<Nz::Vector3ui> ComputeCoordinates(const Nz::Vector3f& position) const = 0;
virtual Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> ComputeVoxelCorners(const Nz::Vector3ui& indices) const = 0;
virtual Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> ComputeVoxelCorners(const Nz::Vector3ui& indices) const;

virtual void DeformNormals(Nz::SparsePtr<Nz::Vector3f> normals, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const;
virtual void DeformNormalsAndTangents(Nz::SparsePtr<Nz::Vector3f> normals, Nz::SparsePtr<Nz::Vector3f> tangents, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const;
virtual bool DeformPositions(Nz::SparsePtr<Nz::Vector3f> positions, std::size_t positionCount) const;

virtual void Deserialize(Nz::ByteStream& byteStream);

Expand Down
5 changes: 5 additions & 0 deletions include/CommonLib/DeformedChunk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ namespace tsom
std::optional<Nz::Vector3ui> ComputeCoordinates(const Nz::Vector3f& position) const override;
Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> ComputeVoxelCorners(const Nz::Vector3ui& indices) const override;

void DeformNormals(Nz::SparsePtr<Nz::Vector3f> normals, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const override;
void DeformNormalsAndTangents(Nz::SparsePtr<Nz::Vector3f> normals, Nz::SparsePtr<Nz::Vector3f> tangents, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const override;
bool DeformPositions(Nz::SparsePtr<Nz::Vector3f> positions, std::size_t positionCount) const override;

inline void UpdateDeformationRadius(float deformationRadius);

DeformedChunk& operator=(const DeformedChunk&) = delete;
DeformedChunk& operator=(DeformedChunk&&) = delete;

static Nz::Vector3f DeformPosition(const Nz::Vector3f& position, const Nz::Vector3f& deformationCenter, float deformationRadius);
static Nz::Quaternionf GetNormalDeformation(const Nz::Vector3f& position, const Nz::Vector3f& faceNormal, const Nz::Vector3f& deformationCenter, float deformationRadius);

private:
Nz::Vector3f m_deformationCenter;
Expand Down
17 changes: 17 additions & 0 deletions include/CommonLib/DeformedChunk.inl
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,21 @@ namespace tsom

return innerPos + normal * std::min(deformationRadius, distToCenter);
}

inline Nz::Quaternionf DeformedChunk::GetNormalDeformation(const Nz::Vector3f& position, const Nz::Vector3f& faceNormal, const Nz::Vector3f& deformationCenter, float deformationRadius)
{
float distToCenter = std::max({
std::abs(position.x - deformationCenter.x),
std::abs(position.y - deformationCenter.y),
std::abs(position.z - deformationCenter.z),
});

float innerReductionSize = std::max(distToCenter - deformationRadius, 0.f);
Nz::Boxf innerBox(deformationCenter - Nz::Vector3f(innerReductionSize), Nz::Vector3f(innerReductionSize * 2.f));

Nz::Vector3f innerPos = Nz::Vector3f::Clamp(position, innerBox.GetMinimum(), innerBox.GetMaximum());
Nz::Vector3f normal = Nz::Vector3f::Normalize(position - innerPos);

return Nz::Quaternionf::RotationBetween(faceNormal, normal);
}
}
1 change: 0 additions & 1 deletion include/CommonLib/FlatChunk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ namespace tsom

std::shared_ptr<Nz::Collider3D> BuildCollider() const override;
std::optional<Nz::Vector3ui> ComputeCoordinates(const Nz::Vector3f& position) const override;
Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> ComputeVoxelCorners(const Nz::Vector3ui& indices) const override;

FlatChunk& operator=(const FlatChunk&) = delete;
FlatChunk& operator=(FlatChunk&&) = delete;
Expand Down
2 changes: 1 addition & 1 deletion src/ClientLib/ClientChunkEntities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ namespace tsom

std::shared_ptr<Nz::StaticMesh> staticMesh = std::make_shared<Nz::StaticMesh>(std::move(vertexBuffer), std::move(indexBuffer));
staticMesh->GenerateAABB();
staticMesh->GenerateTangents();
staticMesh->GenerateTangents(); //< FIXME: Tangent generation should be fixed

std::shared_ptr<Nz::Mesh> chunkMesh = std::make_shared<Nz::Mesh>();
chunkMesh->CreateStatic();
Expand Down
62 changes: 53 additions & 9 deletions src/CommonLib/Chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ namespace tsom
VertexAttributes vertexAttributes = addVertices(pos.size());
assert(vertexAttributes.position);

indices.push_back(vertexAttributes.firstIndex);
indices.push_back(vertexAttributes.firstIndex + 2);
indices.push_back(vertexAttributes.firstIndex + 1);

indices.push_back(vertexAttributes.firstIndex + 1);
indices.push_back(vertexAttributes.firstIndex + 2);
indices.push_back(vertexAttributes.firstIndex + 3);

for (std::size_t i = 0; i < pos.size(); ++i)
vertexAttributes.position[i] = pos[i];

Expand All @@ -36,9 +44,17 @@ namespace tsom
vertexAttributes.normal[i] = faceDirection;
}

if (vertexAttributes.tangent)
{
Nz::Vector3f edgeCenter = (pos[0] + pos[1]) * 0.5f;
Nz::Vector3f tangent = Nz::Vector3f::Normalize(edgeCenter - faceCenter);

for (std::size_t i = 0; i < pos.size(); ++i)
vertexAttributes.tangent[i] = tangent;
}

if (vertexAttributes.uv)
{
// Get face up vector
Nz::Vector3f faceUp = s_dirNormals[DirectionFromNormal(Nz::Vector3f::Normalize(faceCenter - gravityCenter))];

// Make up the rotation from the face up to the regular up
Expand Down Expand Up @@ -92,13 +108,14 @@ namespace tsom
}
}

indices.push_back(vertexAttributes.firstIndex);
indices.push_back(vertexAttributes.firstIndex + 2);
indices.push_back(vertexAttributes.firstIndex + 1);

indices.push_back(vertexAttributes.firstIndex + 1);
indices.push_back(vertexAttributes.firstIndex + 2);
indices.push_back(vertexAttributes.firstIndex + 3);
// deform positions after generating UV
if (DeformPositions(vertexAttributes.position, pos.size()))
{
if (vertexAttributes.normal && vertexAttributes.tangent)
DeformNormalsAndTangents(vertexAttributes.normal, vertexAttributes.tangent, faceDirection, vertexAttributes.position, pos.size());
else if (vertexAttributes.normal)
DeformNormals(vertexAttributes.normal, faceDirection, vertexAttributes.position, pos.size());
}
};

// Find and lock all neighbor chunks to avoid discrepancies between chunks
Expand Down Expand Up @@ -183,7 +200,8 @@ namespace tsom

const auto& blockData = m_blockLibrary.GetBlockData(blockIndex);

Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> corners = ComputeVoxelCorners({ x, y, z });
// Get unaltered voxel corners and deform them next
Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> corners = Chunk::ComputeVoxelCorners({ x, y, z });

Nz::Vector3f blockCenter = std::accumulate(corners.begin(), corners.end(), Nz::Vector3f::Zero()) / corners.size();

Expand Down Expand Up @@ -249,6 +267,32 @@ namespace tsom
}
}

Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> Chunk::ComputeVoxelCorners(const Nz::Vector3ui& indices) const
{
float fX = indices.x * m_blockSize;
float fY = indices.y * m_blockSize;
float fZ = indices.z * m_blockSize;

Nz::Boxf box(fX, fZ, fY, m_blockSize, m_blockSize, m_blockSize);
return box.GetCorners();
}

void Chunk::DeformNormals(Nz::SparsePtr<Nz::Vector3f> normals, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const
{
/* nothing to do */
}

void Chunk::DeformNormalsAndTangents(Nz::SparsePtr<Nz::Vector3f> normals, Nz::SparsePtr<Nz::Vector3f> tangents, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const
{
/* nothing to do */
}

bool Chunk::DeformPositions(Nz::SparsePtr<Nz::Vector3f> /*positions*/, std::size_t /*positionCount*/) const
{
/* nothing to do */
return false;
}

void Chunk::Deserialize(Nz::ByteStream& byteStream)
{
Nz::UInt32 chunkBinaryVersion;
Expand Down
27 changes: 27 additions & 0 deletions src/CommonLib/DeformedChunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,31 @@ namespace tsom

return corners;
}

void DeformedChunk::DeformNormals(Nz::SparsePtr<Nz::Vector3f> normals, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const
{
for (std::size_t i = 0; i < vertexCount; ++i)
{
Nz::Quaternionf rotation = GetNormalDeformation(positions[i], referenceNormal, m_deformationCenter, m_deformationRadius);
normals[i] = rotation * normals[i];
}
}

void DeformedChunk::DeformNormalsAndTangents(Nz::SparsePtr<Nz::Vector3f> normals, Nz::SparsePtr<Nz::Vector3f> tangents, const Nz::Vector3f& referenceNormal, Nz::SparsePtr<const Nz::Vector3f> positions, std::size_t vertexCount) const
{
for (std::size_t i = 0; i < vertexCount; ++i)
{
Nz::Quaternionf rotation = GetNormalDeformation(positions[i], referenceNormal, m_deformationCenter, m_deformationRadius);
normals[i] = rotation * normals[i];
tangents[i] = rotation * tangents[i];
}
}

bool DeformedChunk::DeformPositions(Nz::SparsePtr<Nz::Vector3f> positions, std::size_t positionCount) const
{
for (std::size_t i = 0; i < positionCount; ++i)
positions[i] = DeformPosition(positions[i], m_deformationCenter, m_deformationRadius);

return true;
}
}
8 changes: 0 additions & 8 deletions src/CommonLib/FlatChunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,6 @@ namespace tsom
return pos;
}

Nz::EnumArray<Nz::BoxCorner, Nz::Vector3f> FlatChunk::ComputeVoxelCorners(const Nz::Vector3ui& indices) const
{
Nz::Vector3f blockPos = (Nz::Vector3f(indices) - Nz::Vector3f(m_size) * 0.5f) * m_blockSize;

Nz::Boxf box(blockPos.x, blockPos.z, blockPos.y, m_blockSize, m_blockSize, m_blockSize);
return box.GetCorners();
}

void FlatChunk::BuildCollider(const Nz::Vector3ui& dims, Nz::Bitset<Nz::UInt64> collisionCellMask, Nz::FunctionRef<void(const Nz::Boxf& box)> callback)
{
auto GetBlockLocalIndex = [&](const Nz::Vector3ui& indices)
Expand Down

0 comments on commit 1e9b4fa

Please sign in to comment.