diff --git a/Hydrogent/include/HnMeshUtils.hpp b/Hydrogent/include/HnMeshUtils.hpp index 0ba9f631..13f8cbbf 100644 --- a/Hydrogent/include/HnMeshUtils.hpp +++ b/Hydrogent/include/HnMeshUtils.hpp @@ -77,6 +77,32 @@ class HnMeshUtils final pxr::VtIntArray& SubsetStart) const; + /// Computes the edge indices. + /// + /// \param[in] UseFaceVertexIndices - Whether to use face vertex indices. + /// \return The edge indices. + /// + /// Example: + /// Input: + /// FaceVertexCounts = {4, 4} + /// FaceVertexIndices= {0, 1, 2, 3, 3, 2, 4, 5} + /// + /// V1________V2_______V4 + /// |1 2|5 6| + /// | | | + /// | | | + /// |0______3|4______7| + /// V0 V3 V5 + /// + /// Output: + /// UseFaceVertexIndices == false + /// EdgeIndices = {0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4} + /// + /// UseFaceVertexIndices == true + /// EdgeIndices = {0, 1, 1, 2, 2, 3, 3, 0, 3, 2, 2, 4, 4, 5, 5, 3} + pxr::VtVec2iArray ComputeEdgeIndices(bool UseFaceVertexIndices) const; + + /// Converts vertex/varying primvar data to face-varying primvar data. /// /// \param[in] VertexData - The vertex/varying primvar data. @@ -108,6 +134,10 @@ class HnMeshUtils final /// pxr::VtValue ConvertVertexPrimvarToFaceVarying(const pxr::VtValue& VertexData, size_t ValuesPerVertex = 1) const; +private: + template + void ProcessFaces(HandleFaceType&& HandleFace) const; + private: const pxr::HdMeshTopology& m_Topology; const pxr::SdfPath& m_MeshId; diff --git a/Hydrogent/interface/HnMesh.hpp b/Hydrogent/interface/HnMesh.hpp index 67016808..f72b4613 100644 --- a/Hydrogent/interface/HnMesh.hpp +++ b/Hydrogent/interface/HnMesh.hpp @@ -240,9 +240,8 @@ class HnMesh final : public pxr::HdMesh struct StagingIndexData { pxr::VtVec3iArray FaceIndices; - - std::vector MeshEdgeIndices; - std::vector PointIndices; + pxr::VtVec2iArray EdgeIndices; + pxr::VtIntArray PointIndices; }; std::unique_ptr m_StagingIndexData; diff --git a/Hydrogent/src/HnMesh.cpp b/Hydrogent/src/HnMesh.cpp index ca643f90..c7b30cd7 100644 --- a/Hydrogent/src/HnMesh.cpp +++ b/Hydrogent/src/HnMesh.cpp @@ -920,10 +920,9 @@ void HnMesh::UpdateIndexData() m_IndexData.Subsets.clear(); } - //pxr::HdMeshUtil MeshUtil{&m_Topology, Id}; - //MeshUtil.EnumerateEdges(&m_StagingIndexData->MeshEdgeIndices); - m_IndexData.NumFaceTriangles = static_cast(m_StagingIndexData->FaceIndices.size()); - m_IndexData.NumEdges = static_cast(m_StagingIndexData->MeshEdgeIndices.size()); + m_StagingIndexData->EdgeIndices = MeshUtils.ComputeEdgeIndices(!m_HasFaceVaryingPrimvars); + m_IndexData.NumFaceTriangles = static_cast(m_StagingIndexData->FaceIndices.size()); + m_IndexData.NumEdges = static_cast(m_StagingIndexData->EdgeIndices.size()); } void HnMesh::AllocatePooledResources(pxr::HdSceneDelegate& SceneDelegate, @@ -991,9 +990,9 @@ void HnMesh::AllocatePooledResources(pxr::HdSceneDelegate& SceneDelegate, } } - if (!m_StagingIndexData->MeshEdgeIndices.empty()) + if (!m_StagingIndexData->EdgeIndices.empty()) { - for (pxr::GfVec2i& Edge : m_StagingIndexData->MeshEdgeIndices) + for (pxr::GfVec2i& Edge : m_StagingIndexData->EdgeIndices) { Edge[0] += StartVertex; Edge[1] += StartVertex; @@ -1002,7 +1001,7 @@ void HnMesh::AllocatePooledResources(pxr::HdSceneDelegate& SceneDelegate, if (!m_StagingIndexData->PointIndices.empty()) { - for (Uint32& Point : m_StagingIndexData->PointIndices) + for (int& Point : m_StagingIndexData->PointIndices) { Point += StartVertex; } @@ -1027,7 +1026,7 @@ void HnMesh::AllocatePooledResources(pxr::HdSceneDelegate& SceneDelegate, m_IndexData.FaceStartIndex = m_IndexData.FaceAllocation->GetOffset() / sizeof(Uint32); } - if (!m_StagingIndexData->MeshEdgeIndices.empty()) + if (!m_StagingIndexData->EdgeIndices.empty()) { m_IndexData.EdgeAllocation = ResMgr.AllocateIndices(sizeof(Uint32) * m_IndexData.NumEdges * 2); m_IndexData.EdgeStartIndex = m_IndexData.EdgeAllocation->GetOffset() / sizeof(Uint32); @@ -1158,11 +1157,11 @@ void HnMesh::UpdateIndexBuffer(HnRenderDelegate& RenderDelegate) m_IndexData.FaceAllocation); } - if (!m_StagingIndexData->MeshEdgeIndices.empty()) + if (!m_StagingIndexData->EdgeIndices.empty()) { - VERIFY_EXPR(m_IndexData.NumEdges == static_cast(m_StagingIndexData->MeshEdgeIndices.size())); + VERIFY_EXPR(m_IndexData.NumEdges == static_cast(m_StagingIndexData->EdgeIndices.size())); m_IndexData.Edges = PrepareIndexBuffer("Edge Index Buffer", - m_StagingIndexData->MeshEdgeIndices.data(), + m_StagingIndexData->EdgeIndices.data(), m_IndexData.NumEdges * sizeof(Uint32) * 2, m_IndexData.EdgeAllocation); } diff --git a/Hydrogent/src/HnMeshUtils.cpp b/Hydrogent/src/HnMeshUtils.cpp index f6af51a2..499fef1f 100644 --- a/Hydrogent/src/HnMeshUtils.cpp +++ b/Hydrogent/src/HnMeshUtils.cpp @@ -45,61 +45,75 @@ HnMeshUtils::~HnMeshUtils() { } +template +void HnMeshUtils::ProcessFaces(HandleFaceType&& HandleFace) const +{ + const pxr::VtIntArray& FaceVertCounts = m_Topology.GetFaceVertexCounts(); + const size_t NumFaces = FaceVertCounts.size(); + VERIFY_EXPR(NumFaces == static_cast(m_Topology.GetNumFaces())); + + int FaceStartVertex = 0; + for (size_t i = 0; i < NumFaces; ++i) + { + const int VertCount = FaceVertCounts[i]; + if (VertCount >= 3) + { + HandleFace(i, FaceStartVertex, VertCount); + } + FaceStartVertex += VertCount; + } +} + void HnMeshUtils::Triangulate(bool UseFaceVertexIndices, pxr::VtVec3iArray& TriangleIndices, pxr::VtIntArray& SubsetStart) const { const size_t NumFaces = m_Topology.GetNumFaces(); - const pxr::VtIntArray& FaceVertCounts = m_Topology.GetFaceVertexCounts(); const pxr::VtIntArray& FaceVertexIndices = m_Topology.GetFaceVertexIndices(); - const size_t NumVertexIndices = FaceVertexIndices.size(); - - auto ProcessFaces = [&](auto HandleFace) { - int CurrVertex = 0; - for (size_t i = 0; i < NumFaces; ++i) - { - const int VertCount = FaceVertCounts[i]; - if (VertCount >= 3) - { - HandleFace(i, CurrVertex, VertCount); - } - CurrVertex += VertCount; - } - }; + const int NumVertexIndices = static_cast(FaceVertexIndices.size()); // Count the number of triangles size_t NumTriangles = 0; - ProcessFaces([&](size_t FaceId, int StartVertex, int VertCount) { - NumTriangles += VertCount - 2; - }); + ProcessFaces( + [&](size_t FaceId, int StartVertex, int VertCount) { + NumTriangles += VertCount - 2; + }); // Triangulate faces TriangleIndices.reserve(NumTriangles); std::vector FaceStartTriangle(NumFaces + 1); - ProcessFaces([&](size_t FaceId, int StartVertex, int VertCount) { - FaceStartTriangle[FaceId] = TriangleIndices.size(); - for (int i = 0; i < VertCount - 2; ++i) - { - pxr::GfVec3i Triangle{ - StartVertex, - StartVertex + i + 1, - StartVertex + i + 2, - }; - if (UseFaceVertexIndices) + ProcessFaces( + [&](size_t FaceId, int StartVertex, int VertCount) { + FaceStartTriangle[FaceId] = TriangleIndices.size(); + for (int i = 0; i < VertCount - 2; ++i) { - for (size_t j = 0; j < 3; ++j) + pxr::GfVec3i Triangle{ + StartVertex, + StartVertex + i + 1, + StartVertex + i + 2, + }; + if (UseFaceVertexIndices) { - int Idx = Triangle[j]; - if (Idx < static_cast(NumVertexIndices)) + int& Idx0 = Triangle[0]; + int& Idx1 = Triangle[1]; + int& Idx2 = Triangle[2]; + if (Idx0 < NumVertexIndices && Idx1 < NumVertexIndices && Idx2 < NumVertexIndices) + { + Idx0 = FaceVertexIndices[Idx0]; + Idx1 = FaceVertexIndices[Idx1]; + Idx2 = FaceVertexIndices[Idx2]; + } + else { - Triangle[j] = FaceVertexIndices[Idx]; + Idx0 = 0; + Idx1 = 0; + Idx2 = 0; } } + TriangleIndices.push_back(Triangle); } - TriangleIndices.push_back(Triangle); - } - }); + }); VERIFY_EXPR(TriangleIndices.size() == NumTriangles); FaceStartTriangle.back() = TriangleIndices.size(); @@ -161,6 +175,49 @@ void HnMeshUtils::Triangulate(bool UseFaceVertexIndices, } } +pxr::VtVec2iArray HnMeshUtils::ComputeEdgeIndices(bool UseFaceVertexIndices) const +{ + size_t NumEdges = 0; + ProcessFaces( + [&](size_t FaceId, int StartVertex, int VertCount) { + NumEdges += VertCount; + }); + + pxr::VtVec2iArray EdgeIndices; + EdgeIndices.reserve(NumEdges); + + ProcessFaces( + [&](size_t FaceId, int StartVertex, int VertCount) { + for (int v = 0; v < VertCount - 1; ++v) + EdgeIndices.push_back({StartVertex + v, StartVertex + (v + 1)}); + EdgeIndices.push_back({StartVertex + VertCount - 1, StartVertex}); + }); + VERIFY_EXPR(EdgeIndices.size() == NumEdges); + + if (UseFaceVertexIndices) + { + const pxr::VtIntArray& FaceVertexIndices = m_Topology.GetFaceVertexIndices(); + const size_t NumVertexIndices = FaceVertexIndices.size(); + for (pxr::GfVec2i& Edge : EdgeIndices) + { + int& Idx0 = Edge[0]; + int& Idx1 = Edge[1]; + if (Idx0 < NumVertexIndices && Idx1 < NumVertexIndices) + { + Idx0 = FaceVertexIndices[Idx0]; + Idx1 = FaceVertexIndices[Idx1]; + } + else + { + Idx0 = 0; + Idx1 = 0; + } + } + } + + return EdgeIndices; +} + template pxr::VtValue ConvertVertexArrayToFaceVaryingArray(const pxr::VtIntArray& FaceVertexIndices, const pxr::VtArray& VertexData, size_t ValuesPerVertex) {