diff options
| author | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
|---|---|---|
| committer | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
| commit | 236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch) | |
| tree | e486f2fa39dba203563895541e92c60ed3e25759 /sdk/extensions/assetutils/source/NvBlastExtAssetUtils.cpp | |
| parent | Added screens to welcome page (diff) | |
| download | blast-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.cpp | 416 |
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); + } +} |