You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
462 lines
20 KiB
C++
462 lines
20 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AZTestShared/Math/MathTestHelpers.h>
|
|
|
|
#include <AzCore/Interface/Interface.h>
|
|
#include <AzCore/Component/TickBus.h>
|
|
|
|
#include <UnitTestHelper.h>
|
|
#include <TriangleInputHelper.h>
|
|
|
|
#include <NvCloth/IClothSystem.h>
|
|
#include <NvCloth/ISolver.h>
|
|
#include <NvCloth/ICloth.h>
|
|
#include <NvCloth/IFabricCooker.h>
|
|
|
|
#include <System/Cloth.h>
|
|
#include <System/Solver.h>
|
|
|
|
namespace UnitTest
|
|
{
|
|
TEST(NvClothSystem, ClothSystem_DefaultSolver_Exists)
|
|
{
|
|
NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
|
|
|
|
EXPECT_TRUE(defaultSolver != nullptr);
|
|
EXPECT_TRUE(defaultSolver->GetName() == NvCloth::DefaultSolverName);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_FindOrCreateSolverDefaultName_ReturnsDefaultSolver)
|
|
{
|
|
NvCloth::ISolver* defaultSolverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
|
|
NvCloth::ISolver* defaultSolverFromFindOrCreateFunc = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(NvCloth::DefaultSolverName);
|
|
|
|
EXPECT_EQ(defaultSolverFromGetter, defaultSolverFromFindOrCreateFunc);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_FindOrCreateSolverEmptyName_ReturnsNull)
|
|
{
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("");
|
|
|
|
EXPECT_TRUE(solver == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_FindOrCreateSolver_ReturnsValidSolver)
|
|
{
|
|
const AZStd::string solverName = "Solver_FindOrCreateSolver";
|
|
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
|
|
|
|
EXPECT_TRUE(solver != nullptr);
|
|
EXPECT_TRUE(solver->GetName() == solverName);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying solver to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_FindOrCreateSolverTwice_ReturnsSameSolver)
|
|
{
|
|
const AZStd::string solverName = "Solver_FindOrCreateSolverTwice";
|
|
|
|
NvCloth::ISolver* solverA = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
|
|
NvCloth::ISolver* solverB = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
|
|
|
|
EXPECT_EQ(solverA, solverB);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying solver to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solverA);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_DestroySolverNullptr_DoesNotFail)
|
|
{
|
|
NvCloth::ISolver* solver = nullptr;
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
|
|
EXPECT_TRUE(solver == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_DestroySolver_SolverIsDestroyed)
|
|
{
|
|
const AZStd::string solverName = "Solver_DestroySolver";
|
|
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
|
|
|
|
EXPECT_TRUE(solver != nullptr);
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
|
|
EXPECT_TRUE(solver == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetSolverEmpyName_ReturnsNull)
|
|
{
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver("");
|
|
|
|
EXPECT_TRUE(solver == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetSolverUnknownName_ReturnsNull)
|
|
{
|
|
const AZStd::string solverName = "Solver_GetSolverUnknownName";
|
|
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
|
|
|
|
EXPECT_TRUE(solver == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetSolver_ReturnsSolver)
|
|
{
|
|
const AZStd::string solverName = "Solver_GetSolver";
|
|
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
|
|
NvCloth::ISolver* solverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
|
|
|
|
EXPECT_TRUE(solver != nullptr);
|
|
EXPECT_EQ(solver, solverFromGetter);
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
|
|
solverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
|
|
|
|
EXPECT_TRUE(solverFromGetter == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_CreateClothNoInitialParticles_ReturnsNull)
|
|
{
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth({}, {});
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_CreateClothInvalidFabric_ReturnsNull)
|
|
{
|
|
const float width = 1.0f;
|
|
const float height = 1.0f;
|
|
const AZ::u32 segmentsX = 5;
|
|
const AZ::u32 segmentsY = 5;
|
|
|
|
const TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(planeXY.m_vertices, {});
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_CreateClothInitialParticlesMismatchFabricNumParticles_ReturnsNull)
|
|
{
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
|
|
auto otherVertices = fabricCookedData.m_particles;
|
|
otherVertices.resize(otherVertices.size() / 2);
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(
|
|
otherVertices, // otherVertices has a different number of vertices than FabricCookedData
|
|
fabricCookedData);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_CreateCloth_ReturnsValidCloth)
|
|
{
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
EXPECT_TRUE(cloth != nullptr);
|
|
EXPECT_TRUE(cloth->GetId().IsValid());
|
|
EXPECT_THAT(cloth->GetInitialParticles(), ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), fabricCookedData.m_particles));
|
|
EXPECT_EQ(cloth->GetInitialIndices(), fabricCookedData.m_indices);
|
|
EXPECT_THAT(cloth->GetParticles(), ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), fabricCookedData.m_particles));
|
|
EXPECT_NE(cloth->GetClothConfigurator(), nullptr);
|
|
ExpectEq(cloth->GetFabricCookedData(), fabricCookedData);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_DestroyClothNullptr_DoesNotFail)
|
|
{
|
|
NvCloth::ICloth* cloth = nullptr;
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_DestroyCloth_ClothIsDestroyed)
|
|
{
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
EXPECT_TRUE(cloth != nullptr);
|
|
EXPECT_TRUE(cloth->GetId().IsValid());
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetClothInvalidId_ReturnsNull)
|
|
{
|
|
const NvCloth::ClothId clothId;
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(clothId);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetClothUnknownId_ReturnsNull)
|
|
{
|
|
const NvCloth::ClothId clothId(5);
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(clothId);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_GetCloth_ReturnsCloth)
|
|
{
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
EXPECT_TRUE(cloth != nullptr);
|
|
EXPECT_TRUE(cloth->GetId().IsValid());
|
|
|
|
NvCloth::ICloth* clothFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(cloth->GetId());
|
|
|
|
EXPECT_TRUE(clothFromGetter != nullptr);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothNull_ReturnsFalse)
|
|
{
|
|
NvCloth::ICloth* cloth = nullptr;
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
|
|
|
|
EXPECT_FALSE(clothAdded);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothToInvalidSolver_ReturnsFalse)
|
|
{
|
|
const AZStd::string solverName = "";
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solverName);
|
|
|
|
EXPECT_FALSE(clothAdded);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothToNonExistentSolver_ReturnsFalse)
|
|
{
|
|
const AZStd::string solverName = "Solver_AddClothToNonExistentSolver";
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solverName);
|
|
|
|
EXPECT_FALSE(clothAdded);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothToDefaultSolver_ReturnsTrue)
|
|
{
|
|
NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
|
|
|
|
EXPECT_TRUE(clothAdded);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothToSolver_ReturnsTrue)
|
|
{
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("Solver_AddClothToSolver");
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(solver)->GetNumCloths() == 0);
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solver->GetName());
|
|
|
|
EXPECT_TRUE(clothAdded);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == solver->GetName());
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(solver)->GetNumCloths() == 1);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth and solver to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_AddClothTwice_NothingHappensSecondTime)
|
|
{
|
|
NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
|
|
EXPECT_TRUE(clothAdded);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
|
|
|
|
clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
|
|
EXPECT_TRUE(clothAdded);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_RemoveClothNull_NothingHappens)
|
|
{
|
|
NvCloth::ICloth* cloth = nullptr;
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
|
|
|
|
EXPECT_TRUE(cloth == nullptr);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_RemoveClothTwice_NothingHappensSecondTime)
|
|
{
|
|
NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
|
|
EXPECT_TRUE(clothAdded);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
|
|
EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
}
|
|
|
|
TEST(NvClothSystem, ClothSystem_Tick_SolverAndClothIsUpdated)
|
|
{
|
|
const float deltaTimeSim = 1.0f / 60.0f;
|
|
|
|
NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("Solver_Tick");
|
|
|
|
const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
|
|
NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
|
|
|
|
bool solverPreSimulationEventSignaled = false;
|
|
NvCloth::ISolver::PreSimulationEvent::Handler solverPreSimulationEventHandler(
|
|
[&solverPreSimulationEventSignaled](const AZStd::string&, float)
|
|
{
|
|
solverPreSimulationEventSignaled = true;
|
|
});
|
|
|
|
bool solverPostSimulationEventSignaled = false;
|
|
NvCloth::ISolver::PostSimulationEvent::Handler solverPostSimulationEventHandler(
|
|
[&solverPostSimulationEventSignaled](const AZStd::string&, float)
|
|
{
|
|
solverPostSimulationEventSignaled = true;
|
|
});
|
|
|
|
bool clothPreSimulationEventSignaled = false;
|
|
NvCloth::ICloth::PreSimulationEvent::Handler clothPreSimulationEventHandler(
|
|
[&clothPreSimulationEventSignaled](NvCloth::ClothId, float)
|
|
{
|
|
clothPreSimulationEventSignaled = true;
|
|
});
|
|
|
|
bool clothPostSimulationEventSignaled = false;
|
|
NvCloth::ICloth::PostSimulationEvent::Handler clothPostSimulationEventHandler(
|
|
[&clothPostSimulationEventSignaled](NvCloth::ClothId, float, const AZStd::vector<NvCloth::SimParticleFormat>&)
|
|
{
|
|
clothPostSimulationEventSignaled = true;
|
|
});
|
|
|
|
solver->ConnectPreSimulationEventHandler(solverPreSimulationEventHandler);
|
|
solver->ConnectPostSimulationEventHandler(solverPostSimulationEventHandler);
|
|
cloth->ConnectPreSimulationEventHandler(clothPreSimulationEventHandler);
|
|
cloth->ConnectPostSimulationEventHandler(clothPostSimulationEventHandler);
|
|
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solver->GetName()); // It needs at least one cloth in the solver to simulate
|
|
|
|
// Ticking Cloth System to update all its solvers
|
|
AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick,
|
|
deltaTimeSim,
|
|
AZ::ScriptTimePoint(AZStd::chrono::system_clock::now()));
|
|
|
|
EXPECT_TRUE(solverPreSimulationEventSignaled);
|
|
EXPECT_TRUE(solverPostSimulationEventSignaled);
|
|
EXPECT_TRUE(clothPreSimulationEventSignaled);
|
|
EXPECT_TRUE(clothPostSimulationEventSignaled);
|
|
|
|
solverPreSimulationEventSignaled = false;
|
|
solverPostSimulationEventSignaled = false;
|
|
clothPreSimulationEventSignaled = false;
|
|
clothPostSimulationEventSignaled = false;
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth); // Leave solver without have any cloths
|
|
|
|
// Ticking Cloth System to update all its solvers
|
|
AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick,
|
|
deltaTimeSim,
|
|
AZ::ScriptTimePoint(AZStd::chrono::system_clock::now()));
|
|
|
|
EXPECT_FALSE(solverPreSimulationEventSignaled);
|
|
EXPECT_FALSE(solverPostSimulationEventSignaled);
|
|
EXPECT_FALSE(clothPreSimulationEventSignaled);
|
|
EXPECT_FALSE(clothPostSimulationEventSignaled);
|
|
|
|
// NOTE: IClothSystem is persistent as it's part of the test environment.
|
|
// Destroying cloth and solver to avoid leaving it in the environment.
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
|
|
AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
|
|
}
|
|
} // namespace UnitTest
|