// Copyright Epic Games, Inc. All Rights Reserved. #include "gstests/Defs.h" #include "gstests/Fixtures.h" #include "genesplicer/GeneSplicerDNAReaderImpl.h" #include "genesplicer/dna/Aliases.h" #include "genesplicer/splicedata/genepool/SingleJointBehavior.h" #include "genesplicer/splicedata/genepool/BlendShapeDeltas.h" #include "genesplicer/splicedata/rawgenes/RawGenes.h" #include "genesplicer/types/Aliases.h" #include "genesplicer/types/VariableWidthMatrix.h" #include "genesplicer/types/Vec3.h" #include "genesplicer/types/BlockStorage.h" namespace gs4 { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 6326) #endif inline void assertVec3Near(Vec3 result, Vec3 expected, float threshold) { ASSERT_NEAR(result.x, expected.x, threshold); ASSERT_NEAR(result.y, expected.y, threshold); ASSERT_NEAR(result.z, expected.z, threshold); } inline void assertNeutralMeshes(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getMeshCount(), expected->getMeshCount()); for (std::uint16_t meshIdx = 0u; meshIdx < expected->getMeshCount(); ++meshIdx) { ASSERT_EQ(output->getVertexPositionCount(meshIdx), expected->getVertexPositionCount(meshIdx)); for (std::uint32_t vertexIdx = 0u; vertexIdx < expected->getVertexPositionCount(meshIdx); ++vertexIdx) { Vec3 resultPosition = output->getVertexPosition(meshIdx, vertexIdx); Vec3 expectedPosition = expected->getVertexPosition(meshIdx, vertexIdx); assertVec3Near(resultPosition, expectedPosition, threshold); } } } inline void assertNeutralMeshes(ConstArrayView neutralMeshes, Reader* expected) { std::uint16_t expectedMeshCount = expected->getMeshCount(); auto actualMeshCount = static_cast(neutralMeshes.size()); ASSERT_EQ(expectedMeshCount, actualMeshCount); for (std::uint16_t meshIdx = 0u; meshIdx < actualMeshCount; meshIdx++) { auto expectedVerticesXs = expected->getVertexPositionXs(meshIdx); const auto& actualVerticesXs = neutralMeshes[meshIdx].xs; ASSERT_ELEMENTS_AND_SIZE_EQ(expectedVerticesXs, actualVerticesXs); auto expectedVerticesYs = expected->getVertexPositionYs(meshIdx); const auto& actualVerticesYs = neutralMeshes[meshIdx].ys; ASSERT_ELEMENTS_AND_SIZE_EQ(expectedVerticesYs, actualVerticesYs); auto expectedVerticesZs = expected->getVertexPositionZs(meshIdx); const auto& actualVerticesZs = neutralMeshes[meshIdx].zs; ASSERT_ELEMENTS_AND_SIZE_EQ(expectedVerticesZs, actualVerticesZs); } } inline void assertNeutralMeshPoolData(ConstArrayView > actualData, const Vector > >& expectedData) { ASSERT_EQ(actualData.size(), expectedData.size()); for (std::uint16_t meshIndex = 0; meshIndex < expectedData.size(); meshIndex++) { const auto& mesh = actualData[meshIndex]; const auto& expectedMesh = expectedData[meshIndex]; std::size_t blockCount = mesh.rowCount(); ASSERT_EQ(blockCount, expectedMesh.size()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { for (std::size_t dnaIdx = 0u; dnaIdx < mesh[blockIdx].size(); dnaIdx++) { ASSERT_EQ(mesh[blockIdx][dnaIdx], expectedMesh[blockIdx][dnaIdx]); } } } } inline void assertBlendShapeTargets(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getMeshCount(), expected->getMeshCount()); for (std::uint16_t meshIdx = 0u; meshIdx < expected->getMeshCount(); ++meshIdx) { ASSERT_EQ(output->getBlendShapeTargetCount(meshIdx), expected->getBlendShapeTargetCount(meshIdx)); for (std::uint16_t bsIdx = 0u; bsIdx < expected->getBlendShapeTargetCount(meshIdx); ++bsIdx) { ASSERT_EQ(output->getBlendShapeTargetDeltaCount(meshIdx, bsIdx), expected->getBlendShapeTargetDeltaCount(meshIdx, bsIdx)); auto resultIndices = output->getBlendShapeTargetVertexIndices(meshIdx, bsIdx); auto expectedIndices = expected->getBlendShapeTargetVertexIndices(meshIdx, bsIdx); ASSERT_EQ(resultIndices, expectedIndices); for (std::uint32_t deltaIdx = 0u; deltaIdx < expected->getBlendShapeTargetDeltaCount(meshIdx, bsIdx); ++deltaIdx) { Vec3 resultDelta = output->getBlendShapeTargetDelta(meshIdx, bsIdx, deltaIdx); Vec3 expectedDelta = expected->getBlendShapeTargetDelta(meshIdx, bsIdx, deltaIdx); assertVec3Near(resultDelta, expectedDelta, threshold); } } } } inline void assertBlendShapeTargets(const VariableWidthMatrix& blendShapeTargets, Reader* expected) { std::uint16_t expectedMeshCount = expected->getMeshCount(); ASSERT_EQ(blendShapeTargets.rowCount(), expectedMeshCount); for (std::uint16_t meshIndex = 0u; meshIndex < expectedMeshCount; meshIndex++) { auto mesh = blendShapeTargets[meshIndex]; std::uint16_t expectedBlendShapeCount = expected->getBlendShapeTargetCount(meshIndex); ASSERT_EQ(mesh.size(), expectedBlendShapeCount); for (std::uint16_t bsIdx = 0u; bsIdx < expectedBlendShapeCount; bsIdx++) { auto expectedIndices = expected->getBlendShapeTargetVertexIndices(meshIndex, bsIdx); ASSERT_ELEMENTS_AND_SIZE_EQ(mesh[bsIdx].vertexIndices, expectedIndices); auto expectedXs = expected->getBlendShapeTargetDeltaXs(meshIndex, bsIdx); auto expectedYs = expected->getBlendShapeTargetDeltaYs(meshIndex, bsIdx); auto expectedZs = expected->getBlendShapeTargetDeltaZs(meshIndex, bsIdx); const auto& actualDeltas = mesh[bsIdx].deltas; ASSERT_ELEMENTS_AND_SIZE_EQ(actualDeltas.xs, expectedXs); ASSERT_ELEMENTS_AND_SIZE_EQ(actualDeltas.ys, expectedYs); ASSERT_ELEMENTS_AND_SIZE_EQ(actualDeltas.zs, expectedZs); } } } inline void assertBlendShapePoolVertexIndices(ConstArrayView > indices, const Vector >& expectedIndices) { ASSERT_EQ(indices.size(), expectedIndices.size()); for (std::uint16_t meshIndex = 0u; meshIndex < indices.size(); meshIndex++) { const auto& mesh = indices[meshIndex]; const auto& expectedMesh = expectedIndices[meshIndex]; auto blendShapeCount = static_cast(mesh.rowCount()); ASSERT_EQ(blendShapeCount, expectedMesh.size()); for (std::uint16_t bsIdx = 0u; bsIdx < blendShapeCount; bsIdx++) { ASSERT_EQ(mesh[bsIdx], expectedMesh[bsIdx]); } } } template inline void assertBlendShapePoolDeltas(const VariableWidthMatrix > >& deltas, const Matrix > >& expectedDeltas) { ASSERT_EQ(deltas.rowCount(), expectedDeltas.size()); for (std::uint16_t meshIndex = 0; meshIndex < expectedDeltas.size(); meshIndex++) { auto mesh = deltas[meshIndex]; const auto& expectedMesh = expectedDeltas[meshIndex]; ASSERT_EQ(mesh.size(), expectedMesh.size()); for (std::uint16_t bsIdx = 0u; bsIdx < mesh.size(); bsIdx++) { const auto& blendShape = mesh[bsIdx]; const auto& expectedBlendShape = expectedMesh[bsIdx]; auto blockCount = static_cast(blendShape.rowCount()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { for (std::size_t dnaIdx = 0u; dnaIdx < blendShape[blockIdx].size(); dnaIdx++) { const auto& dnaValues = blendShape[blockIdx][dnaIdx]; const auto& expectedDNAValues = expectedBlendShape[blockIdx][dnaIdx]; ASSERT_EQ(dnaValues, expectedDNAValues); } } } } } template inline void assertBlendShapePoolArchDeltas(const Vector > >& deltas, const Vector > >& expectedDeltas) { ASSERT_EQ(deltas.size(), expectedDeltas.size()); for (std::uint16_t meshIndex = 0; meshIndex < expectedDeltas.size(); meshIndex++) { auto mesh = deltas[meshIndex]; const auto& expectedMesh = expectedDeltas[meshIndex]; ASSERT_EQ(mesh.rowCount(), expectedMesh.size()); for (std::uint16_t bsIdx = 0u; bsIdx < mesh.rowCount(); bsIdx++) { const auto& blendShape = mesh[bsIdx]; const auto& expectedBlendShape = expectedMesh[bsIdx]; auto blockCount = static_cast(blendShape.size()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { const auto& archValues = blendShape[blockIdx]; const auto& expectedDNAValues = expectedBlendShape[blockIdx]; ASSERT_EQ(archValues, expectedDNAValues); } } } } inline void assertBlendShapePoolDNAIndices(const VariableWidthMatrix >& dnaIndices, const Matrix >& expectedDNAIndices) { ASSERT_EQ(dnaIndices.rowCount(), expectedDNAIndices.size()); for (std::uint16_t meshIndex = 0; meshIndex < expectedDNAIndices.size(); meshIndex++) { auto mesh = dnaIndices[meshIndex]; const auto& expectedMesh = expectedDNAIndices[meshIndex]; ASSERT_EQ(mesh.size(), expectedMesh.size()); for (std::uint16_t bsIdx = 0u; bsIdx < mesh.size(); bsIdx++) { const auto& blendShape = mesh[bsIdx]; const auto& expectedBlendShape = expectedMesh[bsIdx]; auto blockCount = static_cast(blendShape.rowCount()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { for (std::size_t dnaIdx = 0u; dnaIdx < blendShape[blockIdx].size(); dnaIdx++) { const auto& indices = blendShape[blockIdx][dnaIdx]; const auto& expectedIndices = expectedBlendShape[blockIdx][dnaIdx]; ASSERT_EQ(indices, expectedIndices); } } } } } inline void assertNeutralJointTranslations(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getJointCount(), expected->getJointCount()); for (std::uint16_t jointIdx = 0u; jointIdx < expected->getJointCount(); ++jointIdx) { Vec3 resultOffset = output->getNeutralJointTranslation(jointIdx); Vec3 expectedOffset = expected->getNeutralJointTranslation(jointIdx); assertVec3Near(resultOffset, expectedOffset, threshold); } } inline void assertNeutralJointTranslation(const RawVector3Vector& neutralJoints, Reader* expected) { auto expectedTranslationXs = expected->getNeutralJointTranslationXs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.xs, expectedTranslationXs); auto expectedTranslationYs = expected->getNeutralJointTranslationYs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.ys, expectedTranslationYs); auto expectedTranslationZs = expected->getNeutralJointTranslationZs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.zs, expectedTranslationZs); } inline void assertNeutralJoints(const RawVector3Vector& actual, Vector expected, float threshold) { ASSERT_EQ(actual.size(), expected.size()); for (std::size_t i = 0; i < actual.size(); i++) { ASSERT_NEAR(actual.xs[i], expected[i].x, threshold); ASSERT_NEAR(actual.ys[i], expected[i].y, threshold); ASSERT_NEAR(actual.zs[i], expected[i].z, threshold); } } inline void assertNeutralJointPool(const XYZTiledMatrix<16u>& actual, const Matrix >& expected) { std::size_t blockCount = actual.rowCount(); ASSERT_EQ(blockCount, expected.size()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { for (std::size_t dnaIdx = 0u; dnaIdx < expected[blockIdx].size(); dnaIdx++) { const auto& actualBlock = actual[blockIdx][dnaIdx]; const auto& expectedBlock = expected[blockIdx][dnaIdx]; for (std::size_t i = 0; i < 16; i++) { ASSERT_NEAR(actualBlock.Xs[i], expectedBlock.Xs[i], 0.001); ASSERT_NEAR(actualBlock.Ys[i], expectedBlock.Ys[i], 0.001); ASSERT_NEAR(actualBlock.Zs[i], expectedBlock.Zs[i], 0.001); } } } } inline void assertNeutralJointRotations(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getJointCount(), expected->getJointCount()); for (std::uint16_t jointIdx = 0u; jointIdx < expected->getJointCount(); ++jointIdx) { Vec3 resultOffset = output->getNeutralJointRotation(jointIdx); Vec3 expectedOffset = expected->getNeutralJointRotation(jointIdx); assertVec3Near(resultOffset, expectedOffset, threshold); } } inline void assertNeutralJointRotation(const RawVector3Vector& neutralJoints, Reader* expected) { auto expectedRotationXs = expected->getNeutralJointRotationXs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.xs, expectedRotationXs); auto expectedRotationYs = expected->getNeutralJointRotationYs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.ys, expectedRotationYs); auto expectedRotationZs = expected->getNeutralJointRotationZs(); ASSERT_ELEMENTS_AND_SIZE_EQ(neutralJoints.zs, expectedRotationZs); } inline void assertJointBehavior(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getJointGroupCount(), expected->getJointGroupCount()); for (std::uint16_t jointGroupIdx = 0u; jointGroupIdx < expected->getJointGroupCount(); ++jointGroupIdx) { auto resultOutputIndices = output->getJointGroupOutputIndices(jointGroupIdx); auto expectedOutputIndices = expected->getJointGroupOutputIndices(jointGroupIdx); ASSERT_EQ(resultOutputIndices, expectedOutputIndices); auto resultValues = output->getJointGroupValues(jointGroupIdx); auto expectedValues = expected->getJointGroupValues(jointGroupIdx); ASSERT_ELEMENTS_NEAR(resultValues, expectedValues, expectedValues.size(), threshold); auto resultLODs = output->getJointGroupLODs(jointGroupIdx); auto expectedLODs = expected->getJointGroupLODs(jointGroupIdx); ASSERT_EQ(resultLODs, expectedLODs); } } inline void assertJointBehavior(ConstArrayView jointGroups, Reader* expected) { std::uint16_t expectedJointGroupCount = expected->getJointGroupCount(); ASSERT_EQ(jointGroups.size(), expectedJointGroupCount); for (std::uint16_t jointGroupIdx = 0u; jointGroupIdx < expectedJointGroupCount; jointGroupIdx++) { const auto& actualJointGroup = jointGroups[jointGroupIdx]; auto expectedInputIndices = expected->getJointGroupInputIndices(jointGroupIdx); ASSERT_ELEMENTS_AND_SIZE_EQ(expectedInputIndices, actualJointGroup.inputIndices); auto expectedOutputIndices = expected->getJointGroupOutputIndices(jointGroupIdx); ASSERT_ELEMENTS_AND_SIZE_EQ(expectedOutputIndices, actualJointGroup.outputIndices); auto expectedLODs = expected->getJointGroupLODs(jointGroupIdx); ASSERT_ELEMENTS_AND_SIZE_EQ(expectedLODs, actualJointGroup.lods); auto expectedValues = expected->getJointGroupValues(jointGroupIdx); ASSERT_ELEMENTS_AND_SIZE_EQ(expectedValues, actualJointGroup.values); } } inline void assertJointBehaviorPoolIndices(const VariableWidthMatrix& indices, const Matrix& expectedIndices) { auto jointGroupCount = static_cast(expectedIndices.size()); ASSERT_EQ(indices.rowCount(), jointGroupCount); for (std::uint16_t jntGrpIdx = 0u; jntGrpIdx < jointGroupCount; jntGrpIdx++) { ASSERT_EQ(indices[jntGrpIdx], expectedIndices[jntGrpIdx]); } } inline void assertJointBehaviorValues(ConstArrayView actualJoints, const Vector& expectedJoints) { for (std::uint16_t jntOffset = 0u; jntOffset < expectedJoints.size(); jntOffset++) { const auto& joint = actualJoints[jntOffset]; const auto& expectedJoint = expectedJoints[jntOffset]; auto blockValues = joint.getValues(); ASSERT_EQ(blockValues.size(), expectedJoint.blockValues.size()); for (std::size_t outPos = 0; outPos < blockValues.size(); outPos++) { const auto& outPosValues = blockValues[outPos]; const auto& expectedOutPosValues = expectedJoint.blockValues[outPos]; ASSERT_EQ(outPosValues.rowCount(), expectedOutPosValues.size()); for (std::size_t vBlockIdx = 0u; vBlockIdx < outPosValues.rowCount(); vBlockIdx++) { for (std::size_t dnaIdx = 0u; dnaIdx < outPosValues[vBlockIdx].size(); dnaIdx++) { ASSERT_EQ(outPosValues[vBlockIdx][dnaIdx], expectedOutPosValues[vBlockIdx][dnaIdx]); } } } } } inline void assertSkinWeights(Reader* output, Reader* expected, float threshold) { ASSERT_EQ(output->getMeshCount(), expected->getMeshCount()); for (std::uint16_t meshIdx = 0; meshIdx < expected->getMeshCount(); ++meshIdx) { ASSERT_EQ(output->getVertexPositionCount(meshIdx), expected->getVertexPositionCount(meshIdx)); for (std::uint32_t vertexIdx = 0; vertexIdx < expected->getVertexPositionCount(meshIdx); ++vertexIdx) { auto resultWeights = output->getSkinWeightsValues(meshIdx, vertexIdx); auto expectedWeights = expected->getSkinWeightsValues(meshIdx, vertexIdx); ASSERT_ELEMENTS_NEAR(resultWeights, expectedWeights, expectedWeights.size(), threshold); auto resultJointIndices = output->getSkinWeightsJointIndices(meshIdx, vertexIdx); auto expectedJointIndices = expected->getSkinWeightsJointIndices(meshIdx, vertexIdx); ASSERT_EQ(resultJointIndices, expectedJointIndices); } } } inline void assertSkinWeights(ConstArrayView > skinWeights, Reader* expected) { std::uint16_t expectedMeshCount = expected->getMeshCount(); auto actualMeshCount = static_cast(skinWeights.size()); ASSERT_EQ(actualMeshCount, expectedMeshCount); for (std::uint16_t meshIdx = 0u; meshIdx < actualMeshCount; meshIdx++) { std::uint32_t expectedSkinWeightCount = expected->getSkinWeightsCount(meshIdx); auto actualSkinWeightCount = static_cast(skinWeights[meshIdx].size()); ASSERT_EQ(actualSkinWeightCount, expectedSkinWeightCount); for (std::uint32_t vertexIdx = 0u; vertexIdx < expectedSkinWeightCount; vertexIdx++) { auto expectedValues = expected->getSkinWeightsValues(meshIdx, vertexIdx); const auto& actualValues = skinWeights[meshIdx][vertexIdx].weights; ASSERT_ELEMENTS_AND_SIZE_EQ(actualValues, expectedValues); auto expectedJointIndices = expected->getSkinWeightsJointIndices(meshIdx, vertexIdx); const auto& actualJointIndices = skinWeights[meshIdx][vertexIdx].jointIndices; ASSERT_ELEMENTS_AND_SIZE_EQ(actualJointIndices, expectedJointIndices); } } } inline void assertSkinWeightPoolJointIndices(ConstArrayView > indices, const Vector >& expectedIndices) { ASSERT_EQ(indices.size(), expectedIndices.size()); for (std::uint32_t meshIndex = 0u; meshIndex < indices.size(); meshIndex++) { const auto& mesh = indices[meshIndex]; const auto& expectedMesh = expectedIndices[meshIndex]; const auto vertexCount = mesh.rowCount(); ASSERT_EQ(vertexCount, expectedMesh.size()); for (std::uint16_t vtxIdx = 0u; vtxIdx < vertexCount; vtxIdx++) { ASSERT_EQ(mesh[vtxIdx], expectedMesh[vtxIdx]); } } } inline void assertSkinWeightPoolValues(const VariableWidthMatrix >& weights, const Matrix > >& expectedWeights) { ASSERT_EQ(weights.rowCount(), expectedWeights.size()); for (std::uint16_t meshIndex = 0; meshIndex < weights.rowCount(); meshIndex++) { auto mesh = weights[meshIndex]; const auto& expectedMesh = expectedWeights[meshIndex]; auto blockCount = static_cast(mesh.size()); ASSERT_EQ(blockCount, expectedMesh.size()); for (std::uint32_t blockIdx = 0u; blockIdx < blockCount; blockIdx++) { const auto& dnaBlock = mesh[blockIdx]; const auto& expectedDNABlock = expectedMesh[blockIdx]; for (std::size_t dnaIdx = 0u; dnaIdx < expectedDNABlock.size(); dnaIdx++) { auto dnaValues = dnaBlock[dnaIdx]; const auto& expectedDNAValues = expectedDNABlock[dnaIdx]; ASSERT_EQ(dnaValues.size(), expectedDNAValues.size()); auto jntPosCount = static_cast(dnaValues.size()); for (std::uint32_t jntPos = 0u; jntPos < jntPosCount; jntPos++) { ASSERT_EQ(dnaValues[jntPos], expectedDNAValues[jntPos]); } } } } } inline void assertRawGenes(const RawGenes& rawGenes, Reader* expected) { ASSERT_EQ(expected->getMeshCount(), rawGenes.getMeshCount()); for (std::uint16_t meshIdx = 0u; meshIdx < rawGenes.getMeshCount(); meshIdx++) { ASSERT_EQ(expected->getVertexPositionCount(meshIdx), rawGenes.getVertexCount(meshIdx)); ASSERT_EQ(expected->getSkinWeightsCount(meshIdx), rawGenes.getSkinWeightsCount(meshIdx)); } ASSERT_EQ(expected->getJointCount(), rawGenes.getJointCount()); assertNeutralMeshes(rawGenes.getNeutralMeshes(), expected); assertBlendShapeTargets(rawGenes.getBlendShapeTargets(), expected); assertSkinWeights(rawGenes.getSkinWeights(), expected); assertNeutralJoints(rawGenes.getNeutralJoints(JointAttribute::Translation), canonical::expectedRawGenesNeutralJointTranslations, 0.0001f); assertNeutralJoints(rawGenes.getNeutralJoints(JointAttribute::Rotation), canonical::expectedRawGenesNeutralJointRotations, 0.0001f); assertJointBehavior(rawGenes.getJointGroups(), expected); } #ifdef _MSC_VER #pragma warning(pop) #endif } // namespace gs4