diff options
Diffstat (limited to 'sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp')
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp | 966 |
1 files changed, 483 insertions, 483 deletions
diff --git a/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp b/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp index 072bb10..2c902d4 100644..100755 --- a/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp +++ b/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp @@ -1,483 +1,483 @@ -// 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) 2018 NVIDIA Corporation. All rights reserved. - - -#include "NvBlastExtAssetUtils.h" -#include "NvBlast.h" -#include "NvBlastIndexFns.h" -#include "NvBlastMemory.h" -#include "NvBlastGlobals.h" -#include "math.h" - -using namespace Nv::Blast; - - -/** -Fill the chunk and bond descriptors from an asset. - -\param[out] chunkDescsWritten the number of chunk descriptors written to chunkDescs -\param[out] bondDescsWritten the number of bond descriptors written to bondDescs -\param[out] chunkDescs user-supplied buffer of NvBlastChunkDesc. Size must be at least NvBlastAssetGetChunkCount(asset, logFn) -\param[out] bondDescs user-supplied buffer of NvBlastBondDesc. Size must be at least NvBlastAssetGetBondCount(asset, logFn) -\param[in] asset asset from which to extract descriptors -*/ -static void fillChunkAndBondDescriptorsFromAsset -( - uint32_t& chunkDescsWritten, - uint32_t& bondDescsWritten, - NvBlastChunkDesc* chunkDescs, - NvBlastBondDesc* bondDescs, - const NvBlastAsset* asset -) -{ - chunkDescsWritten = 0; - bondDescsWritten = 0; - - // Chunk descs - const uint32_t assetChunkCount = NvBlastAssetGetChunkCount(asset, logLL); - const NvBlastChunk* assetChunk = NvBlastAssetGetChunks(asset, logLL); - for (uint32_t i = 0; i < assetChunkCount; ++i, ++assetChunk) - { - NvBlastChunkDesc& chunkDesc = chunkDescs[chunkDescsWritten++]; - memcpy(chunkDesc.centroid, assetChunk->centroid, sizeof(float) * 3); - chunkDesc.volume = assetChunk->volume; - chunkDesc.parentChunkIndex = assetChunk->parentChunkIndex; - chunkDesc.flags = 0; // To be filled in below - chunkDesc.userData = assetChunk->userData; - } - - // Bond descs - const uint32_t assetBondCount = NvBlastAssetGetBondCount(asset, logLL); - const NvBlastBond* assetBond = NvBlastAssetGetBonds(asset, logLL); - for (uint32_t i = 0; i < assetBondCount; ++i, ++assetBond) - { - NvBlastBondDesc& bondDesc = bondDescs[bondDescsWritten++]; - memcpy(&bondDesc.bond, assetBond, sizeof(NvBlastBond)); - } - - // Walk the graph and restore connection descriptors - const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL); - for (uint32_t i = 0; i < graph.nodeCount; ++i) - { - const int32_t currentChunk = graph.chunkIndices[i]; - if (isInvalidIndex(currentChunk)) - { - continue; - } - - chunkDescs[currentChunk].flags |= NvBlastChunkDesc::SupportFlag; // Filling in chunk flags here - - for (uint32_t j = graph.adjacencyPartition[i]; j < graph.adjacencyPartition[i + 1]; ++j) - { - NvBlastBondDesc& bondDesc = bondDescs[graph.adjacentBondIndices[j]]; - bondDesc.chunkIndices[0] = currentChunk; - const uint32_t adjacentChunkIndex = graph.chunkIndices[graph.adjacentNodeIndices[j]]; - bondDesc.chunkIndices[1] = adjacentChunkIndex; - } - } -} - - -/** -Scale a 3-vector v in-place. - -\param[in,out] v The vector to scale. -\param[in] s The scale. Represents the diagonal elements of a diagonal matrix. - -The result will be v <- s*v. -*/ -static inline void scale(NvcVec3& v, const NvcVec3& s) -{ - v.x *= s.x; - v.y *= s.y; - v.z *= s.z; -} - - -/** -Rotate a 3-vector v in-place using a rotation represented by a quaternion q. - -\param[in,out] v The vector to rotate. -\param[in] q The quaternion representation the rotation. - -The format of q is { x, y, z, w } where (x,y,z) is the vector part and w is the scalar part. -The quaternion q MUST be normalized. -*/ -static inline void rotate(NvcVec3& v, const NvcQuat& q) -{ - const float vx = 2.0f * v.x; - const float vy = 2.0f * v.y; - const float vz = 2.0f * v.z; - const float w2 = q.w * q.w - 0.5f; - const float dot2 = (q.x * vx + q.y * vy + q.z * vz); - v.x = vx * w2 + (q.y * vz - q.z * vy) * q.w + q.x * dot2; - v.y = vy * w2 + (q.z * vx - q.x * vz) * q.w + q.y * dot2; - v.z = vz * w2 + (q.x * vy - q.y * vx) * q.w + q.z * dot2; -} - - -/** -Translate a 3-vector v in-place. - -\param[in,out] v The vector to translate. -\param[in] t The translation. - -The result will be v <- v+t. -*/ -static inline void translate(NvcVec3& v, const NvcVec3& t) -{ - v.x += t.x; - v.y += t.y; - v.z += t.z; -} - - -NvBlastAsset* NvBlastExtAssetUtilsAddWorldBonds -( - const NvBlastAsset* asset, - const uint32_t* worldBoundChunks, - uint32_t worldBoundChunkCount, - const NvcVec3* bondDirections, - const uint32_t* bondUserData -) -{ - const uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, logLL); - const uint32_t oldBondCount = NvBlastAssetGetBondCount(asset, logLL); - const uint32_t newBondCount = oldBondCount + worldBoundChunkCount; - - NvBlastChunkDesc* chunkDescs = static_cast<NvBlastChunkDesc*>(NVBLAST_ALLOC(chunkCount * sizeof(NvBlastChunkDesc))); - NvBlastBondDesc* bondDescs = static_cast<NvBlastBondDesc*>(NVBLAST_ALLOC(newBondCount * sizeof(NvBlastBondDesc))); - - // Create chunk descs - uint32_t chunkDescsWritten; - uint32_t bondDescsWritten; - fillChunkAndBondDescriptorsFromAsset(chunkDescsWritten, bondDescsWritten, chunkDescs, bondDescs, asset); - - // Add world bonds - uint32_t bondCount = oldBondCount; - for (uint32_t i = 0; i < worldBoundChunkCount; i++) - { - NvBlastBondDesc& bondDesc = bondDescs[bondCount++]; - const uint32_t chunkIndex = worldBoundChunks[i]; - bondDesc.chunkIndices[0] = chunkIndex; - bondDesc.chunkIndices[1] = invalidIndex<uint32_t>(); - memcpy(&bondDesc.bond.normal, bondDirections + i, sizeof(float) * 3); - bondDesc.bond.area = 1.0f; // Should be set by user - memcpy(&bondDesc.bond.centroid, chunkDescs[chunkIndex].centroid, sizeof(float) * 3); - bondDesc.bond.userData = bondUserData != nullptr ? bondUserData[i] : 0; - } - - // Create new asset - NvBlastAssetDesc assetDesc; - assetDesc.chunkCount = chunkCount; - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = bondCount; - assetDesc.bondDescs = bondDescs; - void* scratch = NVBLAST_ALLOC(NvBlastGetRequiredScratchForCreateAsset(&assetDesc, logLL)); - NvBlastAsset* newAsset = NvBlastCreateAsset(NVBLAST_ALLOC(NvBlastGetAssetMemorySize(&assetDesc, logLL)), &assetDesc, scratch, logLL); - - // Free buffers - NVBLAST_FREE(scratch); - NVBLAST_FREE(bondDescs); - NVBLAST_FREE(chunkDescs); - - return newAsset; -} - - -NvBlastAssetDesc NvBlastExtAssetUtilsMergeAssets -( - const NvBlastAsset** components, - const NvcVec3* scales, - const NvcQuat* rotations, - const NvcVec3* translations, - uint32_t componentCount, - const NvBlastExtAssetUtilsBondDesc* newBondDescs, - uint32_t newBondCount, - uint32_t* chunkIndexOffsets, - uint32_t* chunkReorderMap, - uint32_t chunkReorderMapSize -) -{ - // Count the total number of chunks and bonds in the new asset - uint32_t totalChunkCount = 0; - uint32_t totalBondCount = newBondCount; - for (uint32_t c = 0; c < componentCount; ++c) - { - totalChunkCount += NvBlastAssetGetChunkCount(components[c], logLL); - totalBondCount += NvBlastAssetGetBondCount(components[c], logLL); - } - - // Allocate space for chunk and bond descriptors - NvBlastChunkDesc* chunkDescs = static_cast<NvBlastChunkDesc*>(NVBLAST_ALLOC(totalChunkCount * sizeof(NvBlastChunkDesc))); - NvBlastBondDesc* bondDescs = static_cast<NvBlastBondDesc*>(NVBLAST_ALLOC(totalBondCount * sizeof(NvBlastBondDesc))); - - // Create a list of chunk index offsets per component - uint32_t* offsetStackAlloc = static_cast<uint32_t*>(NvBlastAlloca(componentCount * sizeof(uint32_t))); - if (chunkIndexOffsets == nullptr) - { - chunkIndexOffsets = offsetStackAlloc; // Use local stack alloc if no array is provided - } - - // Fill the chunk and bond descriptors from the components - uint32_t chunkCount = 0; - uint32_t bondCount = 0; - for (uint32_t c = 0; c < componentCount; ++c) - { - chunkIndexOffsets[c] = chunkCount; - uint32_t componentChunkCount; - uint32_t componentBondCount; - fillChunkAndBondDescriptorsFromAsset(componentChunkCount, componentBondCount, chunkDescs + chunkCount, bondDescs + bondCount, components[c]); - // Fix chunks' parent indices - for (uint32_t i = 0; i < componentChunkCount; ++i) - { - if (!isInvalidIndex(chunkDescs[chunkCount + i].parentChunkIndex)) - { - chunkDescs[chunkCount + i].parentChunkIndex += chunkCount; - } - } - // Fix bonds' chunk indices - for (uint32_t i = 0; i < componentBondCount; ++i) - { - NvBlastBondDesc& bondDesc = bondDescs[bondCount + i]; - for (int j = 0; j < 2; ++j) - { - if (!isInvalidIndex(bondDesc.chunkIndices[j])) - { - bondDesc.chunkIndices[j] += chunkCount; - } - } - } - // Transform geometric data - if (scales != nullptr) - { - const NvcVec3& S = scales[c]; - NvcVec3 cofS = { S.y * S.z, S.z * S.x, S.x * S.y }; - float absDetS = S.x * S.y * S.z; - const float sgnDetS = absDetS < 0.0f ? -1.0f : 1.0f; - absDetS *= sgnDetS; - for (uint32_t i = 0; i < componentChunkCount; ++i) - { - scale(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), S); - chunkDescs[chunkCount + i].volume *= absDetS; - } - for (uint32_t i = 0; i < componentBondCount; ++i) - { - NvBlastBond& bond = bondDescs[bondCount + i].bond; - scale(reinterpret_cast<NvcVec3&>(bond.normal), cofS); - float renorm = sqrtf(bond.normal[0] * bond.normal[0] + bond.normal[1] * bond.normal[1] + bond.normal[2] * bond.normal[2]); - bond.area *= renorm; - if (renorm != 0) - { - renorm = sgnDetS / renorm; - bond.normal[0] *= renorm; - bond.normal[1] *= renorm; - bond.normal[2] *= renorm; - } - scale(reinterpret_cast<NvcVec3&>(bond.centroid), S); - } - } - if (rotations != nullptr) - { - for (uint32_t i = 0; i < componentChunkCount; ++i) - { - rotate(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), rotations[c]); - } - for (uint32_t i = 0; i < componentBondCount; ++i) - { - NvBlastBond& bond = bondDescs[bondCount + i].bond; - rotate(reinterpret_cast<NvcVec3&>(bond.normal), rotations[c]); // Normal can be transformed this way since we aren't scaling - rotate(reinterpret_cast<NvcVec3&>(bond.centroid), rotations[c]); - } - } - if (translations != nullptr) - { - for (uint32_t i = 0; i < componentChunkCount; ++i) - { - translate(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), translations[c]); - } - for (uint32_t i = 0; i < componentBondCount; ++i) - { - translate(reinterpret_cast<NvcVec3&>(bondDescs[bondCount + i].bond.centroid), translations[c]); - } - } - chunkCount += componentChunkCount; - bondCount += componentBondCount; - } - - // Fill the bond descriptors from the new bond descs - for (uint32_t b = 0; b < newBondCount; ++b) - { - const NvBlastExtAssetUtilsBondDesc& newBondDesc = newBondDescs[b]; - NvBlastBondDesc& bondDesc = bondDescs[bondCount++]; - memcpy(&bondDesc.bond, &newBondDesc.bond, sizeof(NvBlastBond)); - bondDesc.chunkIndices[0] = !isInvalidIndex(newBondDesc.chunkIndices[0]) ? newBondDesc.chunkIndices[0] + chunkIndexOffsets[newBondDesc.componentIndices[0]] : invalidIndex<uint32_t>(); - bondDesc.chunkIndices[1] = !isInvalidIndex(newBondDesc.chunkIndices[1]) ? newBondDesc.chunkIndices[1] + chunkIndexOffsets[newBondDesc.componentIndices[1]] : invalidIndex<uint32_t>(); - } - - // Create new asset desriptor - NvBlastAssetDesc assetDesc; - assetDesc.chunkCount = chunkCount; - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = bondCount; - assetDesc.bondDescs = bondDescs; - - // Massage the descriptors so that they are valid for scratch creation - void* scratch = NVBLAST_ALLOC(chunkCount * sizeof(NvBlastChunkDesc)); // Enough for NvBlastEnsureAssetExactSupportCoverage and NvBlastReorderAssetDescChunks - - NvBlastEnsureAssetExactSupportCoverage(chunkDescs, chunkCount, scratch, logLL); - - if (chunkReorderMapSize < chunkCount) - { - if (chunkReorderMap != nullptr) - { - // Chunk reorder map is not large enough. Fill it with invalid indices and don't use it. - memset(chunkReorderMap, 0xFF, chunkReorderMapSize * sizeof(uint32_t)); - NVBLAST_LOG_WARNING("NvBlastExtAssetUtilsMergeAssets: insufficient chunkReorderMap array passed in. NvBlastReorderAssetDescChunks will not be used."); - } - chunkReorderMap = nullptr; // Don't use - } - - if (chunkReorderMap != nullptr) - { - NvBlastReorderAssetDescChunks(chunkDescs, chunkCount, bondDescs, bondCount, chunkReorderMap, true, scratch, logLL); - } - - NVBLAST_FREE(scratch); - - return assetDesc; -} - - -/** -Multiply a 3-vector v in-place by value. - -\param[in,out] v The vector to multiply. -\param[in] m The 3x3 matrix. -*/ -static inline void multiply(NvcVec3& v, float value) -{ - v.x *= value; - v.y *= value; - v.z *= value; -} - - -/** -Get Vec3 length -*/ -static inline float length(const NvcVec3& p) -{ - return sqrtf(p.x * p.x + p.y * p.y + p.z * p.z); -} - - -/** -Transform a point in-place: scale, rotate, then translate - -\param[in,out] p The point to transform. -\param[in] S The diagonal elements of a diagonal scale matrix. -\param[in] R A quaternion representing the rotation. Must be normalized. -\param[in] T The translation vector. -*/ -static inline void transform(NvcVec3& p, const NvcVec3& S, const NvcQuat& R, const NvcVec3& T) -{ - scale(p, S); - rotate(p, R); - translate(p, T); -} - - -/** -Transform a vector in-place: scale, then rotate - -\param[in,out] v The vector to transform. -\param[in] S The diagonal elements of a diagonal scale matrix. -\param[in] R A quaternion representing the rotation. Must be normalized. -*/ -static inline void transform(NvcVec3& v, const NvcVec3& S, const NvcQuat& R) -{ - scale(v, S); - rotate(v, R); -} - - -void NvBlastExtAssetTransformInPlace(NvBlastAsset* asset, const NvcVec3* scaling, const NvcQuat* rotation, const NvcVec3* translation) -{ - // Local copies of scaling (S), rotation (R), and translation (T) - NvcVec3 S = { 1, 1, 1 }; - NvcQuat R = { 0, 0, 0, 1 }; - NvcVec3 T = { 0, 0, 0 }; - NvcVec3 cofS = { 1, 1, 1 }; - float absDetS = 1; - float sgnDetS = 1; - - { - if (rotation) - { - R = *rotation; - } - - if (scaling) - { - S = *scaling; - cofS.x = S.y * S.z; - cofS.y = S.z * S.x; - cofS.z = S.x * S.y; - absDetS = S.x * S.y * S.z; - sgnDetS = absDetS < 0.0f ? -1.0f : 1.0f; - absDetS *= sgnDetS; - } - - if (translation) - { - T = *translation; - } - } - - // Chunk descs - const uint32_t assetChunkCount = NvBlastAssetGetChunkCount(asset, logLL); - NvBlastChunk* assetChunk = const_cast<NvBlastChunk*>(NvBlastAssetGetChunks(asset, logLL)); - for (uint32_t i = 0; i < assetChunkCount; ++i, ++assetChunk) - { - transform(reinterpret_cast<NvcVec3&>(assetChunk->centroid), S, R, T); - assetChunk->volume *= absDetS; // Use |detS| to keep the volume positive - } - - // Bond descs - const uint32_t assetBondCount = NvBlastAssetGetBondCount(asset, logLL); - NvBlastBond* assetBond = const_cast<NvBlastBond*>(NvBlastAssetGetBonds(asset, logLL)); - for (uint32_t i = 0; i < assetBondCount; ++i, ++assetBond) - { - transform(reinterpret_cast<NvcVec3&>(assetBond->centroid), S, R, T); - NvcVec3& normal = reinterpret_cast<NvcVec3&>(assetBond->normal); - transform(normal, cofS, R); - const float l = length(normal); - assetBond->area *= l; - multiply(normal, l > 0.f ? sgnDetS / l : 1.f); - } -} +// 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) 2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastExtAssetUtils.h"
+#include "NvBlast.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastMemory.h"
+#include "NvBlastGlobals.h"
+#include "math.h"
+
+using namespace Nv::Blast;
+
+
+/**
+Fill the chunk and bond descriptors from an asset.
+
+\param[out] chunkDescsWritten the number of chunk descriptors written to chunkDescs
+\param[out] bondDescsWritten the number of bond descriptors written to bondDescs
+\param[out] chunkDescs user-supplied buffer of NvBlastChunkDesc. Size must be at least NvBlastAssetGetChunkCount(asset, logFn)
+\param[out] bondDescs user-supplied buffer of NvBlastBondDesc. Size must be at least NvBlastAssetGetBondCount(asset, logFn)
+\param[in] asset asset from which to extract descriptors
+*/
+static void fillChunkAndBondDescriptorsFromAsset
+(
+ uint32_t& chunkDescsWritten,
+ uint32_t& bondDescsWritten,
+ NvBlastChunkDesc* chunkDescs,
+ NvBlastBondDesc* bondDescs,
+ const NvBlastAsset* asset
+)
+{
+ chunkDescsWritten = 0;
+ bondDescsWritten = 0;
+
+ // Chunk descs
+ const uint32_t assetChunkCount = NvBlastAssetGetChunkCount(asset, logLL);
+ const NvBlastChunk* assetChunk = NvBlastAssetGetChunks(asset, logLL);
+ for (uint32_t i = 0; i < assetChunkCount; ++i, ++assetChunk)
+ {
+ NvBlastChunkDesc& chunkDesc = chunkDescs[chunkDescsWritten++];
+ memcpy(chunkDesc.centroid, assetChunk->centroid, sizeof(float) * 3);
+ chunkDesc.volume = assetChunk->volume;
+ chunkDesc.parentChunkIndex = assetChunk->parentChunkIndex;
+ chunkDesc.flags = 0; // To be filled in below
+ chunkDesc.userData = assetChunk->userData;
+ }
+
+ // Bond descs
+ const uint32_t assetBondCount = NvBlastAssetGetBondCount(asset, logLL);
+ const NvBlastBond* assetBond = NvBlastAssetGetBonds(asset, logLL);
+ for (uint32_t i = 0; i < assetBondCount; ++i, ++assetBond)
+ {
+ NvBlastBondDesc& bondDesc = bondDescs[bondDescsWritten++];
+ memcpy(&bondDesc.bond, assetBond, sizeof(NvBlastBond));
+ }
+
+ // Walk the graph and restore connection descriptors
+ const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL);
+ for (uint32_t i = 0; i < graph.nodeCount; ++i)
+ {
+ const int32_t currentChunk = graph.chunkIndices[i];
+ if (isInvalidIndex(currentChunk))
+ {
+ continue;
+ }
+
+ chunkDescs[currentChunk].flags |= NvBlastChunkDesc::SupportFlag; // Filling in chunk flags here
+
+ for (uint32_t j = graph.adjacencyPartition[i]; j < graph.adjacencyPartition[i + 1]; ++j)
+ {
+ NvBlastBondDesc& bondDesc = bondDescs[graph.adjacentBondIndices[j]];
+ bondDesc.chunkIndices[0] = currentChunk;
+ const uint32_t adjacentChunkIndex = graph.chunkIndices[graph.adjacentNodeIndices[j]];
+ bondDesc.chunkIndices[1] = adjacentChunkIndex;
+ }
+ }
+}
+
+
+/**
+Scale a 3-vector v in-place.
+
+\param[in,out] v The vector to scale.
+\param[in] s The scale. Represents the diagonal elements of a diagonal matrix.
+
+The result will be v <- s*v.
+*/
+static inline void scale(NvcVec3& v, const NvcVec3& s)
+{
+ v.x *= s.x;
+ v.y *= s.y;
+ v.z *= s.z;
+}
+
+
+/**
+Rotate a 3-vector v in-place using a rotation represented by a quaternion q.
+
+\param[in,out] v The vector to rotate.
+\param[in] q The quaternion representation the rotation.
+
+The format of q is { x, y, z, w } where (x,y,z) is the vector part and w is the scalar part.
+The quaternion q MUST be normalized.
+*/
+static inline void rotate(NvcVec3& v, const NvcQuat& q)
+{
+ const float vx = 2.0f * v.x;
+ const float vy = 2.0f * v.y;
+ const float vz = 2.0f * v.z;
+ const float w2 = q.w * q.w - 0.5f;
+ const float dot2 = (q.x * vx + q.y * vy + q.z * vz);
+ v.x = vx * w2 + (q.y * vz - q.z * vy) * q.w + q.x * dot2;
+ v.y = vy * w2 + (q.z * vx - q.x * vz) * q.w + q.y * dot2;
+ v.z = vz * w2 + (q.x * vy - q.y * vx) * q.w + q.z * dot2;
+}
+
+
+/**
+Translate a 3-vector v in-place.
+
+\param[in,out] v The vector to translate.
+\param[in] t The translation.
+
+The result will be v <- v+t.
+*/
+static inline void translate(NvcVec3& v, const NvcVec3& t)
+{
+ v.x += t.x;
+ v.y += t.y;
+ v.z += t.z;
+}
+
+
+NvBlastAsset* NvBlastExtAssetUtilsAddWorldBonds
+(
+ const NvBlastAsset* asset,
+ const uint32_t* worldBoundChunks,
+ uint32_t worldBoundChunkCount,
+ const NvcVec3* bondDirections,
+ const uint32_t* bondUserData
+)
+{
+ const uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, logLL);
+ const uint32_t oldBondCount = NvBlastAssetGetBondCount(asset, logLL);
+ const uint32_t newBondCount = oldBondCount + worldBoundChunkCount;
+
+ NvBlastChunkDesc* chunkDescs = static_cast<NvBlastChunkDesc*>(NVBLAST_ALLOC(chunkCount * sizeof(NvBlastChunkDesc)));
+ NvBlastBondDesc* bondDescs = static_cast<NvBlastBondDesc*>(NVBLAST_ALLOC(newBondCount * sizeof(NvBlastBondDesc)));
+
+ // Create chunk descs
+ uint32_t chunkDescsWritten;
+ uint32_t bondDescsWritten;
+ fillChunkAndBondDescriptorsFromAsset(chunkDescsWritten, bondDescsWritten, chunkDescs, bondDescs, asset);
+
+ // Add world bonds
+ uint32_t bondCount = oldBondCount;
+ for (uint32_t i = 0; i < worldBoundChunkCount; i++)
+ {
+ NvBlastBondDesc& bondDesc = bondDescs[bondCount++];
+ const uint32_t chunkIndex = worldBoundChunks[i];
+ bondDesc.chunkIndices[0] = chunkIndex;
+ bondDesc.chunkIndices[1] = invalidIndex<uint32_t>();
+ memcpy(&bondDesc.bond.normal, bondDirections + i, sizeof(float) * 3);
+ bondDesc.bond.area = 1.0f; // Should be set by user
+ memcpy(&bondDesc.bond.centroid, chunkDescs[chunkIndex].centroid, sizeof(float) * 3);
+ bondDesc.bond.userData = bondUserData != nullptr ? bondUserData[i] : 0;
+ }
+
+ // Create new asset
+ NvBlastAssetDesc assetDesc;
+ assetDesc.chunkCount = chunkCount;
+ assetDesc.chunkDescs = chunkDescs;
+ assetDesc.bondCount = bondCount;
+ assetDesc.bondDescs = bondDescs;
+ void* scratch = NVBLAST_ALLOC(NvBlastGetRequiredScratchForCreateAsset(&assetDesc, logLL));
+ NvBlastAsset* newAsset = NvBlastCreateAsset(NVBLAST_ALLOC(NvBlastGetAssetMemorySize(&assetDesc, logLL)), &assetDesc, scratch, logLL);
+
+ // Free buffers
+ NVBLAST_FREE(scratch);
+ NVBLAST_FREE(bondDescs);
+ NVBLAST_FREE(chunkDescs);
+
+ return newAsset;
+}
+
+
+NvBlastAssetDesc NvBlastExtAssetUtilsMergeAssets
+(
+ const NvBlastAsset** components,
+ const NvcVec3* scales,
+ const NvcQuat* rotations,
+ const NvcVec3* translations,
+ uint32_t componentCount,
+ const NvBlastExtAssetUtilsBondDesc* newBondDescs,
+ uint32_t newBondCount,
+ uint32_t* chunkIndexOffsets,
+ uint32_t* chunkReorderMap,
+ uint32_t chunkReorderMapSize
+)
+{
+ // Count the total number of chunks and bonds in the new asset
+ uint32_t totalChunkCount = 0;
+ uint32_t totalBondCount = newBondCount;
+ for (uint32_t c = 0; c < componentCount; ++c)
+ {
+ totalChunkCount += NvBlastAssetGetChunkCount(components[c], logLL);
+ totalBondCount += NvBlastAssetGetBondCount(components[c], logLL);
+ }
+
+ // Allocate space for chunk and bond descriptors
+ NvBlastChunkDesc* chunkDescs = static_cast<NvBlastChunkDesc*>(NVBLAST_ALLOC(totalChunkCount * sizeof(NvBlastChunkDesc)));
+ NvBlastBondDesc* bondDescs = static_cast<NvBlastBondDesc*>(NVBLAST_ALLOC(totalBondCount * sizeof(NvBlastBondDesc)));
+
+ // Create a list of chunk index offsets per component
+ uint32_t* offsetStackAlloc = static_cast<uint32_t*>(NvBlastAlloca(componentCount * sizeof(uint32_t)));
+ if (chunkIndexOffsets == nullptr)
+ {
+ chunkIndexOffsets = offsetStackAlloc; // Use local stack alloc if no array is provided
+ }
+
+ // Fill the chunk and bond descriptors from the components
+ uint32_t chunkCount = 0;
+ uint32_t bondCount = 0;
+ for (uint32_t c = 0; c < componentCount; ++c)
+ {
+ chunkIndexOffsets[c] = chunkCount;
+ uint32_t componentChunkCount;
+ uint32_t componentBondCount;
+ fillChunkAndBondDescriptorsFromAsset(componentChunkCount, componentBondCount, chunkDescs + chunkCount, bondDescs + bondCount, components[c]);
+ // Fix chunks' parent indices
+ for (uint32_t i = 0; i < componentChunkCount; ++i)
+ {
+ if (!isInvalidIndex(chunkDescs[chunkCount + i].parentChunkIndex))
+ {
+ chunkDescs[chunkCount + i].parentChunkIndex += chunkCount;
+ }
+ }
+ // Fix bonds' chunk indices
+ for (uint32_t i = 0; i < componentBondCount; ++i)
+ {
+ NvBlastBondDesc& bondDesc = bondDescs[bondCount + i];
+ for (int j = 0; j < 2; ++j)
+ {
+ if (!isInvalidIndex(bondDesc.chunkIndices[j]))
+ {
+ bondDesc.chunkIndices[j] += chunkCount;
+ }
+ }
+ }
+ // Transform geometric data
+ if (scales != nullptr)
+ {
+ const NvcVec3& S = scales[c];
+ NvcVec3 cofS = { S.y * S.z, S.z * S.x, S.x * S.y };
+ float absDetS = S.x * S.y * S.z;
+ const float sgnDetS = absDetS < 0.0f ? -1.0f : 1.0f;
+ absDetS *= sgnDetS;
+ for (uint32_t i = 0; i < componentChunkCount; ++i)
+ {
+ scale(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), S);
+ chunkDescs[chunkCount + i].volume *= absDetS;
+ }
+ for (uint32_t i = 0; i < componentBondCount; ++i)
+ {
+ NvBlastBond& bond = bondDescs[bondCount + i].bond;
+ scale(reinterpret_cast<NvcVec3&>(bond.normal), cofS);
+ float renorm = sqrtf(bond.normal[0] * bond.normal[0] + bond.normal[1] * bond.normal[1] + bond.normal[2] * bond.normal[2]);
+ bond.area *= renorm;
+ if (renorm != 0)
+ {
+ renorm = sgnDetS / renorm;
+ bond.normal[0] *= renorm;
+ bond.normal[1] *= renorm;
+ bond.normal[2] *= renorm;
+ }
+ scale(reinterpret_cast<NvcVec3&>(bond.centroid), S);
+ }
+ }
+ if (rotations != nullptr)
+ {
+ for (uint32_t i = 0; i < componentChunkCount; ++i)
+ {
+ rotate(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), rotations[c]);
+ }
+ for (uint32_t i = 0; i < componentBondCount; ++i)
+ {
+ NvBlastBond& bond = bondDescs[bondCount + i].bond;
+ rotate(reinterpret_cast<NvcVec3&>(bond.normal), rotations[c]); // Normal can be transformed this way since we aren't scaling
+ rotate(reinterpret_cast<NvcVec3&>(bond.centroid), rotations[c]);
+ }
+ }
+ if (translations != nullptr)
+ {
+ for (uint32_t i = 0; i < componentChunkCount; ++i)
+ {
+ translate(reinterpret_cast<NvcVec3&>(chunkDescs[chunkCount + i].centroid), translations[c]);
+ }
+ for (uint32_t i = 0; i < componentBondCount; ++i)
+ {
+ translate(reinterpret_cast<NvcVec3&>(bondDescs[bondCount + i].bond.centroid), translations[c]);
+ }
+ }
+ chunkCount += componentChunkCount;
+ bondCount += componentBondCount;
+ }
+
+ // Fill the bond descriptors from the new bond descs
+ for (uint32_t b = 0; b < newBondCount; ++b)
+ {
+ const NvBlastExtAssetUtilsBondDesc& newBondDesc = newBondDescs[b];
+ NvBlastBondDesc& bondDesc = bondDescs[bondCount++];
+ memcpy(&bondDesc.bond, &newBondDesc.bond, sizeof(NvBlastBond));
+ bondDesc.chunkIndices[0] = !isInvalidIndex(newBondDesc.chunkIndices[0]) ? newBondDesc.chunkIndices[0] + chunkIndexOffsets[newBondDesc.componentIndices[0]] : invalidIndex<uint32_t>();
+ bondDesc.chunkIndices[1] = !isInvalidIndex(newBondDesc.chunkIndices[1]) ? newBondDesc.chunkIndices[1] + chunkIndexOffsets[newBondDesc.componentIndices[1]] : invalidIndex<uint32_t>();
+ }
+
+ // Create new asset desriptor
+ NvBlastAssetDesc assetDesc;
+ assetDesc.chunkCount = chunkCount;
+ assetDesc.chunkDescs = chunkDescs;
+ assetDesc.bondCount = bondCount;
+ assetDesc.bondDescs = bondDescs;
+
+ // Massage the descriptors so that they are valid for scratch creation
+ void* scratch = NVBLAST_ALLOC(chunkCount * sizeof(NvBlastChunkDesc)); // Enough for NvBlastEnsureAssetExactSupportCoverage and NvBlastReorderAssetDescChunks
+
+ NvBlastEnsureAssetExactSupportCoverage(chunkDescs, chunkCount, scratch, logLL);
+
+ if (chunkReorderMapSize < chunkCount)
+ {
+ if (chunkReorderMap != nullptr)
+ {
+ // Chunk reorder map is not large enough. Fill it with invalid indices and don't use it.
+ memset(chunkReorderMap, 0xFF, chunkReorderMapSize * sizeof(uint32_t));
+ NVBLAST_LOG_WARNING("NvBlastExtAssetUtilsMergeAssets: insufficient chunkReorderMap array passed in. NvBlastReorderAssetDescChunks will not be used.");
+ }
+ chunkReorderMap = nullptr; // Don't use
+ }
+
+ if (chunkReorderMap != nullptr)
+ {
+ NvBlastReorderAssetDescChunks(chunkDescs, chunkCount, bondDescs, bondCount, chunkReorderMap, true, scratch, logLL);
+ }
+
+ NVBLAST_FREE(scratch);
+
+ return assetDesc;
+}
+
+
+/**
+Multiply a 3-vector v in-place by value.
+
+\param[in,out] v The vector to multiply.
+\param[in] m The 3x3 matrix.
+*/
+static inline void multiply(NvcVec3& v, float value)
+{
+ v.x *= value;
+ v.y *= value;
+ v.z *= value;
+}
+
+
+/**
+Get Vec3 length
+*/
+static inline float length(const NvcVec3& p)
+{
+ return sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
+}
+
+
+/**
+Transform a point in-place: scale, rotate, then translate
+
+\param[in,out] p The point to transform.
+\param[in] S The diagonal elements of a diagonal scale matrix.
+\param[in] R A quaternion representing the rotation. Must be normalized.
+\param[in] T The translation vector.
+*/
+static inline void transform(NvcVec3& p, const NvcVec3& S, const NvcQuat& R, const NvcVec3& T)
+{
+ scale(p, S);
+ rotate(p, R);
+ translate(p, T);
+}
+
+
+/**
+Transform a vector in-place: scale, then rotate
+
+\param[in,out] v The vector to transform.
+\param[in] S The diagonal elements of a diagonal scale matrix.
+\param[in] R A quaternion representing the rotation. Must be normalized.
+*/
+static inline void transform(NvcVec3& v, const NvcVec3& S, const NvcQuat& R)
+{
+ scale(v, S);
+ rotate(v, R);
+}
+
+
+void NvBlastExtAssetTransformInPlace(NvBlastAsset* asset, const NvcVec3* scaling, const NvcQuat* rotation, const NvcVec3* translation)
+{
+ // Local copies of scaling (S), rotation (R), and translation (T)
+ NvcVec3 S = { 1, 1, 1 };
+ NvcQuat R = { 0, 0, 0, 1 };
+ NvcVec3 T = { 0, 0, 0 };
+ NvcVec3 cofS = { 1, 1, 1 };
+ float absDetS = 1;
+ float sgnDetS = 1;
+
+ {
+ if (rotation)
+ {
+ R = *rotation;
+ }
+
+ if (scaling)
+ {
+ S = *scaling;
+ cofS.x = S.y * S.z;
+ cofS.y = S.z * S.x;
+ cofS.z = S.x * S.y;
+ absDetS = S.x * S.y * S.z;
+ sgnDetS = absDetS < 0.0f ? -1.0f : 1.0f;
+ absDetS *= sgnDetS;
+ }
+
+ if (translation)
+ {
+ T = *translation;
+ }
+ }
+
+ // Chunk descs
+ const uint32_t assetChunkCount = NvBlastAssetGetChunkCount(asset, logLL);
+ NvBlastChunk* assetChunk = const_cast<NvBlastChunk*>(NvBlastAssetGetChunks(asset, logLL));
+ for (uint32_t i = 0; i < assetChunkCount; ++i, ++assetChunk)
+ {
+ transform(reinterpret_cast<NvcVec3&>(assetChunk->centroid), S, R, T);
+ assetChunk->volume *= absDetS; // Use |detS| to keep the volume positive
+ }
+
+ // Bond descs
+ const uint32_t assetBondCount = NvBlastAssetGetBondCount(asset, logLL);
+ NvBlastBond* assetBond = const_cast<NvBlastBond*>(NvBlastAssetGetBonds(asset, logLL));
+ for (uint32_t i = 0; i < assetBondCount; ++i, ++assetBond)
+ {
+ transform(reinterpret_cast<NvcVec3&>(assetBond->centroid), S, R, T);
+ NvcVec3& normal = reinterpret_cast<NvcVec3&>(assetBond->normal);
+ transform(normal, cofS, R);
+ const float l = length(normal);
+ assetBond->area *= l;
+ multiply(normal, l > 0.f ? sgnDetS / l : 1.f);
+ }
+}
|