/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include <Tests/ActorFixture.h> #include <EMotionFX/Source/Actor.h> #include <EMotionFX/Source/ActorInstance.h> #include <EMotionFX/Source/Node.h> #include <EMotionFX/Source/Skeleton.h> namespace EMotionFX { class SkeletalLODFixture : public ActorFixture { public: void SetUp() { ActorFixture::SetUp(); m_actor->AddLODLevel(); DisableJointsForLOD(m_disabledJointNames, 1); } void DisableJointsForLOD(const std::vector<std::string>& jointNames, AZ::u32 lodLevel) { const Skeleton* skeleton = m_actor->GetSkeleton(); for (const std::string& jointName : jointNames) { Node* joint = skeleton->FindNodeByName(jointName.c_str()); ASSERT_NE(joint, nullptr); joint->SetSkeletalLODStatus(lodLevel, false); } } static void VerifySkeletalLODFlags(const ActorInstance* actorInstance, const std::vector<std::string>& disabledJointNames, AZ::u32 lodLevel) { EXPECT_EQ(actorInstance->GetLODLevel(), lodLevel) << "Please note that setting the LOD level is delayed and happend with the next UpdateTransforms()."; const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); const MCore::Array<AZ::u16>& enabledJoints = actorInstance->GetEnabledNodes(); const AZ::u32 numEnabledJoints = enabledJoints.GetLength(); EXPECT_EQ(actorInstance->GetNumEnabledNodes(), actor->GetNumNodes() - static_cast<AZ::u32>(disabledJointNames.size())) << "The enabled joints on the actor instance are not in sync with the enabledJoints."; const AZ::u32 numJoints = skeleton->GetNumNodes(); for (AZ::u32 i = 0; i < numJoints; ++i) { const Node* joint = skeleton->GetNode(i); // Check the skeletal LOD flag on the joint (actor asset). const bool isJointEnabled = std::find(disabledJointNames.begin(), disabledJointNames.end(), joint->GetName()) == disabledJointNames.end(); EXPECT_EQ(isJointEnabled, joint->GetSkeletalLODStatus(lodLevel)) << "The skeletal LOD flag on the joint does not match the disabled joints set by the test."; // Check if the enabled joints on the actor instance is in sync. bool foundInEnabledJoints = false; for (AZ::u32 j = 0; j < numEnabledJoints; ++j) { const AZ::u16 enabledJointIndex = actorInstance->GetEnabledNode(j); const Node* enabledJoint = skeleton->GetNode(enabledJointIndex); if (joint == enabledJoint) { foundInEnabledJoints = true; break; } } EXPECT_EQ(isJointEnabled, foundInEnabledJoints) << "The joint is disabled (enabled) but has (not) been found in the enabled joints in the actor instance."; } } public: const std::vector<std::string> m_disabledJointNames = { "r_thumb1", "r_thumb2", "r_thumb3", "r_index1", "r_index2", "r_index3" }; }; TEST_F(SkeletalLODFixture, SkeletalLODTest) { // Check default LOD 0 m_actorInstance->UpdateTransformations(0.0f); VerifySkeletalLODFlags(m_actorInstance, {}, 0); // Set to LOD 1 m_actorInstance->SetLODLevel(1); m_actorInstance->UpdateTransformations(0.0f); VerifySkeletalLODFlags(m_actorInstance, m_disabledJointNames, 1); // Set back to LOD0 m_actorInstance->SetLODLevel(0); m_actorInstance->UpdateTransformations(0.0f); VerifySkeletalLODFlags(m_actorInstance, {}, 0); } } // namespace EMotionFX