diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp index eaaf04fcf2..1325455cd9 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp @@ -88,6 +88,10 @@ namespace AZ::Render { RenderTangents(mesh, globalTM); } + if (renderWireframe) + { + RenderWireframe(mesh, globalTM); + } } } } @@ -255,8 +259,6 @@ namespace AZ::Render m_auxVertices.clear(); m_auxVertices.reserve(numTriangles * 2); - m_auxColors.clear(); - m_auxColors.reserve(m_auxVertices.size()); for (uint32 triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex) { @@ -275,17 +277,15 @@ namespace AZ::Render const AZ::Vector3 normalPos = (posA + posB + posC) * (1.0f / 3.0f); m_auxVertices.emplace_back(normalPos); - m_auxColors.emplace_back(colorFaceNormals); m_auxVertices.emplace_back(normalPos + (normalDir * faceNormalsScale)); - m_auxColors.emplace_back(colorFaceNormals); } } RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); lineArgs.m_vertCount = static_cast(m_auxVertices.size()); - lineArgs.m_colors = m_auxColors.data(); - lineArgs.m_colorCount = static_cast(m_auxColors.size()); + lineArgs.m_colors = &colorFaceNormals; + lineArgs.m_colorCount = 1; lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; auxGeom->DrawLines(lineArgs); } @@ -302,8 +302,6 @@ namespace AZ::Render m_auxVertices.clear(); m_auxVertices.reserve(numVertices * 2); - m_auxColors.clear(); - m_auxColors.reserve(m_auxVertices.size()); for (uint32 j = 0; j < numVertices; ++j) { @@ -312,17 +310,15 @@ namespace AZ::Render const AZ::Vector3 normal = worldTM.TransformVector(normals[vertexIndex]).GetNormalizedSafe() * vertexNormalsScale; m_auxVertices.emplace_back(position); - m_auxColors.emplace_back(colorFaceNormals); m_auxVertices.emplace_back(position + normal); - m_auxColors.emplace_back(colorFaceNormals); } } RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); lineArgs.m_vertCount = static_cast(m_auxVertices.size()); - lineArgs.m_colors = m_auxColors.data(); - lineArgs.m_colorCount = static_cast(m_auxColors.size()); + lineArgs.m_colors = &colorVertexNormals; + lineArgs.m_colorCount = 1; lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; auxGeom->DrawLines(lineArgs); } @@ -412,4 +408,67 @@ namespace AZ::Render lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; auxGeom->DrawLines(lineArgs); } + + void AtomActorDebugDraw::RenderWireframe(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM) + { + // Check if the mesh is valid and skip the node in case it's not + if (!mesh) + { + return; + } + + RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue(); + if (!auxGeom) + { + return; + } + + PrepareForMesh(mesh, worldTM); + + const float scale = 0.01f; + + const AZ::Vector3* normals = (AZ::Vector3*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_NORMALS); + const AZ::Color vertexColor = AZ::Color(0.8f, 0.24f, 0.88f, 1.0f); + + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) + { + EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex); + const uint32 numTriangles = subMesh->GetNumPolygons(); + const uint32 startVertex = subMesh->GetStartVertex(); + const uint32* indices = subMesh->GetIndices(); + + m_auxVertices.clear(); + m_auxVertices.reserve(numTriangles * 6); + + for (uint32 triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex) + { + const uint32 triangleStartIndex = triangleIndex * 3; + const uint32 indexA = indices[triangleStartIndex + 0] + startVertex; + const uint32 indexB = indices[triangleStartIndex + 1] + startVertex; + const uint32 indexC = indices[triangleStartIndex + 2] + startVertex; + + const AZ::Vector3 posA = m_worldSpacePositions[indexA] + normals[indexA] * scale; + const AZ::Vector3 posB = m_worldSpacePositions[indexB] + normals[indexB] * scale; + const AZ::Vector3 posC = m_worldSpacePositions[indexC] + normals[indexC] * scale; + + m_auxVertices.emplace_back(posA); + m_auxVertices.emplace_back(posB); + + m_auxVertices.emplace_back(posB); + m_auxVertices.emplace_back(posC); + + m_auxVertices.emplace_back(posC); + m_auxVertices.emplace_back(posA); + } + + RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; + lineArgs.m_verts = m_auxVertices.data(); + lineArgs.m_vertCount = static_cast(m_auxVertices.size()); + lineArgs.m_colors = &vertexColor; + lineArgs.m_colorCount = 1; + lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; + auxGeom->DrawLines(lineArgs); + } + } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h index 9f8b137f13..797de16351 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h @@ -43,6 +43,7 @@ namespace AZ::Render void RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance); void RenderNormals(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, bool vertexNormals, bool faceNormals); void RenderTangents(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM); + void RenderWireframe(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM); EMotionFX::Mesh* m_currentMesh = nullptr; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer. NULL in case we haven't pre-calculated any positions yet. */