diff options
| author | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
| commit | 7115f60b91b5717d90f643fd692010905c7004db (patch) | |
| tree | effd68c6978751c517d54c2f2bb5bb6e7dc93e18 /test/src/unit/TkCompositeTests.cpp | |
| parent | Updating BlastTool zip (diff) | |
| download | blast-1.1.3_rc1.tar.xz blast-1.1.3_rc1.zip | |
Blast 1.1.3. See docs/release_notes.txt.v1.1.3_rc1
Diffstat (limited to 'test/src/unit/TkCompositeTests.cpp')
| -rwxr-xr-x[-rw-r--r--] | test/src/unit/TkCompositeTests.cpp | 1550 |
1 files changed, 775 insertions, 775 deletions
diff --git a/test/src/unit/TkCompositeTests.cpp b/test/src/unit/TkCompositeTests.cpp index 8f55612..96fcc75 100644..100755 --- a/test/src/unit/TkCompositeTests.cpp +++ b/test/src/unit/TkCompositeTests.cpp @@ -1,775 +1,775 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you -// under a form of NVIDIA software license agreement provided separately to you. -// -// Notice -// NVIDIA Corporation and its licensors retain all intellectual property and -// proprietary rights in and to this software and related documentation and -// any modifications thereto. Any use, reproduction, disclosure, or -// distribution of this software and related documentation without an express -// license agreement from NVIDIA Corporation is strictly prohibited. -// -// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES -// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO -// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, -// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. -// -// Information and code furnished is believed to be accurate and reliable. -// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such -// information or for any infringement of patents or other rights of third parties that may -// result from its use. No license is granted by implication or otherwise under any patent -// or patent rights of NVIDIA Corporation. Details are subject to change without notice. -// This code supersedes and replaces all information previously supplied. -// NVIDIA Corporation products are not authorized for use as critical -// components in life support devices or systems without express written approval of -// NVIDIA Corporation. -// -// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. - - -#include "TkBaseTest.h" - -#include <map> -#include <random> -#include <algorithm> - -#include "PsMemoryBuffer.h" - -#include "NvBlastTime.h" - - -/* -Composite and joint tests: - -0) Test serialization of composites and assemblies - -1) Create assembly, actors and joints should be created automatically - -2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - -3) Joint update events should be fired when attached actors change - -4) Joint delete events should be fired when at least one attached actor is deleted - -5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above -*/ - - -struct Composite -{ - std::vector<TkActorDesc> m_actorDescs; - std::vector<physx::PxTransform> m_relTMs; - std::vector<TkJointDesc> m_jointDescs; -}; - - -template<int FailLevel, int Verbosity> -class TkCompositeTest : public TkBaseTest<FailLevel, Verbosity> -{ -public: - - // Composite/joint tests - void createAssembly(std::vector<TkActor*>& actors, std::vector<TkJoint*>& joints, bool createNRFJoints) - { - TkFramework* fw = NvBlastTkFrameworkGet(); - - actors.resize(4, nullptr); - actors[0] = fw->createActor(TkActorDesc(testAssets[0])); - actors[1] = fw->createActor(TkActorDesc(testAssets[0])); - actors[2] = fw->createActor(TkActorDesc(testAssets[1])); - actors[3] = fw->createActor(TkActorDesc(testAssets[1])); - - std::vector<TkFamily*> families(4); - families[0] = &actors[0]->getFamily(); - families[1] = &actors[1]->getFamily(); - families[2] = &actors[2]->getFamily(); - families[3] = &actors[3]->getFamily(); - - EXPECT_FALSE(actors[0] == nullptr); - EXPECT_FALSE(actors[1] == nullptr); - EXPECT_FALSE(actors[2] == nullptr); - EXPECT_FALSE(actors[3] == nullptr); - - const TkJointDesc jointDescsNoNRF[8] = - { - // Actor indices, chunk indices, attach position in the composite frame - { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } }, - { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } }, - - { { families[0], families[2] }, { 8, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { families[0], families[2] }, { 3, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { families[1], families[3] }, { 7, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { families[1], families[3] }, { 4, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } }, - { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f) } } - }; - - const TkJointDesc jointDescsWithNRF[12] = - { - // Actor indices, chunk indices, attach position in the composite frame - { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } }, - { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } }, - - { { families[0], nullptr }, { 8, 0xFFFFFFFF }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { families[0], nullptr }, { 3, 0xFFFFFFFF }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { nullptr, families[2] }, { 0xFFFFFFFF, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { nullptr, families[2] }, { 0xFFFFFFFF, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { families[1], nullptr }, { 7, 0xFFFFFFFF }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { families[1], nullptr }, { 4, 0xFFFFFFFF }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { nullptr, families[3] }, { 0xFFFFFFFF, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { nullptr, families[3] }, { 0xFFFFFFFF, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } }, - { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f), } } - }; - - const TkJointDesc* jointDescs = createNRFJoints ? jointDescsWithNRF : jointDescsNoNRF; - const int jointCount = createNRFJoints ? 12 : 8; - - joints.resize(jointCount, nullptr); - for (int i = 0; i < jointCount; ++i) - { - joints[i] = fw->createJoint(jointDescs[i]); - EXPECT_FALSE(joints[i] == nullptr); - } - } - - void familySerialization(std::vector<TkFamily*>& families, TestFamilyTracker& tracker) - { -#if 1 - NV_UNUSED(families); - NV_UNUSED(tracker); -#else - TkFramework* fw = NvBlastTkFrameworkGet(); - - PsMemoryBuffer* membuf = PX_NEW(PsMemoryBuffer); - EXPECT_TRUE(membuf != nullptr); - if (membuf == nullptr) - { - return; - } - - std::vector<TkFamily*> oldFamilies = families; - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - GTEST_FATAL_FAILURE_("Serialization of families needs to be put into extensions."); -// families[familyNum]->serialize(*membuf); - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - TkFamily* f = families[familyNum]; - - std::vector<TkActor*> actors(f->getActorCount()); - f->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto a : actors) - { - tracker.eraseActor(a); - } - - f->release(); - families[familyNum] = nullptr; - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - GTEST_FATAL_FAILURE_("Deserialization of families needs to be put into extensions."); -// TkFamily* f = reinterpret_cast<TkFamily*>(fw->deserialize(*membuf)); -// f->addListener(tracker); -// families[familyNum] = f; - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - TkFamily* f = families[familyNum]; - - std::vector<TkActor*> actors(f->getActorCount()); - f->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto a : actors) - { - tracker.insertActor(a); - - std::vector<TkJoint*> joints(a->getJointCount()); - a->getJoints(joints.data(), (uint32_t)joints.size()); - - for (auto j : joints) - { - const TkJointData jd = j->getData(); - if (jd.actors[0] != jd.actors[1]) - { - tracker.joints.insert(j); - } - } - } - } - - membuf->release(); -#endif - } - - void recollectActors(std::vector<TkFamily*>& families, std::vector<TkActor*>& actors) - { - uint32_t totalActorCount = 0; - for (auto family : families) - { - EXPECT_LE(family->getActorCount() + totalActorCount, actors.size()); - totalActorCount += family->getActors(actors.data() + totalActorCount, static_cast<uint32_t>(actors.size()) - totalActorCount); - } - } - - void assemblyCreateAndRelease(bool createNRFJoints, bool serializationTest) - { - createFramework(); - createTestAssets(); - - TkFramework* fw = NvBlastTkFrameworkGet(); - - const TkType* familyType = fw->getType(TkTypeIndex::Family); - EXPECT_TRUE(familyType != nullptr); - - TestFamilyTracker tracker; - - std::vector<TkFamily*> families1; - std::vector<TkFamily*> families2; - - // Create one assembly - std::vector<TkActor*> actors1; - std::vector<TkJoint*> joints1; - createAssembly(actors1, joints1, createNRFJoints); - tracker.joints.insert(joints1.begin(), joints1.end()); - - // Create another assembly - std::vector<TkActor*> actors2; - std::vector<TkJoint*> joints2; - createAssembly(actors2, joints2, createNRFJoints); - tracker.joints.insert(joints2.begin(), joints2.end()); - - // Store families and fill group - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - TkFamily& family = actors1[actorNum]->getFamily(); - families1.push_back(&family); - family.addListener(tracker); - } - for (size_t actorNum = 0; actorNum < actors2.size(); ++actorNum) - { - TkFamily& family = actors2[actorNum]->getFamily(); - families2.push_back(&family); - family.addListener(tracker); - } - - if (serializationTest) - { - familySerialization(families1, tracker); - recollectActors(families1, actors1); - familySerialization(families2, tracker); - recollectActors(families2, actors2); - } - - EXPECT_EQ(joints1.size() + joints2.size(), tracker.joints.size()); - - // Release 1st assembly's actors - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - actors1[actorNum]->release(); - } - - if (serializationTest) - { - familySerialization(families2, tracker); - recollectActors(families2, actors2); - } - - EXPECT_EQ(joints2.size(), tracker.joints.size()); - - // Release 2nd assembly's actors - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - actors2[actorNum]->release(); - } - - EXPECT_EQ(0, tracker.joints.size()); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyInternalJoints(bool testAssemblySerialization) - { - createFramework(); - createTestAssets(true); // Create assets with internal joints - - TkFramework* fw = NvBlastTkFrameworkGet(); - - TestFamilyTracker tracker; - - TkGroupDesc gdesc; - gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount(); - TkGroup* group = fw->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - m_groupTM->setGroup(group); - - TkActorDesc adesc(testAssets[0]); - - TkActor* actor1 = fw->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - tracker.insertActor(actor1); - - actor1->getFamily().addListener(tracker); - - TkFamily* family = &actor1->getFamily(); - - group->addActor(*actor1); - - CSParams cs2(2, 0.0f); - NvBlastExtProgramParams csParams2 = { &cs2, nullptr }; - actor1->damage(getCubeSlicerProgram(), &csParams2); - - EXPECT_EQ((size_t)0, tracker.joints.size()); - - m_groupTM->process(); - m_groupTM->wait(); - - if (testAssemblySerialization) - { - std::vector<TkFamily*> families; - families.push_back(family); - familySerialization(families, tracker); - family = families[0]; - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (TkActor* actor : actors) - { - group->addActor(*actor); - } - } - - EXPECT_EQ((size_t)2, family->getActorCount()); - EXPECT_EQ((size_t)4, tracker.joints.size()); // 2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - NvBlastExtProgramParams radialParams = { &radialDamage, nullptr }; - for (TkActor* actor : actors) - { - actor->damage(getFalloffProgram(), &radialParams); - } - - m_groupTM->process(); - m_groupTM->wait(); - - if (testAssemblySerialization) - { - std::vector<TkFamily*> families; - families.push_back(family); - familySerialization(families, tracker); - family = families[0]; - } - - EXPECT_EQ((size_t)8, family->getActorCount()); - EXPECT_EQ((size_t)4, tracker.joints.size()); - - // 3) Joint update events should be fired when attached actors change - - actors.resize(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - for (TkActor* actor : actors) - { - actor->release(); - } - - EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted - - group->release(); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyCompositeWithInternalJoints(bool createNRFJoints, bool serializationTest) - { - createFramework(); - createTestAssets(true); // Create assets with internal joints - - TkFramework* fw = NvBlastTkFrameworkGet(); - - const TkType* familyType = fw->getType(TkTypeIndex::Family); - EXPECT_TRUE(familyType != nullptr); - - if (familyType == nullptr) - { - return; - } - - TestFamilyTracker tracker; - - std::vector<TkFamily*> families; - - // Create assembly - std::vector<TkActor*> actors; - std::vector<TkJoint*> joints; - createAssembly(actors, joints, createNRFJoints); - tracker.joints.insert(joints.begin(), joints.end()); - - TkGroupDesc gdesc; - gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount(); - TkGroup* group = fw->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - m_groupTM->setGroup(group); - - for (size_t i = 0; i < actors.size(); ++i) - { - TkFamily& family = actors[i]->getFamily(); - families.push_back(&family); - family.addListener(tracker); - tracker.insertActor(actors[i]); - group->addActor(*actors[i]); - } - - if (serializationTest) - { - familySerialization(families, tracker); - recollectActors(families, actors); - for (auto actor : actors) - { - group->addActor(*actor); - } - } - - EXPECT_EQ((size_t)4, actors.size()); - - const size_t compJointCount = createNRFJoints ? (size_t)12 : (size_t)8; - - EXPECT_EQ(compJointCount, tracker.joints.size()); - - CSParams cs2(2, 0.0f); - NvBlastExtProgramParams csParams2 = { &cs2, nullptr }; - - size_t totalActorCount = 0; - for (uint32_t i = 0; i < 4; ++i) - { - actors[i]->damage(getCubeSlicerProgram(), &csParams2); - - m_groupTM->process(); - m_groupTM->wait(); - - if (serializationTest) - { - familySerialization(families, tracker); - for (size_t j = 0; j < families.size(); ++j) - { - TkFamily* family = families[j]; - std::vector<TkActor*> a(family->getActorCount()); - family->getActors(a.data(), static_cast<uint32_t>(a.size())); - for (auto actor : a) - { - group->addActor(*actor); - } - EXPECT_TRUE(j <= i || a.size() == 1); - if (j > i && a.size() == 1) - { - actors[j] = a[0]; - } - } - } - - EXPECT_EQ((size_t)2, families[i]->getActorCount()); - EXPECT_EQ((size_t)(compJointCount + 4 * (i + 1)), tracker.joints.size()); // Four joints created per actor - - totalActorCount += families[i]->getActorCount(); - } - - actors.resize(totalActorCount); - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount()); - totalActorCount += families[i]->getActorCount(); - } - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_TRUE(jd.actors[0] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_TRUE(jd.actors[1] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - NvBlastExtProgramParams radialParams = { &radialDamage, nullptr }; - for (TkActor* actor : actors) - { - actor->damage(getFalloffProgram(), &radialParams); - } - - m_groupTM->process(); - m_groupTM->wait(); - - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - totalActorCount += families[i]->getActorCount(); - } - - if (serializationTest) - { - familySerialization(families, tracker); - } - - EXPECT_EQ((size_t)32, totalActorCount); - EXPECT_EQ(compJointCount + (size_t)16, tracker.joints.size()); - - actors.resize(totalActorCount); - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount()); - totalActorCount += families[i]->getActorCount(); - } - - // 3) Joint update events should be fired when attached actors change - - for (TkActor* actor : actors) - { - actor->release(); - } - - EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted - - group->release(); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyExternalJoints_MultiFamilyDamage(bool explicitJointRelease = true) - { - createFramework(); - - const NvBlastChunkDesc chunkDescs[3] = - { -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 4.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { { 0.0f,-1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.0f, 1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 2 } - }; - - const NvBlastBondDesc bondDesc = -// normal area centroid userData chunks - { { { 0.0f, 1.0f, 0.0f }, 1.0f, { 0.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } }; - - TkFramework* framework = NvBlastTkFrameworkGet(); - - TestFamilyTracker tracker; - - TkAssetDesc desc; - desc.chunkCount = 3; - desc.chunkDescs = chunkDescs; - desc.bondCount = 1; - desc.bondDescs = &bondDesc; - desc.bondFlags = nullptr; - TkAsset* asset = framework->createAsset(desc); - EXPECT_TRUE(asset != nullptr); - - TkGroupDesc gdesc; - gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount(); - TkGroup* group = framework->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - m_groupTM->setGroup(group); - - TkActorDesc adesc(asset); - TkActor* actor1 = framework->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - TkActor* actor2 = framework->createActor(adesc); - EXPECT_TRUE(actor2 != nullptr); - - group->addActor(*actor1); - group->addActor(*actor2); - - TkFamily* family1 = &actor1->getFamily(); - TkFamily* family2 = &actor2->getFamily(); - - family1->addListener(tracker); - family2->addListener(tracker); - tracker.insertActor(actor1); - tracker.insertActor(actor2); - - TkJointDesc jdesc; - jdesc.families[0] = family1; - jdesc.families[1] = family2; - jdesc.chunkIndices[0] = 2; - jdesc.chunkIndices[1] = 1; - jdesc.attachPositions[0] = PxVec3(0.0f, 1.0f, 0.0f); - jdesc.attachPositions[1] = PxVec3(0.0f, -1.0f, 0.0f); - TkJoint* joint = framework->createJoint(jdesc); - EXPECT_TRUE(joint != nullptr); - tracker.joints.insert(joint); - - NvBlastExtRadialDamageDesc radialDamage1 = getRadialDamageDesc(0, 1, 0, 2, 2); - NvBlastExtProgramParams radialParams1 = { &radialDamage1, nullptr }; - actor1->damage(getFalloffProgram(), &radialParams1); - NvBlastExtRadialDamageDesc radialDamage2 = getRadialDamageDesc(0, -1, 0, 2, 2); - NvBlastExtProgramParams radialParams2 = { &radialDamage2, nullptr }; - actor2->damage(getFalloffProgram(), &radialParams2); - - m_groupTM->process(); - m_groupTM->wait(); - - TkActor* actors1[2]; - TkActor* actors2[2]; - EXPECT_EQ(2, family1->getActors(actors1, 2)); - EXPECT_EQ(2, family2->getActors(actors2, 2)); - - const TkJointData jdata = joint->getData(); - EXPECT_TRUE(jdata.actors[0] != nullptr); - EXPECT_TRUE(jdata.actors[1] != nullptr); - EXPECT_TRUE(&jdata.actors[0]->getFamily() == family1); - EXPECT_TRUE(&jdata.actors[1]->getFamily() == family2); - - // Clean up - if (explicitJointRelease) - { - joint->release(); - family2->release(); - family1->release(); - asset->release(); - releaseFramework(); - } - else - { - EXPECT_EQ(1, tracker.joints.size()); - releaseFramework(); - // Commenting these out - but shouldn't we be sending delete events when we release the framework? -// EXPECT_EQ(0, tracker.joints.size()); -// EXPECT_EQ(0, tracker.actors.size()); - } - } - -protected: - // http://clang.llvm.org/compatibility.html#dep_lookup_bases - // http://stackoverflow.com/questions/6592512/templates-parent-class-member-variables-not-visible-in-inherited-class - - using TkBaseTest<FailLevel, Verbosity>::testAssets; - using TkBaseTest<FailLevel, Verbosity>::m_taskman; - using TkBaseTest<FailLevel, Verbosity>::m_groupTM; - using TkBaseTest<FailLevel, Verbosity>::createFramework; - using TkBaseTest<FailLevel, Verbosity>::releaseFramework; - using TkBaseTest<FailLevel, Verbosity>::createTestAssets; - using TkBaseTest<FailLevel, Verbosity>::releaseTestAssets; - using TkBaseTest<FailLevel, Verbosity>::getCubeSlicerProgram; - using TkBaseTest<FailLevel, Verbosity>::getDefaultMaterial; - using TkBaseTest<FailLevel, Verbosity>::getRadialDamageDesc; - using TkBaseTest<FailLevel, Verbosity>::getFalloffProgram; -}; - - -typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestAllowWarnings; -typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestStrict; - - -/* -1) Create assembly, actors and joints should be created automatically -*/ - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_NoNRFJoints_NoSerialization) -{ - assemblyCreateAndRelease(false, false); -} - -TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCreateAndRelease_NoNRFJoints_AssemblySerialization) -{ - assemblyCreateAndRelease(false, true); -} - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_WithNRFJoints_NoSerialization) -{ - assemblyCreateAndRelease(true, false); -} - -TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCreateAndRelease_WithNRFJoints_AssemblySerialization) -{ - assemblyCreateAndRelease(true, true); -} - - -/** -2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - -3) Joint update events should be fired when attached actors change - -4) Joint delete events should be fired when at least one attached actor is deleted -*/ - -TEST_F(TkCompositeTestStrict, AssemblyInternalJoints_NoSerialization) -{ - assemblyInternalJoints(false); -} - -TEST_F(TkCompositeTestStrict, DISABLED_AssemblyInternalJoints_AssemblySerialization) -{ - assemblyInternalJoints(true); -} - - -/** -5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above -*/ - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_NoNRFJoints_NoSerialization) -{ - assemblyCompositeWithInternalJoints(false, false); -} - -TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCompositeWithInternalJoints_NoNRFJoints_AssemblySerialization) -{ - assemblyCompositeWithInternalJoints(false, true); -} - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_WithNRFJoints_NoSerialization) -{ - assemblyCompositeWithInternalJoints(true, false); -} - -TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCompositeWithInternalJoints_WithNRFJoints_AssemblySerialization) -{ - assemblyCompositeWithInternalJoints(true, true); -} - - -/* -More tests -*/ - -TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage) -{ - assemblyExternalJoints_MultiFamilyDamage(true); -} - -TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage_AutoJointRelease) -{ - assemblyExternalJoints_MultiFamilyDamage(false); -} +// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "TkBaseTest.h"
+
+#include <map>
+#include <random>
+#include <algorithm>
+
+#include "PsMemoryBuffer.h"
+
+#include "NvBlastTime.h"
+
+
+/*
+Composite and joint tests:
+
+0) Test serialization of composites and assemblies
+
+1) Create assembly, actors and joints should be created automatically
+
+2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched
+
+3) Joint update events should be fired when attached actors change
+
+4) Joint delete events should be fired when at least one attached actor is deleted
+
+5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above
+*/
+
+
+struct Composite
+{
+ std::vector<TkActorDesc> m_actorDescs;
+ std::vector<physx::PxTransform> m_relTMs;
+ std::vector<TkJointDesc> m_jointDescs;
+};
+
+
+template<int FailLevel, int Verbosity>
+class TkCompositeTest : public TkBaseTest<FailLevel, Verbosity>
+{
+public:
+
+ // Composite/joint tests
+ void createAssembly(std::vector<TkActor*>& actors, std::vector<TkJoint*>& joints, bool createNRFJoints)
+ {
+ TkFramework* fw = NvBlastTkFrameworkGet();
+
+ actors.resize(4, nullptr);
+ actors[0] = fw->createActor(TkActorDesc(testAssets[0]));
+ actors[1] = fw->createActor(TkActorDesc(testAssets[0]));
+ actors[2] = fw->createActor(TkActorDesc(testAssets[1]));
+ actors[3] = fw->createActor(TkActorDesc(testAssets[1]));
+
+ std::vector<TkFamily*> families(4);
+ families[0] = &actors[0]->getFamily();
+ families[1] = &actors[1]->getFamily();
+ families[2] = &actors[2]->getFamily();
+ families[3] = &actors[3]->getFamily();
+
+ EXPECT_FALSE(actors[0] == nullptr);
+ EXPECT_FALSE(actors[1] == nullptr);
+ EXPECT_FALSE(actors[2] == nullptr);
+ EXPECT_FALSE(actors[3] == nullptr);
+
+ const TkJointDesc jointDescsNoNRF[8] =
+ {
+ // Actor indices, chunk indices, attach position in the composite frame
+ { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } },
+ { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } },
+
+ { { families[0], families[2] }, { 8, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } },
+ { { families[0], families[2] }, { 3, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } },
+
+ { { families[1], families[3] }, { 7, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } },
+ { { families[1], families[3] }, { 4, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } },
+
+ { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } },
+ { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f) } }
+ };
+
+ const TkJointDesc jointDescsWithNRF[12] =
+ {
+ // Actor indices, chunk indices, attach position in the composite frame
+ { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } },
+ { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } },
+
+ { { families[0], nullptr }, { 8, 0xFFFFFFFF }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } },
+ { { families[0], nullptr }, { 3, 0xFFFFFFFF }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } },
+
+ { { nullptr, families[2] }, { 0xFFFFFFFF, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } },
+ { { nullptr, families[2] }, { 0xFFFFFFFF, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } },
+
+ { { families[1], nullptr }, { 7, 0xFFFFFFFF }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } },
+ { { families[1], nullptr }, { 4, 0xFFFFFFFF }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } },
+
+ { { nullptr, families[3] }, { 0xFFFFFFFF, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } },
+ { { nullptr, families[3] }, { 0xFFFFFFFF, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } },
+
+ { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } },
+ { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f), } }
+ };
+
+ const TkJointDesc* jointDescs = createNRFJoints ? jointDescsWithNRF : jointDescsNoNRF;
+ const int jointCount = createNRFJoints ? 12 : 8;
+
+ joints.resize(jointCount, nullptr);
+ for (int i = 0; i < jointCount; ++i)
+ {
+ joints[i] = fw->createJoint(jointDescs[i]);
+ EXPECT_FALSE(joints[i] == nullptr);
+ }
+ }
+
+ void familySerialization(std::vector<TkFamily*>& families, TestFamilyTracker& tracker)
+ {
+#if 1
+ NV_UNUSED(families);
+ NV_UNUSED(tracker);
+#else
+ TkFramework* fw = NvBlastTkFrameworkGet();
+
+ PsMemoryBuffer* membuf = PX_NEW(PsMemoryBuffer);
+ EXPECT_TRUE(membuf != nullptr);
+ if (membuf == nullptr)
+ {
+ return;
+ }
+
+ std::vector<TkFamily*> oldFamilies = families;
+
+ for (size_t familyNum = 0; familyNum < families.size(); ++familyNum)
+ {
+ GTEST_FATAL_FAILURE_("Serialization of families needs to be put into extensions.");
+// families[familyNum]->serialize(*membuf);
+ }
+
+ for (size_t familyNum = 0; familyNum < families.size(); ++familyNum)
+ {
+ TkFamily* f = families[familyNum];
+
+ std::vector<TkActor*> actors(f->getActorCount());
+ f->getActors(actors.data(), static_cast<uint32_t>(actors.size()));
+ for (auto a : actors)
+ {
+ tracker.eraseActor(a);
+ }
+
+ f->release();
+ families[familyNum] = nullptr;
+ }
+
+ for (size_t familyNum = 0; familyNum < families.size(); ++familyNum)
+ {
+ GTEST_FATAL_FAILURE_("Deserialization of families needs to be put into extensions.");
+// TkFamily* f = reinterpret_cast<TkFamily*>(fw->deserialize(*membuf));
+// f->addListener(tracker);
+// families[familyNum] = f;
+ }
+
+ for (size_t familyNum = 0; familyNum < families.size(); ++familyNum)
+ {
+ TkFamily* f = families[familyNum];
+
+ std::vector<TkActor*> actors(f->getActorCount());
+ f->getActors(actors.data(), static_cast<uint32_t>(actors.size()));
+ for (auto a : actors)
+ {
+ tracker.insertActor(a);
+
+ std::vector<TkJoint*> joints(a->getJointCount());
+ a->getJoints(joints.data(), (uint32_t)joints.size());
+
+ for (auto j : joints)
+ {
+ const TkJointData jd = j->getData();
+ if (jd.actors[0] != jd.actors[1])
+ {
+ tracker.joints.insert(j);
+ }
+ }
+ }
+ }
+
+ membuf->release();
+#endif
+ }
+
+ void recollectActors(std::vector<TkFamily*>& families, std::vector<TkActor*>& actors)
+ {
+ uint32_t totalActorCount = 0;
+ for (auto family : families)
+ {
+ EXPECT_LE(family->getActorCount() + totalActorCount, actors.size());
+ totalActorCount += family->getActors(actors.data() + totalActorCount, static_cast<uint32_t>(actors.size()) - totalActorCount);
+ }
+ }
+
+ void assemblyCreateAndRelease(bool createNRFJoints, bool serializationTest)
+ {
+ createFramework();
+ createTestAssets();
+
+ TkFramework* fw = NvBlastTkFrameworkGet();
+
+ const TkType* familyType = fw->getType(TkTypeIndex::Family);
+ EXPECT_TRUE(familyType != nullptr);
+
+ TestFamilyTracker tracker;
+
+ std::vector<TkFamily*> families1;
+ std::vector<TkFamily*> families2;
+
+ // Create one assembly
+ std::vector<TkActor*> actors1;
+ std::vector<TkJoint*> joints1;
+ createAssembly(actors1, joints1, createNRFJoints);
+ tracker.joints.insert(joints1.begin(), joints1.end());
+
+ // Create another assembly
+ std::vector<TkActor*> actors2;
+ std::vector<TkJoint*> joints2;
+ createAssembly(actors2, joints2, createNRFJoints);
+ tracker.joints.insert(joints2.begin(), joints2.end());
+
+ // Store families and fill group
+ for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum)
+ {
+ TkFamily& family = actors1[actorNum]->getFamily();
+ families1.push_back(&family);
+ family.addListener(tracker);
+ }
+ for (size_t actorNum = 0; actorNum < actors2.size(); ++actorNum)
+ {
+ TkFamily& family = actors2[actorNum]->getFamily();
+ families2.push_back(&family);
+ family.addListener(tracker);
+ }
+
+ if (serializationTest)
+ {
+ familySerialization(families1, tracker);
+ recollectActors(families1, actors1);
+ familySerialization(families2, tracker);
+ recollectActors(families2, actors2);
+ }
+
+ EXPECT_EQ(joints1.size() + joints2.size(), tracker.joints.size());
+
+ // Release 1st assembly's actors
+ for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum)
+ {
+ actors1[actorNum]->release();
+ }
+
+ if (serializationTest)
+ {
+ familySerialization(families2, tracker);
+ recollectActors(families2, actors2);
+ }
+
+ EXPECT_EQ(joints2.size(), tracker.joints.size());
+
+ // Release 2nd assembly's actors
+ for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum)
+ {
+ actors2[actorNum]->release();
+ }
+
+ EXPECT_EQ(0, tracker.joints.size());
+
+ releaseTestAssets();
+ releaseFramework();
+ }
+
+ void assemblyInternalJoints(bool testAssemblySerialization)
+ {
+ createFramework();
+ createTestAssets(true); // Create assets with internal joints
+
+ TkFramework* fw = NvBlastTkFrameworkGet();
+
+ TestFamilyTracker tracker;
+
+ TkGroupDesc gdesc;
+ gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount();
+ TkGroup* group = fw->createGroup(gdesc);
+ EXPECT_TRUE(group != nullptr);
+
+ m_groupTM->setGroup(group);
+
+ TkActorDesc adesc(testAssets[0]);
+
+ TkActor* actor1 = fw->createActor(adesc);
+ EXPECT_TRUE(actor1 != nullptr);
+ tracker.insertActor(actor1);
+
+ actor1->getFamily().addListener(tracker);
+
+ TkFamily* family = &actor1->getFamily();
+
+ group->addActor(*actor1);
+
+ CSParams cs2(2, 0.0f);
+ NvBlastExtProgramParams csParams2 = { &cs2, nullptr };
+ actor1->damage(getCubeSlicerProgram(), &csParams2);
+
+ EXPECT_EQ((size_t)0, tracker.joints.size());
+
+ m_groupTM->process();
+ m_groupTM->wait();
+
+ if (testAssemblySerialization)
+ {
+ std::vector<TkFamily*> families;
+ families.push_back(family);
+ familySerialization(families, tracker);
+ family = families[0];
+ std::vector<TkActor*> actors(family->getActorCount());
+ family->getActors(actors.data(), static_cast<uint32_t>(actors.size()));
+ for (TkActor* actor : actors)
+ {
+ group->addActor(*actor);
+ }
+ }
+
+ EXPECT_EQ((size_t)2, family->getActorCount());
+ EXPECT_EQ((size_t)4, tracker.joints.size()); // 2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched
+
+ std::vector<TkActor*> actors(family->getActorCount());
+ family->getActors(actors.data(), static_cast<uint32_t>(actors.size()));
+
+ for (TkJoint* joint : tracker.joints)
+ {
+ TkJointData jd = joint->getData();
+ EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0]));
+ EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1]));
+ }
+
+ NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0);
+ NvBlastExtProgramParams radialParams = { &radialDamage, nullptr };
+ for (TkActor* actor : actors)
+ {
+ actor->damage(getFalloffProgram(), &radialParams);
+ }
+
+ m_groupTM->process();
+ m_groupTM->wait();
+
+ if (testAssemblySerialization)
+ {
+ std::vector<TkFamily*> families;
+ families.push_back(family);
+ familySerialization(families, tracker);
+ family = families[0];
+ }
+
+ EXPECT_EQ((size_t)8, family->getActorCount());
+ EXPECT_EQ((size_t)4, tracker.joints.size());
+
+ // 3) Joint update events should be fired when attached actors change
+
+ actors.resize(family->getActorCount());
+ family->getActors(actors.data(), static_cast<uint32_t>(actors.size()));
+
+ for (TkJoint* joint : tracker.joints)
+ {
+ TkJointData jd = joint->getData();
+ EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0]));
+ EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1]));
+ }
+
+ for (TkActor* actor : actors)
+ {
+ actor->release();
+ }
+
+ EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted
+
+ group->release();
+
+ releaseTestAssets();
+ releaseFramework();
+ }
+
+ void assemblyCompositeWithInternalJoints(bool createNRFJoints, bool serializationTest)
+ {
+ createFramework();
+ createTestAssets(true); // Create assets with internal joints
+
+ TkFramework* fw = NvBlastTkFrameworkGet();
+
+ const TkType* familyType = fw->getType(TkTypeIndex::Family);
+ EXPECT_TRUE(familyType != nullptr);
+
+ if (familyType == nullptr)
+ {
+ return;
+ }
+
+ TestFamilyTracker tracker;
+
+ std::vector<TkFamily*> families;
+
+ // Create assembly
+ std::vector<TkActor*> actors;
+ std::vector<TkJoint*> joints;
+ createAssembly(actors, joints, createNRFJoints);
+ tracker.joints.insert(joints.begin(), joints.end());
+
+ TkGroupDesc gdesc;
+ gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount();
+ TkGroup* group = fw->createGroup(gdesc);
+ EXPECT_TRUE(group != nullptr);
+
+ m_groupTM->setGroup(group);
+
+ for (size_t i = 0; i < actors.size(); ++i)
+ {
+ TkFamily& family = actors[i]->getFamily();
+ families.push_back(&family);
+ family.addListener(tracker);
+ tracker.insertActor(actors[i]);
+ group->addActor(*actors[i]);
+ }
+
+ if (serializationTest)
+ {
+ familySerialization(families, tracker);
+ recollectActors(families, actors);
+ for (auto actor : actors)
+ {
+ group->addActor(*actor);
+ }
+ }
+
+ EXPECT_EQ((size_t)4, actors.size());
+
+ const size_t compJointCount = createNRFJoints ? (size_t)12 : (size_t)8;
+
+ EXPECT_EQ(compJointCount, tracker.joints.size());
+
+ CSParams cs2(2, 0.0f);
+ NvBlastExtProgramParams csParams2 = { &cs2, nullptr };
+
+ size_t totalActorCount = 0;
+ for (uint32_t i = 0; i < 4; ++i)
+ {
+ actors[i]->damage(getCubeSlicerProgram(), &csParams2);
+
+ m_groupTM->process();
+ m_groupTM->wait();
+
+ if (serializationTest)
+ {
+ familySerialization(families, tracker);
+ for (size_t j = 0; j < families.size(); ++j)
+ {
+ TkFamily* family = families[j];
+ std::vector<TkActor*> a(family->getActorCount());
+ family->getActors(a.data(), static_cast<uint32_t>(a.size()));
+ for (auto actor : a)
+ {
+ group->addActor(*actor);
+ }
+ EXPECT_TRUE(j <= i || a.size() == 1);
+ if (j > i && a.size() == 1)
+ {
+ actors[j] = a[0];
+ }
+ }
+ }
+
+ EXPECT_EQ((size_t)2, families[i]->getActorCount());
+ EXPECT_EQ((size_t)(compJointCount + 4 * (i + 1)), tracker.joints.size()); // Four joints created per actor
+
+ totalActorCount += families[i]->getActorCount();
+ }
+
+ actors.resize(totalActorCount);
+ totalActorCount = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount());
+ totalActorCount += families[i]->getActorCount();
+ }
+
+ for (TkJoint* joint : tracker.joints)
+ {
+ TkJointData jd = joint->getData();
+ EXPECT_TRUE(jd.actors[0] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[0]));
+ EXPECT_TRUE(jd.actors[1] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[1]));
+ }
+
+ NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0);
+ NvBlastExtProgramParams radialParams = { &radialDamage, nullptr };
+ for (TkActor* actor : actors)
+ {
+ actor->damage(getFalloffProgram(), &radialParams);
+ }
+
+ m_groupTM->process();
+ m_groupTM->wait();
+
+ totalActorCount = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ totalActorCount += families[i]->getActorCount();
+ }
+
+ if (serializationTest)
+ {
+ familySerialization(families, tracker);
+ }
+
+ EXPECT_EQ((size_t)32, totalActorCount);
+ EXPECT_EQ(compJointCount + (size_t)16, tracker.joints.size());
+
+ actors.resize(totalActorCount);
+ totalActorCount = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount());
+ totalActorCount += families[i]->getActorCount();
+ }
+
+ // 3) Joint update events should be fired when attached actors change
+
+ for (TkActor* actor : actors)
+ {
+ actor->release();
+ }
+
+ EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted
+
+ group->release();
+
+ releaseTestAssets();
+ releaseFramework();
+ }
+
+ void assemblyExternalJoints_MultiFamilyDamage(bool explicitJointRelease = true)
+ {
+ createFramework();
+
+ const NvBlastChunkDesc chunkDescs[3] =
+ {
+// centroid volume parent idx flags ID
+ { { 0.0f, 0.0f, 0.0f }, 4.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { { 0.0f,-1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { { 0.0f, 1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }
+ };
+
+ const NvBlastBondDesc bondDesc =
+// normal area centroid userData chunks
+ { { { 0.0f, 1.0f, 0.0f }, 1.0f, { 0.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } };
+
+ TkFramework* framework = NvBlastTkFrameworkGet();
+
+ TestFamilyTracker tracker;
+
+ TkAssetDesc desc;
+ desc.chunkCount = 3;
+ desc.chunkDescs = chunkDescs;
+ desc.bondCount = 1;
+ desc.bondDescs = &bondDesc;
+ desc.bondFlags = nullptr;
+ TkAsset* asset = framework->createAsset(desc);
+ EXPECT_TRUE(asset != nullptr);
+
+ TkGroupDesc gdesc;
+ gdesc.workerCount = m_taskman->getCpuDispatcher()->getWorkerCount();
+ TkGroup* group = framework->createGroup(gdesc);
+ EXPECT_TRUE(group != nullptr);
+
+ m_groupTM->setGroup(group);
+
+ TkActorDesc adesc(asset);
+ TkActor* actor1 = framework->createActor(adesc);
+ EXPECT_TRUE(actor1 != nullptr);
+ TkActor* actor2 = framework->createActor(adesc);
+ EXPECT_TRUE(actor2 != nullptr);
+
+ group->addActor(*actor1);
+ group->addActor(*actor2);
+
+ TkFamily* family1 = &actor1->getFamily();
+ TkFamily* family2 = &actor2->getFamily();
+
+ family1->addListener(tracker);
+ family2->addListener(tracker);
+ tracker.insertActor(actor1);
+ tracker.insertActor(actor2);
+
+ TkJointDesc jdesc;
+ jdesc.families[0] = family1;
+ jdesc.families[1] = family2;
+ jdesc.chunkIndices[0] = 2;
+ jdesc.chunkIndices[1] = 1;
+ jdesc.attachPositions[0] = PxVec3(0.0f, 1.0f, 0.0f);
+ jdesc.attachPositions[1] = PxVec3(0.0f, -1.0f, 0.0f);
+ TkJoint* joint = framework->createJoint(jdesc);
+ EXPECT_TRUE(joint != nullptr);
+ tracker.joints.insert(joint);
+
+ NvBlastExtRadialDamageDesc radialDamage1 = getRadialDamageDesc(0, 1, 0, 2, 2);
+ NvBlastExtProgramParams radialParams1 = { &radialDamage1, nullptr };
+ actor1->damage(getFalloffProgram(), &radialParams1);
+ NvBlastExtRadialDamageDesc radialDamage2 = getRadialDamageDesc(0, -1, 0, 2, 2);
+ NvBlastExtProgramParams radialParams2 = { &radialDamage2, nullptr };
+ actor2->damage(getFalloffProgram(), &radialParams2);
+
+ m_groupTM->process();
+ m_groupTM->wait();
+
+ TkActor* actors1[2];
+ TkActor* actors2[2];
+ EXPECT_EQ(2, family1->getActors(actors1, 2));
+ EXPECT_EQ(2, family2->getActors(actors2, 2));
+
+ const TkJointData jdata = joint->getData();
+ EXPECT_TRUE(jdata.actors[0] != nullptr);
+ EXPECT_TRUE(jdata.actors[1] != nullptr);
+ EXPECT_TRUE(&jdata.actors[0]->getFamily() == family1);
+ EXPECT_TRUE(&jdata.actors[1]->getFamily() == family2);
+
+ // Clean up
+ if (explicitJointRelease)
+ {
+ joint->release();
+ family2->release();
+ family1->release();
+ asset->release();
+ releaseFramework();
+ }
+ else
+ {
+ EXPECT_EQ(1, tracker.joints.size());
+ releaseFramework();
+ // Commenting these out - but shouldn't we be sending delete events when we release the framework?
+// EXPECT_EQ(0, tracker.joints.size());
+// EXPECT_EQ(0, tracker.actors.size());
+ }
+ }
+
+protected:
+ // http://clang.llvm.org/compatibility.html#dep_lookup_bases
+ // http://stackoverflow.com/questions/6592512/templates-parent-class-member-variables-not-visible-in-inherited-class
+
+ using TkBaseTest<FailLevel, Verbosity>::testAssets;
+ using TkBaseTest<FailLevel, Verbosity>::m_taskman;
+ using TkBaseTest<FailLevel, Verbosity>::m_groupTM;
+ using TkBaseTest<FailLevel, Verbosity>::createFramework;
+ using TkBaseTest<FailLevel, Verbosity>::releaseFramework;
+ using TkBaseTest<FailLevel, Verbosity>::createTestAssets;
+ using TkBaseTest<FailLevel, Verbosity>::releaseTestAssets;
+ using TkBaseTest<FailLevel, Verbosity>::getCubeSlicerProgram;
+ using TkBaseTest<FailLevel, Verbosity>::getDefaultMaterial;
+ using TkBaseTest<FailLevel, Verbosity>::getRadialDamageDesc;
+ using TkBaseTest<FailLevel, Verbosity>::getFalloffProgram;
+};
+
+
+typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestAllowWarnings;
+typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestStrict;
+
+
+/*
+1) Create assembly, actors and joints should be created automatically
+*/
+
+TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_NoNRFJoints_NoSerialization)
+{
+ assemblyCreateAndRelease(false, false);
+}
+
+TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCreateAndRelease_NoNRFJoints_AssemblySerialization)
+{
+ assemblyCreateAndRelease(false, true);
+}
+
+TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_WithNRFJoints_NoSerialization)
+{
+ assemblyCreateAndRelease(true, false);
+}
+
+TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCreateAndRelease_WithNRFJoints_AssemblySerialization)
+{
+ assemblyCreateAndRelease(true, true);
+}
+
+
+/**
+2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched
+
+3) Joint update events should be fired when attached actors change
+
+4) Joint delete events should be fired when at least one attached actor is deleted
+*/
+
+TEST_F(TkCompositeTestStrict, AssemblyInternalJoints_NoSerialization)
+{
+ assemblyInternalJoints(false);
+}
+
+TEST_F(TkCompositeTestStrict, DISABLED_AssemblyInternalJoints_AssemblySerialization)
+{
+ assemblyInternalJoints(true);
+}
+
+
+/**
+5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above
+*/
+
+TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_NoNRFJoints_NoSerialization)
+{
+ assemblyCompositeWithInternalJoints(false, false);
+}
+
+TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCompositeWithInternalJoints_NoNRFJoints_AssemblySerialization)
+{
+ assemblyCompositeWithInternalJoints(false, true);
+}
+
+TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_WithNRFJoints_NoSerialization)
+{
+ assemblyCompositeWithInternalJoints(true, false);
+}
+
+TEST_F(TkCompositeTestStrict, DISABLED_AssemblyCompositeWithInternalJoints_WithNRFJoints_AssemblySerialization)
+{
+ assemblyCompositeWithInternalJoints(true, true);
+}
+
+
+/*
+More tests
+*/
+
+TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage)
+{
+ assemblyExternalJoints_MultiFamilyDamage(true);
+}
+
+TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage_AutoJointRelease)
+{
+ assemblyExternalJoints_MultiFamilyDamage(false);
+}
|