From 4243fff293f2287c73e5b47c0f54f9f0b183a688 Mon Sep 17 00:00:00 2001 From: Pierre Baillargeon Date: Wed, 31 Jan 2024 09:32:46 -0500 Subject: [PATCH] EMSUSD-996 allowing meshes with insufficient primvars data size. Doing as much work as possible instead of throwing the mesh entirely away. --- lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp | 203 ++++++++++-------- 1 file changed, 111 insertions(+), 92 deletions(-) diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index 83780111fc..af5f72a388 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -82,89 +82,108 @@ void _FillPrimvarData( const VtArray& primvarData, const HdInterpolation& primvarInterp) { + const unsigned int dataSize = primvarData.size(); + switch (primvarInterp) { - case HdInterpolationConstant: + case HdInterpolationConstant: { + SRC_TYPE value {}; + if (dataSize > 0) { + value = primvarData[0]; + } else { + TF_DEBUG(HDVP2_DEBUG_MESH) + .Msg( + "Invalid Hydra prim '%s': " + "primvar %s has %u elements, while its topology " + "references face vertex index %u.\n", + rprimId.asChar(), + primvarName.GetText(), + dataSize, + 0); + } + for (size_t v = 0; v < numVertices; v++) { SRC_TYPE* pointer = reinterpret_cast( reinterpret_cast(&vertexBuffer[v]) + channelOffset); - *pointer = primvarData[0]; + *pointer = value; } break; + } case HdInterpolationVarying: case HdInterpolationVertex: - if (numVertices <= renderingToSceneFaceVtxIds.size()) { - const unsigned int dataSize = primvarData.size(); - for (size_t v = 0; v < numVertices; v++) { - unsigned int index = renderingToSceneFaceVtxIds[v]; - if (index < dataSize) { - SRC_TYPE* pointer = reinterpret_cast( - reinterpret_cast(&vertexBuffer[v]) + channelOffset); - *pointer = primvarData[index]; - } else { - TF_DEBUG(HDVP2_DEBUG_MESH) - .Msg( - "Invalid Hydra prim '%s': " - "primvar %s has %u elements, while its topology " - "references face vertex index %u.\n", - rprimId.asChar(), - primvarName.GetText(), - dataSize, - index); - } - } - } else { - TF_CODING_ERROR( - "Invalid Hydra prim '%s': " - "requires %zu vertices, while the number of elements in " - "renderingToSceneFaceVtxIds is %zu. Skipping primvar update.", - rprimId.asChar(), - numVertices, - renderingToSceneFaceVtxIds.size()); - - memset(vertexBuffer, 0, sizeof(DEST_TYPE) * numVertices); + // The primvar has less data than needed, we issue a warning but + // don't skip update. Truncate the buffer to the lesser length. + if (numVertices > renderingToSceneFaceVtxIds.size()) { + TF_DEBUG(HDVP2_DEBUG_MESH) + .Msg( + "Invalid Hydra prim '%s': " + "requires %zu vertices, while the number of elements in " + "renderingToSceneFaceVtxIds is %zu.", + rprimId.asChar(), + numVertices, + renderingToSceneFaceVtxIds.size()); + numVertices = renderingToSceneFaceVtxIds.size(); } - break; - case HdInterpolationUniform: { - const VtIntArray& faceVertexCounts = topology.GetFaceVertexCounts(); - const size_t numFaces = faceVertexCounts.size(); - if (numFaces <= primvarData.size()) { - // The primvar has more data than needed, we issue a warning but - // don't skip update. Truncate the buffer to the expected length. - if (numFaces < primvarData.size()) { + + for (size_t v = 0; v < numVertices; v++) { + unsigned int index = renderingToSceneFaceVtxIds[v]; + if (index < dataSize) { + SRC_TYPE* pointer = reinterpret_cast( + reinterpret_cast(&vertexBuffer[v]) + channelOffset); + *pointer = primvarData[index]; + } else { TF_DEBUG(HDVP2_DEBUG_MESH) .Msg( "Invalid Hydra prim '%s': " - "primvar %s has %zu elements, while its topology " - "references only upto element index %zu.\n", + "primvar %s has %u elements, while its topology " + "references face vertex index %u.\n", rprimId.asChar(), primvarName.GetText(), - primvarData.size(), - numFaces); + dataSize, + index); } + } + break; + case HdInterpolationUniform: { + const VtIntArray& faceVertexCounts = topology.GetFaceVertexCounts(); + size_t numFaces = faceVertexCounts.size(); - for (size_t f = 0, v = 0; f < numFaces; f++) { - const size_t faceVertexCount = faceVertexCounts[f]; - const size_t faceVertexEnd = v + faceVertexCount; - for (; v < faceVertexEnd; v++) { - SRC_TYPE* pointer = reinterpret_cast( - reinterpret_cast(&vertexBuffer[v]) + channelOffset); - *pointer = primvarData[f]; - } - } - } else { - // The primvar has less data than needed. Issue warning and skip - // update like what is done in HdStMesh. + // The primvar has less data than needed, we issue a warning but + // don't skip update. Truncate the buffer to the lesser length. + if (numFaces > dataSize) { TF_DEBUG(HDVP2_DEBUG_MESH) .Msg( "Invalid Hydra prim '%s': " - "primvar %s has only %zu elements, while its topology expects " - "at least %zu elements. Skipping primvar update.\n", + "primvar %s has only %u elements, while its topology expects " + "at least %zu elements.\n", rprimId.asChar(), primvarName.GetText(), - primvarData.size(), + dataSize, numFaces); + numFaces = dataSize; + } + + // The primvar has more data than needed, we issue a warning but + // don't skip update. Truncate the buffer to the expected length. + if (numFaces < dataSize) { + TF_DEBUG(HDVP2_DEBUG_MESH) + .Msg( + "Invalid Hydra prim '%s': " + "primvar %s has %u elements, while its topology " + "references only upto element index %zu.\n", + rprimId.asChar(), + primvarName.GetText(), + dataSize, + numFaces); + } - memset(vertexBuffer, 0, sizeof(DEST_TYPE) * numVertices); + for (size_t f = 0, v = 0; f < numFaces; f++) { + const size_t faceVertexCount = faceVertexCounts[f]; + const size_t faceVertexEnd = v + faceVertexCount; + for (; v < faceVertexEnd; v++) { + SRC_TYPE* pointer = reinterpret_cast( + reinterpret_cast(&vertexBuffer[v]) + channelOffset); + *pointer = primvarData[f]; + } } break; } @@ -174,46 +193,46 @@ void _FillPrimvarData( // from 0, thus we can save a lookup into the table. If the assumption // about the natural sequence is changed, we will need the lookup and // remap indices. - if (numVertices <= primvarData.size()) { - // If the primvar has more data than needed, we issue a warning, - // but don't skip the primvar update. Truncate the buffer to the - // expected length. - if (numVertices < primvarData.size()) { - TF_DEBUG(HDVP2_DEBUG_MESH) - .Msg( - "Invalid Hydra prim '%s': " - "primvar %s has %zu elements, while its topology references " - "only upto element index %zu.\n", - rprimId.asChar(), - primvarName.GetText(), - primvarData.size(), - numVertices); - } - if (channelOffset == 0 && std::is_same::value) { - const void* source = static_cast(primvarData.cdata()); - memcpy(vertexBuffer, source, sizeof(DEST_TYPE) * numVertices); - } else { - for (size_t v = 0; v < numVertices; v++) { - SRC_TYPE* pointer = reinterpret_cast( - reinterpret_cast(&vertexBuffer[v]) + channelOffset); - *pointer = primvarData[v]; - } - } - } else { - // It is unexpected to have less data than we index into. Issue - // a warning and skip update. + // The primvar has less data than needed, we issue a warning but + // don't skip update. Truncate the buffer to the lesser length. + if (numVertices > dataSize) { + TF_DEBUG(HDVP2_DEBUG_MESH) + .Msg( + "Invalid Hydra prim '%s': " + "primvar %s has only %u elements, while its topology expects " + "at least %zu elements.\n", + rprimId.asChar(), + primvarName.GetText(), + dataSize, + numVertices); + numVertices = dataSize; + } + + // If the primvar has more data than needed, we issue a warning, + // but don't skip the primvar update. Truncate the buffer to the + // expected length. + if (numVertices < dataSize) { TF_DEBUG(HDVP2_DEBUG_MESH) .Msg( "Invalid Hydra prim '%s': " - "primvar %s has only %zu elements, while its topology expects " - "at least %zu elements. Skipping primvar update.\n", + "primvar %s has %u elements, while its topology references " + "only upto element index %zu.\n", rprimId.asChar(), primvarName.GetText(), - primvarData.size(), + dataSize, numVertices); + } - memset(vertexBuffer, 0, sizeof(DEST_TYPE) * numVertices); + if (channelOffset == 0 && std::is_same::value) { + const void* source = static_cast(primvarData.cdata()); + memcpy(vertexBuffer, source, sizeof(DEST_TYPE) * numVertices); + } else { + for (size_t v = 0; v < numVertices; v++) { + SRC_TYPE* pointer = reinterpret_cast( + reinterpret_cast(&vertexBuffer[v]) + channelOffset); + *pointer = primvarData[v]; + } } break; default: