aboutsummaryrefslogtreecommitdiff
path: root/test/src/unit/APITests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/src/unit/APITests.cpp')
-rwxr-xr-x[-rw-r--r--]test/src/unit/APITests.cpp3446
1 files changed, 1723 insertions, 1723 deletions
diff --git a/test/src/unit/APITests.cpp b/test/src/unit/APITests.cpp
index 655a65c..d1ff4cd 100644..100755
--- a/test/src/unit/APITests.cpp
+++ b/test/src/unit/APITests.cpp
@@ -1,1723 +1,1723 @@
-// 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 "BlastBaseTest.h"
-#include "NvBlastIndexFns.h"
-#include "NvBlastExtDamageShaders.h"
-
-#include <algorithm>
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Utils / Tests Common
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-using namespace Nv::Blast;
-
-class APITest : public BlastBaseTest < NvBlastMessage::Error, 1 >
-{
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Tests
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-TEST_F(APITest, Basic)
-{
- // create asset
- const NvBlastAssetDesc& assetDesc = g_assetDescs[0];
-
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- NvBlastExtRadialDamageDesc damage = {
- 10.0f, // compressive
- { 0.0f, 0.0f, 0.0f }, // position
- 4.0f, // min radius - maximum damage
- 6.0f // max radius - zero damage
- };
-
- NvBlastBondFractureData outFracture[12]; /*num lower-support chunks + bonds?*/
-
- NvBlastFractureBuffers events;
- events.bondFractureCount = 12;
- events.bondFractures = outFracture;
- events.chunkFractureCount = 0;
- events.chunkFractures = nullptr;
-
- NvBlastExtProgramParams programParams = { &damage, nullptr };
-
- NvBlastDamageProgram program = {
- NvBlastExtFalloffGraphShader,
- nullptr
- };
-
- NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr);
- NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- EXPECT_EQ(12, events.bondFractureCount);
-
- NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors;
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
- size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr);
- EXPECT_EQ(8, newActorsCount);
- EXPECT_EQ(true, result.deletedActor == actor);
-
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
- EXPECT_TRUE(actorReleaseResult);
- }
- alignedFree(family);
- alignedFree(asset);
-}
-
-TEST_F(APITest, DamageBondsCompressive)
-{
- const size_t bondsCount = 6;
-
- const NvBlastChunkDesc c_chunks[8] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }
- };
-
- const NvBlastBondDesc c_bonds[bondsCount] =
- {
- { { {-1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 2.0f, 0.0f }, 0 }, { 1, 2 } },
- { { {-1.0f, 0.0f, 0.0f }, 1.0f, {-1.0f, 2.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-2.0f, 1.0f, 0.0f }, 0 }, { 3, 4 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-2.0f,-1.0f, 0.0f }, 0 }, { 4, 5 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, {-1.0f,-2.0f, 0.0f }, 0 }, { 5, 6 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f,-2.0f, 0.0f }, 0 }, { 6, 7 } }
- };
-
- // create asset
- const NvBlastAssetDesc assetDesc = { 8, c_chunks, bondsCount, c_bonds };
-
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- // get graph nodes check
- std::vector<uint32_t> graphNodeIndices;
- graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr));
- uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr);
- EXPECT_EQ(graphNodesCount, 7);
-
- NvBlastExtRadialDamageDesc damage = {
- 1.0f, // compressive
- { 4.0f, 2.0f, 0.0f }, // position
- 4.0f, // min radius - maximum damage
- 6.0f // max radius - zero damage
- }; // linear falloff
-
- NvBlastBondFractureData outCommands[bondsCount] = {
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
- };
-
- NvBlastFractureBuffers commands = {
- 6, 0, outCommands, nullptr
- };
-
- NvBlastExtProgramParams programParams = { &damage, nullptr };
-
- NvBlastDamageProgram program = {
- NvBlastExtFalloffGraphShader,
- nullptr
- };
-
- NvBlastActorGenerateFracture(&commands, actor, program, &programParams, messageLog, nullptr);
-
- ASSERT_EQ(3, commands.bondFractureCount);
- ASSERT_EQ(0, commands.chunkFractureCount);
-
- // node indices in _graph_ chunks
- NvBlastBondFractureData expectedCommand[] = {
- { 0, 0, 1, 1.0f },
- { 0, 1, 2, 0.5f },
- { 0, 5, 6, 0.5f }
- };
-
- for (int i = 0; i < 3; i++)
- {
- EXPECT_EQ(expectedCommand[i].nodeIndex0, outCommands[i].nodeIndex0);
- EXPECT_EQ(expectedCommand[i].nodeIndex1, outCommands[i].nodeIndex1);
- EXPECT_EQ(expectedCommand[i].health, outCommands[i].health);
- }
-
- const bool actorReleaseResult = NvBlastActorDeactivate(actor, messageLog);
- EXPECT_TRUE(actorReleaseResult);
- alignedFree(family);
- alignedFree(asset);
-}
-
-TEST_F(APITest, DirectFractureKillsChunk)
-{
- // 1--2
- // | |
- // 3--4 <-- kill 4
-
- const NvBlastChunkDesc c_chunks[9] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 7 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 8 },
- };
-
- const NvBlastBondDesc c_bonds[4] =
- {
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 1.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-1.0f, 0.0f }, 0 }, { 3, 4 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 4 } },
- };
-
- NvBlastAssetDesc assetDesc;
- assetDesc.chunkCount = 9;
- assetDesc.chunkDescs = c_chunks;
- assetDesc.bondCount = 4;
- assetDesc.bondDescs = c_bonds;
-
- // create asset
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- NvBlastChunkFractureData fractureCmd;
- fractureCmd.chunkIndex = 4;
- fractureCmd.health = 1.0f;
-
- NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd };
-
- NvBlastChunkFractureData fractureEvt;
- NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt };
-
- NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- EXPECT_EQ(1, events.chunkFractureCount);
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(5, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
- // check newActors contain original actor
- EXPECT_TRUE(std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; }));
-
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
- EXPECT_TRUE(actorReleaseResult);
- }
- alignedFree(family);
- alignedFree(asset);
-}
-
-TEST_F(APITest, DirectFractureKillsIslandRootChunk)
-{
- // 1--2 <-- kill 1
- // | |
- // 3--4
-
- const NvBlastChunkDesc c_chunks[9] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 7 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 8 },
- };
-
- const NvBlastBondDesc c_bonds[4] =
- {
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 1.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-1.0f, 0.0f }, 0 }, { 3, 4 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } },
- { { { 0.0f,-1.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 4 } },
- };
-
- NvBlastAssetDesc assetDesc;
- assetDesc.chunkCount = 9;
- assetDesc.chunkDescs = c_chunks;
- assetDesc.bondCount = 4;
- assetDesc.bondDescs = c_bonds;
-
- // create asset
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- NvBlastChunkFractureData fractureCmd;
- fractureCmd.chunkIndex = 1;
- fractureCmd.health = 1.0f;
-
- NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd };
-
- NvBlastChunkFractureData fractureEvt;
- NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt };
-
- NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- EXPECT_EQ(1, events.chunkFractureCount);
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(5, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
- // check if newActors don't contain original actor
- EXPECT_TRUE(!std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; }));
-
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
- EXPECT_TRUE(actorReleaseResult);
- }
- alignedFree(family);
- alignedFree(asset);
-}
-
-TEST_F(APITest, SubsupportFracture)
-{
- const NvBlastAssetDesc& assetDesc = g_assetDescs[1]; // cube with subsupport
-
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- // first set of fracture commands
- NvBlastChunkFractureData f1 = { 0, 1, 2.0f };
- NvBlastChunkFractureData f3 = { 0, 3, 0.5f };
- NvBlastChunkFractureData f5 = { 0, 5, 1.0f };
- NvBlastChunkFractureData f7 = { 0, 7, 1.0f };
-
- std::vector<NvBlastChunkFractureData> chunkFractureData;
- chunkFractureData.reserve(assetDesc.chunkCount);
- chunkFractureData.push_back(f1);
- chunkFractureData.push_back(f3);
- chunkFractureData.push_back(f5);
- chunkFractureData.push_back(f7);
- ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
- ASSERT_EQ(4, chunkFractureData.size());
-
- NvBlastFractureBuffers target = { 0, static_cast<uint32_t>(chunkFractureData.capacity()), nullptr, chunkFractureData.data() };
- {
- NvBlastFractureBuffers events = target;
- NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
- NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- ASSERT_EQ(4 + 8, events.chunkFractureCount); // all requested chunks take damage, and the children of one of them
- }
-
- // re-apply same set of commands
- chunkFractureData.clear();
- chunkFractureData.reserve(assetDesc.chunkCount);
- chunkFractureData.push_back(f1);
- chunkFractureData.push_back(f3);
- chunkFractureData.push_back(f5);
- chunkFractureData.push_back(f7);
- ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
- ASSERT_EQ(4, chunkFractureData.size());
-
- {
- NvBlastFractureBuffers events = target;
- NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
- NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- ASSERT_EQ(1, events.chunkFractureCount); // f3 has broken the chunk
- }
-
- // fracture all support chunks
- // the chunks from the previous fractures must not be reported again (since they are all broken already)
- NvBlastChunkFractureData f2 = { 0, 2, 2.0f }; // will damage chunk and children
- NvBlastChunkFractureData f4 = { 0, 4, 0.5f }; // will damage chunk without creating children on split
- NvBlastChunkFractureData f6 = { 0, 6, 2.0f }; // will damage chunk and children
- NvBlastChunkFractureData f8 = { 0, 8, 1.0f }; // will damage chunk
-
- chunkFractureData.clear();
- chunkFractureData.reserve(assetDesc.chunkCount);
- chunkFractureData.push_back(f1);
- chunkFractureData.push_back(f2);
- chunkFractureData.push_back(f3);
- chunkFractureData.push_back(f4);
- chunkFractureData.push_back(f5);
- chunkFractureData.push_back(f6);
- chunkFractureData.push_back(f7);
- chunkFractureData.push_back(f8);
- ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
- ASSERT_EQ(8, chunkFractureData.size());
-
- NvBlastFractureBuffers events = target;
- {
- NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
- NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- ASSERT_EQ(4 + 8 + 8, events.chunkFractureCount); // the new fracture commands all apply, plus two of them damage their children too
- }
-
- for (size_t i = 0; i < events.chunkFractureCount; i++)
- {
- const uint32_t chunkIndex = events.chunkFractures[i].chunkIndex;
-
- ASSERT_TRUE(chunkIndex != 1);
- ASSERT_TRUE(chunkIndex != 3);
- ASSERT_TRUE(chunkIndex != 5);
- ASSERT_TRUE(chunkIndex != 7);
-
- // literal values come from g_cube2ChunkDescs
- bool isInSupportRange = chunkIndex <= 8 && chunkIndex >= 1;
- bool isChildOfTwo = chunkIndex <= 24 && chunkIndex >= 17;
- bool isChildOfSix = chunkIndex <= 56 && chunkIndex >= 49;
-
- ASSERT_TRUE(isInSupportRange || isChildOfTwo || isChildOfSix);
- }
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(64 - 8 + 1, newActorsCount);
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
- EXPECT_TRUE(actorReleaseResult);
- }
- alignedFree(family);
- alignedFree(asset);
-}
-
-static bool hasWarned = false;
-static void myLog(int type, const char* msg, const char* file, int line)
-{
- BlastBaseTest<-1, 0>::messageLog(type, msg, file, line);
- hasWarned = true;
-}
-#define EXPECT_WARNING EXPECT_TRUE(hasWarned); hasWarned=false;
-#define EXPECT_NO_WARNING EXPECT_FALSE(hasWarned); hasWarned=false;
-
-TEST_F(APITest, FractureNoEvents)
-{
- static const uint32_t GUARD = 0xb1a57;
-
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const NvBlastBondDesc c_bonds[3] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
-
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- std::vector<NvBlastChunkFractureData> cfData;
- cfData.resize(0 + 1);
- cfData[cfData.size() - 1].userdata = GUARD;
- std::vector<NvBlastBondFractureData> bfData;
-
- NvBlastChunkFractureData command[] =
- {
- { 0, 1, 10.0f },
- { 0, 2, 10.0f },
- };
-
- NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- EXPECT_NO_WARNING; // events can be null
- EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(9, newActorsCount);
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
- EXPECT_TRUE(actorReleaseResult);
- }
-
- alignedFree(family);
- alignedFree(asset);
-
- EXPECT_NO_WARNING;
-}
-
-TEST_F(APITest, FractureBufferLimits)
-{
- static const uint32_t GUARD = 0xb1a57;
-
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const NvBlastBondDesc c_bonds[3] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
- {
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_TRUE(asset != nullptr);
-
- for (uint32_t i = 0; i < 14; i++)
- {
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- std::vector<NvBlastChunkFractureData> cfData;
- cfData.resize(i + 1);
- cfData[cfData.size() - 1].userdata = GUARD;
- std::vector<NvBlastBondFractureData> bfData;
-
- NvBlastChunkFractureData command[] =
- {
- { 0, 1, 10.0f },
- { 0, 2, 10.0f },
- };
-
- NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
- NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
-
- NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
-
- EXPECT_WARNING;
- EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
- EXPECT_EQ(i, events.chunkFractureCount);
- for (uint32_t i = 0; i < events.chunkFractureCount; i++)
- {
- EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
- }
-
- EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog));
- alignedFree(family);
- }
-
- {
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- std::vector<NvBlastChunkFractureData> cfData;
- cfData.resize(14 + 1);
- cfData[cfData.size() - 1].userdata = GUARD;
- std::vector<NvBlastBondFractureData> bfData;
-
- NvBlastChunkFractureData command[] =
- {
- { 0, 1, 10.0f },
- { 0, 2, 10.0f },
- };
-
- NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
- NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
-
- NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- EXPECT_NO_WARNING;
- EXPECT_EQ(14, events.chunkFractureCount);
- for (uint32_t i = 0; i < events.chunkFractureCount; i++)
- {
- EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
- }
- ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(9, newActorsCount);
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
- EXPECT_TRUE(actorReleaseResult);
- }
-
- alignedFree(family);
- }
-
- alignedFree(asset);
- }
- EXPECT_NO_WARNING;
-}
-
-TEST_F(APITest, FractureBufferLimitsInSitu)
-{
- static const uint32_t GUARD = 0xb1a57;
-
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // cenroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
-
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const NvBlastBondDesc c_bonds[3] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
- {
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_TRUE(asset != nullptr);
-
- for (uint32_t i = 0; i < 14 - 2; i++)
- {
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- std::vector<NvBlastChunkFractureData> cfData;
- cfData.resize(2 + i + 1);
-
- std::vector<NvBlastBondFractureData> bfData;
-
- cfData[0].userdata = 0;
- cfData[0].chunkIndex = 1;
- cfData[0].health = 10.0f;
-
- cfData[1].userdata = 0;
- cfData[1].chunkIndex = 2;
- cfData[1].health = 10.0f;
-
- cfData[2 + i].userdata = GUARD;
-
- NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() };
- NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
-
- NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- EXPECT_WARNING;
- EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
- EXPECT_EQ(2 + i, events.chunkFractureCount);
- for (uint32_t i = 0; i < events.chunkFractureCount; i++)
- {
- EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
- }
-
- EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog));
-
- alignedFree(family);
- }
-
- {
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- std::vector<NvBlastChunkFractureData> cfData;
- cfData.resize(14 + 1);
- cfData[cfData.size() - 1].userdata = GUARD;
- std::vector<NvBlastBondFractureData> bfData;
-
- cfData[0].userdata = 0;
- cfData[0].chunkIndex = 1;
- cfData[0].health = 10.0f;
-
- cfData[1].userdata = 0;
- cfData[1].chunkIndex = 2;
- cfData[1].health = 10.0f;
-
- cfData[14].userdata = GUARD;
-
- NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() };
- NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
-
- NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- EXPECT_NO_WARNING;
- EXPECT_EQ(14, events.chunkFractureCount);
- for (uint32_t i = 0; i < events.chunkFractureCount; i++)
- {
- EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
- }
- ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
- newActors.resize(newActorsCount);
-
- EXPECT_EQ(9, newActorsCount);
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
- EXPECT_TRUE(actorReleaseResult);
- }
- alignedFree(family);
- }
-
- alignedFree(asset);
- }
- EXPECT_NO_WARNING;
-}
-
-/*
-This test checks if bond or chunk fracture commands passed to NvBlastActorApplyFracture do not correspond to
-the actor passed in they (commands) will be ignored and warning message will be fired.
-*/
-TEST_F(APITest, FractureWarnAndFilterOtherActorCommands)
-{
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // centroid volume parent idx flags ID
- { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const NvBlastBondDesc c_bonds[4] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } }
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 4, c_bonds };
-
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- // split in 2
- std::vector<NvBlastActor*> actors;
- {
- NvBlastBondFractureData command[] =
- {
- { 0, 0, 2, 10.0f },
- { 0, 1, 2, 10.0f }
- };
-
- NvBlastFractureBuffers commands = { 2, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(2, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
-
- actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
- }
-
- // damage bonds belonging to other actors, nothing expected to be broken
- {
- for (uint32_t i = 0; i < actors.size(); ++i)
- {
- NvBlastActor* actor = actors[i];
- NvBlastActor* otherActor = actors[(i + 1) % 2];
-
- // get graph nodes check
- std::vector<uint32_t> graphNodeIndices;
- graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(otherActor, nullptr));
- uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), otherActor, nullptr);
- EXPECT_EQ(graphNodesCount, 2);
-
- NvBlastBondFractureData command[] =
- {
- { 0, graphNodeIndices[0], graphNodeIndices[1], 10.0f }
- };
-
- NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_WARNING;
- EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(0, newActorsCount);
- EXPECT_EQ(nullptr, result.deletedActor);
- }
- }
-
- // damage bonds, split actors in 2 each
- std::vector<NvBlastActor*> actors2;
- {
- for (uint32_t i = 0; i < 2; ++i)
- {
- NvBlastActor* actor = actors[i];
-
- // get graph nodes check
- std::vector<uint32_t> graphNodeIndices;
- graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr));
- uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr);
- EXPECT_EQ(graphNodesCount, 2);
-
- NvBlastBondFractureData command[] =
- {
- { 0, graphNodeIndices[0], graphNodeIndices[1], 10.0f }
- };
-
- NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(2, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
-
- actors2.insert(actors2.begin(), result.newActors, result.newActors + newActorsCount);
- }
- }
-
- // damage chunk belonging to other actor (expect no split or damage taken)
- {
- for (uint32_t i = 0; i < actors.size(); ++i)
- {
- NvBlastActor* actor = actors[i];
- NvBlastActor* otherActor = actors[(i + 1) % 2];
-
- uint32_t chunkToDamage;
- NvBlastActorGetVisibleChunkIndices(&chunkToDamage, 1, otherActor, myLog);
-
- NvBlastChunkFractureData command[] =
- {
- { 0, chunkToDamage, 0.9f },
- };
-
- NvBlastFractureBuffers commands = { 0, 1, nullptr, command };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_WARNING;
- EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(0, newActorsCount);
- EXPECT_EQ(nullptr, result.deletedActor);
-
- EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
- EXPECT_NE(chunkToDamage, chunkIndex);
- }
- }
-
- for (NvBlastActor* actor : actors2)
- {
- NvBlastActorDeactivate(actor, myLog);
- }
-
- alignedFree(family);
- alignedFree(asset);
-
- EXPECT_NO_WARNING;
-}
-
-/**
-If duplicate bonds are passed asset create routine will ignore them (but fire warning)
-We pass duplicated bonds to world chunk and fully fracture actor once.
-*/
-TEST_F(APITest, FractureWithBondDuplicates)
-{
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // centroid volume parent idx flags ID
- { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 8 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const uint32_t bondCount = 20;
- const uint32_t world = ~(uint32_t)0; // world chunk => invalid index
- const NvBlastBondDesc c_bonds[bondCount] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 1, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, 1 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 3, 1 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 5, 1 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 5, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, 5 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, world } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 7, 5 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 7, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 7 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 6 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 4 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, world } }
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, bondCount, c_bonds };
-
- // create asset
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_WARNING;
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
- // split in 2
- std::vector<NvBlastActor*> actors;
- {
- NvBlastExtRadialDamageDesc damage = {
- 10.0f, // compressive
- { 0.0f, 0.0f, 0.0f }, // position
- 100.0f, // min radius - maximum damage
- 100.0f // max radius - zero damage
- };
-
- NvBlastBondFractureData outBondFracture[bondCount];
- NvBlastChunkFractureData outChunkFracture[chunksCount];
-
- NvBlastFractureBuffers events;
- events.bondFractureCount = 2;
- events.bondFractures = outBondFracture;
- events.chunkFractureCount = 2;
- events.chunkFractures = outChunkFracture;
-
- NvBlastExtProgramParams programParams = { &damage, nullptr };
-
- NvBlastDamageProgram program = {
- NvBlastExtFalloffGraphShader,
- NvBlastExtFalloffSubgraphShader
- };
-
- NvBlastActorGenerateFracture(&events, actor, program, &programParams, myLog, nullptr);
- NvBlastActorApplyFracture(nullptr, actor, &events, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(8, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
-
- actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
- }
-
- for (NvBlastActor* actor : actors)
- {
- NvBlastActorDeactivate(actor, myLog);
- }
-
- alignedFree(family);
- alignedFree(asset);
-
- EXPECT_NO_WARNING;
-}
-
-#if 0
-TEST(APITest, UserChunkMap)
-{
- for (int i = 0; i < 2; ++i)
- {
- // Choose descriptor list
- const NvBlastAssetDesc* descs = nullptr;
- size_t size = 0;
- switch (i)
- {
- case 0:
- descs = g_assetDescs;
- size = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]);
- break;
- case 1:
- descs = g_assetDescsMissingCoverage;
- size = sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]);
- break;
- default:
- continue;
- }
-
- // Iterate over list
- for (size_t j = 0; j < size; ++j)
- {
- // Create asset
- const NvBlastAssetDesc* desc = descs + j;
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(desc));
- std::vector<uint32_t> chunkMap(desc->chunkCount);
- NvBlastAsset* asset = NvBlastCreateAsset(&chunkMap[0], desc, alignedAlloc<malloc>, scratch.data(), nullptr);
- EXPECT_TRUE(asset);
-
- // Test map
- Nv::Blast::Asset& a = static_cast<Nv::Blast::Asset&>(asset);
- uint32_t supportChunkCount = 0;
- uint32_t subsupportChunkCount = 0;
- for (uint32_t i = 0; i < desc->chunkCount; ++i)
- {
- const uint32_t map = chunkMap[i];
- if (Nv::Blast::isInvalidIndex(map))
- {
- continue;
- }
- else if (map < a.m_firstSubsupportChunkIndex)
- {
- EXPECT_LT(map, asset.m_graph.m_nodeCount);
- ++supportChunkCount;
- }
- else
- {
- EXPECT_LT(map, asset.m_chunkCount);
- EXPECT_GE(map, asset.m_graph.m_nodeCount);
- ++subsupportChunkCount;
- }
- }
- EXPECT_EQ(supportChunkCount, asset.m_graph.m_nodeCount);
- EXPECT_EQ(subsupportChunkCount, a.getLowerSupportChunkCount() - asset.m_graph.m_nodeCount);
-
- // Release asset
- NvBlastAssetRelease(asset, free, nullptr);
- }
- }
-}
-#endif
-
-TEST_F(APITest, NoBondsSausage)
-{
- // create asset
- const NvBlastChunkDesc c_chunks[4] =
- {
- // centroid volume parent idx flags ID
- { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 2 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 3 }
- };
-
- NvBlastAssetDesc assetDesc;
- assetDesc.chunkCount = 4;
- assetDesc.chunkDescs = c_chunks;
- assetDesc.bondCount = 0;
- assetDesc.bondDescs = nullptr;
-
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
- const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, messageLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
- EXPECT_TRUE(actor != nullptr);
-
- // check visible chunk
- {
- EXPECT_EQ(NvBlastActorGetVisibleChunkCount(actor, messageLog), 1);
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, messageLog);
- EXPECT_EQ(chunks[chunkIndex].userData, 0);
- }
-
- // damage
- NvBlastExtRadialDamageDesc damage = {
- 10.0f, // compressive
- { 0.0f, 0.0f, 0.0f }, // position
- 4.0f, // min radius - maximum damage
- 6.0f // max radius - zero damage
- };
-
- NvBlastBondFractureData outBondFracture[2];
- NvBlastChunkFractureData outChunkFracture[2];
-
- NvBlastFractureBuffers events;
- events.bondFractureCount = 2;
- events.bondFractures = outBondFracture;
- events.chunkFractureCount = 2;
- events.chunkFractures = outChunkFracture;
-
- NvBlastExtProgramParams programParams = { &damage, nullptr };
-
- NvBlastDamageProgram program = {
- NvBlastExtFalloffGraphShader,
- NvBlastExtFalloffSubgraphShader
- };
-
- NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr);
- NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
- EXPECT_EQ(0, events.bondFractureCount);
- EXPECT_EQ(1, events.chunkFractureCount);
-
- // split
- NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors;
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
- size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr);
- EXPECT_EQ(1, newActorsCount);
- EXPECT_EQ(true, result.deletedActor == actor);
-
- // check visible chunk
- {
- EXPECT_EQ(NvBlastActorGetVisibleChunkCount(result.newActors[0], messageLog), 1);
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, result.newActors[0], messageLog);
- EXPECT_EQ(chunks[chunkIndex].userData, 3);
- }
-
- // release all
- for (uint32_t i = 0; i < newActorsCount; ++i)
- {
- const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
- EXPECT_TRUE(actorReleaseResult);
- }
-
- alignedFree(family);
- alignedFree(asset);
-}
-
-TEST_F(APITest, SplitOnlyWhenNecessary)
-{
- static const uint32_t GUARD = 0xb1a57;
-
- const uint32_t chunksCount = 17;
- const NvBlastChunkDesc c_chunks[chunksCount] =
- {
- // centroid volume parent idx flags ID
- { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
-
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
- { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
- };
-
- const NvBlastBondDesc c_bonds[4] =
- {
- // normal, area, centroid, userdata, chunks
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
- { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } }
- };
-
- NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 4, c_bonds };
-
- // create asset with chunk map
- std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
- void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
- NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
- EXPECT_TRUE(asset != nullptr);
-
- // create actor
- NvBlastActorDesc actorDesc;
- actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
- actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
- void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
- NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
- scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
- NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
- EXPECT_TRUE(actor != nullptr);
-
-
- // damage health only (expect no split)
- {
- NvBlastBondFractureData command[] =
- {
- { 0, 0, 1, 0.99f },
- { 0, 1, 2, 0.50f },
- { 0, 2, 3, 0.01f }
- };
-
- NvBlastFractureBuffers commands = { 3, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(0, newActorsCount);
- EXPECT_EQ(nullptr, result.deletedActor);
-
- EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
- EXPECT_EQ(0, chunkIndex);
- }
-
- // break 1 bond (expect no split)
- {
- NvBlastBondFractureData command[] =
- {
- { 0, 0, 2, 10.0f },
- };
-
- NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(0, newActorsCount);
- EXPECT_EQ(nullptr, result.deletedActor);
-
- EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
- EXPECT_EQ(0, chunkIndex);
- }
-
- // split in 4
- std::vector<NvBlastActor*> actors;
- {
- NvBlastBondFractureData command[] =
- {
- { 0, 0, 1, 10.0f },
- { 0, 1, 2, 10.0f },
- { 0, 2, 3, 10.0f }
- };
-
- NvBlastFractureBuffers commands = { 3, 0, command, nullptr };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(4, newActorsCount);
- EXPECT_EQ(actor, result.deletedActor);
-
- actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
- }
-
- // damage chunk's health only (expect no split)
- {
- for (NvBlastActor* actor : actors)
- {
- uint32_t chunkToDamage;
- NvBlastActorGetVisibleChunkIndices(&chunkToDamage, 1, actor, myLog);
-
- NvBlastChunkFractureData command[] =
- {
- { 0, chunkToDamage, 0.9f },
- };
-
- NvBlastFractureBuffers commands = { 0, 1, nullptr, command };
- NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
- EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
-
- scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
- std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
- NvBlastActorSplitEvent result;
- result.deletedActor = nullptr;
- result.newActors = newActors.data();
- size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
-
- EXPECT_EQ(0, newActorsCount);
- EXPECT_EQ(nullptr, result.deletedActor);
-
- EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
- uint32_t chunkIndex;
- NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
- EXPECT_EQ(chunkToDamage, chunkIndex);
- }
- }
-
- for (NvBlastActor* actor : actors)
- {
- NvBlastActorDeactivate(actor, myLog);
- }
-
- alignedFree(family);
- alignedFree(asset);
-
- EXPECT_NO_WARNING;
-}
-
-#if NV_WINDOWS_FAMILY
-#include <windows.h>
-TEST_F(APITest,CExportsNoNameMangling)
-{
-
- //
- // tests the lib-link-free approach using unmangled names (extern "C")
- //
-
-#if NV_WIN32
-#if NV_DEBUG
- const char* dllName = "NvBlastDebug_x86.dll";
-#elif NV_CHECKED
- const char* dllName = "NvBlastChecked_x86.dll";
-#elif NV_PROFILE
- const char* dllName = "NvBlastProfile_x86.dll";
-#else
- const char* dllName = "NvBlast_x86.dll";
-#endif
-#elif NV_WIN64
-#if NV_DEBUG
- const char* dllName = "NvBlastDebug_x64.dll";
-#elif NV_CHECKED
- const char* dllName = "NvBlastChecked_x64.dll";
-#elif NV_PROFILE
- const char* dllName = "NvBlastProfile_x64.dll";
-#else
- const char* dllName = "NvBlast_x64.dll";
-#endif
-#endif
-
- HMODULE dllHandle = LoadLibrary(TEXT(dllName));
- DWORD error = GetLastError();
- ASSERT_TRUE(dllHandle != nullptr);
-
-
- // Asset functions
- typedef size_t(*NvBlastGetRequiredScratchForCreateAsset)(const NvBlastAssetDesc* desc);
- typedef size_t(*NvBlastGetAssetMemorySize)(const NvBlastAssetDesc* desc);
- typedef NvBlastAsset*(*NvBlastCreateAsset)(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvBlastLog logFn);
-
- NvBlastGetRequiredScratchForCreateAsset assetCreateRequiredScratch = (NvBlastGetRequiredScratchForCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastGetRequiredScratchForCreateAsset"));
- ASSERT_TRUE(assetCreateRequiredScratch != nullptr);
-
- NvBlastGetAssetMemorySize assetGetMemorySize = (NvBlastGetAssetMemorySize)GetProcAddress(dllHandle, TEXT("NvBlastGetAssetMemorySize"));
- ASSERT_TRUE(assetGetMemorySize != nullptr);
-
- NvBlastCreateAsset assetCreate = (NvBlastCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastCreateAsset"));
- ASSERT_TRUE(assetCreate != nullptr);
-
- // Family functions
- typedef NvBlastFamily* (*NvBlastAssetCreateFamily)(void* mem, const NvBlastAsset* asset, NvBlastLog logFn);
- typedef size_t(*NVBLASTASSETGETFAMILYMEMORYSIZE)(const NvBlastAsset* asset);
-
- NVBLASTASSETGETFAMILYMEMORYSIZE familyGetMemorySize = (NVBLASTASSETGETFAMILYMEMORYSIZE)GetProcAddress(dllHandle, TEXT("NvBlastAssetGetFamilyMemorySize"));
- ASSERT_TRUE(familyGetMemorySize != nullptr);
-
- NvBlastAssetCreateFamily familyCreate = (NvBlastAssetCreateFamily)GetProcAddress(dllHandle, TEXT("NvBlastAssetCreateFamily"));
- ASSERT_TRUE(familyCreate != nullptr);
-
-
- // Actor functions
- typedef size_t(*NvBlastFamilyGetRequiredScratchForCreateFirstActor)(const NvBlastFamily* family);
- typedef NvBlastActor* (*NvBlastFamilyCreateFirstActor)(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn);
- typedef bool(*NVBLASTACTORDEACTIVATE)(NvBlastActor* actor);
-
- NvBlastFamilyGetRequiredScratchForCreateFirstActor actorcreaterequiredscratch = (NvBlastFamilyGetRequiredScratchForCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyGetRequiredScratchForCreateFirstActor"));
- ASSERT_TRUE(actorcreaterequiredscratch != nullptr);
-
- NvBlastFamilyCreateFirstActor actorCreate = (NvBlastFamilyCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyCreateFirstActor"));
- ASSERT_TRUE(actorCreate != nullptr);
-
- NVBLASTACTORDEACTIVATE actorRelease = (NVBLASTACTORDEACTIVATE)GetProcAddress(dllHandle, TEXT("NvBlastActorDeactivate"));
- ASSERT_TRUE(actorRelease != nullptr);
-
-
- const NvBlastChunkDesc c_chunks[] =
- {
- // centroid volume parent idx flags ID
- { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
- { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
- };
-
- NvBlastAssetDesc assetDesc;
- assetDesc.bondCount = 0;
- assetDesc.bondDescs = nullptr;
- assetDesc.chunkCount = 4;
- assetDesc.chunkDescs = c_chunks;
-
- NvBlastAsset* asset;
- {
- size_t requiredsize = assetCreateRequiredScratch(&assetDesc);
- std::vector<char>scratch(requiredsize);
- void* mem = alignedZeroedAlloc(assetGetMemorySize(&assetDesc));
- asset = assetCreate(mem, &assetDesc, scratch.data(), myLog);
- ASSERT_TRUE(asset != nullptr);
- }
-
- void* fmem = alignedZeroedAlloc(familyGetMemorySize(asset));
- NvBlastFamily* family = familyCreate(fmem, asset, myLog);
-
- {
- NvBlastActorDesc actorD;
- actorD.initialBondHealths = actorD.initialSupportChunkHealths = nullptr;
- actorD.uniformInitialBondHealth = actorD.uniformInitialLowerSupportChunkHealth = 1.0f;
-
- size_t requiredsize = actorcreaterequiredscratch(family);
- std::vector<char>scratch(requiredsize);
- NvBlastActor* actor = actorCreate(family, &actorD, scratch.data(), myLog);
- ASSERT_TRUE(actor != nullptr);
-
- ASSERT_TRUE(actorRelease(actor));
- }
-
- alignedFree(family);
- alignedFree(asset);
-
- EXPECT_NO_WARNING;
-}
-#endif
+// 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 "BlastBaseTest.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastExtDamageShaders.h"
+
+#include <algorithm>
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utils / Tests Common
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+using namespace Nv::Blast;
+
+class APITest : public BlastBaseTest < NvBlastMessage::Error, 1 >
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Tests
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(APITest, Basic)
+{
+ // create asset
+ const NvBlastAssetDesc& assetDesc = g_assetDescs[0];
+
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ NvBlastExtRadialDamageDesc damage = {
+ 10.0f, // compressive
+ { 0.0f, 0.0f, 0.0f }, // position
+ 4.0f, // min radius - maximum damage
+ 6.0f // max radius - zero damage
+ };
+
+ NvBlastBondFractureData outFracture[12]; /*num lower-support chunks + bonds?*/
+
+ NvBlastFractureBuffers events;
+ events.bondFractureCount = 12;
+ events.bondFractures = outFracture;
+ events.chunkFractureCount = 0;
+ events.chunkFractures = nullptr;
+
+ NvBlastExtProgramParams programParams = { &damage, nullptr };
+
+ NvBlastDamageProgram program = {
+ NvBlastExtFalloffGraphShader,
+ nullptr
+ };
+
+ NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr);
+ NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ EXPECT_EQ(12, events.bondFractureCount);
+
+ NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors;
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr);
+ EXPECT_EQ(8, newActorsCount);
+ EXPECT_EQ(true, result.deletedActor == actor);
+
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+TEST_F(APITest, DamageBondsCompressive)
+{
+ const size_t bondsCount = 6;
+
+ const NvBlastChunkDesc c_chunks[8] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }
+ };
+
+ const NvBlastBondDesc c_bonds[bondsCount] =
+ {
+ { { {-1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 2.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { {-1.0f, 0.0f, 0.0f }, 1.0f, {-1.0f, 2.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-2.0f, 1.0f, 0.0f }, 0 }, { 3, 4 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-2.0f,-1.0f, 0.0f }, 0 }, { 4, 5 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, {-1.0f,-2.0f, 0.0f }, 0 }, { 5, 6 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f,-2.0f, 0.0f }, 0 }, { 6, 7 } }
+ };
+
+ // create asset
+ const NvBlastAssetDesc assetDesc = { 8, c_chunks, bondsCount, c_bonds };
+
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ // get graph nodes check
+ std::vector<uint32_t> graphNodeIndices;
+ graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr));
+ uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr);
+ EXPECT_EQ(graphNodesCount, 7);
+
+ NvBlastExtRadialDamageDesc damage = {
+ 1.0f, // compressive
+ { 4.0f, 2.0f, 0.0f }, // position
+ 4.0f, // min radius - maximum damage
+ 6.0f // max radius - zero damage
+ }; // linear falloff
+
+ NvBlastBondFractureData outCommands[bondsCount] = {
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
+ };
+
+ NvBlastFractureBuffers commands = {
+ 6, 0, outCommands, nullptr
+ };
+
+ NvBlastExtProgramParams programParams = { &damage, nullptr };
+
+ NvBlastDamageProgram program = {
+ NvBlastExtFalloffGraphShader,
+ nullptr
+ };
+
+ NvBlastActorGenerateFracture(&commands, actor, program, &programParams, messageLog, nullptr);
+
+ ASSERT_EQ(3, commands.bondFractureCount);
+ ASSERT_EQ(0, commands.chunkFractureCount);
+
+ // node indices in _graph_ chunks
+ NvBlastBondFractureData expectedCommand[] = {
+ { 0, 0, 1, 1.0f },
+ { 0, 1, 2, 0.5f },
+ { 0, 5, 6, 0.5f }
+ };
+
+ for (int i = 0; i < 3; i++)
+ {
+ EXPECT_EQ(expectedCommand[i].nodeIndex0, outCommands[i].nodeIndex0);
+ EXPECT_EQ(expectedCommand[i].nodeIndex1, outCommands[i].nodeIndex1);
+ EXPECT_EQ(expectedCommand[i].health, outCommands[i].health);
+ }
+
+ const bool actorReleaseResult = NvBlastActorDeactivate(actor, messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+TEST_F(APITest, DirectFractureKillsChunk)
+{
+ // 1--2
+ // | |
+ // 3--4 <-- kill 4
+
+ const NvBlastChunkDesc c_chunks[9] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 7 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 8 },
+ };
+
+ const NvBlastBondDesc c_bonds[4] =
+ {
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 1.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-1.0f, 0.0f }, 0 }, { 3, 4 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 4 } },
+ };
+
+ NvBlastAssetDesc assetDesc;
+ assetDesc.chunkCount = 9;
+ assetDesc.chunkDescs = c_chunks;
+ assetDesc.bondCount = 4;
+ assetDesc.bondDescs = c_bonds;
+
+ // create asset
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ NvBlastChunkFractureData fractureCmd;
+ fractureCmd.chunkIndex = 4;
+ fractureCmd.health = 1.0f;
+
+ NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd };
+
+ NvBlastChunkFractureData fractureEvt;
+ NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ EXPECT_EQ(1, events.chunkFractureCount);
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(5, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+ // check newActors contain original actor
+ EXPECT_TRUE(std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; }));
+
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+TEST_F(APITest, DirectFractureKillsIslandRootChunk)
+{
+ // 1--2 <-- kill 1
+ // | |
+ // 3--4
+
+ const NvBlastChunkDesc c_chunks[9] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 7 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 8 },
+ };
+
+ const NvBlastBondDesc c_bonds[4] =
+ {
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 1.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-1.0f, 0.0f }, 0 }, { 3, 4 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, {-1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } },
+ { { { 0.0f,-1.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 4 } },
+ };
+
+ NvBlastAssetDesc assetDesc;
+ assetDesc.chunkCount = 9;
+ assetDesc.chunkDescs = c_chunks;
+ assetDesc.bondCount = 4;
+ assetDesc.bondDescs = c_bonds;
+
+ // create asset
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ NvBlastChunkFractureData fractureCmd;
+ fractureCmd.chunkIndex = 1;
+ fractureCmd.health = 1.0f;
+
+ NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd };
+
+ NvBlastChunkFractureData fractureEvt;
+ NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ EXPECT_EQ(1, events.chunkFractureCount);
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(5, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+ // check if newActors don't contain original actor
+ EXPECT_TRUE(!std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; }));
+
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+TEST_F(APITest, SubsupportFracture)
+{
+ const NvBlastAssetDesc& assetDesc = g_assetDescs[1]; // cube with subsupport
+
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ // first set of fracture commands
+ NvBlastChunkFractureData f1 = { 0, 1, 2.0f };
+ NvBlastChunkFractureData f3 = { 0, 3, 0.5f };
+ NvBlastChunkFractureData f5 = { 0, 5, 1.0f };
+ NvBlastChunkFractureData f7 = { 0, 7, 1.0f };
+
+ std::vector<NvBlastChunkFractureData> chunkFractureData;
+ chunkFractureData.reserve(assetDesc.chunkCount);
+ chunkFractureData.push_back(f1);
+ chunkFractureData.push_back(f3);
+ chunkFractureData.push_back(f5);
+ chunkFractureData.push_back(f7);
+ ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
+ ASSERT_EQ(4, chunkFractureData.size());
+
+ NvBlastFractureBuffers target = { 0, static_cast<uint32_t>(chunkFractureData.capacity()), nullptr, chunkFractureData.data() };
+ {
+ NvBlastFractureBuffers events = target;
+ NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
+ NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ ASSERT_EQ(4 + 8, events.chunkFractureCount); // all requested chunks take damage, and the children of one of them
+ }
+
+ // re-apply same set of commands
+ chunkFractureData.clear();
+ chunkFractureData.reserve(assetDesc.chunkCount);
+ chunkFractureData.push_back(f1);
+ chunkFractureData.push_back(f3);
+ chunkFractureData.push_back(f5);
+ chunkFractureData.push_back(f7);
+ ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
+ ASSERT_EQ(4, chunkFractureData.size());
+
+ {
+ NvBlastFractureBuffers events = target;
+ NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
+ NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ ASSERT_EQ(1, events.chunkFractureCount); // f3 has broken the chunk
+ }
+
+ // fracture all support chunks
+ // the chunks from the previous fractures must not be reported again (since they are all broken already)
+ NvBlastChunkFractureData f2 = { 0, 2, 2.0f }; // will damage chunk and children
+ NvBlastChunkFractureData f4 = { 0, 4, 0.5f }; // will damage chunk without creating children on split
+ NvBlastChunkFractureData f6 = { 0, 6, 2.0f }; // will damage chunk and children
+ NvBlastChunkFractureData f8 = { 0, 8, 1.0f }; // will damage chunk
+
+ chunkFractureData.clear();
+ chunkFractureData.reserve(assetDesc.chunkCount);
+ chunkFractureData.push_back(f1);
+ chunkFractureData.push_back(f2);
+ chunkFractureData.push_back(f3);
+ chunkFractureData.push_back(f4);
+ chunkFractureData.push_back(f5);
+ chunkFractureData.push_back(f6);
+ chunkFractureData.push_back(f7);
+ chunkFractureData.push_back(f8);
+ ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity());
+ ASSERT_EQ(8, chunkFractureData.size());
+
+ NvBlastFractureBuffers events = target;
+ {
+ NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() };
+ NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ ASSERT_EQ(4 + 8 + 8, events.chunkFractureCount); // the new fracture commands all apply, plus two of them damage their children too
+ }
+
+ for (size_t i = 0; i < events.chunkFractureCount; i++)
+ {
+ const uint32_t chunkIndex = events.chunkFractures[i].chunkIndex;
+
+ ASSERT_TRUE(chunkIndex != 1);
+ ASSERT_TRUE(chunkIndex != 3);
+ ASSERT_TRUE(chunkIndex != 5);
+ ASSERT_TRUE(chunkIndex != 7);
+
+ // literal values come from g_cube2ChunkDescs
+ bool isInSupportRange = chunkIndex <= 8 && chunkIndex >= 1;
+ bool isChildOfTwo = chunkIndex <= 24 && chunkIndex >= 17;
+ bool isChildOfSix = chunkIndex <= 56 && chunkIndex >= 49;
+
+ ASSERT_TRUE(isInSupportRange || isChildOfTwo || isChildOfSix);
+ }
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(64 - 8 + 1, newActorsCount);
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+static bool hasWarned = false;
+static void myLog(int type, const char* msg, const char* file, int line)
+{
+ BlastBaseTest<-1, 0>::messageLog(type, msg, file, line);
+ hasWarned = true;
+}
+#define EXPECT_WARNING EXPECT_TRUE(hasWarned); hasWarned=false;
+#define EXPECT_NO_WARNING EXPECT_FALSE(hasWarned); hasWarned=false;
+
+TEST_F(APITest, FractureNoEvents)
+{
+ static const uint32_t GUARD = 0xb1a57;
+
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const NvBlastBondDesc c_bonds[3] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
+
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ std::vector<NvBlastChunkFractureData> cfData;
+ cfData.resize(0 + 1);
+ cfData[cfData.size() - 1].userdata = GUARD;
+ std::vector<NvBlastBondFractureData> bfData;
+
+ NvBlastChunkFractureData command[] =
+ {
+ { 0, 1, 10.0f },
+ { 0, 2, 10.0f },
+ };
+
+ NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ EXPECT_NO_WARNING; // events can be null
+ EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(9, newActorsCount);
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+
+ EXPECT_NO_WARNING;
+}
+
+TEST_F(APITest, FractureBufferLimits)
+{
+ static const uint32_t GUARD = 0xb1a57;
+
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const NvBlastBondDesc c_bonds[3] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
+ {
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ for (uint32_t i = 0; i < 14; i++)
+ {
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ std::vector<NvBlastChunkFractureData> cfData;
+ cfData.resize(i + 1);
+ cfData[cfData.size() - 1].userdata = GUARD;
+ std::vector<NvBlastBondFractureData> bfData;
+
+ NvBlastChunkFractureData command[] =
+ {
+ { 0, 1, 10.0f },
+ { 0, 2, 10.0f },
+ };
+
+ NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
+ NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
+
+ EXPECT_WARNING;
+ EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
+ EXPECT_EQ(i, events.chunkFractureCount);
+ for (uint32_t i = 0; i < events.chunkFractureCount; i++)
+ {
+ EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
+ }
+
+ EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog));
+ alignedFree(family);
+ }
+
+ {
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ std::vector<NvBlastChunkFractureData> cfData;
+ cfData.resize(14 + 1);
+ cfData[cfData.size() - 1].userdata = GUARD;
+ std::vector<NvBlastBondFractureData> bfData;
+
+ NvBlastChunkFractureData command[] =
+ {
+ { 0, 1, 10.0f },
+ { 0, 2, 10.0f },
+ };
+
+ NvBlastFractureBuffers commands = { 0, 2, nullptr, command };
+ NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ EXPECT_NO_WARNING;
+ EXPECT_EQ(14, events.chunkFractureCount);
+ for (uint32_t i = 0; i < events.chunkFractureCount; i++)
+ {
+ EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
+ }
+ ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(9, newActorsCount);
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+
+ alignedFree(family);
+ }
+
+ alignedFree(asset);
+ }
+ EXPECT_NO_WARNING;
+}
+
+TEST_F(APITest, FractureBufferLimitsInSitu)
+{
+ static const uint32_t GUARD = 0xb1a57;
+
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // cenroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
+
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const NvBlastBondDesc c_bonds[3] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds };
+ {
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ for (uint32_t i = 0; i < 14 - 2; i++)
+ {
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ std::vector<NvBlastChunkFractureData> cfData;
+ cfData.resize(2 + i + 1);
+
+ std::vector<NvBlastBondFractureData> bfData;
+
+ cfData[0].userdata = 0;
+ cfData[0].chunkIndex = 1;
+ cfData[0].health = 10.0f;
+
+ cfData[1].userdata = 0;
+ cfData[1].chunkIndex = 2;
+ cfData[1].health = 10.0f;
+
+ cfData[2 + i].userdata = GUARD;
+
+ NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() };
+ NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ EXPECT_WARNING;
+ EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
+ EXPECT_EQ(2 + i, events.chunkFractureCount);
+ for (uint32_t i = 0; i < events.chunkFractureCount; i++)
+ {
+ EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
+ }
+
+ EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog));
+
+ alignedFree(family);
+ }
+
+ {
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ std::vector<NvBlastChunkFractureData> cfData;
+ cfData.resize(14 + 1);
+ cfData[cfData.size() - 1].userdata = GUARD;
+ std::vector<NvBlastBondFractureData> bfData;
+
+ cfData[0].userdata = 0;
+ cfData[0].chunkIndex = 1;
+ cfData[0].health = 10.0f;
+
+ cfData[1].userdata = 0;
+ cfData[1].chunkIndex = 2;
+ cfData[1].health = 10.0f;
+
+ cfData[14].userdata = GUARD;
+
+ NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() };
+ NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() };
+
+ NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ EXPECT_NO_WARNING;
+ EXPECT_EQ(14, events.chunkFractureCount);
+ for (uint32_t i = 0; i < events.chunkFractureCount; i++)
+ {
+ EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata);
+ }
+ ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata);
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+ newActors.resize(newActorsCount);
+
+ EXPECT_EQ(9, newActorsCount);
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+ alignedFree(family);
+ }
+
+ alignedFree(asset);
+ }
+ EXPECT_NO_WARNING;
+}
+
+/*
+This test checks if bond or chunk fracture commands passed to NvBlastActorApplyFracture do not correspond to
+the actor passed in they (commands) will be ignored and warning message will be fired.
+*/
+TEST_F(APITest, FractureWarnAndFilterOtherActorCommands)
+{
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // centroid volume parent idx flags ID
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const NvBlastBondDesc c_bonds[4] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } }
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 4, c_bonds };
+
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ // split in 2
+ std::vector<NvBlastActor*> actors;
+ {
+ NvBlastBondFractureData command[] =
+ {
+ { 0, 0, 2, 10.0f },
+ { 0, 1, 2, 10.0f }
+ };
+
+ NvBlastFractureBuffers commands = { 2, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(2, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+
+ actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
+ }
+
+ // damage bonds belonging to other actors, nothing expected to be broken
+ {
+ for (uint32_t i = 0; i < actors.size(); ++i)
+ {
+ NvBlastActor* actor = actors[i];
+ NvBlastActor* otherActor = actors[(i + 1) % 2];
+
+ // get graph nodes check
+ std::vector<uint32_t> graphNodeIndices;
+ graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(otherActor, nullptr));
+ uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), otherActor, nullptr);
+ EXPECT_EQ(graphNodesCount, 2);
+
+ NvBlastBondFractureData command[] =
+ {
+ { 0, graphNodeIndices[0], graphNodeIndices[1], 10.0f }
+ };
+
+ NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_WARNING;
+ EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(0, newActorsCount);
+ EXPECT_EQ(nullptr, result.deletedActor);
+ }
+ }
+
+ // damage bonds, split actors in 2 each
+ std::vector<NvBlastActor*> actors2;
+ {
+ for (uint32_t i = 0; i < 2; ++i)
+ {
+ NvBlastActor* actor = actors[i];
+
+ // get graph nodes check
+ std::vector<uint32_t> graphNodeIndices;
+ graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr));
+ uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr);
+ EXPECT_EQ(graphNodesCount, 2);
+
+ NvBlastBondFractureData command[] =
+ {
+ { 0, graphNodeIndices[0], graphNodeIndices[1], 10.0f }
+ };
+
+ NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(2, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+
+ actors2.insert(actors2.begin(), result.newActors, result.newActors + newActorsCount);
+ }
+ }
+
+ // damage chunk belonging to other actor (expect no split or damage taken)
+ {
+ for (uint32_t i = 0; i < actors.size(); ++i)
+ {
+ NvBlastActor* actor = actors[i];
+ NvBlastActor* otherActor = actors[(i + 1) % 2];
+
+ uint32_t chunkToDamage;
+ NvBlastActorGetVisibleChunkIndices(&chunkToDamage, 1, otherActor, myLog);
+
+ NvBlastChunkFractureData command[] =
+ {
+ { 0, chunkToDamage, 0.9f },
+ };
+
+ NvBlastFractureBuffers commands = { 0, 1, nullptr, command };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_WARNING;
+ EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(0, newActorsCount);
+ EXPECT_EQ(nullptr, result.deletedActor);
+
+ EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
+ EXPECT_NE(chunkToDamage, chunkIndex);
+ }
+ }
+
+ for (NvBlastActor* actor : actors2)
+ {
+ NvBlastActorDeactivate(actor, myLog);
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+
+ EXPECT_NO_WARNING;
+}
+
+/**
+If duplicate bonds are passed asset create routine will ignore them (but fire warning)
+We pass duplicated bonds to world chunk and fully fracture actor once.
+*/
+TEST_F(APITest, FractureWithBondDuplicates)
+{
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // centroid volume parent idx flags ID
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 8 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const uint32_t bondCount = 20;
+ const uint32_t world = ~(uint32_t)0; // world chunk => invalid index
+ const NvBlastBondDesc c_bonds[bondCount] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 1, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, 1 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 2, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 3, 1 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 4, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 5, 1 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 5, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, 5 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 6, world } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 7, 5 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 7, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 7 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 6 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, 4 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f,{ 1.0f, 0.0f, 0.0f }, 0 },{ 8, world } }
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, bondCount, c_bonds };
+
+ // create asset
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_WARNING;
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ // split in 2
+ std::vector<NvBlastActor*> actors;
+ {
+ NvBlastExtRadialDamageDesc damage = {
+ 10.0f, // compressive
+ { 0.0f, 0.0f, 0.0f }, // position
+ 100.0f, // min radius - maximum damage
+ 100.0f // max radius - zero damage
+ };
+
+ NvBlastBondFractureData outBondFracture[bondCount];
+ NvBlastChunkFractureData outChunkFracture[chunksCount];
+
+ NvBlastFractureBuffers events;
+ events.bondFractureCount = 2;
+ events.bondFractures = outBondFracture;
+ events.chunkFractureCount = 2;
+ events.chunkFractures = outChunkFracture;
+
+ NvBlastExtProgramParams programParams = { &damage, nullptr };
+
+ NvBlastDamageProgram program = {
+ NvBlastExtFalloffGraphShader,
+ NvBlastExtFalloffSubgraphShader
+ };
+
+ NvBlastActorGenerateFracture(&events, actor, program, &programParams, myLog, nullptr);
+ NvBlastActorApplyFracture(nullptr, actor, &events, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(8, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+
+ actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
+ }
+
+ for (NvBlastActor* actor : actors)
+ {
+ NvBlastActorDeactivate(actor, myLog);
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+
+ EXPECT_NO_WARNING;
+}
+
+#if 0
+TEST(APITest, UserChunkMap)
+{
+ for (int i = 0; i < 2; ++i)
+ {
+ // Choose descriptor list
+ const NvBlastAssetDesc* descs = nullptr;
+ size_t size = 0;
+ switch (i)
+ {
+ case 0:
+ descs = g_assetDescs;
+ size = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]);
+ break;
+ case 1:
+ descs = g_assetDescsMissingCoverage;
+ size = sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]);
+ break;
+ default:
+ continue;
+ }
+
+ // Iterate over list
+ for (size_t j = 0; j < size; ++j)
+ {
+ // Create asset
+ const NvBlastAssetDesc* desc = descs + j;
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(desc));
+ std::vector<uint32_t> chunkMap(desc->chunkCount);
+ NvBlastAsset* asset = NvBlastCreateAsset(&chunkMap[0], desc, alignedAlloc<malloc>, scratch.data(), nullptr);
+ EXPECT_TRUE(asset);
+
+ // Test map
+ Nv::Blast::Asset& a = static_cast<Nv::Blast::Asset&>(asset);
+ uint32_t supportChunkCount = 0;
+ uint32_t subsupportChunkCount = 0;
+ for (uint32_t i = 0; i < desc->chunkCount; ++i)
+ {
+ const uint32_t map = chunkMap[i];
+ if (Nv::Blast::isInvalidIndex(map))
+ {
+ continue;
+ }
+ else if (map < a.m_firstSubsupportChunkIndex)
+ {
+ EXPECT_LT(map, asset.m_graph.m_nodeCount);
+ ++supportChunkCount;
+ }
+ else
+ {
+ EXPECT_LT(map, asset.m_chunkCount);
+ EXPECT_GE(map, asset.m_graph.m_nodeCount);
+ ++subsupportChunkCount;
+ }
+ }
+ EXPECT_EQ(supportChunkCount, asset.m_graph.m_nodeCount);
+ EXPECT_EQ(subsupportChunkCount, a.getLowerSupportChunkCount() - asset.m_graph.m_nodeCount);
+
+ // Release asset
+ NvBlastAssetRelease(asset, free, nullptr);
+ }
+ }
+}
+#endif
+
+TEST_F(APITest, NoBondsSausage)
+{
+ // create asset
+ const NvBlastChunkDesc c_chunks[4] =
+ {
+ // centroid volume parent idx flags ID
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 2 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 3 }
+ };
+
+ NvBlastAssetDesc assetDesc;
+ assetDesc.chunkCount = 4;
+ assetDesc.chunkDescs = c_chunks;
+ assetDesc.bondCount = 0;
+ assetDesc.bondDescs = nullptr;
+
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog);
+ const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, messageLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog);
+ EXPECT_TRUE(actor != nullptr);
+
+ // check visible chunk
+ {
+ EXPECT_EQ(NvBlastActorGetVisibleChunkCount(actor, messageLog), 1);
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, messageLog);
+ EXPECT_EQ(chunks[chunkIndex].userData, 0);
+ }
+
+ // damage
+ NvBlastExtRadialDamageDesc damage = {
+ 10.0f, // compressive
+ { 0.0f, 0.0f, 0.0f }, // position
+ 4.0f, // min radius - maximum damage
+ 6.0f // max radius - zero damage
+ };
+
+ NvBlastBondFractureData outBondFracture[2];
+ NvBlastChunkFractureData outChunkFracture[2];
+
+ NvBlastFractureBuffers events;
+ events.bondFractureCount = 2;
+ events.bondFractures = outBondFracture;
+ events.chunkFractureCount = 2;
+ events.chunkFractures = outChunkFracture;
+
+ NvBlastExtProgramParams programParams = { &damage, nullptr };
+
+ NvBlastDamageProgram program = {
+ NvBlastExtFalloffGraphShader,
+ NvBlastExtFalloffSubgraphShader
+ };
+
+ NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr);
+ NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+ EXPECT_EQ(0, events.bondFractureCount);
+ EXPECT_EQ(1, events.chunkFractureCount);
+
+ // split
+ NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors;
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog));
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr);
+ EXPECT_EQ(1, newActorsCount);
+ EXPECT_EQ(true, result.deletedActor == actor);
+
+ // check visible chunk
+ {
+ EXPECT_EQ(NvBlastActorGetVisibleChunkCount(result.newActors[0], messageLog), 1);
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, result.newActors[0], messageLog);
+ EXPECT_EQ(chunks[chunkIndex].userData, 3);
+ }
+
+ // release all
+ for (uint32_t i = 0; i < newActorsCount; ++i)
+ {
+ const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog);
+ EXPECT_TRUE(actorReleaseResult);
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+}
+
+TEST_F(APITest, SplitOnlyWhenNecessary)
+{
+ static const uint32_t GUARD = 0xb1a57;
+
+ const uint32_t chunksCount = 17;
+ const NvBlastChunkDesc c_chunks[chunksCount] =
+ {
+ // centroid volume parent idx flags ID
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 },
+
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 },
+ { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 },
+ };
+
+ const NvBlastBondDesc c_bonds[4] =
+ {
+ // normal, area, centroid, userdata, chunks
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 2 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 2, 3 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 3, 4 } },
+ { { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 }, { 1, 3 } }
+ };
+
+ NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 4, c_bonds };
+
+ // create asset with chunk map
+ std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog));
+ void* amem = alignedZeroedAlloc(NvBlastGetAssetMemorySize(&assetDesc, myLog));
+ NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog);
+ EXPECT_TRUE(asset != nullptr);
+
+ // create actor
+ NvBlastActorDesc actorDesc;
+ actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr;
+ actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ void* fmem = alignedZeroedAlloc(NvBlastAssetGetFamilyMemorySize(asset, myLog));
+ NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog);
+ scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog));
+ NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog);
+ EXPECT_TRUE(actor != nullptr);
+
+
+ // damage health only (expect no split)
+ {
+ NvBlastBondFractureData command[] =
+ {
+ { 0, 0, 1, 0.99f },
+ { 0, 1, 2, 0.50f },
+ { 0, 2, 3, 0.01f }
+ };
+
+ NvBlastFractureBuffers commands = { 3, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(0, newActorsCount);
+ EXPECT_EQ(nullptr, result.deletedActor);
+
+ EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
+ EXPECT_EQ(0, chunkIndex);
+ }
+
+ // break 1 bond (expect no split)
+ {
+ NvBlastBondFractureData command[] =
+ {
+ { 0, 0, 2, 10.0f },
+ };
+
+ NvBlastFractureBuffers commands = { 1, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(0, newActorsCount);
+ EXPECT_EQ(nullptr, result.deletedActor);
+
+ EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
+ EXPECT_EQ(0, chunkIndex);
+ }
+
+ // split in 4
+ std::vector<NvBlastActor*> actors;
+ {
+ NvBlastBondFractureData command[] =
+ {
+ { 0, 0, 1, 10.0f },
+ { 0, 1, 2, 10.0f },
+ { 0, 2, 3, 10.0f }
+ };
+
+ NvBlastFractureBuffers commands = { 3, 0, command, nullptr };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_TRUE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(4, newActorsCount);
+ EXPECT_EQ(actor, result.deletedActor);
+
+ actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount);
+ }
+
+ // damage chunk's health only (expect no split)
+ {
+ for (NvBlastActor* actor : actors)
+ {
+ uint32_t chunkToDamage;
+ NvBlastActorGetVisibleChunkIndices(&chunkToDamage, 1, actor, myLog);
+
+ NvBlastChunkFractureData command[] =
+ {
+ { 0, chunkToDamage, 0.9f },
+ };
+
+ NvBlastFractureBuffers commands = { 0, 1, nullptr, command };
+ NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr);
+ EXPECT_FALSE(NvBlastActorIsSplitRequired(actor, messageLog));
+
+ scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog));
+ std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog));
+ NvBlastActorSplitEvent result;
+ result.deletedActor = nullptr;
+ result.newActors = newActors.data();
+ size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr);
+
+ EXPECT_EQ(0, newActorsCount);
+ EXPECT_EQ(nullptr, result.deletedActor);
+
+ EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog));
+ uint32_t chunkIndex;
+ NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog);
+ EXPECT_EQ(chunkToDamage, chunkIndex);
+ }
+ }
+
+ for (NvBlastActor* actor : actors)
+ {
+ NvBlastActorDeactivate(actor, myLog);
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+
+ EXPECT_NO_WARNING;
+}
+
+#if NV_WINDOWS_FAMILY
+#include <windows.h>
+TEST_F(APITest,CExportsNoNameMangling)
+{
+
+ //
+ // tests the lib-link-free approach using unmangled names (extern "C")
+ //
+
+#if NV_WIN32
+#if NV_DEBUG
+ const char* dllName = "NvBlastDebug_x86.dll";
+#elif NV_CHECKED
+ const char* dllName = "NvBlastChecked_x86.dll";
+#elif NV_PROFILE
+ const char* dllName = "NvBlastProfile_x86.dll";
+#else
+ const char* dllName = "NvBlast_x86.dll";
+#endif
+#elif NV_WIN64
+#if NV_DEBUG
+ const char* dllName = "NvBlastDebug_x64.dll";
+#elif NV_CHECKED
+ const char* dllName = "NvBlastChecked_x64.dll";
+#elif NV_PROFILE
+ const char* dllName = "NvBlastProfile_x64.dll";
+#else
+ const char* dllName = "NvBlast_x64.dll";
+#endif
+#endif
+
+ HMODULE dllHandle = LoadLibrary(TEXT(dllName));
+ DWORD error = GetLastError();
+ ASSERT_TRUE(dllHandle != nullptr);
+
+
+ // Asset functions
+ typedef size_t(*NvBlastGetRequiredScratchForCreateAsset)(const NvBlastAssetDesc* desc);
+ typedef size_t(*NvBlastGetAssetMemorySize)(const NvBlastAssetDesc* desc);
+ typedef NvBlastAsset*(*NvBlastCreateAsset)(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvBlastLog logFn);
+
+ NvBlastGetRequiredScratchForCreateAsset assetCreateRequiredScratch = (NvBlastGetRequiredScratchForCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastGetRequiredScratchForCreateAsset"));
+ ASSERT_TRUE(assetCreateRequiredScratch != nullptr);
+
+ NvBlastGetAssetMemorySize assetGetMemorySize = (NvBlastGetAssetMemorySize)GetProcAddress(dllHandle, TEXT("NvBlastGetAssetMemorySize"));
+ ASSERT_TRUE(assetGetMemorySize != nullptr);
+
+ NvBlastCreateAsset assetCreate = (NvBlastCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastCreateAsset"));
+ ASSERT_TRUE(assetCreate != nullptr);
+
+ // Family functions
+ typedef NvBlastFamily* (*NvBlastAssetCreateFamily)(void* mem, const NvBlastAsset* asset, NvBlastLog logFn);
+ typedef size_t(*NVBLASTASSETGETFAMILYMEMORYSIZE)(const NvBlastAsset* asset);
+
+ NVBLASTASSETGETFAMILYMEMORYSIZE familyGetMemorySize = (NVBLASTASSETGETFAMILYMEMORYSIZE)GetProcAddress(dllHandle, TEXT("NvBlastAssetGetFamilyMemorySize"));
+ ASSERT_TRUE(familyGetMemorySize != nullptr);
+
+ NvBlastAssetCreateFamily familyCreate = (NvBlastAssetCreateFamily)GetProcAddress(dllHandle, TEXT("NvBlastAssetCreateFamily"));
+ ASSERT_TRUE(familyCreate != nullptr);
+
+
+ // Actor functions
+ typedef size_t(*NvBlastFamilyGetRequiredScratchForCreateFirstActor)(const NvBlastFamily* family);
+ typedef NvBlastActor* (*NvBlastFamilyCreateFirstActor)(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn);
+ typedef bool(*NVBLASTACTORDEACTIVATE)(NvBlastActor* actor);
+
+ NvBlastFamilyGetRequiredScratchForCreateFirstActor actorcreaterequiredscratch = (NvBlastFamilyGetRequiredScratchForCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyGetRequiredScratchForCreateFirstActor"));
+ ASSERT_TRUE(actorcreaterequiredscratch != nullptr);
+
+ NvBlastFamilyCreateFirstActor actorCreate = (NvBlastFamilyCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyCreateFirstActor"));
+ ASSERT_TRUE(actorCreate != nullptr);
+
+ NVBLASTACTORDEACTIVATE actorRelease = (NVBLASTACTORDEACTIVATE)GetProcAddress(dllHandle, TEXT("NvBlastActorDeactivate"));
+ ASSERT_TRUE(actorRelease != nullptr);
+
+
+ const NvBlastChunkDesc c_chunks[] =
+ {
+ // centroid volume parent idx flags ID
+ { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
+ { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 },
+ };
+
+ NvBlastAssetDesc assetDesc;
+ assetDesc.bondCount = 0;
+ assetDesc.bondDescs = nullptr;
+ assetDesc.chunkCount = 4;
+ assetDesc.chunkDescs = c_chunks;
+
+ NvBlastAsset* asset;
+ {
+ size_t requiredsize = assetCreateRequiredScratch(&assetDesc);
+ std::vector<char>scratch(requiredsize);
+ void* mem = alignedZeroedAlloc(assetGetMemorySize(&assetDesc));
+ asset = assetCreate(mem, &assetDesc, scratch.data(), myLog);
+ ASSERT_TRUE(asset != nullptr);
+ }
+
+ void* fmem = alignedZeroedAlloc(familyGetMemorySize(asset));
+ NvBlastFamily* family = familyCreate(fmem, asset, myLog);
+
+ {
+ NvBlastActorDesc actorD;
+ actorD.initialBondHealths = actorD.initialSupportChunkHealths = nullptr;
+ actorD.uniformInitialBondHealth = actorD.uniformInitialLowerSupportChunkHealth = 1.0f;
+
+ size_t requiredsize = actorcreaterequiredscratch(family);
+ std::vector<char>scratch(requiredsize);
+ NvBlastActor* actor = actorCreate(family, &actorD, scratch.data(), myLog);
+ ASSERT_TRUE(actor != nullptr);
+
+ ASSERT_TRUE(actorRelease(actor));
+ }
+
+ alignedFree(family);
+ alignedFree(asset);
+
+ EXPECT_NO_WARNING;
+}
+#endif