aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp
diff options
context:
space:
mode:
authorAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
committerAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
commit236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch)
treee486f2fa39dba203563895541e92c60ed3e25759 /sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp
parentAdded screens to welcome page (diff)
downloadblast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz
blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp')
-rw-r--r--sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp416
1 files changed, 416 insertions, 0 deletions
diff --git a/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp b/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp
new file mode 100644
index 0000000..956764e
--- /dev/null
+++ b/sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp
@@ -0,0 +1,416 @@
+// 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) 2017 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 NvcQuat* rotations,
+ const NvcVec3* translations,
+ uint32_t componentCount,
+ const NvBlastExtAssetUtilsBondDesc* newBondDescs,
+ uint32_t newBondCount
+)
+{
+ // 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* chunkIndexOffsets = static_cast<uint32_t*>(NvBlastAlloca(componentCount * sizeof(uint32_t)));
+
+ // 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 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 (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;
+
+ 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 ? -1 : 1;
+ 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);
+ }
+}