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 | |
| 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')
167 files changed, 17506 insertions, 6872 deletions
diff --git a/sdk/extensions/assetutils/include/NvBlastExtAssetUtils.h b/sdk/extensions/assetutils/include/NvBlastExtAssetUtils.h new file mode 100644 index 0000000..3d5b3b9 --- /dev/null +++ b/sdk/extensions/assetutils/include/NvBlastExtAssetUtils.h @@ -0,0 +1,125 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTASSETUTILS_H +#define NVBLASTEXTASSETUTILS_H + + +#include "NvBlastTypes.h" +#include "NvCTypes.h" +#include <stdint.h> + + +/** +Reauthor the provided asset to bond the specified support chunks to the world. + +\param[in] asset Pointer to the original asset. Won't be modified. +\param[in] worldBoundChunks Array of support chunk indices which are to be bound to the world. +\param[in] worldBoundChunksCount Size of worldBoundChunks array. +\param[in] bondDirections Array of normals for each bond (size worldBoundChunksCount) +\param[in] bondUserData Array of user data values for the new bonds, of size worldBoundChunksCount. May be NULL. If NULL, bond user data will be set to zero. + +\return a new asset with added bonds if successful, NULL otherwise. +*/ +NVBLAST_API NvBlastAsset* NvBlastExtAssetUtilsAddWorldBonds +( + const NvBlastAsset* asset, + const uint32_t* worldBoundChunks, + uint32_t worldBoundChunkCount, + const NvcVec3* bondDirections, + const uint32_t* bondUserData +); + + +/** +Bond descriptor used to merge assets. + +In addition to the NvBlastBondDesc fields, adds "component" indices to indicate +to which component asset the chunk indices in NvBlastBondDesc refer. Used in the +function NvBlastExtAssetUtilsMergeAssets. +*/ +struct NvBlastExtAssetUtilsBondDesc : public NvBlastBondDesc +{ + uint32_t componentIndices[2]; //!< The asset component for the corresponding chunkIndices[2] value. +}; + + +/** +Creates an asset descriptor which will build an asset that merges several assets. Each asset (or component) +is given a transform, applied to the geometric information in the chunk and bond descriptors. + +New bond descriptors may be given to bond support chunks from different components. + +An NvBlastAsset may appear more than once in the components array. + +NOTE: This function allocates memory using the allocator in NvBlastGlobals, to create the new chunk and bond +descriptor arrays referenced in the returned NvBlastAssetDesc. The user must free this memory after use with +NVBLAST_FREE appied to the pointers in the returned NvBlastAssetDesc. + +\param[in] components An array of assets to merge, of size componentCount. +\param[in] rotations An array of rotations to apply to the geometric data in the chunks and bonds, + stored quaternion format. The quaternions MUST be normalized. If NULL, no rotations are applied. + If not NULL, the array must be of size componentCount. +\param[in] translations An array of transforms to apply to the geometric data in the chunks and bonds. + If NULL, no translations are applied. If not NULL, the array must be of size componentCount. +\param[in] componentCount The size of the components and relativeTransforms arrays. +\param[in] newBondDescs Descriptors of type NvBlastExtAssetUtilsBondDesc for new bonds between components, of size newBondCount. If NULL, newBondCount must be 0. +\param[in] newBondCount The size of the newBondDescs array. + +\return an asset descriptor that will build an asset which merges the components, using NvBlastCreateAsset. +*/ +NVBLAST_API NvBlastAssetDesc NvBlastExtAssetUtilsMergeAssets +( + const NvBlastAsset** components, + const NvcQuat* rotations, + const NvcVec3* translations, + uint32_t componentCount, + const NvBlastExtAssetUtilsBondDesc* newBondDescs, + uint32_t newBondCount +); + + +/** +Transforms asset in place using scale, rotation, transform. +Chunk centroids, chunk bond centroids and bond normals are being transformed. +Chunk volume and bond area are changed accordingly. + +\param[in, out] asset Pointer to the asset to be transformed (modified). +\param[in] scale Pointer to scale to be applied. Can be nullptr. +\param[in] rotation Pointer to rotation to be applied. Can be nullptr. +\param[in] translation Pointer to translation to be applied. Can be nullptr. +*/ +NVBLAST_API void NvBlastExtAssetTransformInPlace +( + NvBlastAsset* asset, + const NvcVec3* scale, + const NvcQuat* rotation, + const NvcVec3* translation +); + +#endif // ifndef NVBLASTEXTASSETUTILS_H 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); + } +} diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoring.h b/sdk/extensions/authoring/include/NvBlastExtAuthoring.h new file mode 100644 index 0000000..ce21c65 --- /dev/null +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoring.h @@ -0,0 +1,119 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTAUTHORING_H +#define NVBLASTAUTHORING_H + +#include "NvBlastExtAuthoringTypes.h" + +namespace physx +{ + class PxCooking; + class PxPhysicsInsertionCallback; +} + +namespace Nv +{ + namespace Blast + { + class Mesh; + class VoronoiSitesGenerator; + class FractureTool; + class ConvexMeshBuilder; + class BlastBondGenerator; + class MeshCleaner; + } +} + +/** +Constructs mesh object from array of triangles. +User should call release() after usage. + +\param[in] positions Array for vertex positions, 3 * verticesCount floats will be read +\param[in] normals Array for vertex normals, 3 * verticesCount floats will be read +\param[in] uv Array for vertex uv coordinates, 2 * verticesCount floats will be read +\param[in] verticesCount Number of vertices in mesh +\param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle. +\param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3) + +\return pointer to Nv::Blast::Mesh if it was created succefully otherwise return nullptr +*/ +NVBLAST_API Nv::Blast::Mesh* NvBlastExtAuthoringCreateMesh(const physx::PxVec3* positions, const physx::PxVec3* normals, + const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount); + +/** +Voronoi sites should not be generated outside of the fractured mesh, so VoronoiSitesGenerator +should be supplied with fracture mesh. +\param[in] mesh Fracture mesh +\param[in] rnd User supplied random value generator. +\return Pointer to VoronoiSitesGenerator. User's code should release it after usage. +*/ +NVBLAST_API Nv::Blast::VoronoiSitesGenerator* NvBlastExtAuthoringCreateVoronoiSitesGenerator(Nv::Blast::Mesh* mesh, + Nv::Blast::RandomGeneratorBase* rng); + +/** +Create FractureTool object. +\return Pointer to create FractureTool. User's code should release it after usage. +*/ +NVBLAST_API Nv::Blast::FractureTool* NvBlastExtAuthoringCreateFractureTool(); + +/** +Create BlastBondGenerator +\return Pointer to created BlastBondGenerator. User's code should release it after usage. +*/ +NVBLAST_API Nv::Blast::BlastBondGenerator* NvBlastExtAuthoringCreateBondGenerator(physx::PxCooking* cooking, + physx::PxPhysicsInsertionCallback* insertionCallback); + +/** +Create ConvexMeshBuilder +\return Pointer to created ConvexMeshBuilder. User's code should release it after usage. +*/ +NVBLAST_API Nv::Blast::ConvexMeshBuilder* NvBlastExtAuthoringCreateConvexMeshBuilder(physx::PxCooking* cooking, + physx::PxPhysicsInsertionCallback* insertionCallback); + +/** +Performs pending fractures and generates fractured asset, render and collision geometry + +\param[in] fTool Fracture tool created by NvBlastExtAuthoringCreateFractureTool +\param[in] bondGenerator Bond generator created by NvBlastExtAuthoringCreateBondGenerator +\param[in] collisionBuilder Collision builder created by NvBlastExtAuthoringCreateConvexMeshBuilder +\param[in] defaultSupportDepth All new chunks will be marked as support if its depth equal to defaultSupportDepth. + By default leaves (chunks without children) marked as support. +\return Authoring result +*/ +NVBLAST_API Nv::Blast::AuthoringResult* NvBlastExtAuthoringProcessFracture(Nv::Blast::FractureTool& fTool, + Nv::Blast::BlastBondGenerator& bondGenerator, Nv::Blast::ConvexMeshBuilder& collisionBuilder, int32_t defaultSupportDepth = -1); + + +/** + Creates MeshCleaner object + \return pointer to Nv::Blast::Mesh if it was created succefully otherwise return nullptr +*/ +NVBLAST_API Nv::Blast::MeshCleaner* NvBlastExtAuthoringCreateMeshCleaner(); + +#endif // ifndef NVBLASTAUTHORING_H diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h index 68767eb..4f5d0e6 100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h @@ -1,35 +1,54 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #ifndef NVBLASTEXTAUTHORINGBONDGENERATOR_H #define NVBLASTEXTAUTHORINGBONDGENERATOR_H #include "NvBlastExtAuthoringTypes.h" -#include "NvBlastExtAuthoringFractureTool.h" -#include "NvBlastTypes.h" -#include "../cooking/PxCooking.h" -#include <PxPlane.h> -#include <NvBlastExtAuthoringCollisionBuilder.h> + +namespace physx +{ +class PxPlane; +class PxCooking; +class PxPhysicsInsertionCallback; +} + struct NvBlastBondDesc; struct NvBlastChunkDesc; struct NvBlastBond; -using namespace physx; - - namespace Nv { namespace Blast { // Forward declarations +class FractureTool; class TriangleProcessor; struct PlaneChunkIndexer; @@ -61,73 +80,75 @@ struct PlaneChunkIndexer class BlastBondGenerator { public: - - BlastBondGenerator(physx::PxCooking* cooking, physx::PxPhysicsInsertionCallback* insertionCallback) : mPxCooking(cooking), mPxInsertionCallback(insertionCallback){}; + virtual ~BlastBondGenerator() {} + + /** + Release BlastBondGenerator memory + */ + virtual void release() = 0; /** This method based on marking triangles during fracture process, so can be used only with internally fractured meshes. - \param[in] tool FractureTool which contains chunks representation, tool->finalizeFracturing() should be called before. - \param[in] chunkIsSupport Array of flags, if true - chunk is support. Array size should be equal to chunk count in tool. - \param[out] resultBondDescs Array of created bond descriptors. - \param[out] resultChunkDescriptors Array of created chunk descriptors. - \return 0 if success + \note User should call NVBLAST_FREE for resultBondDescs when it not needed anymore + \param[in] tool FractureTool which contains chunks representation, tool->finalizeFracturing() should be called before. + \param[in] chunkIsSupport Pointer to array of flags, if true - chunk is support. Array size should be equal to chunk count in tool. + \param[out] resultBondDescs Pointer to array of created bond descriptors. + \param[out] resultChunkDescriptors Pointer to array of created chunk descriptors. + \return Number of created bonds */ - int32_t buildDescFromInternalFracture(FractureTool* tool, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& resultBondDescs, std::vector<NvBlastChunkDesc>& resultChunkDescriptors); + virtual int32_t buildDescFromInternalFracture(FractureTool* tool, const bool* chunkIsSupport, + NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors) = 0; /** Creates bond description between two meshes - \param[in] meshA Array of triangles of mesh A. - \param[in] meshB Array of triangles of mesh B. - \param[out] resultBond Result bond description. - \param[in] conf Bond creation mode. - \return 0 if success + \param[in] meshACount Number of triangles in mesh A + \param[in] meshA Pointer to array of triangles of mesh A. + \param[in] meshBCount Number of triangles in mesh B + \param[in] meshB Pointer to array of triangles of mesh B. + \param[out] resultBond Result bond description. + \param[in] conf Bond creation mode. + \return 0 if success */ - int32_t createBondBetweenMeshes(const std::vector<Triangle>& meshA, const std::vector<Triangle>& meshB, NvBlastBond& resultBond, BondGenerationConfig conf = BondGenerationConfig()); + virtual int32_t createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB, + NvBlastBond& resultBond, BondGenerationConfig conf = BondGenerationConfig()) = 0; /** Creates bond description between number of meshes - \param[in] geometry Array of arrays of triangles for each chunk. - \param[out] resultBond Array of result bonds. - \param[in] overlaps Array of pairs - indexes of chunks, for which bond should be created. - \param[in] cfg Bond creation mode. - \return 0 if success + \note User should call NVBLAST_FREE for resultBondDescs when it not needed anymore + \param[in] meshCount Number of meshes + \param[in] geometryOffset Pointer to array of triangle offsets for each mesh. + Containts meshCount + 1 element, last one is total number of triangles in geometry + \param[in] geometry Pointer to array of triangles. + Triangles from geometryOffset[i] to geometryOffset[i+1] correspond to i-th mesh. + \param[in] overlapsCount Number of overlaps + \param[in] overlaps Pointer to array of pairs - indexes of chunks, for which bond should be created. + \param[out] resultBond Pointer to array of result bonds. + \param[in] cfg Bond creation mode. + \return Number of created bonds */ - int32_t createBondBetweenMeshes(const std::vector<std::vector<Triangle> >& geometry, std::vector<NvBlastBondDesc>& resultBond, const std::vector<std::pair<uint32_t, uint32_t> >& overlaps, BondGenerationConfig cfg); + virtual int32_t createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + uint32_t overlapsCount, const uint32_t* overlapsA, const uint32_t* overlapsB, + NvBlastBondDesc*& resultBond, BondGenerationConfig cfg) = 0; /** Creates bond description for prefractured meshes, when there is no info about which chunks should be connected with bond. - \param[in] geometry Array of arrays of triangles for each chunk. - \param[in] chunkIsSupport Array of flags, if true - chunk is support. Array size should be equal to chunk count in tool. - \param[out] resultBondDescs Array of result bonds. - \param[in] conf Bond creation mode. - \return 0 if success + \note User should call NVBLAST_FREE for resultBondDescs when it not needed anymore + \param[in] meshCount Number of meshes + \param[in] geometryOffset Pointer to array of triangle offsets for each mesh. + Containts meshCount + 1 element, last one is total number of triangles in geometry + \param[in] geometry Pointer to array of triangles. + Triangles from geometryOffset[i] to geometryOffset[i+1] correspond to i-th mesh. + \param[in] chunkIsSupport Pointer to array of flags, if true - chunk is support. Array size should be equal to chunk count in tool. + \param[out] resultBondDescs Pointer to array of result bonds. + \param[in] conf Bond creation mode. + \return Number of created bonds */ - int32_t bondsFromPrefractured(const std::vector<std::vector<Triangle>>& geometry, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& resultBondDescs, BondGenerationConfig conf = BondGenerationConfig()); + virtual int32_t bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool*& chunkIsSupport, NvBlastBondDesc*& resultBondDescs, + BondGenerationConfig conf = BondGenerationConfig()) = 0; -private: - float processWithMidplanes(TriangleProcessor* trProcessor, const std::vector<physx::PxVec3>& chunk1Points, const std::vector<physx::PxVec3>& chunk2Points, - const std::vector<physx::PxVec3>& hull1p,const std::vector<physx::PxVec3>& hull2p, physx::PxVec3& normal, physx::PxVec3& centroid); - - int32_t createFullBondListAveraged(const std::vector<std::vector<Triangle>>& chunksGeometry, const std::vector<bool>& supportFlags, std::vector<NvBlastBondDesc>& mResultBondDescs, BondGenerationConfig conf); - int32_t createFullBondListExact(const std::vector<std::vector<Triangle>>& chunksGeometry, const std::vector<bool>& supportFlags, std::vector<NvBlastBondDesc>& mResultBondDescs, BondGenerationConfig conf); - int32_t createFullBondListExactInternal(const std::vector<std::vector<Triangle>>& chunksGeometry, std::vector < PlaneChunkIndexer >& planeTriangleMapping , std::vector<NvBlastBondDesc>& mResultBondDescs); - int32_t createBondForcedInternal(const std::vector<PxVec3>& hull0, const std::vector<PxVec3>& hull1,const CollisionHull& cHull0, const CollisionHull& cHull1,PxBounds3 bound0, PxBounds3 bound1, NvBlastBond& resultBond, float overlapping); - - void buildGeometryCache(const std::vector<std::vector<Triangle> >& geometry); - void resetGeometryCache(); - - physx::PxCooking* mPxCooking; - physx::PxPhysicsInsertionCallback* mPxInsertionCallback; - - - std::vector<std::vector<Triangle> > mGeometryCache; - - std::vector<PlaneChunkIndexer> mPlaneCache; - std::vector<CollisionHull> mCHullCache; - std::vector<std::vector<physx::PxVec3> > mHullsPointsCache; - std::vector<physx::PxBounds3 > mBoundsCache; }; } // namespace Blast diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h index b3e143a..1e851bb 100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h @@ -1,26 +1,42 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAUTHORINGCOLLISIONBUILDER_H #define NVBLASTEXTAUTHORINGCOLLISIONBUILDER_H #include "NvBlastTypes.h" -#include <vector> -#include <PxVec3.h> namespace physx { - class PxCooking; - class PxPhysicsInsertionCallback; - class PxVec3; - class PxConvexMesh; +class PxCooking; +class PxPhysicsInsertionCallback; +class PxVec3; +class PxConvexMesh; } @@ -29,32 +45,7 @@ namespace Nv namespace Blast { -/** - Collision hull geometry format. -*/ -struct CollisionHull -{ - /** - Collision hull polygon format. - */ - struct HullPolygon - { - // Polygon base plane - float mPlane[4]; - // Number vertices in polygon - uint16_t mNbVerts; - // First index in CollisionHull.indices array for this polygon - uint16_t mIndexBase; - }; - ///** - - CollisionHull(){}; - - std::vector<physx::PxVec3> points; - std::vector<uint32_t> indices; - std::vector<HullPolygon> polygonData; -}; - +struct CollisionHull; /** ConvexMeshBuilder provides routine to build collision hulls from array of vertices. @@ -64,35 +55,38 @@ struct CollisionHull class ConvexMeshBuilder { public: + virtual ~ConvexMeshBuilder() {} /** - Constructor should be provided with PxCoocking and PxPhysicsInsertionCallback objects. + Release ConvexMeshBuilder memory */ - ConvexMeshBuilder(physx::PxCooking* cooking, physx::PxPhysicsInsertionCallback* insertionCallback) : mInsertionCallback(insertionCallback), mCooking(cooking) {} + virtual void release() = 0; /** Method creates CollisionHull from provided array of vertices. + \param[in] verticesCount Number of vertices \param[in] vertexData Vertex array of some object, for which collision geometry should be built \param[out] output Reference on CollisionHull object in which generated geometry should be saved */ - void buildCollisionGeometry(const std::vector<physx::PxVec3>& vertexData, CollisionHull& output); + virtual CollisionHull* buildCollisionGeometry(uint32_t verticesCount, const physx::PxVec3* vertexData) = 0; /** Method creates PxConvexMesh from provided array of vertices. - \param[in] vertexData Vertex array of some object, for which collision geometry should be built + \param[in] verticesCount Number of vertices + \param[in] vertexData Vertex array of some object, for which collision geometry should be built \return pointer to the PxConvexMesh object if it was built successfully, 'nullptr' otherwise. */ - physx::PxConvexMesh* buildConvexMesh(std::vector<physx::PxVec3>& vertexData); + virtual physx::PxConvexMesh* buildConvexMesh(uint32_t verticesCount, const physx::PxVec3* vertexData) = 0; /** Method creates PxConvexMesh from provided ConvexHull geometry - \param[in] hull ConvexHull geometry + \param[in] hull ConvexHull geometry \return pointer to the PxConvexMesh object if it was built successfully, 'nullptr' otherwise. */ - physx::PxConvexMesh* buildConvexMesh(CollisionHull& hull); + virtual physx::PxConvexMesh* buildConvexMesh(const CollisionHull& hull) = 0; /** @@ -102,18 +96,13 @@ public: This method trims all intersecting parts of collision geometry. As a drawback, trimming collision geometry can lead to penetrating render meshes during simulation. - - \param[in] in ConvexHull geometry which should be clipped. - \param[in] chunkDepth Array of depth levels of convex hulls corresponding chunks. + \param[in] chunksCount Number of chunks + \param[in,out] in ConvexHull geometry which should be clipped. + \param[in] chunkDepth Array of depth levels of convex hulls corresponding chunks. */ - - void trimCollisionGeometry(std::vector<CollisionHull>& in, const std::vector<uint32_t>& chunkDepth); - + virtual void trimCollisionGeometry(uint32_t chunksCount, CollisionHull** in, const uint32_t* chunkDepth) = 0; -private: - physx::PxPhysicsInsertionCallback* mInsertionCallback; - physx::PxCooking* mCooking; }; } // namespace Blast diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h index 528ffbc..82959ac 100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h @@ -1,19 +1,35 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTAUTHORINGFRACTURETOOL_H #define NVBLASTAUTHORINGFRACTURETOOL_H -#include "NvBlastExtAuthoringMesh.h" -#include "NvBlastTypes.h" - +#include "NvBlastExtAuthoringTypes.h" namespace Nv { @@ -21,8 +37,8 @@ namespace Blast { class SpatialAccelerator; -class ChunkPostProcessor; - +class Triangulator; +class Mesh; /* Chunk data, chunk with chunkId == 0 is always source mesh. @@ -38,119 +54,83 @@ struct ChunkInfo /* Slicing fracturing configuration - - - default: - x_slices = 1; - y_slices = 1; - z_slices = 1; - - offset_variations = 0.f; - angle_variations = 0.f; - noiseAmplitude = 0.f; - noiseFrequency = 1.f; - noiseOctaveNumber = 1; - surfaceResolution = 1; */ struct SlicingConfiguration { /** Number of slices in each direction */ - int32_t x_slices, y_slices, z_slices; + int32_t x_slices = 1, y_slices = 1, z_slices = 1; /** Offset variation, value in [0, 1] */ - float offset_variations; + float offset_variations = 0.f; + /** Angle variation, value in [0, 1] */ - float angle_variations; - + float angle_variations = 0.f; /** Noisy slicing configutaion: Amplitude of cutting surface noise. If it is 0 - noise is disabled. */ - float noiseAmplitude; + float noiseAmplitude = 0.f; + /** Frequencey of cutting surface noise. */ - float noiseFrequency; + float noiseFrequency = 1.f; + /** Octave number in slicing surface noise. */ - uint32_t noiseOctaveNumber; - /** - Cutting surface resolution. - */ - int32_t surfaceResolution; - + uint32_t noiseOctaveNumber = 1; - SlicingConfiguration() - { - reset(); - } /** - Set default params. + Cutting surface resolution. */ - void reset() - { - x_slices = 1; - y_slices = 1; - z_slices = 1; - - offset_variations = 0.f; - angle_variations = 0.f; - noiseAmplitude = 0.f; - noiseFrequency = 1.f; - noiseOctaveNumber = 1; - surfaceResolution = 1; - } - + int32_t surfaceResolution = 1; }; - /** Class for voronoi sites generation inside supplied mesh. */ class VoronoiSitesGenerator { public: - - /** - Voronoi sites should not be generated outside of the fractured mesh, so VoronoiSitesGenerator - should be supplied with fracture mesh. - \param[in] mesh Fracture mesh - \param[in] rnd User supplied random value generator. - \return + virtual ~VoronoiSitesGenerator() {} + + /** + Release VoronoiSitesGenerator memory */ - VoronoiSitesGenerator(Mesh* mesh, RandomGeneratorBase* rnd); - ~VoronoiSitesGenerator(); + virtual void release() = 0; /** Set base fracture mesh */ - void setBaseMesh(Mesh* m); + virtual void setBaseMesh(const Mesh* mesh) = 0; /** - Returns reference on vector of generated voronoi sites. + Access to generated voronoi sites. + \param[out] Pointer to generated voronoi sites + \return Count of generated voronoi sites. */ - std::vector<physx::PxVec3>& getVoronoiSites(); + virtual uint32_t getVoronoiSites(const physx::PxVec3*& sites) = 0; /** Add site in particular point \param[in] site Site coordinates */ - void addSite(const physx::PxVec3& site); + virtual void addSite(const physx::PxVec3& site) = 0; /** Uniformly generate sites inside the mesh \param[in] numberOfSites Number of generated sites */ - void uniformlyGenerateSitesInMesh(const uint32_t numberOfSites); + virtual void uniformlyGenerateSitesInMesh(uint32_t numberOfSites) = 0; /** Generate sites in clustered fashion @@ -158,7 +138,7 @@ public: \param[in] sitesPerCluster Number of sites in each cluster \param[in] clusterRadius Voronoi cells cluster radius */ - void clusteredSitesGeneration(const uint32_t numberOfClusters, const uint32_t sitesPerCluster, float clusterRadius); + virtual void clusteredSitesGeneration(uint32_t numberOfClusters, uint32_t sitesPerCluster, float clusterRadius) = 0; /** Radial pattern of sites generation @@ -170,7 +150,7 @@ public: \param[in] angleOffset Angle offset at each radial step \param[in] variability Randomness of sites distribution */ - void radialPattern(const physx::PxVec3& center, const physx::PxVec3& normal, float radius, int32_t angularSteps, int32_t radialSteps, float angleOffset = 0.0f, float variability = 0.0f); + virtual void radialPattern(const physx::PxVec3& center, const physx::PxVec3& normal, float radius, int32_t angularSteps, int32_t radialSteps, float angleOffset = 0.0f, float variability = 0.0f) = 0; /** Generate sites inside sphere @@ -178,16 +158,16 @@ public: \param[in] radius Radius of sphere \param[in] center Center of sphere */ - void generateInSphere(const uint32_t count, const float radius, const physx::PxVec3& center); + virtual void generateInSphere(const uint32_t count, const float radius, const physx::PxVec3& center) = 0; /** Set stencil mesh. With stencil mesh sites are generated only inside both of fracture and stencil meshes. \param[in] stencil Stencil mesh. */ - void setStencil(Mesh* stencil); + virtual void setStencil(const Mesh* stencil) = 0; /** Removes stencil mesh */ - void clearStencil(); + virtual void clearStencil() = 0; /** Deletes sites inside supplied sphere @@ -195,18 +175,9 @@ public: \param[in] center Center of sphere \param[in] eraserProbability Probability of removing some particular site */ - void deleteInSphere(const float radius, const physx::PxVec3& center, const float eraserProbability = 1); - -private: - std::vector<physx::PxVec3> mGeneratedSites; - Mesh* mMesh; - Mesh* mStencil; - RandomGeneratorBase* mRnd; - SpatialAccelerator* mAccelerator; + virtual void deleteInSphere(const float radius, const physx::PxVec3& center, const float eraserProbability = 1) = 0; }; - - /** FractureTool class provides methods to fracture provided mesh and generate Blast asset data */ @@ -214,44 +185,34 @@ class FractureTool { public: + virtual ~FractureTool() {} /** - FractureTool can log asset creation info if logCallback is provided. + Release FractureTool memory */ - FractureTool(NvBlastLog logCallback = nullptr) - { - mPlaneIndexerOffset = 1; - mChunkIdCounter = 0; - mRemoveIslands = false; - mLoggingCallback = logCallback; - } - - ~FractureTool() - { - reset(); - } + virtual void release() = 0; /** Reset FractureTool state. */ - void reset(); + virtual void reset() = 0; /** Set input mesh wich will be fractured, FractureTool will be reseted. */ - void setSourceMesh(Mesh* mesh); + virtual void setSourceMesh(const Mesh* mesh) = 0; /** - Get chunk mesh in polygonal representation + Get chunk mesh in polygonal representation. User's code should release it after usage. */ - Mesh getChunkMesh(int32_t chunkId); + virtual Mesh* createChunkMesh(int32_t chunkId) = 0; /** Input mesh is scaled and transformed internally to fit unit cube centered in origin. Method provides offset vector and scale parameter; */ - void getTransformation(physx::PxVec3& offset, float& scale); + virtual void getTransformation(physx::PxVec3& offset, float& scale) = 0; /** @@ -262,7 +223,7 @@ public: Case replaceChunk == true && chunkId == 0 considered as wrong input parameters \return If 0, fracturing is successful. */ - int32_t voronoiFracturing(uint32_t chunkId, const std::vector<physx::PxVec3>& cellPoints, bool replaceChunk); + virtual int32_t voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPoints, bool replaceChunk) = 0; /** Fractures specified chunk with voronoi method. Cells can be scaled along x,y,z axes. @@ -274,7 +235,7 @@ public: Case replaceChunk == true && chunkId == 0 considered as wrong input parameters \return If 0, fracturing is successful. */ - int32_t voronoiFracturing(uint32_t chunkId, const std::vector<physx::PxVec3>& cellPoints, const physx::PxVec3& scale, bool replaceChunk); + virtual int32_t voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPoints, const physx::PxVec3& scale, bool replaceChunk) = 0; /** @@ -287,37 +248,20 @@ public: \return If 0, fracturing is successful. */ - int32_t slicing(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd); + virtual int32_t slicing(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) = 0; /** Creates resulting fractured mesh geometry from intermediate format */ - void finalizeFracturing(); + virtual void finalizeFracturing() = 0; - /** - Get chunk information - */ - const std::vector<ChunkInfo>& getChunkList(); - + virtual uint32_t getChunkCount() const = 0; /** - Tesselate interior surfaces - \param[in] averageEdgeLength - Average length of edge on internal surface. - */ - void tesselate(float averageEdgeLength); - - /** - Apply noise to interior surfaces. Must be called only after tesselation! - \param[in] amplitude Amplitude of noise - \param[in] frequency Frequency of noise - \param[in] octaves Number of noise octaves - \param[in] falloff - damping of noise around of external surface - \param[in] relaxIterations - number of smoothing iterations before applying noise - \param[in] relaxFactor - amount of smoothing before applying noise. - \param[in] seed Random seed value + Get chunk information */ - void applyNoise(float amplitude, float frequency, int32_t octaves, float falloff, int32_t relaxIterations, float relaxFactor, int32_t seed = 0); + virtual const ChunkInfo& getChunkInfo(int32_t chunkIndex) = 0; /** Get percentage of mesh overlap. @@ -326,110 +270,78 @@ public: \param[in] meshB Mesh B \return mesh overlap percentage */ - static float getMeshOverlap(Mesh& meshA, Mesh& meshB); + virtual float getMeshOverlap(const Mesh& meshA, const Mesh& meshB) = 0; /** Get chunk base mesh \param[in] chunkIndex Chunk index \param[out] output Array of triangles to be filled + \return number of triangles in base mesh */ - void getBaseMesh(int32_t chunkIndex, std::vector<Triangle>& output); - - /** - Get chunk mesh with noise - \param[in] chunkIndex Chunk index - \param[out] output Array of triangles to be filled - */ - void getNoisedMesh(int32_t chunkIndex, std::vector<Triangle>& output); - + virtual uint32_t getBaseMesh(int32_t chunkIndex, Triangle*& output) = 0; /** Return index of chunk with specified chunkId \param[in] chunkId Chunk ID \return Chunk index in internal buffer, if not exist -1 is returned. */ - int32_t getChunkIndex(int32_t chunkId); + virtual int32_t getChunkIndex(int32_t chunkId) = 0; /** Return id of chunk with specified index. \param[in] chunkIndex Chunk index \return Chunk id or -1 if there is no such chunk. */ - int32_t getChunkId(int32_t chunkIndex); + virtual int32_t getChunkId(int32_t chunkIndex) = 0; /** Return depth level of the given chunk \param[in] chunkId Chunk ID \return Chunk depth or -1 if there is no such chunk. */ - int32_t getChunkDepth(int32_t chunkId); + virtual int32_t getChunkDepth(int32_t chunkId) = 0; /** Return array of chunks IDs with given depth. - \param[in] depth Chunk depth - \return Array of chunk IDs + \param[in] depth Chunk depth + \param[out] Pointer to array of chunk IDs + \return Number of chunks in array */ - std::vector<int32_t> getChunksIdAtDepth(uint32_t depth); + virtual uint32_t getChunksIdAtDepth(uint32_t depth, int32_t*& chunkIds) = 0; /** Get result geometry without noise as vertex and index buffers, where index buffers contain series of triplets which represent triangles. \param[out] vertexBuffer Array of vertices to be filled - \param[out] indexBuffer Array of arrays of indices to be filled + \param[out] indexBuffer Array of indices to be filled + \param[out] indexBufferOffsets Array of offsets in indexBuffer for each base mesh. + Contains getChunkCount() + 1 elements. Last one is indexBuffer size + \return Number of vertices in vertexBuffer */ - void getBufferedBaseMeshes(std::vector<Vertex>& vertexBuffer, std::vector<std::vector<uint32_t> >& indexBuffer); - - /** - Get result geometry after tesselation and application of noise as vertex and index buffers, where index buffers contain series of triplets - which represent triangles. - \param[out] vertexBuffer Array of vertices to be filled - \param[out] indexBuffer Array of arrays of indices to be filled - */ - void getBufferedNoiseMeshes(std::vector<Vertex>& vertexBuffer, std::vector<std::vector<uint32_t> >& indexBuffer); + virtual uint32_t getBufferedBaseMeshes(Vertex*& vertexBuffer, uint32_t*& indexBuffer, uint32_t*& indexBufferOffsets) = 0; /** Set automatic islands removing. May cause instabilities. \param[in] isRemoveIslands Flag whether remove or not islands. */ - void setRemoveIslands(bool isRemoveIslands); + virtual void setRemoveIslands(bool isRemoveIslands) = 0; /** Try find islands and remove them on some specifical chunk. If chunk has childs, island removing can lead to wrong results! Apply it before further chunk splitting. \param[in] chunkId Chunk ID which should be checked for islands \return Number of found islands is returned */ - int32_t islandDetectionAndRemoving(int32_t chunkId); - -private: - void eraseChunk(int32_t chunkId); - bool isAncestorForChunk(int32_t ancestorId, int32_t chunkId); - void deleteAllChildsOfChunk(int32_t chunkId); - int32_t slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd); + virtual int32_t islandDetectionAndRemoving(int32_t chunkId) = 0; -protected: /** - Mesh scaled to unite-cube and translated to the origin + Check if input mesh contains open edges. Open edges can lead to wrong fracturing results. + \return true if mesh contains open edges */ - float mScaleFactor; - physx::PxVec3 mOffset; - - /* Chunk mesh wrappers */ - std::vector<ChunkPostProcessor*> mChunkPostprocessors; - - - - int32_t mPlaneIndexerOffset; - int32_t mChunkIdCounter; - std::vector<ChunkInfo> mChunkData; - - bool mRemoveIslands; - - NvBlastLog mLoggingCallback; + virtual bool isMeshContainOpenEdges(const Mesh* input) = 0; }; } // namespace Blast } // namespace Nv - #endif // ifndef NVBLASTAUTHORINGFRACTURETOOL_H diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h index 2b1806a..039da52 100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h @@ -1,19 +1,35 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTAUTHORINGMESH_H #define NVBLASTAUTHORINGMESH_H #include "NvBlastExtAuthoringTypes.h" -#include <vector> - namespace Nv { @@ -26,147 +42,106 @@ namespace Blast class Mesh { public: + virtual ~Mesh() {} /** - Constructs mesh object from array of triangles. - \param[in] position Array of vertex positions - \param[in] normals Array of vertex normals - \param[in] uv Array of vertex uv coordinates - \param[in] verticesCount Vertices count - \param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle. - \param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3) + Release Mesh memory */ - Mesh(physx::PxVec3* position, physx::PxVec3* normals, physx::PxVec2* uv, uint32_t verticesCount, uint32_t* indices, uint32_t indicesCount); + virtual void release() = 0; /** - Constructs mesh object from array of facets. - \param[in] vertices Array of vertices - \param[in] edges Array of edges - \param[in] facets Array of facets - \param[in] posCount Vertices count - \param[in] edgesCount Edges count - \param[in] facetsCount Facets count + Return true if mesh is valid */ - Mesh(Vertex* vertices, Edge* edges, Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount); + virtual bool isValid() const = 0; - ~Mesh(); + /** + Return writable pointer on vertices array + */ + virtual Vertex* getVerticesWritable() = 0; /** - Return true if mesh is valid + Return pointer on vertices array + */ + virtual const Vertex* getVertices() const = 0; + + + /** + Return writable pointer on edges array */ - bool isValid(); + virtual Edge* getEdgesWritable() = 0; /** - Return pointer on vertices array + Return pointer on edges array */ - Vertex* getVertices(); + virtual const Edge* getEdges() const = 0; /** - Return pointer on edges array + Return writable pointer on facets array */ - Edge* getEdges(); + virtual Facet* getFacetsBufferWritable() = 0; /** - Return pointer on facets array + Return pointer on facets array */ - Facet* getFacetsBuffer(); + virtual const Facet* getFacetsBuffer() const = 0; /** + Return writable pointer on specified facet + */ + virtual Facet* getFacetWritable(int32_t facet) = 0; + /** Return pointer on specified facet */ - Facet* getFacet(int32_t facet); + virtual const Facet* getFacet(int32_t facet) const = 0; /** Return edges count */ - uint32_t getEdgesCount(); + virtual uint32_t getEdgesCount() const = 0; /** Return vertices count */ - uint32_t getVerticesCount(); + virtual uint32_t getVerticesCount() const = 0; /** Return facet count */ - uint32_t getFacetCount(); + virtual uint32_t getFacetCount() const = 0; /** Return reference on mesh bounding box. */ - physx::PxBounds3& getBoundingBox(); + virtual const physx::PxBounds3& getBoundingBox() const = 0; + + /** + Return writable reference on mesh bounding box. + */ + virtual physx::PxBounds3& getBoundingBoxWritable() = 0; + + + /** + Set per-facet material id. + */ + virtual void setMaterialId(int32_t* materialIds) = 0; + + /** + Set per-facet smoothing group. + */ + virtual void setSmoothingGroup(int32_t* smoothingGroup) = 0; /** Recalculate bounding box */ - void recalculateBoundingBox(); + virtual void recalculateBoundingBox() = 0; /** Compute mesh volume. Can be used only for triangulated meshes. Return mesh volume. If mesh is not triangulated return 0. */ - float getMeshVolume(); - -private: - std::vector<Vertex> mVertices; - std::vector<Edge> mEdges; - std::vector<Facet> mFacets; - physx::PxBounds3 mBounds; + virtual float getMeshVolume() = 0; }; - -/** - Helper functions -*/ - -/** - Set cutting box at some particular position. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] mesh Cutting box mesh - \param[in] size Cutting box size - \param[in] id Cutting box ID -*/ -void setCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, Mesh* mesh, float size, int32_t id); -/** - Create cutting box at some particular position. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] size Cutting box size - \param[in] id Cutting box ID -*/ -Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int32_t id); - -/** - Create box at some particular position. - \param[in] point Cutting face center - \param[in] size Cutting box size -*/ -Mesh* getBigBox(const physx::PxVec3& point, float size); - -/** - Create slicing box with noisy cutting surface. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] size Cutting box size - \param[in] jaggedPlaneSize Noisy surface size - \param[in] resolution Noisy surface resolution - \param[in] id Cutting box ID - \param[in] amplitude Noise amplitude - \param[in] frequency Noise frequency - \param[in] octaves Noise octaves - \param[in] seed Random generator seed, used for noise generation. -*/ -Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed); - - -/** - Inverses normals of cutting box and sets indices. - \param[in] mesh Cutting box mesh - \param[in] id Cutting box ID -*/ -void inverseNormalAndSetIndices(Mesh* mesh, int32_t id); - } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringMeshCleaner.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringMeshCleaner.h new file mode 100644 index 0000000..b352e80 --- /dev/null +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringMeshCleaner.h @@ -0,0 +1,71 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTAUTHORINGMESHCLEANER_H +#define NVBLASTEXTAUTHORINGMESHCLEANER_H + +#include "NvBlastExtAuthoringTypes.h" + +/** + FractureTool has requirements to input meshes to fracture them successfully: + 1) Mesh should be closed (watertight) + 2) There should not be self-intersections and open-edges. +*/ + +/** + Mesh cleaner input is closed mesh with self-intersections and open-edges (only in the interior). + It tries to track outer hull to make input mesh solid and meet requierements of FractureTool. If mesh contained some internal cavities they will be removed. +*/ + +namespace Nv +{ +namespace Blast +{ + +class Mesh; + +class MeshCleaner +{ +public: + virtual ~MeshCleaner() {} + + /** + Tries to remove self intersections and open edges in interior of mesh. + \param[in] mesh Mesh to be cleaned. + \return Cleaned mesh or nullptr if failed. + */ + virtual Mesh* cleanMesh(const Mesh* mesh) = 0; + + virtual void release() = 0; +}; + + +} // namespace Blast +} // namespace Nv + +#endif // ifndef NVBLASTEXTAUTHORINGMESHCLEANER_H
\ No newline at end of file diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h index de28866..13865f7 100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTAUTHORINGTYPES_H #define NVBLASTAUTHORINGTYPES_H @@ -14,7 +32,6 @@ #include <PxVec3.h> #include <PxVec2.h> #include <PxBounds3.h> -#include <algorithm> #include "NvBlastTypes.h" #define NOT_VALID_VERTEX INT32_MAX @@ -51,6 +68,13 @@ struct Vertex physx::PxVec2 uv[1]; // UV-coordinates array, currently supported only one UV coordinate. }; + +// Interior material ID +#define MATERIAL_INTERIOR 1000 +#define SMOOTHING_GROUP_INTERIOR 1000 + + + /** Mesh triangle representation */ @@ -59,7 +83,9 @@ struct Triangle Triangle() {}; Triangle(Vertex a, Vertex b, Vertex c) : a(a), b(b), c(c) {}; Vertex a, b, c; - int32_t userInfo; + int32_t userData; + int32_t materialId; + int32_t smoothingGroup; // NOT SUPPORTED ATM. physx::PxVec3 getNormal() { return ((b.p - a.p).cross(c.p - a.p)); @@ -91,10 +117,28 @@ struct TriangleIndexed return (a == ea || a == eb || a == ec) && (b == ea || b == eb || b == ec); } + Triangle convertToTriangle(Vertex* vertices) + { + Triangle tr; + tr.a = vertices[ea]; + tr.b = vertices[eb]; + tr.c = vertices[ec]; + + tr.userData = userData; + tr.materialId = materialId; + tr.smoothingGroup = smoothingGroup; + return tr; + } + uint32_t ea, eb, ec; - int32_t userInfo; + int32_t materialId; + int32_t smoothingGroup; + int32_t userData; }; + + + /** Mesh facet representation */ @@ -103,11 +147,14 @@ struct Facet int32_t firstEdgeNumber; uint32_t edgesCount; int32_t userData; - Facet(int32_t fEdge = 0, uint32_t eCount = 0, int32_t userData = 0) : firstEdgeNumber(fEdge), edgesCount(eCount), userData(userData) {} + int32_t materialId; + int32_t smoothingGroup; + + Facet(int32_t fEdge = 0, uint32_t eCount = 0, int32_t materialId = 0, int32_t userData = 0, int32_t smoothingGroup = 0) : firstEdgeNumber(fEdge), edgesCount(eCount), materialId(materialId), userData(userData), smoothingGroup(smoothingGroup) {} }; /** -Abstract base class for user-defined random value generator. + Abstract base class for user-defined random value generator. */ class RandomGeneratorBase { @@ -119,6 +166,110 @@ public: virtual ~RandomGeneratorBase() {}; }; +/** + Collision hull geometry format. +*/ +struct CollisionHull +{ + /** + Collision hull polygon format. + */ + struct HullPolygon + { + // Polygon base plane + float mPlane[4]; + // Number vertices in polygon + uint16_t mNbVerts; + // First index in CollisionHull.indices array for this polygon + uint16_t mIndexBase; + }; + ///** + + uint32_t pointsCount; + uint32_t indicesCount; + uint32_t polygonDataCount; + physx::PxVec3* points; + uint32_t* indices; + HullPolygon* polygonData; + + virtual ~CollisionHull() {} + + virtual void release() = 0; +}; + +/** + Authoring results. Which contains NvBlastAsset, render and collision meshes +*/ +struct AuthoringResult +{ + uint32_t chunkCount; //Number of chunks in Blast asset + + uint32_t bondCount; //Number of bonds in Blast asset + + NvBlastAsset* asset; //Blast asset + + /** + assetToFractureChunkIdMap used for getting internal FractureChunkId with FractureTool::getChunkId. + FractureChunkId = FractureTool.getChunkId(aResult.assetToFractureChunkIdMap(AssetChunkId); + */ + uint32_t* assetToFractureChunkIdMap; + + /** + Offsets for render mesh geometry. Contains chunkCount + 1 element. + First triangle for i-th chunk: aResult.geometry[aResult.geometryOffset[i]] + aResult.geometryOffset[chunkCount+1] is total number of triangles in geometry + */ + uint32_t* geometryOffset; + + Triangle* geometry; //Raw array of Triangle for all chunks + + NvBlastChunkDesc* chunkDescs; //Array of chunk descriptors. Contains chunkCount elements + + NvBlastBondDesc* bondDescs; //Array of bond descriptors. Contains bondCount elements + + /** + Collision hull offsets. Contains chunkCount + 1 element. + First collision hull for i-th chunk: aResult.collisionHull[aResult.collisionHullOffset[i]] + aResult.collisionHullOffset[chunkCount+1] is total number of collision hulls in collisionHull + */ + uint32_t* collisionHullOffset; + + CollisionHull** collisionHull; //Raw array of pointers to collision hull for all chunks. + + /** + Array of chunk physics parameters. Contains chunkCount elements + */ + struct ExtPxChunk* physicsChunks; + + /** + Array of phisics subchunks (convex mesh) descriptors. + Use collisionHullOffset for accessing elements. + */ + struct ExtPxSubchunk* physicsSubchunks; + + /** + Array of material names. + */ + char** materialNames; + /** + Size of array of material names. + */ + + uint32_t materialCount; + + //// Member functions //// + virtual ~AuthoringResult() {} + + /** + Free collision hulls data + */ + virtual void releaseCollisionHulls() = 0; + + /** + Free all data and AuthoringResult + */ + virtual void release() = 0; +}; } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.cpp b/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.cpp index 73c59b8..7306b57 100644 --- a/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtApexSharedParts.h" @@ -906,14 +924,14 @@ static void _arrayVec3ToVec4(const PxVec3* src, const Vec3V& scale, Vec4V* dst, } -bool importerHullsInProximityApexFree(const std::vector<PxVec3>& hull0, PxBounds3& hull0Bounds, const physx::PxTransform& localToWorldRT0In, const physx::PxVec3& scale0In, - const std::vector<PxVec3>& hull1, PxBounds3& hull1Bounds, const physx::PxTransform& localToWorldRT1In, const physx::PxVec3& scale1In, +bool importerHullsInProximityApexFree(uint32_t hull0Count, const PxVec3* hull0, PxBounds3& hull0Bounds, const physx::PxTransform& localToWorldRT0In, const physx::PxVec3& scale0In, + uint32_t hull1Count, const PxVec3* hull1, PxBounds3& hull1Bounds, const physx::PxTransform& localToWorldRT1In, const physx::PxVec3& scale1In, physx::PxF32 maxDistance, Separation* separation) { - const PxU32 numVerts0 = static_cast<PxU32>(hull0.size()); - const PxU32 numVerts1 = static_cast<PxU32>(hull1.size()); + const PxU32 numVerts0 = static_cast<PxU32>(hull0Count); + const PxU32 numVerts1 = static_cast<PxU32>(hull1Count); const PxU32 numAov0 = (numVerts0 + 3) >> 2; const PxU32 numAov1 = (numVerts1 + 3) >> 2; Vec4V* verts0 = (Vec4V*)alloca((numAov0 + numAov1) * sizeof(Vec4V) * 3); @@ -936,8 +954,8 @@ bool importerHullsInProximityApexFree(const std::vector<PxVec3>& hull0, PxBounds vert1[i] = hull1[i]; } - _arrayVec3ToVec4(&vert0[0], scale0, verts0, numVerts0); - _arrayVec3ToVec4(&vert1[0], scale1, verts1, numVerts1); + _arrayVec3ToVec4(vert0.data(), scale0, verts0, numVerts0); + _arrayVec3ToVec4(vert1.data(), scale1, verts1, numVerts1); const PxTransform trans1To0 = localToWorldRT0In.transformInv(localToWorldRT1In); diff --git a/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.h b/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.h index 68e0412..5d1f990 100644 --- a/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.h +++ b/sdk/extensions/authoring/source/NvBlastExtApexSharedParts.h @@ -1,18 +1,35 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAPEXSHAREDPARTS_H #define NVBLASTEXTAPEXSHAREDPARTS_H #include "NvBlast.h" -#include <vector> #include <PxPlane.h> namespace physx { @@ -40,9 +57,9 @@ struct Separation /** Function to compute midplane between two convex hulls. Is copied from APEX. */ -bool importerHullsInProximityApexFree(const std::vector<physx::PxVec3>& hull0, physx::PxBounds3& hull0Bounds, const physx::PxTransform& localToWorldRT0In, const physx::PxVec3& scale0In, - const std::vector<physx::PxVec3>& hull1, physx::PxBounds3& hull1Bounds, const physx::PxTransform& localToWorldRT1In, const physx::PxVec3& scale1In, - physx::PxF32 maxDistance, Separation* separation); +bool importerHullsInProximityApexFree( uint32_t hull0Count, const physx::PxVec3* hull0, physx::PxBounds3& hull0Bounds, const physx::PxTransform& localToWorldRT0In, const physx::PxVec3& scale0In, + uint32_t hull1Count, const physx::PxVec3* hull1, physx::PxBounds3& hull1Bounds, const physx::PxTransform& localToWorldRT1In, const physx::PxVec3& scale1In, + physx::PxF32 maxDistance, Separation* separation); } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp new file mode 100644 index 0000000..95a7bee --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp @@ -0,0 +1,262 @@ +/* +* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#include "NvBlastExtAuthoring.h" +#include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringMeshCleanerImpl.h" +#include "NvBlastExtAuthoringFractureToolImpl.h" +#include "NvBlastExtAuthoringCollisionBuilderImpl.h" +#include "NvBlastExtAuthoringBondGeneratorImpl.h" +#include "NvBlastTypes.h" +#include "NvBlastIndexFns.h" +#include "NvBlast.h" +#include "NvBlastGlobals.h" +#include "NvBlastExtPxAsset.h" + +#include <algorithm> +#include <memory> + +using namespace Nv::Blast; +using namespace physx; + +#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? new T[x] : nullptr; +#define SAFE_ARRAY_DELETE(x) if (x != nullptr) {delete[] x; x = nullptr;} + +Mesh* NvBlastExtAuthoringCreateMesh(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount) +{ + return new MeshImpl(position, normals, uv, verticesCount, indices, indicesCount); +} + +MeshCleaner* NvBlastExtAuthoringCreateMeshCleaner() +{ + return new MeshCleanerImpl; +} + +VoronoiSitesGenerator* NvBlastExtAuthoringCreateVoronoiSitesGenerator(Mesh* mesh, RandomGeneratorBase* rng) +{ + return new VoronoiSitesGeneratorImpl(mesh, rng); +} + +FractureTool* NvBlastExtAuthoringCreateFractureTool() +{ + return new FractureToolImpl; +} + +BlastBondGenerator* NvBlastExtAuthoringCreateBondGenerator(PxCooking* cooking, PxPhysicsInsertionCallback* insertionCallback) +{ + return new BlastBondGeneratorImpl(cooking, insertionCallback); +} + +ConvexMeshBuilder* NvBlastExtAuthoringCreateConvexMeshBuilder(PxCooking* cooking, PxPhysicsInsertionCallback* insertionCallback) +{ + return new ConvexMeshBuilderImpl(cooking, insertionCallback); +} + +void buildPhysicsChunks(ConvexMeshBuilder& collisionBuilder, AuthoringResult& result) +{ + uint32_t chunkCount = (uint32_t)result.chunkCount; + result.collisionHullOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1); + result.collisionHullOffset[0] = 0; + result.collisionHull = SAFE_ARRAY_NEW(CollisionHull*, chunkCount); + result.physicsSubchunks = SAFE_ARRAY_NEW(ExtPxSubchunk, chunkCount); + result.physicsChunks = SAFE_ARRAY_NEW(ExtPxChunk, chunkCount); + for (uint32_t i = 0; i < chunkCount; ++i) + { + std::vector<physx::PxVec3> vertices; + for (uint32_t p = result.geometryOffset[i]; p < result.geometryOffset[i+1]; ++p) + { + Nv::Blast::Triangle& tri = result.geometry[p]; + vertices.push_back(tri.a.p); + vertices.push_back(tri.b.p); + vertices.push_back(tri.c.p); + } + + result.collisionHullOffset[i + 1] = result.collisionHullOffset[i] + 1; + result.collisionHull[i] = collisionBuilder.buildCollisionGeometry((uint32_t)vertices.size(), vertices.data()); + result.physicsSubchunks[i].transform = physx::PxTransform(physx::PxIdentity); + result.physicsSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(*result.collisionHull[i])); + + result.physicsChunks[i].isStatic = false; + result.physicsChunks[i].subchunkCount = 1; + result.physicsChunks[i].firstSubchunkIndex = i; + //outPhysicsChunks.get()[i].subchunks = &outPhysicsSubchunks[i]; + } +} + + +struct AuthoringResultImpl : public AuthoringResult +{ + void releaseCollisionHulls() override + { + if (collisionHull != nullptr) + { + for (uint32_t ch = 0; ch < collisionHullOffset[chunkCount]; ch++) + { + collisionHull[ch]->release(); + } + SAFE_ARRAY_DELETE(collisionHullOffset); + SAFE_ARRAY_DELETE(collisionHull); + } + } + + void release() override + { + releaseCollisionHulls(); + NVBLAST_FREE(asset); + SAFE_ARRAY_DELETE(assetToFractureChunkIdMap); + SAFE_ARRAY_DELETE(geometryOffset); + SAFE_ARRAY_DELETE(geometry); + SAFE_ARRAY_DELETE(chunkDescs); + SAFE_ARRAY_DELETE(bondDescs); + SAFE_ARRAY_DELETE(physicsChunks); + SAFE_ARRAY_DELETE(physicsSubchunks); + delete this; + } +}; + +AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBondGenerator& bondGenerator, ConvexMeshBuilder& collisionBuilder, int32_t defaultSupportDepth) +{ + fTool.finalizeFracturing(); + const uint32_t chunkCount = fTool.getChunkCount(); + if (chunkCount == 0) + { + return nullptr; + } + AuthoringResultImpl* ret = new AuthoringResultImpl; + if (ret == nullptr) + { + return nullptr; + } + AuthoringResult& aResult = *ret; + aResult.chunkCount = chunkCount; + + std::shared_ptr<bool> isSupport(new bool[chunkCount], [](bool* b) {delete[] b; }); + memset(isSupport.get(), 0, sizeof(bool) * chunkCount); + for (uint32_t i = 0; i < fTool.getChunkCount(); ++i) + { + if (defaultSupportDepth < 0 || fTool.getChunkDepth(fTool.getChunkId(i)) < defaultSupportDepth) + { + isSupport.get()[i] = fTool.getChunkInfo(i).isLeaf; + } + else if (fTool.getChunkDepth(fTool.getChunkId(i)) == defaultSupportDepth) + { + isSupport.get()[i] = true; + } + } + + BondGenerationConfig cnf; + cnf.bondMode = BondGenerationConfig::EXACT; + + //NvBlastChunkDesc>& chunkDescs = aResult.chunkDescs; + //std::shared_ptr<NvBlastBondDesc>& bondDescs = aResult.bondDescs; + const uint32_t bondCount = bondGenerator.buildDescFromInternalFracture(&fTool, isSupport.get(), aResult.bondDescs, aResult.chunkDescs); + aResult.bondCount = bondCount; + if (bondCount == 0) + { + aResult.bondDescs = nullptr; + } + + // order chunks, build map + std::vector<uint32_t> chunkReorderInvMap; + { + std::vector<uint32_t> chunkReorderMap(chunkCount); + std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc)); + NvBlastEnsureAssetExactSupportCoverage(aResult.chunkDescs, chunkCount, scratch.data(), logLL); + NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), aResult.chunkDescs, chunkCount, scratch.data(), logLL); + NvBlastApplyAssetDescChunkReorderMapInPlace(aResult.chunkDescs, chunkCount, aResult.bondDescs, bondCount, chunkReorderMap.data(), true, scratch.data(), logLL); + chunkReorderInvMap.resize(chunkReorderMap.size()); + Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size())); + } + + // get result geometry + aResult.geometryOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1); + aResult.assetToFractureChunkIdMap = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1); + aResult.geometryOffset[0] = 0; + std::vector<Nv::Blast::Triangle*> chunkGeometry(chunkCount); + for (uint32_t i = 0; i < chunkCount; ++i) + { + uint32_t chunkIndex = chunkReorderInvMap[i]; + aResult.geometryOffset[i+1] = aResult.geometryOffset[i] + fTool.getBaseMesh(chunkIndex, chunkGeometry[i]); + aResult.assetToFractureChunkIdMap[i] = chunkIndex; + } + aResult.geometry = SAFE_ARRAY_NEW(Triangle, aResult.geometryOffset[chunkCount]); + for (uint32_t i = 0; i < chunkCount; ++i) + { + uint32_t trianglesCount = aResult.geometryOffset[i + 1] - aResult.geometryOffset[i]; + memcpy(aResult.geometry + aResult.geometryOffset[i], chunkGeometry[i], trianglesCount * sizeof(Nv::Blast::Triangle)); + } + + float maxX = INT32_MIN; + float maxY = INT32_MIN; + float maxZ = INT32_MIN; + + float minX = INT32_MAX; + float minY = INT32_MAX; + float minZ = INT32_MAX; + + for (uint32_t i = 0; i < bondCount; i++) + { + NvBlastBondDesc& bondDesc = aResult.bondDescs[i]; + + minX = std::min(minX, bondDesc.bond.centroid[0]); + maxX = std::max(maxX, bondDesc.bond.centroid[0]); + + minY = std::min(minY, bondDesc.bond.centroid[1]); + maxY = std::max(maxY, bondDesc.bond.centroid[1]); + + minZ = std::min(minZ, bondDesc.bond.centroid[2]); + maxZ = std::max(maxZ, bondDesc.bond.centroid[2]); + } + + //std::cout << "Bond bounds: " << std::endl; + //std::cout << "MIN: " << minX << ", " << minY << ", " << minZ << std::endl; + //std::cout << "MAX: " << maxX << ", " << maxY << ", " << maxZ << std::endl; + + // prepare physics data (convexes) + buildPhysicsChunks(collisionBuilder, aResult); + + // set NvBlastChunk volume from Px geometry + for (uint32_t i = 0; i < chunkCount; i++) + { + float totalVolume = 0.f; + for (uint32_t k = 0; k < aResult.physicsChunks[i].subchunkCount; k++) + { + const auto& subChunk = aResult.physicsSubchunks[aResult.physicsChunks[i].firstSubchunkIndex + k]; + physx::PxVec3 localCenterOfMass; physx::PxMat33 intertia; float mass; + subChunk.geometry.convexMesh->getMassInformation(mass, intertia, localCenterOfMass); + const physx::PxVec3 scale = subChunk.geometry.scale.scale; + mass *= scale.x * scale.y * scale.z; + totalVolume += mass / 1.0f; // unit density + } + + aResult.chunkDescs[i].volume = totalVolume; + } + + // build and serialize ExtPhysicsAsset + NvBlastAssetDesc descriptor; + descriptor.bondCount = bondCount; + descriptor.bondDescs = aResult.bondDescs; + descriptor.chunkCount = chunkCount; + descriptor.chunkDescs = aResult.chunkDescs; + + std::vector<uint8_t> scratch(static_cast<unsigned int>(NvBlastGetRequiredScratchForCreateAsset(&descriptor, logLL))); + void* mem = NVBLAST_ALLOC(NvBlastGetAssetMemorySize(&descriptor, logLL)); + aResult.asset = NvBlastCreateAsset(mem, &descriptor, scratch.data(), logLL); + + //aResult.asset = std::shared_ptr<NvBlastAsset>(asset, [=](NvBlastAsset* asset) + //{ + // NVBLAST_FREE(asset); + //}); + + //std::cout << "Done" << std::endl; + ret->materialCount = 0; + ret->materialNames = nullptr; + return ret; +}
\ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp index 075bce9..40ddec1 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtAuthoringAccelerator.h" #include "NvBlastExtAuthoringMesh.h" @@ -25,16 +43,16 @@ DummyAccelerator::DummyAccelerator(int32_t count) :count(count) { current = 0; } -void DummyAccelerator::setState(Vertex* pos, Edge* ed, Facet& fc) +void DummyAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) { current = 0; - (void)pos; - (void)ed; - (void)fc; + NV_UNUSED(pos); + NV_UNUSED(ed); + NV_UNUSED(fc); } void DummyAccelerator::setState(const physx::PxVec3& point) { current = 0; - (void)point; + NV_UNUSED(point); } int32_t DummyAccelerator::getNextFacet() { @@ -49,7 +67,7 @@ int32_t DummyAccelerator::getNextFacet() -BBoxBasedAccelerator::BBoxBasedAccelerator(Mesh* mesh, int32_t resolution) : mResolution(resolution), alreadyGotValue(1) +BBoxBasedAccelerator::BBoxBasedAccelerator(const Mesh* mesh, int32_t resolution) : mResolution(resolution), alreadyGotValue(1) { mBounds = mesh->getBoundingBox(); mSpatialMap.resize(resolution * resolution * resolution); @@ -124,14 +142,14 @@ int32_t BBoxBasedAccelerator::getNextFacet() } return facetId; } -void BBoxBasedAccelerator::setState(Vertex* pos, Edge* ed, Facet& fc) +void BBoxBasedAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) { alreadyGotValue++; mIteratorCell = -1; mIteratorFacet = -1; cellList.clear(); facetBox.setEmpty(); - Edge* edge = ed + fc.firstEdgeNumber; + const Edge* edge = ed + fc.firstEdgeNumber; uint32_t count = fc.edgesCount; for (uint32_t ec = 0; ec < count; ++ec) { @@ -195,13 +213,13 @@ bool BBoxBasedAccelerator::testCellPolygonIntersection(int32_t cellId, PxBounds3 return false; } -void BBoxBasedAccelerator::buildAccelStructure(Vertex* pos, Edge* edges, Facet* fc, int32_t facetCount) +void BBoxBasedAccelerator::buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount) { for (int32_t facet = 0; facet < facetCount; ++facet) { PxBounds3 bBox; bBox.setEmpty(); - Edge* edge = &edges[0] + fc->firstEdgeNumber; + const Edge* edge = &edges[0] + fc->firstEdgeNumber; int32_t count = fc->edgesCount; for (int32_t ec = 0; ec < count; ++ec) { @@ -349,15 +367,15 @@ enum TrivialFlags -int32_t testFacetUnitCubeIntersection(Vertex* vertices, Edge* edges, Facet& fc, PxBounds3 cube, float fattening) +int32_t testFacetUnitCubeIntersection(const Vertex* vertices, const Edge* edges, const Facet& fc, PxBounds3 cube, float fattening) { - Edge* ed = edges + fc.firstEdgeNumber; + const Edge* ed = edges + fc.firstEdgeNumber; int32_t trivialFlags = ALL_ONE; cube.fattenFast(fattening); for (uint32_t i = 0; i < fc.edgesCount; ++i) { { - PxVec3& p = vertices[ed->s].p; + const PxVec3& p = vertices[ed->s].p; if (cube.contains(p)) return 1; if (p.x < cube.getCenter().x + 0.5) @@ -376,7 +394,7 @@ int32_t testFacetUnitCubeIntersection(Vertex* vertices, Edge* edges, Facet& fc, trivialFlags &= HAS_POINT_ABOVE_LOW_Z; } { - PxVec3& p = vertices[ed->e].p; + const PxVec3& p = vertices[ed->e].p; if (cube.contains(p)) return 1; if (p.x < cube.getCenter().x + 0.5) @@ -411,9 +429,9 @@ int32_t testFacetUnitCubeIntersection(Vertex* vertices, Edge* edges, Facet& fc, /** Compute normal */ - PxVec3& v1 = vertices[ed->s].p; - PxVec3* v2 = nullptr; - PxVec3* v3 = nullptr; + const PxVec3& v1 = vertices[ed->s].p; + const PxVec3* v2 = nullptr; + const PxVec3* v3 = nullptr; for (uint32_t i = 0; i < fc.edgesCount; ++i) { @@ -476,7 +494,7 @@ int32_t testFacetUnitCubeIntersection(Vertex* vertices, Edge* edges, Facet& fc, } -IntersectionTestingAccelerator::IntersectionTestingAccelerator(Mesh* in, int32_t resolution) +IntersectionTestingAccelerator::IntersectionTestingAccelerator(const Mesh* in, int32_t resolution) { @@ -563,7 +581,7 @@ int32_t IntersectionTestingAccelerator::getNextFacet() return facetId; } -void IntersectionTestingAccelerator::setState(Vertex* pos, Edge* ed, Facet& fc) +void IntersectionTestingAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) { alreadyGotValue++; mIteratorCell = -1; diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h index 8284cd7..909dc86 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAUTHORINGACCELERATOR_H #define NVBLASTEXTAUTHORINGACCELERATOR_H @@ -36,7 +54,7 @@ public: \param[in] ed Edge buffer \param[in] fc Facet which should be tested. */ - virtual void setState(Vertex* pos, Edge* ed, Facet& fc) = 0; + virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc) = 0; /** Set state of accelerator to return all facets which possibly can cover given point. Needed for testing whether point is inside mesh. \param[in] point Point which should be tested. @@ -62,7 +80,7 @@ public: \param[in] count Mesh facets count for which accelerator should be built. */ DummyAccelerator(int32_t count); - virtual void setState(Vertex* pos, Edge* ed, Facet& fc); + virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc); virtual void setState(const physx::PxVec3& point); virtual int32_t getNextFacet(); @@ -83,15 +101,15 @@ public: \param[in] mesh Mesh for which acceleration structure should be built. \param[in] resolution Resolution on 3d grid. */ - BBoxBasedAccelerator(Mesh* mesh, int32_t resolution); + BBoxBasedAccelerator(const Mesh* mesh, int32_t resolution); virtual ~BBoxBasedAccelerator(); int32_t getNextFacet(); - void setState(Vertex* pos, Edge* ed, Facet& fc); + void setState(const Vertex* pos, const Edge* ed, const Facet& fc); void setState(const physx::PxVec3& p); private: bool testCellPolygonIntersection(int32_t cellId, physx::PxBounds3& facetBB); - void buildAccelStructure(Vertex* pos, Edge* edges, Facet* fc, int32_t facetCount); + void buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount); int32_t mResolution; physx::PxBounds3 mBounds; @@ -121,9 +139,9 @@ private: class IntersectionTestingAccelerator : public SpatialAccelerator { public: - IntersectionTestingAccelerator(Mesh* mesh, int32_t resolution); + IntersectionTestingAccelerator(const Mesh* mesh, int32_t resolution); int32_t getNextFacet(); - void setState(Vertex* pos, Edge* ed, Facet& fc); + void setState(const Vertex* pos, const Edge* ed, const Facet& fc); void setState(const physx::PxVec3& p); diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGenerator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp index b2c3883..a4a2ce7 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGenerator.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + // This warning arises when using some stl containers with older versions of VC // c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code @@ -15,22 +33,25 @@ #pragma warning(disable : 4702) #endif -#include <NvBlastExtAuthoringBondGenerator.h> -#include <NvBlastTypes.h> +#include <NvBlastExtAuthoringBondGeneratorImpl.h> #include <NvBlast.h> #include "NvBlastExtTriangleProcessor.h" #include "NvBlastExtApexSharedParts.h" -#include "NvBlastExtAuthoringCollisionBuilder.h" +#include "NvBlastExtAuthoringCollisionBuilderImpl.h" #include "NvBlastExtAuthoringInternalCommon.h" +#include "NvBlastExtAuthoringTypes.h" #include <vector> #include <map> #include <PxPlane.h> #include <algorithm> #include <cmath> +#include <memory> using physx::PxVec3; using physx::PxBounds3; +#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? new T[x] : nullptr; + //#define DEBUG_OUTPUT #ifdef DEBUG_OUTPUT @@ -125,8 +146,7 @@ namespace Nv int32_t m_chunkId; }; - - float BlastBondGenerator::processWithMidplanes(TriangleProcessor* trProcessor, const std::vector<PxVec3>& chunk1Points, const std::vector<PxVec3>& chunk2Points, + float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const std::vector<PxVec3>& chunk1Points, const std::vector<PxVec3>& chunk2Points, const std::vector<PxVec3>& hull1p, const std::vector<PxVec3>& hull2p, PxVec3& normal, PxVec3& centroid) { PxBounds3 bounds; @@ -163,7 +183,7 @@ namespace Nv chunk2Centroid *= (1.0f / chunk2Points.size()); Separation separation; - if (!importerHullsInProximityApexFree(hull1p, aBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull2p, bBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation)) + if (!importerHullsInProximityApexFree(hull1p.size(), hull1p.data(), aBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull2p.size(), hull2p.data(), bBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation)) { return 0.0; } @@ -221,53 +241,39 @@ namespace Nv return area * 0.5f; } - - int32_t BlastBondGenerator::bondsFromPrefractured(const std::vector<std::vector<Triangle>>& geometry, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& resultBondDescs, BondGenerationConfig conf) - { - int32_t ret_val = 0; - switch (conf.bondMode) - { - case BondGenerationConfig::AVERAGE: - ret_val = createFullBondListAveraged(geometry, chunkIsSupport, resultBondDescs, conf); - break; - case BondGenerationConfig::EXACT: - ret_val = createFullBondListExact(geometry, chunkIsSupport, resultBondDescs, conf); - break; - } - return ret_val; - } - - int32_t BlastBondGenerator::createFullBondListAveraged(const std::vector<std::vector<Triangle>>& chunksGeometry, const std::vector<bool>& supportFlags, std::vector<NvBlastBondDesc>& mResultBondDescs, BondGenerationConfig conf) + int32_t BlastBondGeneratorImpl::createFullBondListAveraged(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf) { NV_UNUSED(conf); - std::vector<std::vector<PxVec3> > chunksPoints(chunksGeometry.size()); + std::vector<std::vector<PxVec3> > chunksPoints(meshCount); - for (uint32_t i = 0; i < chunksGeometry.size(); ++i) + for (uint32_t i = 0; i < meshCount; ++i) { if (!supportFlags[i]) { continue; } - for (uint32_t j = 0; j < chunksGeometry[i].size(); ++j) + uint32_t count = geometryOffset[i + 1] - geometryOffset[i]; + for (uint32_t j = 0; j < count; ++j) { - chunksPoints[i].push_back(chunksGeometry[i][j].a.p); - chunksPoints[i].push_back(chunksGeometry[i][j].b.p); - chunksPoints[i].push_back(chunksGeometry[i][j].c.p); + chunksPoints[i].push_back(geometry[geometryOffset[i] + j].a.p); + chunksPoints[i].push_back(geometry[geometryOffset[i] + j].b.p); + chunksPoints[i].push_back(geometry[geometryOffset[i] + j].c.p); } } - Nv::Blast::ConvexMeshBuilder builder(mPxCooking, mPxInsertionCallback); + Nv::Blast::ConvexMeshBuilderImpl builder(mPxCooking, mPxInsertionCallback); - std::vector<CollisionHull> cHulls(chunksGeometry.size()); + std::vector<CollisionHull*> cHulls(meshCount); - for (uint32_t i = 0; i < chunksGeometry.size(); ++i) + for (uint32_t i = 0; i < meshCount; ++i) { if (!supportFlags[i]) { continue; } - builder.buildCollisionGeometry(chunksPoints[i], cHulls[i]); + cHulls[i] = builder.buildCollisionGeometry(chunksPoints[i].size(), chunksPoints[i].data()); } std::vector<std::vector<PxVec3> > hullPoints(cHulls.size()); @@ -279,24 +285,23 @@ namespace Nv continue; } - hullPoints[chunk].resize(cHulls[chunk].points.size()); - for (uint32_t i = 0; i < cHulls[chunk].points.size(); ++i) + hullPoints[chunk].resize(cHulls[chunk]->pointsCount); + for (uint32_t i = 0; i < cHulls[chunk]->pointsCount; ++i) { - hullPoints[chunk][i].x = cHulls[chunk].points[i].x; - hullPoints[chunk][i].y = cHulls[chunk].points[i].y; - hullPoints[chunk][i].z = cHulls[chunk].points[i].z; + hullPoints[chunk][i] = cHulls[chunk]->points[i]; } + cHulls[chunk]->release(); } TriangleProcessor trProcessor; - - for (uint32_t i = 0; i < chunksGeometry.size(); ++i) + std::vector<NvBlastBondDesc> mResultBondDescs; + for (uint32_t i = 0; i < meshCount; ++i) { if (!supportFlags[i]) { continue; } - for (uint32_t j = i + 1; j < chunksGeometry.size(); ++j) + for (uint32_t j = i + 1; j < meshCount; ++j) { if (!supportFlags[i]) { @@ -327,8 +332,9 @@ namespace Nv } } - - return 0; + resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size()); + memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc)*mResultBondDescs.size()); + return mResultBondDescs.size(); } uint32_t isSamePlane(PxPlane& a, PxPlane& b) @@ -340,39 +346,48 @@ namespace Nv return 1; } - int32_t BlastBondGenerator::createFullBondListExact(const std::vector<std::vector<Triangle>>& chunksGeometry, const std::vector<bool>& supportFlags, std::vector<NvBlastBondDesc>& mResultBondDescs, BondGenerationConfig conf) + int32_t BlastBondGeneratorImpl::createFullBondListExact(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf) { std::vector < PlaneChunkIndexer > planeTriangleMapping; NV_UNUSED(conf); - for (uint32_t i = 0; i < chunksGeometry.size(); ++i) + for (uint32_t i = 0; i < meshCount; ++i) { if (!supportFlags[i]) { continue; } - for (uint32_t j = 0; j < chunksGeometry[i].size(); ++j) + uint32_t count = geometryOffset[i + 1] - geometryOffset[i]; + for (uint32_t j = 0; j < count; ++j) { #ifdef DEBUG_OUTPUT - meshBuffer.push_back(chunksGeometry[i][j].a.p ); - meshBuffer.push_back(chunksGeometry[i][j].b.p); - meshBuffer.push_back(chunksGeometry[i][j].c.p ); + meshBuffer.push_back(geometry[geometryOffset[i] + j].a.p ); + meshBuffer.push_back(geometry[geometryOffset[i] + j].b.p); + meshBuffer.push_back(geometry[geometryOffset[i] + j].c.p ); #endif - PxPlane nPlane = PxPlane(chunksGeometry[i][j].a.p, chunksGeometry[i][j].b.p, chunksGeometry[i][j].c.p); + PxPlane nPlane = PxPlane(geometry[geometryOffset[i] + j].a.p, geometry[geometryOffset[i] + j].b.p, geometry[geometryOffset[i] + j].c.p); planeTriangleMapping.push_back(PlaneChunkIndexer(i, j, nPlane)); } } std::sort(planeTriangleMapping.begin(), planeTriangleMapping.end(), planeComparer); - return createFullBondListExactInternal(chunksGeometry, planeTriangleMapping, mResultBondDescs); + return createFullBondListExactInternal(meshCount, geometryOffset, geometry, planeTriangleMapping, resultBondDescs); } - void BlastBondGenerator::buildGeometryCache(const std::vector<std::vector<Triangle> >& geometry) + void BlastBondGeneratorImpl::buildGeometryCache(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry) { - mGeometryCache = geometry; - mHullsPointsCache.resize(geometry.size()); - mBoundsCache.resize(geometry.size()); - mCHullCache.resize(geometry.size()); + uint32_t geometryCount = geometryOffset[meshCount]; + for (uint32_t i = 0; i < meshCount; i++) + { + mGeometryCache.push_back(std::vector<Triangle>()); + uint32_t count = geometryOffset[i + 1] - geometryOffset[i]; + mGeometryCache.back().resize(count); + memcpy(mGeometryCache.back().data(), geometry + geometryOffset[i], sizeof(Triangle) * count); + } + mHullsPointsCache.resize(geometryCount); + mBoundsCache.resize(geometryCount); + mCHullCache.resize(geometryCount); for (uint32_t i = 0; i < mGeometryCache.size(); ++i) { for (uint32_t j = 0; j < mGeometryCache[i].size(); ++j) @@ -395,36 +410,39 @@ namespace Nv chunksPoints[sp++] = mGeometryCache[ch][i].c.p; } - Nv::Blast::ConvexMeshBuilder builder(mPxCooking, mPxInsertionCallback); - - CollisionHull& cHull = mCHullCache[ch]; + Nv::Blast::ConvexMeshBuilderImpl builder(mPxCooking, mPxInsertionCallback); - builder.buildCollisionGeometry(chunksPoints, cHull); + mCHullCache[ch] = builder.buildCollisionGeometry(chunksPoints.size(), chunksPoints.data()); - mHullsPointsCache[ch].resize(cHull.points.size()); + mHullsPointsCache[ch].resize(mCHullCache[ch]->pointsCount); mBoundsCache[ch].setEmpty(); - for (uint32_t i = 0; i < cHull.points.size(); ++i) + for (uint32_t i = 0; i < mCHullCache[ch]->pointsCount; ++i) { - mHullsPointsCache[ch][i].x = cHull.points[i].x; - mHullsPointsCache[ch][i].y = cHull.points[i].y; - mHullsPointsCache[ch][i].z = cHull.points[i].z; + mHullsPointsCache[ch][i] = mCHullCache[ch]->points[i]; mBoundsCache[ch].include(mHullsPointsCache[ch][i]); } } } - void BlastBondGenerator::resetGeometryCache() + void BlastBondGeneratorImpl::resetGeometryCache() { mGeometryCache.clear(); mPlaneCache.clear(); mHullsPointsCache.clear(); + for (auto h : mCHullCache) + { + h->release(); + } mCHullCache.clear(); mBoundsCache.clear(); } - int32_t BlastBondGenerator::createFullBondListExactInternal(const std::vector<std::vector<Triangle>>& chunksGeometry, std::vector < PlaneChunkIndexer >& planeTriangleMapping, std::vector<NvBlastBondDesc>& mResultBondDescs) + int32_t BlastBondGeneratorImpl::createFullBondListExactInternal(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + std::vector<PlaneChunkIndexer>& planeTriangleMapping, NvBlastBondDesc*& resultBondDescs) { + NV_UNUSED(meshCount); + std::map<std::pair<int32_t, int32_t>, std::pair<NvBlastBondDesc, int32_t> > bonds; TriangleProcessor trPrc; @@ -446,7 +464,7 @@ namespace Nv // uint32_t endIndex = (uint32_t)planeTriangleMapping.size(); PlaneChunkIndexer& mappedTr = planeTriangleMapping[tIndex]; - const Triangle& trl = chunksGeometry[mappedTr.chunkId][mappedTr.trId]; + const Triangle& trl = geometry[geometryOffset[mappedTr.chunkId] + mappedTr.trId]; PxPlane pln = mappedTr.plane; TrPrcTriangle trp(trl.a.p, trl.b.p, trl.c.p); PxVec3 trCentroid = (trl.a.p + trl.b.p + trl.c.p) * (1.0f / 3.0f); @@ -493,8 +511,7 @@ namespace Nv bonds[bondEndPoints].first.bond.normal[1] = pln.n[1]; bonds[bondEndPoints].first.bond.normal[2] = pln.n[2]; } - - const Triangle& trl2 = chunksGeometry[mappedTr2.chunkId][mappedTr2.trId]; + const Triangle& trl2 = geometry[geometryOffset[mappedTr2.chunkId] + mappedTr2.trId]; TrPrcTriangle trp2(trl2.a.p, trl2.b.p, trl2.c.p); @@ -536,6 +553,7 @@ namespace Nv } } + std::vector<NvBlastBondDesc> mResultBondDescs; for (auto it : bonds) { if (it.second.first.bond.area > 0) @@ -553,21 +571,23 @@ namespace Nv saveGeometryToObj(meshBuffer, "Mesh.obj"); saveGeometryToObj(intersectionBuffer, "inter.obj"); #endif - return 0; + resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size()); + memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc)*mResultBondDescs.size()); + return mResultBondDescs.size(); } - int32_t BlastBondGenerator::createBondForcedInternal(const std::vector<PxVec3>& hull0, const std::vector<PxVec3>& hull1, + int32_t BlastBondGeneratorImpl::createBondForcedInternal(const std::vector<PxVec3>& hull0, const std::vector<PxVec3>& hull1, const CollisionHull& cHull0,const CollisionHull& cHull1, PxBounds3 bound0, PxBounds3 bound1, NvBlastBond& resultBond, float overlapping) { TriangleProcessor trProcessor; Separation separation; - importerHullsInProximityApexFree(hull0, bound0, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull1, bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation); + importerHullsInProximityApexFree(hull0.size(), hull0.data(), bound0, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation); if (std::isnan(separation.plane.d)) { - importerHullsInProximityApexFree(hull0, bound0, PxTransform(PxVec3(0.000001f, 0.000001f, 0.000001f)), PxVec3(1, 1, 1), hull1, bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation); + importerHullsInProximityApexFree(hull0.size(), hull0.data(), bound0, PxTransform(PxVec3(0.000001f, 0.000001f, 0.000001f)), PxVec3(1, 1, 1), hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation); if (std::isnan(separation.plane.d)) { return 1; @@ -581,9 +601,9 @@ namespace Nv dst[0][0] = 0; dst[0][1] = MAXIMUM_EXTENT; - for (uint32_t p = 0; p < cHull0.points.size(); ++p) + for (uint32_t p = 0; p < cHull0.pointsCount; ++p) { - float d = pl.distance(PxVec3(cHull0.points[p].x, cHull0.points[p].y, cHull0.points[p].z)); + float d = pl.distance(cHull0.points[p]); if (PxAbs(d) > PxAbs(dst[0][0])) { dst[0][0] = d; @@ -596,9 +616,9 @@ namespace Nv dst[1][0] = 0; dst[1][1] = MAXIMUM_EXTENT; - for (uint32_t p = 0; p < cHull1.points.size(); ++p) + for (uint32_t p = 0; p < cHull1.pointsCount; ++p) { - float d = pl.distance(PxVec3(cHull1.points[p].x, cHull1.points[p].y, cHull1.points[p].z)); + float d = pl.distance(cHull0.points[p]); if (PxAbs(d) > PxAbs(dst[1][0])) { dst[1][0] = d; @@ -612,16 +632,16 @@ namespace Nv float cvOffset[2] = { dst[0][1] + (dst[0][0] - dst[0][1]) * overlapping, dst[1][1] + (dst[1][0] - dst[1][1]) * overlapping }; - for (uint32_t i = 0; i < cHull0.polygonData.size(); ++i) + for (uint32_t i = 0; i < cHull0.polygonDataCount; ++i) { - uint32_t offset = cHull0.polygonData[i].mIndexBase; + auto& pd = cHull0.polygonData[i]; PxVec3 result; - for (uint32_t j = 0; j < cHull0.polygonData[i].mNbVerts; ++j) + for (uint32_t j = 0; j < pd.mNbVerts; ++j) { - uint32_t nxj = (j + 1) % cHull0.polygonData[i].mNbVerts; - const uint32_t* ind = &cHull0.indices[0]; - PxVec3 a = hull0[ind[j + offset]] - pl.n * cvOffset[0]; - PxVec3 b = hull0[ind[nxj + offset]] - pl.n * cvOffset[0]; + uint32_t nxj = (j + 1) % pd.mNbVerts; + const uint32_t* ind = cHull0.indices; + PxVec3 a = hull0[ind[j + pd.mIndexBase]] - pl.n * cvOffset[0]; + PxVec3 b = hull0[ind[nxj + pd.mIndexBase]] - pl.n * cvOffset[0]; if (getPlaneSegmentIntersection(pl, a, b, result)) { @@ -630,16 +650,16 @@ namespace Nv } } - for (uint32_t i = 0; i < cHull1.polygonData.size(); ++i) + for (uint32_t i = 0; i < cHull1.polygonDataCount; ++i) { - uint32_t offset = cHull1.polygonData[i].mIndexBase; + auto& pd = cHull1.polygonData[i]; PxVec3 result; - for (uint32_t j = 0; j < cHull1.polygonData[i].mNbVerts; ++j) + for (uint32_t j = 0; j < pd.mNbVerts; ++j) { - uint32_t nxj = (j + 1) % cHull1.polygonData[i].mNbVerts; - const uint32_t* ind = &cHull1.indices[0]; - PxVec3 a = hull1[ind[j + offset]] - pl.n * cvOffset[1]; - PxVec3 b = hull1[ind[nxj + offset]] - pl.n * cvOffset[1]; + uint32_t nxj = (j + 1) % pd.mNbVerts; + const uint32_t* ind = cHull1.indices; + PxVec3 a = hull1[ind[j + pd.mIndexBase]] - pl.n * cvOffset[1]; + PxVec3 b = hull1[ind[nxj + pd.mIndexBase]] - pl.n * cvOffset[1]; if (getPlaneSegmentIntersection(pl, a, b, result)) { @@ -696,56 +716,59 @@ namespace Nv return 0; } - - int32_t BlastBondGenerator::buildDescFromInternalFracture(FractureTool* tool, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& mResultBondDescs, std::vector<NvBlastChunkDesc>& mResultChunkDescriptors) + int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool, const bool* chunkIsSupport, + NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors) { - const std::vector<ChunkInfo>& chunkData = tool->getChunkList(); - std::vector<std::vector<Triangle> > trianglesBuffer(chunkData.size()); + uint32_t chunkCount = tool->getChunkCount(); + std::vector<uint32_t> trianglesCount(chunkCount); + std::vector<Triangle*> trianglesBuffer(chunkCount); for (uint32_t i = 0; i < trianglesBuffer.size(); ++i) { - tool->getBaseMesh(i, trianglesBuffer[i]); + trianglesCount[i] = tool->getBaseMesh(i, trianglesBuffer[i]); } - if (chunkData.empty() || trianglesBuffer.empty()) + if (chunkCount == 0) { - return 1; + return 0; } - mResultChunkDescriptors.resize(trianglesBuffer.size()); + resultChunkDescriptors = SAFE_ARRAY_NEW(NvBlastChunkDesc, trianglesBuffer.size()); std::vector<Bond> bondDescriptors; - mResultChunkDescriptors[0].parentChunkIndex = UINT32_MAX; - mResultChunkDescriptors[0].userData = 0; + resultChunkDescriptors[0].parentChunkIndex = UINT32_MAX; + resultChunkDescriptors[0].userData = 0; + resultChunkDescriptors[0].flags = NvBlastChunkDesc::NoFlags; { PxVec3 chunkCentroid(0, 0, 0); - for (uint32_t tr = 0; tr < trianglesBuffer[0].size(); ++tr) + for (uint32_t tr = 0; tr < trianglesCount[0]; ++tr) { chunkCentroid += trianglesBuffer[0][tr].a.p; chunkCentroid += trianglesBuffer[0][tr].b.p; chunkCentroid += trianglesBuffer[0][tr].c.p; } - chunkCentroid *= (1.0f / (3 * trianglesBuffer[0].size())); - mResultChunkDescriptors[0].centroid[0] = chunkCentroid[0]; - mResultChunkDescriptors[0].centroid[1] = chunkCentroid[1]; - mResultChunkDescriptors[0].centroid[2] = chunkCentroid[2]; + chunkCentroid *= (1.0f / (3 * trianglesCount[0])); + resultChunkDescriptors[0].centroid[0] = chunkCentroid[0]; + resultChunkDescriptors[0].centroid[1] = chunkCentroid[1]; + resultChunkDescriptors[0].centroid[2] = chunkCentroid[2]; } - for (uint32_t i = 1; i < chunkData.size(); ++i) + for (uint32_t i = 1; i < chunkCount; ++i) { - - mResultChunkDescriptors[i].userData = i; - mResultChunkDescriptors[i].parentChunkIndex = tool->getChunkIndex(chunkData[i].parent); + NvBlastChunkDesc& desc = resultChunkDescriptors[i]; + desc.userData = i; + desc.parentChunkIndex = tool->getChunkIndex(tool->getChunkInfo(i).parent); + desc.flags = NvBlastChunkDesc::NoFlags; if (chunkIsSupport[i]) - mResultChunkDescriptors[i].flags = NvBlastChunkDesc::SupportFlag; + desc.flags = NvBlastChunkDesc::SupportFlag; PxVec3 chunkCentroid(0, 0, 0); - for (uint32_t tr = 0; tr < trianglesBuffer[i].size(); ++tr) + for (uint32_t tr = 0; tr < trianglesCount[i]; ++tr) { chunkCentroid += trianglesBuffer[i][tr].a.p; chunkCentroid += trianglesBuffer[i][tr].b.p; chunkCentroid += trianglesBuffer[i][tr].c.p; Triangle& trRef = trianglesBuffer[i][tr]; - int32_t id = trRef.userInfo; + int32_t id = trRef.userData; if (id == 0) continue; bondDescriptors.push_back(Bond()); @@ -754,10 +777,10 @@ namespace Nv bond.m_planeIndex = id; bond.triangleIndex = tr; } - chunkCentroid *= (1.0f / (3 * trianglesBuffer[i].size())); - mResultChunkDescriptors[i].centroid[0] = chunkCentroid[0]; - mResultChunkDescriptors[i].centroid[1] = chunkCentroid[1]; - mResultChunkDescriptors[i].centroid[2] = chunkCentroid[2]; + chunkCentroid *= (1.0f / (3 * trianglesCount[i])); + desc.centroid[0] = chunkCentroid[0]; + desc.centroid[1] = chunkCentroid[1]; + desc.centroid[2] = chunkCentroid[2]; } std::sort(bondDescriptors.begin(), bondDescriptors.end()); if (bondDescriptors.empty()) @@ -778,6 +801,7 @@ namespace Nv chunkId = -1; planeId = bondDescriptors[0].m_planeIndex; + std::vector<NvBlastBondDesc> mResultBondDescs; for (uint32_t i = 0; i <= bondDescriptors.size(); ++i) { if (i == bondDescriptors.size() || (chunkId != bondDescriptors[i].m_chunkId || abs(planeId) != abs(bondDescriptors[i].m_planeIndex))) @@ -866,70 +890,81 @@ namespace Nv bb.include(trianglesBuffer[chunkId][tr].c.p); } - return 0; + resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size()); + memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc) * mResultBondDescs.size()); + + return mResultBondDescs.size(); } - int32_t BlastBondGenerator::createBondBetweenMeshes(const std::vector<std::vector<Triangle> >& geometry, std::vector<NvBlastBondDesc>& resultBond,const std::vector<std::pair<uint32_t, uint32_t> >& overlaps, BondGenerationConfig cfg) + int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + uint32_t overlapsCount, const uint32_t* overlapsA, const uint32_t* overlapsB, NvBlastBondDesc*& resultBond, BondGenerationConfig cfg) { if (cfg.bondMode == BondGenerationConfig::AVERAGE) { resetGeometryCache(); - buildGeometryCache(geometry); + buildGeometryCache(meshCount, geometryOffset, geometry); } - resultBond.clear(); - resultBond.resize(overlaps.size()); + resultBond = SAFE_ARRAY_NEW(NvBlastBondDesc, overlapsCount); if (cfg.bondMode == BondGenerationConfig::EXACT) { - for (uint32_t i = 0; i < overlaps.size(); ++i) + for (uint32_t i = 0; i < overlapsCount; ++i) { - resultBond[i].chunkIndices[0] = overlaps[i].first; - resultBond[i].chunkIndices[1] = overlaps[i].second; - createBondBetweenMeshes(geometry[overlaps[i].first], geometry[overlaps[i].second], resultBond[i].bond, cfg); + NvBlastBondDesc& desc = resultBond[i]; + desc.chunkIndices[0] = overlapsA[i]; + desc.chunkIndices[1] = overlapsB[i]; + uint32_t meshACount = geometryOffset[overlapsA[i] + 1] - geometryOffset[overlapsA[i]]; + uint32_t meshBCount = geometryOffset[overlapsB[i] + 1] - geometryOffset[overlapsB[i]]; + createBondBetweenMeshes(meshACount, geometry + geometryOffset[overlapsA[i]], + meshBCount, geometry + geometryOffset[overlapsB[i]], desc.bond, cfg); } } else { - for (uint32_t i = 0; i < overlaps.size(); ++i) + for (uint32_t i = 0; i < overlapsCount; ++i) { - resultBond[i].chunkIndices[0] = overlaps[i].first; - resultBond[i].chunkIndices[1] = overlaps[i].second; - createBondForcedInternal(mHullsPointsCache[overlaps[i].first], mHullsPointsCache[overlaps[i].second], mCHullCache[overlaps[i].first], mCHullCache[overlaps[i].second], - mBoundsCache[overlaps[i].first], mBoundsCache[overlaps[i].second], resultBond[i].bond, 0.3f); + NvBlastBondDesc& desc = resultBond[i]; + desc.chunkIndices[0] = overlapsA[i]; + desc.chunkIndices[1] = overlapsB[i]; + createBondForcedInternal(mHullsPointsCache[overlapsA[i]], mHullsPointsCache[overlapsB[i]], *mCHullCache[overlapsA[i]], *mCHullCache[overlapsB[i]], + mBoundsCache[overlapsA[i]], mBoundsCache[overlapsB[i]], desc.bond, 0.3f); } } - return 0; + return overlapsCount; } - - int32_t BlastBondGenerator::createBondBetweenMeshes(const std::vector<Triangle>& meshA, const std::vector<Triangle>& meshB, NvBlastBond& resultBond, BondGenerationConfig conf) + int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB, + NvBlastBond& resultBond, BondGenerationConfig conf) { float overlapping = 0.3; if (conf.bondMode == BondGenerationConfig::EXACT) { - std::vector<std::vector<Triangle> > chunks; - chunks.push_back(meshA); - chunks.push_back(meshB); - std::vector<bool> isSupport(2, true); - std::vector<NvBlastBondDesc> desc; - createFullBondListExact(chunks, isSupport, desc, conf); - if (desc.size() > 0) + std::vector<uint32_t> chunksOffsets = { 0, meshACount, meshACount + meshBCount }; + std::vector<Triangle> chunks; + chunks.resize(meshACount + meshBCount); + memcpy(chunks.data(), meshA, sizeof(Triangle) * meshACount); + memcpy(chunks.data() + meshACount, meshB, sizeof(Triangle) * meshBCount); + std::shared_ptr<bool> isSupport(new bool[2] {true, true}, [](bool* b) { delete[] b; }); + NvBlastBondDesc* desc; + uint32_t descSize = createFullBondListExact(2, chunksOffsets.data(), chunks.data(), isSupport.get(), desc, conf); + if (descSize > 0) { - resultBond = desc.back().bond; + resultBond = desc->bond; } else { + memset(&resultBond, 0, sizeof(NvBlastBond)); return 1; } return 0; } - std::vector<PxVec3> chunksPoints1(meshA.size() * 3); - std::vector<PxVec3> chunksPoints2(meshB.size() * 3); + std::vector<PxVec3> chunksPoints1(meshACount * 3); + std::vector<PxVec3> chunksPoints2(meshBCount * 3); int32_t sp = 0; - for (uint32_t i = 0; i < meshA.size(); ++i) + for (uint32_t i = 0; i < meshACount; ++i) { chunksPoints1[sp++] = meshA[i].a.p; chunksPoints1[sp++] = meshA[i].b.p; @@ -943,7 +978,7 @@ namespace Nv } sp = 0; - for (uint32_t i = 0; i < meshB.size(); ++i) + for (uint32_t i = 0; i < meshBCount; ++i) { chunksPoints2[sp++] = meshB[i].a.p; chunksPoints2[sp++] = meshB[i].b.p; @@ -956,16 +991,16 @@ namespace Nv } - Nv::Blast::ConvexMeshBuilder builder(mPxCooking, mPxInsertionCallback); + Nv::Blast::ConvexMeshBuilderImpl builder(mPxCooking, mPxInsertionCallback); - CollisionHull cHull[2]; + CollisionHull* cHull[2]; - builder.buildCollisionGeometry(chunksPoints1, cHull[0]); - builder.buildCollisionGeometry(chunksPoints2, cHull[1]); + cHull[0] = builder.buildCollisionGeometry(chunksPoints1.size(), chunksPoints1.data()); + cHull[1] = builder.buildCollisionGeometry(chunksPoints2.size(), chunksPoints2.data()); std::vector<PxVec3> hullPoints[2]; - hullPoints[0].resize(cHull[0].points.size()); - hullPoints[1].resize(cHull[1].points.size()); + hullPoints[0].resize(cHull[0]->pointsCount); + hullPoints[1].resize(cHull[1]->pointsCount); PxBounds3 bb[2]; @@ -974,18 +1009,40 @@ namespace Nv for (uint32_t cv = 0; cv < 2; ++cv) { - for (uint32_t i = 0; i < cHull[cv].points.size(); ++i) + for (uint32_t i = 0; i < cHull[cv]->pointsCount; ++i) { - hullPoints[cv][i].x = cHull[cv].points[i].x; - hullPoints[cv][i].y = cHull[cv].points[i].y; - hullPoints[cv][i].z = cHull[cv].points[i].z; + hullPoints[cv][i] = cHull[cv]->points[i]; bb[cv].include(hullPoints[cv][i]); } } - return createBondForcedInternal(hullPoints[0], hullPoints[1], cHull[0], cHull[1], bb[0], bb[1], resultBond, overlapping); + auto ret = createBondForcedInternal(hullPoints[0], hullPoints[1], *cHull[0], *cHull[1], bb[0], bb[1], resultBond, overlapping); + + cHull[0]->release(); + cHull[1]->release(); + + return ret; } + int32_t BlastBondGeneratorImpl::bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryCount, const Triangle* geometry, + const bool*& chunkIsSupport, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf) + { + int32_t ret_val = 0; + switch (conf.bondMode) + { + case BondGenerationConfig::AVERAGE: + ret_val = createFullBondListAveraged(meshCount, geometryCount, geometry, chunkIsSupport, resultBondDescs, conf); + break; + case BondGenerationConfig::EXACT: + ret_val = createFullBondListExact(meshCount, geometryCount, geometry, chunkIsSupport, resultBondDescs, conf); + break; + } + return ret_val; + } + void BlastBondGeneratorImpl::release() + { + delete this; + } } } diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h new file mode 100644 index 0000000..35c4b23 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h @@ -0,0 +1,104 @@ +// 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. + + +#ifndef NVBLASTEXTAUTHORINGBONDGENERATORIMPL_H +#define NVBLASTEXTAUTHORINGBONDGENERATORIMPL_H + +#include "NvBlastExtAuthoringBondGenerator.h" +#include "NvBlastExtAuthoringFractureTool.h" +#include "../cooking/PxCooking.h" +#include <PxPlane.h> +#include <NvBlastExtAuthoringCollisionBuilder.h> +#include <vector> + +namespace Nv +{ +namespace Blast +{ + +/** + Tool for gathering bond information from provided mesh geometry +*/ + +class BlastBondGeneratorImpl : public BlastBondGenerator +{ +public: + + BlastBondGeneratorImpl(physx::PxCooking* cooking, physx::PxPhysicsInsertionCallback* insertionCallback) + : mPxCooking(cooking), mPxInsertionCallback(insertionCallback){}; + + virtual void release() override; + + virtual int32_t buildDescFromInternalFracture(FractureTool* tool, const bool* chunkIsSupport, + NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors) override; + + virtual int32_t createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB, + NvBlastBond& resultBond, BondGenerationConfig conf = BondGenerationConfig()) override; + + virtual int32_t createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + uint32_t overlapsCount, const uint32_t* overlapsA, const uint32_t* overlapsB, + NvBlastBondDesc*& resultBond, BondGenerationConfig cfg) override; + + virtual int32_t bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool*& chunkIsSupport, NvBlastBondDesc*& resultBondDescs, + BondGenerationConfig conf = BondGenerationConfig()) override; + +private: + float processWithMidplanes( TriangleProcessor* trProcessor, + const std::vector<physx::PxVec3>& chunk1Points, const std::vector<physx::PxVec3>& chunk2Points, + const std::vector<physx::PxVec3>& hull1p, const std::vector<physx::PxVec3>& hull2p, + physx::PxVec3& normal, physx::PxVec3& centroid); + + int32_t createFullBondListAveraged( uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf); + int32_t createFullBondListExact( uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf); + int32_t createFullBondListExactInternal(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, + std::vector<PlaneChunkIndexer>& planeTriangleMapping , NvBlastBondDesc*& resultBondDescs); + int32_t createBondForcedInternal( const std::vector<physx::PxVec3>& hull0, const std::vector<physx::PxVec3>& hull1,const CollisionHull& cHull0, + const CollisionHull& cHull1, physx::PxBounds3 bound0, physx::PxBounds3 bound1, NvBlastBond& resultBond, float overlapping); + + void buildGeometryCache(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry); + void resetGeometryCache(); + + physx::PxCooking* mPxCooking; + physx::PxPhysicsInsertionCallback* mPxInsertionCallback; + + + std::vector<std::vector<Triangle> > mGeometryCache; + + std::vector<PlaneChunkIndexer> mPlaneCache; + std::vector<CollisionHull*> mCHullCache; + std::vector<std::vector<physx::PxVec3> > mHullsPointsCache; + std::vector<physx::PxBounds3 > mBoundsCache; +}; + +} // namespace Blast +} // namespace Nv + +#endif // NVBLASTEXTAUTHORINGBONDGENERATORIMPL_H
\ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp index b5030d7..7705173 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp @@ -1,15 +1,34 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastGlobals.h" #include "NvBlastExtAuthoringBooleanTool.h" -#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringMeshImpl.h" #include "NvBlastExtAuthoringAccelerator.h" #include <math.h> @@ -41,7 +60,6 @@ NV_FORCE_INLINE void vec2Lerp(const PxVec2& a, const PxVec2& b, PxVec2& out, flo out.y = (b.y - a.y) * t + a.y; } - NV_FORCE_INLINE int32_t BooleanEvaluator::addIfNotExist(Vertex& p) { mVerticesAggregate.push_back(p); @@ -187,18 +205,26 @@ int32_t shadowing10(const PxVec3& sEdge, const PxVec3& eEdge, const PxVec3& p) Vertex-facet shadowing functions */ -int32_t vfStatus02(const PxVec3& p, const Vertex* points, const Edge* edges, int32_t edgesCount, Vertex& out1, Vertex& out2) +int32_t vfStatus02(const PxVec3& p, const Vertex* points, const Edge* edges, int32_t edgesCount, Vertex* out) { int32_t val = 0; Vertex pnt; bool hasOnEdge = false; + out[0].p.y = -MAXIMUM_EXTENT; + out[1].p.y = MAXIMUM_EXTENT; for (int32_t i = 0; i < edgesCount; ++i) { val -= shadowing01(points[edges->s], points[edges->e], p, pnt, hasOnEdge); if (hasOnEdge != 0) { - out2 = out1; - out1 = pnt; + if (p.y > pnt.p.y && pnt.p.y > out[0].p.y) + { + out[0] = pnt; + } + if (p.y < pnt.p.y && pnt.p.y < out[1].p.y) + { + out[1] = pnt; + } } ++edges; } @@ -208,24 +234,24 @@ int32_t vfStatus02(const PxVec3& p, const Vertex* points, const Edge* edges, int int32_t shadowing02(const PxVec3& p, const Vertex* points, const Edge* edges, int edgesCount, bool& hasOnFacetPoint, Vertex& onFacetPoint) { - Vertex p1, p2; - int32_t stat = vfStatus02(p, points, edges, edgesCount, p1, p2); + Vertex outp[2]; + int32_t stat = vfStatus02(p, points, edges, edgesCount, outp); float z = 0; hasOnFacetPoint = false; if (stat != 0) { + Vertex& p1 = outp[0]; + Vertex& p2 = outp[1]; PxVec3 vc = p2.p - p1.p; float t = 0; - t = (abs(vc.x) > abs(vc.y)) ? (p.x - p1.p.x) / vc.x : (p.y - p1.p.y) / vc.y; - t = (t < 0) ? 0 : t; - t = (t > 1) ? 1 : t; - z = t * vc.z + p1.p.z; + t = (std::abs(vc.x) > std::abs(vc.y)) ? (p.x - p1.p.x) / vc.x : (p.y - p1.p.y) / vc.y; + t = PxClamp(t, 0.0f, 1.0f); + z = t * vc.z + p1.p.z; hasOnFacetPoint = true; onFacetPoint.p.x = p.x; onFacetPoint.p.y = p.y; onFacetPoint.p.z = z; - vec2Lerp(p1.uv[0], p2.uv[0], onFacetPoint.uv[0], t); vec3Lerp(p1.n, p2.n, onFacetPoint.n, t); @@ -237,18 +263,27 @@ int32_t shadowing02(const PxVec3& p, const Vertex* points, const Edge* edges, in return 0; } -int32_t vfStatus20(const PxVec3& p, const Vertex* points, const Edge* edges, int32_t edgesCount, Vertex& out1, Vertex& out2) +int32_t vfStatus20(const PxVec3& p, const Vertex* points, const Edge* edges, int32_t edgesCount, Vertex* out) { int32_t val = 0; Vertex pnt; bool hasOnEdge = false; + out[0].p.y = -MAXIMUM_EXTENT; + out[1].p.y = MAXIMUM_EXTENT; + for (int32_t i = 0; i < edgesCount; ++i) { val += shadowing10(points[edges->s], points[edges->e], p, pnt, hasOnEdge); if (hasOnEdge != 0) { - out2 = out1; - out1 = pnt; + if (p.y > pnt.p.y && pnt.p.y > out[0].p.y) + { + out[0] = pnt; + } + if (p.y < pnt.p.y && pnt.p.y < out[1].p.y) + { + out[1] = pnt; + } } ++edges; } @@ -257,17 +292,18 @@ int32_t vfStatus20(const PxVec3& p, const Vertex* points, const Edge* edges, int int32_t shadowing20(const PxVec3& p, const Vertex* points, const Edge* edges, int edgesCount, bool& hasOnFacetPoint, Vertex& onFacetPoint) { - Vertex p1, p2; - int32_t stat = vfStatus20(p, points, edges, edgesCount, p1, p2); + Vertex outp[2]; + int32_t stat = vfStatus20(p, points, edges, edgesCount, outp); hasOnFacetPoint = false; if (stat != 0) { + Vertex& p1 = outp[0]; + Vertex& p2 = outp[1]; PxVec3 vc = p2.p - p1.p; float t = 0; - t = (abs(vc.x) > abs(vc.y)) ? (p.x - p1.p.x) / vc.x : (p.y - p1.p.y) / vc.y; - t = (t < 0) ? 0 : t; - t = (t > 1) ? 1 : t; - + t = (std::abs(vc.x) > std::abs(vc.y)) ? (p.x - p1.p.x) / vc.x : (p.y - p1.p.y) / vc.y; + t = PxClamp(t, 0.0f, 1.0f); + hasOnFacetPoint = true; onFacetPoint.p.x = p.x; onFacetPoint.p.y = p.y; @@ -291,91 +327,72 @@ NV_FORCE_INLINE int32_t edgesCrossCheck(const PxVec3& eAs, const PxVec3& eAe, co return shadowing01(eBs, eBe, eAe) - shadowing01(eBs, eBe, eAs) + shadowing10(eAs, eAe, eBe) - shadowing10(eAs, eAe, eBs); } + + int32_t edgesIntersection(const Vertex& eAs, const Vertex& eAe, const Vertex& eBs, const Vertex& eBe, Vertex& intersectionA, Vertex& intersectionB, bool& hasPoints) { int32_t status = edgesCrossCheck(eAs.p, eAe.p, eBs.p, eBe.p); hasPoints = false; if (status == 0) + { return 0; - Vertex tempPoint; + } + Vertex tempPoint; Vertex bShadowingPair[2]; Vertex aShadowingPair[2]; bool hasOnEdge = false; - int32_t shadowingType = shadowing10(eAs, eAe, eBs.p, tempPoint, hasOnEdge); - bool aShadowing = false; - bool bShadowing = false; + bool bShadowing = false; + /** + Search for two pairs where parts of A shadows B, and where B shadows are. + Needed for search intersection point. + */ - if (shadowingType == 0 && hasOnEdge) - { - aShadowing = true; - aShadowingPair[0] = eBs; - aShadowingPair[1] = tempPoint; - } - else + for (auto p : { &eBs, &eBe }) { - if (shadowingType == 1 || shadowingType == -1) + int32_t shadowingType = shadowing10(eAs, eAe, p->p, tempPoint, hasOnEdge); + if (shadowingType == 0 && !aShadowing && hasOnEdge) { - bShadowing = true; - bShadowingPair[0] = eBs; - bShadowingPair[1] = tempPoint; + aShadowing = true; + aShadowingPair[0] = *p; + aShadowingPair[1] = tempPoint; } - } - - shadowingType = shadowing10(eAs, eAe, eBe.p, tempPoint, hasOnEdge); - - if (shadowingType == 0 && !aShadowing && hasOnEdge) - { - aShadowing = true; - aShadowingPair[0] = eBe; - aShadowingPair[1] = tempPoint; - } - else - { - if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + else { - bShadowing = true; - bShadowingPair[0] = eBe; - bShadowingPair[1] = tempPoint; + if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + { + bShadowing = true; + bShadowingPair[0] = *p; + bShadowingPair[1] = tempPoint; + } } } - shadowingType = shadowing01(eBs, eBe, eAe.p, tempPoint, hasOnEdge); - - if (shadowingType == 0 && !aShadowing && hasOnEdge) + if (!aShadowing || !bShadowing) { - aShadowing = true; - aShadowingPair[1] = eAe; - aShadowingPair[0] = tempPoint; - } - else - { - if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + for (auto p : { &eAs, &eAe }) { - bShadowing = true; - bShadowingPair[1] = eAe; - bShadowingPair[0] = tempPoint; - } - } + int32_t shadowingType = shadowing01(eBs, eBe, p->p, tempPoint, hasOnEdge); - shadowingType = shadowing01(eBs, eBe, eAs.p, tempPoint, hasOnEdge); - - if (shadowingType == 0 && !aShadowing && hasOnEdge) - { - aShadowing = true; - aShadowingPair[1] = eAs; - aShadowingPair[0] = tempPoint; - } - else - { - if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) - { - bShadowing = true; - bShadowingPair[1] = eAs; - bShadowingPair[0] = tempPoint; + if (shadowingType == 0 && !aShadowing && hasOnEdge) + { + aShadowing = true; + aShadowingPair[1] = *p; + aShadowingPair[0] = tempPoint; + } + else + { + if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + { + bShadowing = true; + bShadowingPair[1] = *p; + bShadowingPair[0] = tempPoint; + } + } } } + float deltaPlus = bShadowingPair[0].p.y - bShadowingPair[1].p.y; float deltaMinus = aShadowingPair[0].p.y - aShadowingPair[1].p.y; float div = 0; @@ -413,43 +430,30 @@ int32_t edgeFacetIntersection12(const Vertex& edSt, const Vertex& edEnd, const V Vertex bShadowingPair[2]; Vertex aShadowingPair[2]; bool hasPoint = false; - int32_t shadowingType = shadowing02(edEnd.p, points, edges, edgesCount, hasPoint, p1); - status -= shadowingType; bool aShadowing = false; bool bShadowing = false; - - if (shadowingType == 0 && hasPoint) + int32_t mlt = -1; + int32_t shadowingType; + for (auto p : { &edEnd, &edSt }) { - aShadowing = true; - aShadowingPair[0] = p1; - aShadowingPair[1] = edEnd; - } - else - { - if (shadowingType == 1 || shadowingType == -1) + shadowingType = shadowing02(p->p, points, edges, edgesCount, hasPoint, p1); + status += mlt * shadowingType; + if (shadowingType == 0 && !aShadowing && hasPoint) { - bShadowing = true; - bShadowingPair[0] = p1; - bShadowingPair[1] = edEnd; + aShadowing = true; + aShadowingPair[0] = p1; + aShadowingPair[1] = *p; } - } - - shadowingType = shadowing02(edSt.p, points, edges, edgesCount, hasPoint, p1); - status += shadowingType; - if (shadowingType == 0 && !aShadowing && hasPoint) - { - aShadowing = true; - aShadowingPair[0] = p1; - aShadowingPair[1] = edSt; - } - else - { - if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + else { - bShadowing = true; - bShadowingPair[0] = p1; - bShadowingPair[1] = edSt; + if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + { + bShadowing = true; + bShadowingPair[0] = p1; + bShadowingPair[1] = *p; + } } + mlt = 1; } for (int32_t ed = 0; ed < edgesCount; ++ed) @@ -472,14 +476,11 @@ int32_t edgeFacetIntersection12(const Vertex& edSt, const Vertex& edEnd, const V } } } - if (status == 0) - { - return 0; - } - if (!bShadowing || !aShadowing) + if (!status || !bShadowing || !aShadowing) { return 0; } + float deltaPlus = bShadowingPair[0].p.z - bShadowingPair[1].p.z; float div = 0; if (deltaPlus != 0) @@ -508,42 +509,32 @@ int32_t edgeFacetIntersection21(const Vertex& edSt, const Vertex& edEnd, const V Vertex bShadowingPair[2]; Vertex aShadowingPair[2]; bool hasPoint = false; - int32_t shadowingType = shadowing20(edEnd.p, points, edges, edgesCount, hasPoint, p1); - status = shadowingType; bool aShadowing = false; bool bShadowing = false; - if (shadowingType == 0 && hasPoint) - { - aShadowing = true; - aShadowingPair[0] = edEnd; - aShadowingPair[1] = p1; - } - else + + int32_t shadowingType; + int32_t mlt = 1; + for (auto p : { &edEnd, &edSt }) { - if (shadowingType == 1 || shadowingType == -1) + shadowingType = shadowing20(p->p, points, edges, edgesCount, hasPoint, p1); + status += mlt * shadowingType; + + if (shadowingType == 0 && !aShadowing && hasPoint) { - bShadowing = true; - bShadowingPair[0] = edEnd; - bShadowingPair[1] = p1; + aShadowing = true; + aShadowingPair[0] = *p; + aShadowingPair[1] = p1; } - } - - shadowingType = shadowing20(edSt.p, points, edges, edgesCount, hasPoint, p1); - status -= shadowingType; - if (shadowingType == 0 && !aShadowing && hasPoint) - { - aShadowing = true; - aShadowingPair[0] = edSt; - aShadowingPair[1] = p1; - } - else - { - if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + else { - bShadowing = true; - bShadowingPair[0] = edSt; - bShadowingPair[1] = p1; + if ((shadowingType == 1 || shadowingType == -1) && !bShadowing) + { + bShadowing = true; + bShadowingPair[0] = *p; + bShadowingPair[1] = p1; + } } + mlt = -1; } for (int32_t ed = 0; ed < edgesCount; ++ed) @@ -569,11 +560,7 @@ int32_t edgeFacetIntersection21(const Vertex& edSt, const Vertex& edEnd, const V } } } - if (status == 0) - { - return 0; - } - if (!bShadowing || !aShadowing) + if (!status || !bShadowing || !aShadowing) { return 0; } @@ -595,7 +582,7 @@ int32_t edgeFacetIntersection21(const Vertex& edSt, const Vertex& edEnd, const V return status; } -int32_t BooleanEvaluator::vertexMeshStatus03(const PxVec3& p, Mesh* mesh) +int32_t BooleanEvaluator::vertexMeshStatus03(const PxVec3& p, const Mesh* mesh) { int32_t status = 0; Vertex pnt; @@ -604,7 +591,7 @@ int32_t BooleanEvaluator::vertexMeshStatus03(const PxVec3& p, Mesh* mesh) int32_t facet = mAcceleratorB->getNextFacet(); while (facet != -1) { - Edge* ed = mesh->getEdges() + mesh->getFacet(facet)->firstEdgeNumber; + const Edge* ed = mesh->getEdges() + mesh->getFacet(facet)->firstEdgeNumber; status += shadowing02(p, mesh->getVertices(), ed, mesh->getFacet(facet)->edgesCount, hasPoint, pnt); facet = mAcceleratorB->getNextFacet(); } @@ -618,7 +605,7 @@ int32_t BooleanEvaluator::vertexMeshStatus03(const PxVec3& p, Mesh* mesh) return status; } -int32_t BooleanEvaluator::vertexMeshStatus30(const PxVec3& p, Mesh* mesh) +int32_t BooleanEvaluator::vertexMeshStatus30(const PxVec3& p, const Mesh* mesh) { int32_t status = 0; bool hasPoints = false; @@ -627,7 +614,7 @@ int32_t BooleanEvaluator::vertexMeshStatus30(const PxVec3& p, Mesh* mesh) int32_t facet = mAcceleratorA->getNextFacet(); while ( facet != -1) { - Edge* ed = mesh->getEdges() + mesh->getFacet(facet)->firstEdgeNumber; + const Edge* ed = mesh->getEdges() + mesh->getFacet(facet)->firstEdgeNumber; status -= shadowing20(p, mesh->getVertices(), ed, mesh->getFacet(facet)->edgesCount, hasPoints, point); facet = mAcceleratorA->getNextFacet(); } @@ -675,7 +662,7 @@ struct VertexPairComparator } }; -int32_t BooleanEvaluator::isPointContainedInMesh(Mesh* msh, const PxVec3& point) +int32_t BooleanEvaluator::isPointContainedInMesh(const Mesh* msh, const PxVec3& point) { if (msh == nullptr) { @@ -687,7 +674,7 @@ int32_t BooleanEvaluator::isPointContainedInMesh(Mesh* msh, const PxVec3& point) } -int32_t BooleanEvaluator::isPointContainedInMesh(Mesh* msh, SpatialAccelerator* spAccel, const PxVec3& point) +int32_t BooleanEvaluator::isPointContainedInMesh(const Mesh* msh, SpatialAccelerator* spAccel, const PxVec3& point) { if (msh == nullptr) { @@ -724,8 +711,8 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) Vertex newPointA; Vertex newPointB; - Vertex* meshAPoints = mMeshA->getVertices(); - Vertex* meshBPoints = mMeshB->getVertices(); + const Vertex* meshAPoints = mMeshA->getVertices(); + const Vertex* meshBPoints = mMeshB->getVertices(); EdgeWithParent newEdge; mEdgeFacetIntersectionData12.clear(); mEdgeFacetIntersectionData21.clear(); @@ -739,10 +726,10 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) int32_t facetA = mAcceleratorA->getNextFacet(); while (facetA != -1) { - Edge* facetBEdges = mMeshB->getEdges() + mMeshB->getFacet(facetB)->firstEdgeNumber; - Edge* facetAEdges = mMeshA->getEdges() + mMeshA->getFacet(facetA)->firstEdgeNumber; - Edge* fbe = facetBEdges; - Edge* fae = facetAEdges; + const Edge* facetBEdges = mMeshB->getEdges() + mMeshB->getFacet(facetB)->firstEdgeNumber; + const Edge* facetAEdges = mMeshA->getEdges() + mMeshA->getFacet(facetA)->firstEdgeNumber; + const Edge* fbe = facetBEdges; + const Edge* fae = facetAEdges; retainedStarts.clear(); retainedEnds.clear(); PxVec3 compositeEndPoint(0, 0, 0); @@ -814,7 +801,7 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) } if (retainedStarts.size() != retainedEnds.size()) { - NVBLAST_LOG_ERROR(mLoggingCallback, "Not equal number of starting and ending vertices! Probably input mesh has open edges."); + NVBLAST_LOG_ERROR("Not equal number of starting and ending vertices! Probably input mesh has open edges."); return; } if (retainedStarts.size() > 1) @@ -856,7 +843,7 @@ void BooleanEvaluator::buildFastFaceFaceIntersection(BooleanConf mode) Vertex newPointA; Vertex newPointB; - Vertex* meshAPoints = mMeshA->getVertices(); + const Vertex* meshAPoints = mMeshA->getVertices(); EdgeWithParent newEdge; mEdgeFacetIntersectionData12.clear(); @@ -867,10 +854,10 @@ void BooleanEvaluator::buildFastFaceFaceIntersection(BooleanConf mode) for (uint32_t facetA = 0; facetA < mMeshA->getFacetCount(); ++facetA) { - Edge* facetAEdges = mMeshA->getEdges() + mMeshA->getFacet(facetA)->firstEdgeNumber; + const Edge* facetAEdges = mMeshA->getEdges() + mMeshA->getFacet(facetA)->firstEdgeNumber; int32_t facetB = 0; - Edge* facetBEdges = mMeshB->getEdges() + mMeshB->getFacet(facetB)->firstEdgeNumber; - Edge* fae = facetAEdges; + const Edge* facetBEdges = mMeshB->getEdges() + mMeshB->getFacet(facetB)->firstEdgeNumber; + const Edge* fae = facetAEdges; retainedStarts.clear(); retainedEnds.clear(); PxVec3 compositeEndPoint(0, 0, 0); @@ -911,7 +898,7 @@ void BooleanEvaluator::buildFastFaceFaceIntersection(BooleanConf mode) } if (retainedStarts.size() != retainedEnds.size()) { - NVBLAST_LOG_ERROR(mLoggingCallback, "Not equal number of starting and ending vertices! Probably input mesh has open edges."); + NVBLAST_LOG_ERROR("Not equal number of starting and ending vertices! Probably input mesh has open edges."); return; } if (retainedStarts.size() > 1) @@ -942,11 +929,11 @@ void BooleanEvaluator::collectRetainedPartsFromA(BooleanConf mode) int32_t statusValue = 0; int32_t inclusionValue = 0; - Vertex* vertices = mMeshA->getVertices(); + const Vertex* vertices = mMeshA->getVertices(); Vertex newPoint; VertexComparator comp; - PxBounds3& bMeshBoudning = mMeshB->getBoundingBox(); - Edge* facetEdges = mMeshA->getEdges(); + const PxBounds3& bMeshBoudning = mMeshB->getBoundingBox(); + const Edge* facetEdges = mMeshA->getEdges(); std::vector<Vertex> retainedStartVertices; std::vector<Vertex> retainedEndVertices; retainedStartVertices.reserve(255); @@ -1053,7 +1040,7 @@ void BooleanEvaluator::collectRetainedPartsFromA(BooleanConf mode) facetEdges++; if (retainedStartVertices.size() != retainedEndVertices.size()) { - NVBLAST_LOG_ERROR(mLoggingCallback, "Not equal number of starting and ending vertices! Probably input mesh has open edges."); + NVBLAST_LOG_ERROR("Not equal number of starting and ending vertices! Probably input mesh has open edges."); return; } if (retainedEndVertices.size() > 1) @@ -1082,11 +1069,11 @@ void BooleanEvaluator::collectRetainedPartsFromB(BooleanConf mode) { int32_t statusValue = 0; int32_t inclusionValue = 0; - Vertex* vertices = mMeshB->getVertices(); + const Vertex* vertices = mMeshB->getVertices(); Vertex newPoint; VertexComparator comp; - PxBounds3& aMeshBoudning = mMeshA->getBoundingBox(); - Edge* facetEdges = mMeshB->getEdges(); + const PxBounds3& aMeshBoudning = mMeshA->getBoundingBox(); + const Edge* facetEdges = mMeshB->getEdges(); std::vector<Vertex> retainedStartVertices; std::vector<Vertex> retainedEndVertices; retainedStartVertices.reserve(255); @@ -1194,7 +1181,7 @@ void BooleanEvaluator::collectRetainedPartsFromB(BooleanConf mode) facetEdges++; if (retainedStartVertices.size() != retainedEndVertices.size()) { - NVBLAST_LOG_ERROR(mLoggingCallback, "Not equal number of starting and ending vertices! Probably input mesh has open edges."); + NVBLAST_LOG_ERROR("Not equal number of starting and ending vertices! Probably input mesh has open edges."); return; } if (retainedEndVertices.size() - lastPos > 1) @@ -1222,7 +1209,7 @@ bool EdgeWithParentSortComp(const EdgeWithParent& a, const EdgeWithParent& b) } -void BooleanEvaluator::performBoolean(Mesh* meshA, Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode) +void BooleanEvaluator::performBoolean(const Mesh* meshA, const Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode) { reset(); mMeshA = meshA; @@ -1236,7 +1223,7 @@ void BooleanEvaluator::performBoolean(Mesh* meshA, Mesh* meshB, SpatialAccelerat mAcceleratorB = nullptr; } -void BooleanEvaluator::performBoolean(Mesh* meshA, Mesh* meshB, BooleanConf mode) +void BooleanEvaluator::performBoolean(const Mesh* meshA, const Mesh* meshB, BooleanConf mode) { reset(); mMeshA = meshA; @@ -1247,7 +1234,7 @@ void BooleanEvaluator::performBoolean(Mesh* meshA, Mesh* meshB, BooleanConf mode } -void BooleanEvaluator::performFastCutting(Mesh* meshA, Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode) +void BooleanEvaluator::performFastCutting(const Mesh* meshA, const Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode) { reset(); mMeshA = meshA; @@ -1260,7 +1247,7 @@ void BooleanEvaluator::performFastCutting(Mesh* meshA, Mesh* meshB, SpatialAccel mAcceleratorB = nullptr; } -void BooleanEvaluator::performFastCutting(Mesh* meshA, Mesh* meshB, BooleanConf mode) +void BooleanEvaluator::performFastCutting(const Mesh* meshA, const Mesh* meshB, BooleanConf mode) { reset(); mMeshA = meshA; @@ -1273,13 +1260,12 @@ void BooleanEvaluator::performFastCutting(Mesh* meshA, Mesh* meshB, BooleanConf -BooleanEvaluator::BooleanEvaluator(NvBlastLog loggingCallback) +BooleanEvaluator::BooleanEvaluator() { mMeshA = nullptr; mMeshB = nullptr; mAcceleratorA = nullptr; mAcceleratorB = nullptr; - mLoggingCallback = loggingCallback; } BooleanEvaluator::~BooleanEvaluator() { @@ -1301,6 +1287,7 @@ Mesh* BooleanEvaluator::createNewMesh() int32_t lastParent = mEdgeAggregate[0].parent; uint32_t collected = 0; int32_t userData = 0; + int32_t materialId = 0; for (uint32_t i = 0; i < mEdgeAggregate.size(); ++i) { if (mEdgeAggregate[i].parent != lastParent) @@ -1308,12 +1295,14 @@ Mesh* BooleanEvaluator::createNewMesh() if (lastParent < (int32_t)mMeshA->getFacetCount()) { userData = mMeshA->getFacet(lastParent)->userData; + materialId = mMeshA->getFacet(lastParent)->materialId; } else { userData = mMeshB->getFacet(lastParent - mMeshA->getFacetCount())->userData; + materialId = mMeshB->getFacet(lastParent - mMeshA->getFacetCount())->materialId; } - newFacets.push_back(Facet(lastPos, collected, userData)); + newFacets.push_back(Facet(lastPos, collected, materialId, userData)); lastPos = i; lastParent = mEdgeAggregate[i].parent; collected = 0; @@ -1326,13 +1315,16 @@ Mesh* BooleanEvaluator::createNewMesh() if (lastParent < (int32_t)mMeshA->getFacetCount()) { userData = mMeshA->getFacet(lastParent)->userData; + materialId = mMeshA->getFacet(lastParent)->materialId; + } else { userData = mMeshB->getFacet(pr)->userData; + materialId = mMeshB->getFacet(pr)->materialId; } - newFacets.push_back(Facet(lastPos, collected, userData)); - return new Mesh(&mVerticesAggregate[0], &newEdges[0], &newFacets[0], static_cast<uint32_t>(mVerticesAggregate.size()), static_cast<uint32_t>(mEdgeAggregate.size()), static_cast<uint32_t>(newFacets.size())); + newFacets.push_back(Facet(lastPos, collected, materialId, userData)); + return new MeshImpl(mVerticesAggregate.data(), newEdges.data(), newFacets.data(), static_cast<uint32_t>(mVerticesAggregate.size()), static_cast<uint32_t>(mEdgeAggregate.size()), static_cast<uint32_t>(newFacets.size())); } void BooleanEvaluator::reset() diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h index 0b0b73a..f362495 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAUTHORINGBOOLEANTOOL_H #define NVBLASTEXTAUTHORINGBOOLEANTOOL_H @@ -92,7 +110,7 @@ class BooleanEvaluator { public: - BooleanEvaluator(NvBlastLog logCallback = nullptr); + BooleanEvaluator(); ~BooleanEvaluator(); /** @@ -103,7 +121,7 @@ public: \param[in] spAccelB Acceleration structure for mesh B \param[in] mode Boolean operation type */ - void performBoolean(Mesh* meshA, Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode); + void performBoolean(const Mesh* meshA, const Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode); /** Perform boolean operation on two polygonal meshes (A and B). @@ -111,7 +129,7 @@ public: \param[in] meshB Mesh B \param[in] mode Boolean operation type */ - void performBoolean(Mesh* meshA, Mesh* meshB, BooleanConf mode); + void performBoolean(const Mesh* meshA, const Mesh* meshB, BooleanConf mode); /** Perform cutting of mesh with some large box, which represents cutting plane. This method skips part of intersetion computations, so @@ -122,7 +140,7 @@ public: \param[in] spAccelB Acceleration structure for cutting box \param[in] mode Boolean operation type */ - void performFastCutting(Mesh* meshA, Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode); + void performFastCutting(const Mesh* meshA, const Mesh* meshB, SpatialAccelerator* spAccelA, SpatialAccelerator* spAccelB, BooleanConf mode); /** Perform cutting of mesh with some large box, which represents cutting plane. This method skips part of intersetion computations, so @@ -131,7 +149,7 @@ public: \param[in] meshB Cutting box \param[in] mode Boolean operation type */ - void performFastCutting(Mesh* meshA, Mesh* meshB, BooleanConf mode); + void performFastCutting(const Mesh* meshA, const Mesh* meshB, BooleanConf mode); /** Test whether point contained in mesh. @@ -139,7 +157,7 @@ public: \param[in] point Point which should be tested \return not 0 if point is inside of mesh */ - int32_t isPointContainedInMesh(Mesh* mesh, const physx::PxVec3& point); + int32_t isPointContainedInMesh(const Mesh* mesh, const physx::PxVec3& point); /** Test whether point contained in mesh. \param[in] mesh Mesh geometry @@ -147,7 +165,7 @@ public: \param[in] point Point which should be tested \return not 0 if point is inside of mesh */ - int32_t isPointContainedInMesh(Mesh* mesh, SpatialAccelerator* spAccel, const physx::PxVec3& point); + int32_t isPointContainedInMesh(const Mesh* mesh, SpatialAccelerator* spAccel, const physx::PxVec3& point); /** @@ -172,11 +190,11 @@ private: void addEdgeIfValid(EdgeWithParent& ed); private: - int32_t vertexMeshStatus03(const physx::PxVec3& p, Mesh* mesh); - int32_t vertexMeshStatus30(const physx::PxVec3& p, Mesh* mesh); + int32_t vertexMeshStatus03(const physx::PxVec3& p, const Mesh* mesh); + int32_t vertexMeshStatus30(const physx::PxVec3& p, const Mesh* mesh); - Mesh* mMeshA; - Mesh* mMeshB; + const Mesh* mMeshA; + const Mesh* mMeshB; SpatialAccelerator* mAcceleratorA; SpatialAccelerator* mAcceleratorB; @@ -186,8 +204,6 @@ private: std::vector<std::vector<EdgeFacetIntersectionData> > mEdgeFacetIntersectionData12; std::vector<std::vector<EdgeFacetIntersectionData> > mEdgeFacetIntersectionData21; - - NvBlastLog mLoggingCallback; }; } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilder.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp index becdce9..39c7586 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilder.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp @@ -1,14 +1,32 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. -#include "NvBlastExtAuthoringCollisionBuilder.h" + +#include "NvBlastExtAuthoringCollisionBuilderImpl.h" #include <PxConvexMesh.h> #include <PxVec3.h> #include <PxBounds3.h> @@ -18,18 +36,31 @@ #include <NvBlastExtAuthoringInternalCommon.h> #include <NvBlastExtAuthoringBooleanTool.h> -#include <NvBlastExtAuthoringMesh.h> +#include <NvBlastExtAuthoringMeshImpl.h> using namespace physx; +#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? new T[x] : nullptr; +#define SAFE_ARRAY_DELETE(x) if (x != nullptr) {delete[] x; x = nullptr;} + namespace Nv { namespace Blast { -void ConvexMeshBuilder::buildCollisionGeometry(const std::vector<PxVec3>& vData, CollisionHull& output) +void CollisionHullImpl::release() +{ + SAFE_ARRAY_DELETE(points); + SAFE_ARRAY_DELETE(indices); + SAFE_ARRAY_DELETE(polygonData); + delete this; +} + +CollisionHull* ConvexMeshBuilderImpl::buildCollisionGeometry(uint32_t verticesCount, const physx::PxVec3* vData) { - std::vector<physx::PxVec3> vertexData = vData; + CollisionHull* output = new CollisionHullImpl(); + std::vector<physx::PxVec3> vertexData(verticesCount); + memcpy(vertexData.data(), vData, sizeof(physx::PxVec3) * verticesCount); PxConvexMeshDesc convexMeshDescr; PxConvexMesh* resultConvexMesh; @@ -72,13 +103,16 @@ void ConvexMeshBuilder::buildCollisionGeometry(const std::vector<PxVec3>& vData, convexMeshDescr.points.count = (uint32_t)vertexData.size(); resultConvexMesh = mCooking->createConvexMesh(convexMeshDescr, *mInsertionCallback); } - output.polygonData.resize(resultConvexMesh->getNbPolygons()); - output.points.resize(resultConvexMesh->getNbVertices()); + output->polygonDataCount = resultConvexMesh->getNbPolygons(); + if (output->polygonDataCount) + output->polygonData = SAFE_ARRAY_NEW(CollisionHull::HullPolygon, output->polygonDataCount); + output->pointsCount = resultConvexMesh->getNbVertices(); + output->points = SAFE_ARRAY_NEW(PxVec3, output->pointsCount); int32_t indicesCount = 0; PxHullPolygon hPoly; for (uint32_t i = 0; i < resultConvexMesh->getNbPolygons(); ++i) { - CollisionHull::HullPolygon& pd = output.polygonData[i]; + CollisionHull::HullPolygon& pd = output->polygonData[i]; resultConvexMesh->getPolygonData(i, hPoly); pd.mIndexBase = hPoly.mIndexBase; pd.mNbVerts = hPoly.mNbVerts; @@ -98,47 +132,49 @@ void ConvexMeshBuilder::buildCollisionGeometry(const std::vector<PxVec3>& vData, pd.mPlane[3] /= length; indicesCount = PxMax(indicesCount, pd.mIndexBase + pd.mNbVerts); } - output.indices.resize(indicesCount); + output->indicesCount = indicesCount; + output->indices = SAFE_ARRAY_NEW(uint32_t, indicesCount); for (uint32_t i = 0; i < resultConvexMesh->getNbVertices(); ++i) { PxVec3 p = resultConvexMesh->getVertices()[i] * scale + bbCenter; - output.points[i] = p; + output->points[i] = p; } for (int32_t i = 0; i < indicesCount; ++i) { - output.indices[i] = resultConvexMesh->getIndexBuffer()[i]; + output->indices[i] = resultConvexMesh->getIndexBuffer()[i]; } resultConvexMesh->release(); + return output; } -void ConvexMeshBuilder::trimCollisionGeometry(std::vector<CollisionHull>& in, const std::vector<uint32_t>& chunkDepth) +void ConvexMeshBuilderImpl::trimCollisionGeometry(uint32_t chunksCount, CollisionHull** in, const uint32_t* chunkDepth) { - std::vector<std::vector<PxPlane> > chunkMidplanes(in.size()); - std::vector<PxVec3> centers(in.size()); - std::vector<PxBounds3> hullsBounds(in.size()); - for (uint32_t i = 0; i < in.size(); ++i) + std::vector<std::vector<PxPlane> > chunkMidplanes(chunksCount); + std::vector<PxVec3> centers(chunksCount); + std::vector<PxBounds3> hullsBounds(chunksCount); + for (uint32_t i = 0; i < chunksCount; ++i) { hullsBounds[i].setEmpty(); centers[i] = PxVec3(0, 0, 0); - for (uint32_t p = 0; p < in[i].points.size(); ++p) + for (uint32_t p = 0; p < in[i]->pointsCount; ++p) { - centers[i] += in[i].points[p]; - hullsBounds[i].include(in[i].points[p]); + centers[i] += in[i]->points[p]; + hullsBounds[i].include(in[i]->points[p]); } centers[i] = hullsBounds[i].getCenter(); } Separation params; - for (uint32_t hull = 0; hull < in.size(); ++hull) + for (uint32_t hull = 0; hull < chunksCount; ++hull) { - for (uint32_t hull2 = hull + 1; hull2 < in.size(); ++hull2) + for (uint32_t hull2 = hull + 1; hull2 < chunksCount; ++hull2) { if (chunkDepth[hull] != chunkDepth[hull2]) { continue; } - if (importerHullsInProximityApexFree(in[hull].points, hullsBounds[hull], PxTransform(PxIdentity), PxVec3(1, 1, 1), - in[hull2].points, hullsBounds[hull2], PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.0, ¶ms) == false) + if (importerHullsInProximityApexFree(in[hull]->pointsCount, in[hull]->points, hullsBounds[hull], PxTransform(PxIdentity), PxVec3(1, 1, 1), + in[hull2]->pointsCount, in[hull2]->points, hullsBounds[hull2], PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.0, ¶ms) == false) { continue; } @@ -147,22 +183,22 @@ void ConvexMeshBuilder::trimCollisionGeometry(std::vector<CollisionHull>& in, co float d = FLT_MAX; PxVec3 n1; PxVec3 n2; - for (uint32_t p = 0; p < in[hull].points.size(); ++p) + for (uint32_t p = 0; p < in[hull]->pointsCount; ++p) { - float ld = (in[hull].points[p] - c2).magnitude(); + float ld = (in[hull]->points[p] - c2).magnitude(); if (ld < d) { - n1 = in[hull].points[p]; + n1 = in[hull]->points[p]; d = ld; } } d = FLT_MAX; - for (uint32_t p = 0; p < in[hull2].points.size(); ++p) + for (uint32_t p = 0; p < in[hull2]->pointsCount; ++p) { - float ld = (in[hull2].points[p] - c1).magnitude(); + float ld = (in[hull2]->points[p] - c1).magnitude(); if (ld < d) { - n2 = in[hull2].points[p]; + n2 = in[hull2]->points[p]; d = ld; } } @@ -176,31 +212,32 @@ void ConvexMeshBuilder::trimCollisionGeometry(std::vector<CollisionHull>& in, co } } std::vector<PxVec3> hPoints; - for (uint32_t i = 0; i < in.size(); ++i) + for (uint32_t i = 0; i < chunksCount; ++i) { std::vector<Facet> facets; std::vector<Vertex> vertices; std::vector<Edge> edges; - for (uint32_t fc = 0; fc < in[i].polygonData.size(); ++fc) + for (uint32_t fc = 0; fc < in[i]->polygonDataCount; ++fc) { Facet nFc; nFc.firstEdgeNumber = edges.size(); - uint32_t n = in[i].polygonData[fc].mNbVerts; + auto& pd = in[i]->polygonData[fc]; + uint32_t n = pd.mNbVerts; for (uint32_t ed = 0; ed < n; ++ed) { - uint32_t vr1 = in[i].indices[(ed) + in[i].polygonData[fc].mIndexBase]; - uint32_t vr2 = in[i].indices[(ed + 1) % n + in[i].polygonData[fc].mIndexBase]; + uint32_t vr1 = in[i]->indices[(ed) + pd.mIndexBase]; + uint32_t vr2 = in[i]->indices[(ed + 1) % n + pd.mIndexBase]; edges.push_back(Edge(vr1, vr2)); } nFc.edgesCount = n; facets.push_back(nFc); } - vertices.resize(in[i].points.size()); - for (uint32_t vr = 0; vr < in[i].points.size(); ++vr) + vertices.resize(in[i]->pointsCount); + for (uint32_t vr = 0; vr < in[i]->pointsCount; ++vr) { - vertices[vr].p = in[i].points[vr]; + vertices[vr].p = in[i]->points[vr]; } - Mesh* hullMesh = new Mesh(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); + Mesh* hullMesh = new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); BooleanEvaluator evl; Mesh* cuttingMesh = getCuttingBox(PxVec3(0, 0, 0), PxVec3(0, 0, 1), 40, 0); for (uint32_t p = 0; p < chunkMidplanes[i].size(); ++p) @@ -228,52 +265,60 @@ void ConvexMeshBuilder::trimCollisionGeometry(std::vector<CollisionHull>& in, co hPoints[v] = hullMesh->getVertices()[v].p; } delete hullMesh; - buildCollisionGeometry(hPoints, in[i]); + if (in[i] != nullptr) + { + in[i]->release(); + } + in[i] = buildCollisionGeometry(hPoints.size(), hPoints.data()); } } -PxConvexMesh* ConvexMeshBuilder::buildConvexMesh(std::vector<PxVec3>& vertexData) +PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMesh(uint32_t verticesCount, const physx::PxVec3* vertexData) { - CollisionHull hull; - buildCollisionGeometry(vertexData, hull); + CollisionHull* hull = buildCollisionGeometry(verticesCount, vertexData); PxConvexMeshDesc convexMeshDescr; - convexMeshDescr.indices.data = hull.indices.data(); - convexMeshDescr.indices.count = (uint32_t)hull.indices.size(); + convexMeshDescr.indices.data = hull->indices; + convexMeshDescr.indices.count = (uint32_t)hull->indicesCount; convexMeshDescr.indices.stride = sizeof(uint32_t); - convexMeshDescr.points.data = hull.points.data(); - convexMeshDescr.points.count = (uint32_t)hull.points.size(); + convexMeshDescr.points.data = hull->points; + convexMeshDescr.points.count = (uint32_t)hull->pointsCount; convexMeshDescr.points.stride = sizeof(PxVec3); - convexMeshDescr.polygons.data = hull.polygonData.data(); - convexMeshDescr.polygons.count = (uint32_t)hull.polygonData.size(); + convexMeshDescr.polygons.data = hull->polygonData; + convexMeshDescr.polygons.count = (uint32_t)hull->polygonDataCount; convexMeshDescr.polygons.stride = sizeof(PxHullPolygon); PxConvexMesh* convexMesh = mCooking->createConvexMesh(convexMeshDescr, *mInsertionCallback); + hull->release(); return convexMesh; } -PxConvexMesh* ConvexMeshBuilder::buildConvexMesh(CollisionHull& hull) +PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMesh(const CollisionHull& hull) { PxConvexMeshDesc convexMeshDescr; - convexMeshDescr.indices.data = hull.indices.data(); - convexMeshDescr.indices.count = (uint32_t)hull.indices.size(); + convexMeshDescr.indices.data = hull.indices; + convexMeshDescr.indices.count = (uint32_t)hull.indicesCount; convexMeshDescr.indices.stride = sizeof(uint32_t); - convexMeshDescr.points.data = hull.points.data(); - convexMeshDescr.points.count = (uint32_t)hull.points.size(); + convexMeshDescr.points.data = hull.points; + convexMeshDescr.points.count = (uint32_t)hull.pointsCount; convexMeshDescr.points.stride = sizeof(PxVec3); - convexMeshDescr.polygons.data = hull.polygonData.data(); - convexMeshDescr.polygons.count = (uint32_t)hull.polygonData.size(); + convexMeshDescr.polygons.data = hull.polygonData; + convexMeshDescr.polygons.count = (uint32_t)hull.polygonDataCount; convexMeshDescr.polygons.stride = sizeof(PxHullPolygon); PxConvexMesh* convexMesh = mCooking->createConvexMesh(convexMeshDescr, *mInsertionCallback); return convexMesh; } +void ConvexMeshBuilderImpl::release() +{ + delete this; +} } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h new file mode 100644 index 0000000..709c880 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h @@ -0,0 +1,73 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTAUTHORINGCOLLISIONBUILDERIIMPL_H +#define NVBLASTEXTAUTHORINGCOLLISIONBUILDERIIMPL_H + +#include "NvBlastExtAuthoringCollisionBuilder.h" +#include "NvBlastExtAuthoringTypes.h" + +namespace Nv +{ +namespace Blast +{ + +struct CollisionHullImpl : public CollisionHull +{ + void release() override; +}; + +class ConvexMeshBuilderImpl : public ConvexMeshBuilder +{ +public: + + /** + Constructor should be provided with PxCoocking and PxPhysicsInsertionCallback objects. + */ + ConvexMeshBuilderImpl(physx::PxCooking* cooking, physx::PxPhysicsInsertionCallback* insertionCallback) : mInsertionCallback(insertionCallback), mCooking(cooking) {} + + virtual void release() override; + + virtual CollisionHull* buildCollisionGeometry(uint32_t verticesCount, const physx::PxVec3* vertexData) override; + + virtual physx::PxConvexMesh* buildConvexMesh(uint32_t verticesCount, const physx::PxVec3* vertexData) override; + + virtual physx::PxConvexMesh* buildConvexMesh(const CollisionHull& hull) override; + + virtual void trimCollisionGeometry(uint32_t chunksCount, CollisionHull** in, const uint32_t* chunkDepth) override; + +private: + physx::PxPhysicsInsertionCallback* mInsertionCallback; + physx::PxCooking* mCooking; +}; + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTEXTAUTHORINGCOLLISIONBUILDERIIMPL_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureTool.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp index 48830fe..91c81bc 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureTool.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp @@ -8,7 +8,9 @@ * license agreement from NVIDIA CORPORATION is strictly prohibited. */ -#include "NvBlastExtAuthoringFractureTool.h" +#include "NvBlastExtAuthoringFractureToolImpl.h" +#include "NvBlastExtAuthoringMeshImpl.h" + // This warning arises when using some stl containers with older versions of VC // c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code #if NV_VC && NV_VC < 14 @@ -22,6 +24,7 @@ #include "NvBlastExtAuthoringBooleanTool.h" #include "NvBlastExtAuthoringAccelerator.h" #include "NvBlast.h" +#include "NvBlastGlobals.h" #include "NvBlastExtAuthoringPerlinNoise.h" #include <NvBlastAssert.h> using namespace physx; @@ -133,7 +136,7 @@ bool blastBondComparator(const NvBlastBondDesc& a, const NvBlastBondDesc& b) #define MAX_VORONOI_ATTEMPT_NUMBER 450 -VoronoiSitesGenerator::VoronoiSitesGenerator(Mesh* mesh, RandomGeneratorBase* rnd) +VoronoiSitesGeneratorImpl::VoronoiSitesGeneratorImpl(const Mesh* mesh, RandomGeneratorBase* rnd) { mMesh = mesh; mRnd = rnd; @@ -141,7 +144,7 @@ VoronoiSitesGenerator::VoronoiSitesGenerator(Mesh* mesh, RandomGeneratorBase* rn mStencil = nullptr; } -void VoronoiSitesGenerator::setBaseMesh(Mesh* m) +void VoronoiSitesGeneratorImpl::setBaseMesh(const Mesh* m) { mGeneratedSites.clear(); delete mAccelerator; @@ -149,28 +152,32 @@ void VoronoiSitesGenerator::setBaseMesh(Mesh* m) mAccelerator = new BBoxBasedAccelerator(mMesh, DEFAULT_BB_ACCELARATOR_RES); } -VoronoiSitesGenerator::~VoronoiSitesGenerator() +VoronoiSitesGeneratorImpl::~VoronoiSitesGeneratorImpl() { delete mAccelerator; mAccelerator = nullptr; } +void VoronoiSitesGeneratorImpl::release() +{ + delete this; +} -void VoronoiSitesGenerator::setStencil(Mesh* stencil) +void VoronoiSitesGeneratorImpl::setStencil(const Mesh* stencil) { mStencil = stencil; } -void VoronoiSitesGenerator::clearStencil() +void VoronoiSitesGeneratorImpl::clearStencil() { mStencil = nullptr; } -void VoronoiSitesGenerator::uniformlyGenerateSitesInMesh(const uint32_t sitesCount) +void VoronoiSitesGeneratorImpl::uniformlyGenerateSitesInMesh(const uint32_t sitesCount) { - BooleanEvaluator voronoiMeshEval(nullptr); + BooleanEvaluator voronoiMeshEval; PxVec3 mn = mMesh->getBoundingBox().minimum; PxVec3 mx = mMesh->getBoundingBox().maximum; PxVec3 vc = mx - mn; @@ -198,9 +205,9 @@ void VoronoiSitesGenerator::uniformlyGenerateSitesInMesh(const uint32_t sitesCou } -void VoronoiSitesGenerator::clusteredSitesGeneration(const uint32_t numberOfClusters, const uint32_t sitesPerCluster, float clusterRadius) +void VoronoiSitesGeneratorImpl::clusteredSitesGeneration(const uint32_t numberOfClusters, const uint32_t sitesPerCluster, float clusterRadius) { - BooleanEvaluator voronoiMeshEval(nullptr); + BooleanEvaluator voronoiMeshEval; PxVec3 mn = mMesh->getBoundingBox().minimum; PxVec3 mx = mMesh->getBoundingBox().maximum; PxVec3 middle = (mx + mn) * 0.5; @@ -260,15 +267,15 @@ void VoronoiSitesGenerator::clusteredSitesGeneration(const uint32_t numberOfClus #define IN_SPHERE_ATTEMPT_NUMBER 20 -void VoronoiSitesGenerator::addSite(const physx::PxVec3& site) +void VoronoiSitesGeneratorImpl::addSite(const physx::PxVec3& site) { mGeneratedSites.push_back(site); } -void VoronoiSitesGenerator::generateInSphere(const uint32_t count, const float radius, const physx::PxVec3& center) +void VoronoiSitesGeneratorImpl::generateInSphere(const uint32_t count, const float radius, const physx::PxVec3& center) { - BooleanEvaluator voronoiMeshEval(nullptr); + BooleanEvaluator voronoiMeshEval; uint32_t attemptNumber = 0; uint32_t generatedSites = 0; std::vector<PxVec3> tempPoints; @@ -295,7 +302,7 @@ void VoronoiSitesGenerator::generateInSphere(const uint32_t count, const float r } -void VoronoiSitesGenerator::deleteInSphere(const float radius, const physx::PxVec3& center, float deleteProbability) +void VoronoiSitesGeneratorImpl::deleteInSphere(const float radius, const physx::PxVec3& center, float deleteProbability) { float r2 = radius * radius; for (uint32_t i = 0; i < mGeneratedSites.size(); ++i) @@ -310,11 +317,11 @@ void VoronoiSitesGenerator::deleteInSphere(const float radius, const physx::PxVe } -void VoronoiSitesGenerator::radialPattern(const physx::PxVec3& center, const physx::PxVec3& normal, float radius, int32_t angularSteps, int32_t radialSteps, float angleOffset, float variability) +void VoronoiSitesGeneratorImpl::radialPattern(const physx::PxVec3& center, const physx::PxVec3& normal, float radius, int32_t angularSteps, int32_t radialSteps, float angleOffset, float variability) { // mGeneratedSites.push_back(center); physx::PxVec3 t1, t2; - if (abs(normal.z) < 0.9) + if (std::abs(normal.z) < 0.9) { t1 = normal.cross(PxVec3(0, 0, 1)); } @@ -346,14 +353,16 @@ void VoronoiSitesGenerator::radialPattern(const physx::PxVec3& center, const phy } } - -std::vector<PxVec3>& VoronoiSitesGenerator::getVoronoiSites() +uint32_t VoronoiSitesGeneratorImpl::getVoronoiSites(const physx::PxVec3*& sites) { - return mGeneratedSites; + if (mGeneratedSites.size()) + { + sites = &mGeneratedSites[0]; + } + return (uint32_t)mGeneratedSites.size(); } - -int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<physx::PxVec3>& cellPointsIn, bool replaceChunk) +int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPointsIn, bool replaceChunk) { if (chunkId == 0 && replaceChunk) { @@ -361,7 +370,7 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys } int32_t chunkIndex = getChunkIndex(chunkId); - if (chunkIndex == -1 || cellPointsIn.size() < 2) + if (chunkIndex == -1 || cellCount < 2) { return 1; } @@ -373,8 +382,8 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys Mesh* mesh = mChunkData[chunkIndex].meshData; - std::vector<PxVec3> cellPoints(cellPointsIn.size()); - for (uint32_t i = 0; i < cellPointsIn.size(); ++i) + std::vector<PxVec3> cellPoints(cellCount); + for (uint32_t i = 0; i < cellCount; ++i) { cellPoints[i] = (cellPointsIn[i] - mOffset) * (1.0f / mScaleFactor); } @@ -382,8 +391,8 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys /** Prebuild accelerator structure */ - BooleanEvaluator eval(mLoggingCallback); - BooleanEvaluator voronoiMeshEval(mLoggingCallback); + BooleanEvaluator eval; + BooleanEvaluator voronoiMeshEval; BBoxBasedAccelerator spAccel = BBoxBasedAccelerator(mesh, DEFAULT_BB_ACCELARATOR_RES); @@ -436,20 +445,86 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys return 0; } -Mesh FractureTool::getChunkMesh(int32_t chunkId) +Mesh* FractureToolImpl::createChunkMesh(int32_t chunkId) { - Mesh temp = *mChunkData[getChunkIndex(chunkId)].meshData; - for (uint32_t i = 0; i < temp.getVerticesCount(); ++i) + int32_t chunkIndex = getChunkIndex(chunkId); + if (chunkIndex < 0 || static_cast<size_t>(chunkIndex) >= mChunkData.size()) { - temp.getVertices()[i].p = temp.getVertices()[i].p * mScaleFactor + mOffset; + return nullptr; } - temp.recalculateBoundingBox(); + + auto temp = new MeshImpl(*reinterpret_cast<MeshImpl*>(mChunkData[chunkIndex].meshData)); + for (uint32_t i = 0; i < temp->getVerticesCount(); ++i) + { + temp->getVerticesWritable()[i].p = temp->getVertices()[i].p * mScaleFactor + mOffset; + } + temp->recalculateBoundingBox(); return temp; } +bool FractureToolImpl::isMeshContainOpenEdges(const Mesh* input) +{ + std::map<PxVec3, int32_t, VrtPositionComparator> vertexMapping; + std::vector<int32_t> vertexRemappingArray(input->getVerticesCount()); + std::vector<Edge> remappedEdges(input->getEdgesCount()); + /** + Remap vertices + */ + + const Vertex* vrx = input->getVertices(); + for (uint32_t i = 0; i < input->getVerticesCount(); ++i) + { + auto it = vertexMapping.find(vrx->p); + if (it == vertexMapping.end()) + { + vertexMapping[vrx->p] = i; + vertexRemappingArray[i] = i; + } + else + { + vertexRemappingArray[i] = it->second; + } + ++vrx; + } + + const Edge* ed = input->getEdges(); + for (uint32_t i = 0; i < input->getEdgesCount(); ++i) + { + remappedEdges[i].s = vertexRemappingArray[ed->s]; + remappedEdges[i].e = vertexRemappingArray[ed->e]; + if (remappedEdges[i].e < remappedEdges[i].s) + { + std::swap(remappedEdges[i].s, remappedEdges[i].e); + } + ++ed; + } + + std::sort(remappedEdges.begin(), remappedEdges.end()); + + int32_t collected = 1; + for (uint32_t i = 1; i < remappedEdges.size(); ++i) + { + if (remappedEdges[i - 1].s == remappedEdges[i].s && remappedEdges[i - 1].e == remappedEdges[i].e) + { + collected++; + } + else + { + if (collected & 1) + { + return true; + } + else + { + collected = 1; + } + } + } + return collected & 1; +} -int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<physx::PxVec3>& cellPointsIn, const physx::PxVec3& scale, bool replaceChunk) +int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPointsIn, const physx::PxVec3& scale, bool replaceChunk) { if (chunkId == 0 && replaceChunk) { @@ -457,7 +532,7 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys } int32_t chunkIndex = getChunkIndex(chunkId); - if (chunkIndex == -1 || cellPointsIn.size() < 2) + if (chunkIndex == -1 || cellCount < 2) { return 1; } @@ -469,8 +544,8 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys Mesh* mesh = mChunkData[chunkIndex].meshData; - std::vector<PxVec3> cellPoints(cellPointsIn.size()); - for (uint32_t i = 0; i < cellPointsIn.size(); ++i) + std::vector<PxVec3> cellPoints(cellCount); + for (uint32_t i = 0; i < cellCount; ++i) { cellPoints[i] = (cellPointsIn[i] - mOffset) * (1.0f / mScaleFactor); @@ -482,8 +557,8 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys /** Prebuild accelerator structure */ - BooleanEvaluator eval(mLoggingCallback); - BooleanEvaluator voronoiMeshEval(mLoggingCallback); + BooleanEvaluator eval; + BooleanEvaluator voronoiMeshEval; BBoxBasedAccelerator spAccel = BBoxBasedAccelerator(mesh, DEFAULT_BB_ACCELARATOR_RES); @@ -507,9 +582,9 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys for (uint32_t v = 0; v < cell->getVerticesCount(); ++v) { - cell->getVertices()[v].p.x *= scale.x; - cell->getVertices()[v].p.y *= scale.y; - cell->getVertices()[v].p.z *= scale.z; + cell->getVerticesWritable()[v].p.x *= scale.x; + cell->getVerticesWritable()[v].p.y *= scale.y; + cell->getVerticesWritable()[v].p.z *= scale.z; } cell->recalculateBoundingBox(); DummyAccelerator dmAccel(cell->getFacetCount()); @@ -546,7 +621,7 @@ int32_t FractureTool::voronoiFracturing(uint32_t chunkId, const std::vector<phys } -int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) +int32_t FractureToolImpl::slicing(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) { if (conf.noiseAmplitude != 0) { @@ -570,9 +645,9 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool chunkIndex = getChunkIndex(chunkId); - Mesh* mesh = new Mesh(*mChunkData[chunkIndex].meshData); + Mesh* mesh = new MeshImpl(*reinterpret_cast <MeshImpl*>(mChunkData[chunkIndex].meshData)); - BooleanEvaluator bTool(mLoggingCallback); + BooleanEvaluator bTool; int32_t x_slices = conf.x_slices; int32_t y_slices = conf.y_slices; @@ -607,8 +682,8 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool PxVec3 randVect = PxVec3(2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1); PxVec3 lDir = dir + randVect * conf.angle_variations; - setCuttingBox(center, lDir, slBox, 20, mPlaneIndexerOffset); - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); + setCuttingBox(center, -lDir, slBox, 20, mPlaneIndexerOffset); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); ch.meshData = bTool.createNewMesh(); if (ch.meshData != 0) @@ -617,7 +692,7 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool } inverseNormalAndSetIndices(slBox, -mPlaneIndexerOffset); ++mPlaneIndexerOffset; - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); Mesh* result = bTool.createNewMesh(); delete mesh; mesh = result; @@ -647,8 +722,8 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool PxVec3 lDir = dir + randVect * conf.angle_variations; - setCuttingBox(center, lDir, slBox, 20, mPlaneIndexerOffset); - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); + setCuttingBox(center, -lDir, slBox, 20, mPlaneIndexerOffset); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); ch.meshData = bTool.createNewMesh(); if (ch.meshData != 0) { @@ -656,7 +731,7 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool } inverseNormalAndSetIndices(slBox, -mPlaneIndexerOffset); ++mPlaneIndexerOffset; - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); Mesh* result = bTool.createNewMesh(); delete mesh; mesh = result; @@ -685,8 +760,8 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool { PxVec3 randVect = PxVec3(2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1); PxVec3 lDir = dir + randVect * conf.angle_variations; - setCuttingBox(center, lDir, slBox, 20, mPlaneIndexerOffset); - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); + setCuttingBox(center, -lDir, slBox, 20, mPlaneIndexerOffset); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); ch.meshData = bTool.createNewMesh(); if (ch.meshData != 0) { @@ -696,7 +771,7 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool } inverseNormalAndSetIndices(slBox, -mPlaneIndexerOffset); ++mPlaneIndexerOffset; - bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_INTERSECION()); + bTool.performFastCutting(mesh, slBox, BooleanConfigurations::BOOLEAN_DIFFERENCE()); Mesh* result = bTool.createNewMesh(); delete mesh; mesh = result; @@ -735,7 +810,7 @@ int32_t FractureTool::slicing(uint32_t chunkId, SlicingConfiguration conf, bool return 0; } -int32_t FractureTool::slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) +int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) { if (replaceChunk && chunkId == 0) { @@ -754,9 +829,9 @@ int32_t FractureTool::slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, chunkIndex = getChunkIndex(chunkId); - Mesh* mesh = new Mesh(*mChunkData[chunkIndex].meshData); + Mesh* mesh = new MeshImpl(*reinterpret_cast <MeshImpl*>(mChunkData[chunkIndex].meshData)); - BooleanEvaluator bTool(mLoggingCallback); + BooleanEvaluator bTool; int32_t x_slices = conf.x_slices; int32_t y_slices = conf.y_slices; @@ -784,7 +859,7 @@ int32_t FractureTool::slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, std::vector<ChunkInfo> ySlicedChunks; std::vector<uint32_t> newlyCreatedChunksIds; float noisyPartSize = 1.8f; - int32_t acceleratorRes = 5; + int32_t acceleratorRes = 8; /** Slice along x direction */ @@ -930,7 +1005,7 @@ int32_t FractureTool::slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, -int32_t FractureTool::getChunkIndex(int32_t chunkId) +int32_t FractureToolImpl::getChunkIndex(int32_t chunkId) { for (uint32_t i = 0; i < mChunkData.size(); ++i) { @@ -942,7 +1017,7 @@ int32_t FractureTool::getChunkIndex(int32_t chunkId) return -1; } -int32_t FractureTool::getChunkDepth(int32_t chunkId) +int32_t FractureToolImpl::getChunkDepth(int32_t chunkId) { int32_t chunkIndex = getChunkIndex(chunkId); if (chunkIndex == -1) @@ -960,41 +1035,50 @@ int32_t FractureTool::getChunkDepth(int32_t chunkId) return depth; } -std::vector<int32_t> FractureTool::getChunksIdAtDepth(uint32_t depth) +uint32_t FractureToolImpl::getChunksIdAtDepth(uint32_t depth, int32_t*& chunkIds) { - std::vector<int32_t> chunkIds; + std::vector<int32_t> _chunkIds; for (uint32_t i = 0; i < mChunkData.size(); ++i) { if (getChunkDepth(mChunkData[i].chunkId) == (int32_t)depth) { - chunkIds.push_back(mChunkData[i].chunkId); + _chunkIds.push_back(mChunkData[i].chunkId); } } - return chunkIds; + chunkIds = new int32_t[_chunkIds.size()]; + memcpy(chunkIds, _chunkIds.data(), _chunkIds.size() * sizeof(int32_t)); + + return (uint32_t)_chunkIds.size(); } -void FractureTool::getTransformation(PxVec3& offset, float& scale) +void FractureToolImpl::getTransformation(PxVec3& offset, float& scale) { offset = mOffset; scale = mScaleFactor; } -void FractureTool::setSourceMesh(Mesh* mesh) +void FractureToolImpl::setSourceMesh(const Mesh* meshInput) { - if (mesh == nullptr) + if (meshInput == nullptr) { return; } reset(); + if (isMeshContainOpenEdges(meshInput)) + { + NVBLAST_LOG_WARNING("WARNING! Input mesh contains open edges, it may lead to wrong fractruing results!. \n"); + } + + mChunkData.resize(1); - mChunkData[0].meshData = new Mesh(*mesh); + mChunkData[0].meshData = new MeshImpl(*reinterpret_cast <const MeshImpl*>(meshInput)); mChunkData[0].parent = -1; mChunkData[0].isLeaf = true; mChunkData[0].chunkId = mChunkIdCounter++; - mesh = mChunkData[0].meshData; + Mesh* mesh = mChunkData[0].meshData; /** Move to origin and scale to unit cube @@ -1005,24 +1089,30 @@ void FractureTool::setSourceMesh(Mesh* mesh) mScaleFactor = std::max(bbSizes.x, std::max(bbSizes.y, bbSizes.z)); - Vertex* verticesBuffer = mesh->getVertices(); + Vertex* verticesBuffer = mesh->getVerticesWritable(); for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) { verticesBuffer[i].p = (verticesBuffer[i].p - mOffset) * (1.0f / mScaleFactor); } - mesh->getBoundingBox().minimum = (mesh->getBoundingBox().minimum - mOffset) * (1.0f / mScaleFactor); - mesh->getBoundingBox().maximum = (mesh->getBoundingBox().maximum - mOffset) * (1.0f / mScaleFactor); + mesh->getBoundingBoxWritable().minimum = (mesh->getBoundingBox().minimum - mOffset) * (1.0f / mScaleFactor); + mesh->getBoundingBoxWritable().maximum = (mesh->getBoundingBox().maximum - mOffset) * (1.0f / mScaleFactor); for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { - mesh->getFacet(i)->userData = 0; // Mark facet as initial boundary facet + mesh->getFacetWritable(i)->userData = 0; // Mark facet as initial boundary facet } } -void FractureTool::reset() +void FractureToolImpl::release() +{ + delete this; +} + + +void FractureToolImpl::reset() { mChunkPostprocessors.clear(); for (uint32_t i = 0; i < mChunkData.size(); ++i) @@ -1035,9 +1125,7 @@ void FractureTool::reset() } - - -bool FractureTool::isAncestorForChunk(int32_t ancestorId, int32_t chunkId) +bool FractureToolImpl::isAncestorForChunk(int32_t ancestorId, int32_t chunkId) { if (ancestorId == chunkId) { @@ -1059,7 +1147,7 @@ bool FractureTool::isAncestorForChunk(int32_t ancestorId, int32_t chunkId) return false; } -void FractureTool::eraseChunk(int32_t chunkId) +void FractureToolImpl::eraseChunk(int32_t chunkId) { deleteAllChildsOfChunk(chunkId); int32_t index = getChunkIndex(chunkId); @@ -1072,7 +1160,7 @@ void FractureTool::eraseChunk(int32_t chunkId) } -void FractureTool::deleteAllChildsOfChunk(int32_t chunkId) +void FractureToolImpl::deleteAllChildsOfChunk(int32_t chunkId) { std::vector<int32_t> chunkToDelete; for (uint32_t i = 0; i < mChunkData.size(); ++i) @@ -1091,7 +1179,7 @@ void FractureTool::deleteAllChildsOfChunk(int32_t chunkId) } } -void FractureTool::finalizeFracturing() +void FractureToolImpl::finalizeFracturing() { for (uint32_t i = 0; i < mChunkPostprocessors.size(); ++i) { @@ -1100,7 +1188,7 @@ void FractureTool::finalizeFracturing() mChunkPostprocessors.resize(mChunkData.size()); for (uint32_t i = 0; i < mChunkPostprocessors.size(); ++i) { - mChunkPostprocessors[i] = new ChunkPostProcessor(); + mChunkPostprocessors[i] = new Triangulator(); } for (uint32_t i = 0; i < mChunkPostprocessors.size(); ++i) @@ -1131,89 +1219,38 @@ void FractureTool::finalizeFracturing() } -const std::vector<ChunkInfo>& FractureTool::getChunkList() +uint32_t FractureToolImpl::getChunkCount() const { - return mChunkData; + return (uint32_t)mChunkData.size(); } -void FractureTool::getBaseMesh(int32_t chunkIndex, std::vector<Triangle>& output) +const ChunkInfo& FractureToolImpl::getChunkInfo(int32_t chunkId) { - NVBLAST_ASSERT(mChunkPostprocessors.size() > 0); - if (mChunkPostprocessors.size() == 0) - { - return; // finalizeFracturing() should be called before getting mesh! - } - output = mChunkPostprocessors[chunkIndex]->getBaseMesh(); - - /* Scale mesh back */ - - for (uint32_t i = 0; i < output.size(); ++i) - { - output[i].a.p = output[i].a.p * mScaleFactor + mOffset; - output[i].b.p = output[i].b.p * mScaleFactor + mOffset; - output[i].c.p = output[i].c.p * mScaleFactor + mOffset; - } + return mChunkData[chunkId]; } -void FractureTool::getNoisedMesh(int32_t chunkIndex, std::vector<Triangle>& output) +uint32_t FractureToolImpl::getBaseMesh(int32_t chunkIndex, Triangle*& output) { NVBLAST_ASSERT(mChunkPostprocessors.size() > 0); if (mChunkPostprocessors.size() == 0) - { - return; // finalizeFracturing() should be called before getting mesh! - } - - if (mChunkData[chunkIndex].chunkId == 0) - { - output = mChunkPostprocessors[chunkIndex]->getBaseMesh(); - } - else - { - output = mChunkPostprocessors[chunkIndex]->getNoisyMesh(); + { + return 0; // finalizeFracturing() should be called before getting mesh! } + auto baseMesh = mChunkPostprocessors[chunkIndex]->getBaseMesh(); + output = new Triangle[baseMesh.size()]; + memcpy(output, baseMesh.data(), baseMesh.size() * sizeof(Triangle)); - for (uint32_t i = 0; i < output.size(); ++i) - { - output[i].a.p = output[i].a.p * mScaleFactor + mOffset; - output[i].b.p = output[i].b.p * mScaleFactor + mOffset; - output[i].c.p = output[i].c.p * mScaleFactor + mOffset; - } -} + /* Scale mesh back */ -void FractureTool::tesselate(float averateEdgeLength) -{ - NVBLAST_ASSERT(mChunkPostprocessors.size() > 0); - if (mChunkPostprocessors.size() == 0) + for (uint32_t i = 0; i < baseMesh.size(); ++i) { - return; // finalizeFracturing() should be called before tesselation! + Triangle& triangle = output[i]; + triangle.a.p = triangle.a.p * mScaleFactor + mOffset; + triangle.b.p = triangle.b.p * mScaleFactor + mOffset; + triangle.c.p = triangle.c.p * mScaleFactor + mOffset; } - for (uint32_t i = 0; i < mChunkPostprocessors.size(); ++i) - { - if (mChunkData[i].chunkId == 0) // skip source mesh - { - continue; - } - mChunkPostprocessors[i]->tesselateInternalSurface(averateEdgeLength / mScaleFactor); - } -} - -void FractureTool::applyNoise(float amplitude, float frequency, int32_t octaves, float falloff, int32_t relaxIterations, float relaxFactor, int32_t seed) -{ - octaves = octaves <= 0 ? 1 : octaves; - if (mChunkPostprocessors.empty()) - { - return; - } - SimplexNoise noise(amplitude / mScaleFactor, frequency * mScaleFactor, octaves, seed); - for (uint32_t i = 0; i < mChunkPostprocessors.size(); ++i) - { - if (mChunkData[i].chunkId == 0) // skip source mesh - { - continue; - } - mChunkPostprocessors[i]->applyNoise(noise, falloff, relaxIterations, relaxFactor); - } + return baseMesh.size(); } float getVolume(std::vector<Triangle>& triangles) @@ -1230,7 +1267,7 @@ float getVolume(std::vector<Triangle>& triangles) return (1.0f / 6.0f) * PxAbs(volume); } -float FractureTool::getMeshOverlap(Mesh& meshA, Mesh& meshB) +float FractureToolImpl::getMeshOverlap(const Mesh& meshA, const Mesh& meshB) { BooleanEvaluator bTool; bTool.performBoolean(&meshA, &meshB, BooleanConfigurations::BOOLEAN_INTERSECION()); @@ -1240,7 +1277,7 @@ float FractureTool::getMeshOverlap(Mesh& meshA, Mesh& meshB) return 0.0f; } - ChunkPostProcessor postProcessor; + Triangulator postProcessor; postProcessor.triangulate(&meshA); float baseVolume = getVolume(postProcessor.getBaseMesh()); @@ -1297,19 +1334,19 @@ void weldVertices(std::map<Vertex, uint32_t, VrtComp>& vertexMapping, std::vecto } -void FractureTool::setRemoveIslands(bool isRemoveIslands) +void FractureToolImpl::setRemoveIslands(bool isRemoveIslands) { mRemoveIslands = isRemoveIslands; } -int32_t FractureTool::islandDetectionAndRemoving(int32_t chunkId) +int32_t FractureToolImpl::islandDetectionAndRemoving(int32_t chunkId) { if (chunkId == 0) { return 0; } int32_t chunkIndex = getChunkIndex(chunkId); - ChunkPostProcessor prc; + Triangulator prc; prc.triangulate(mChunkData[chunkIndex].meshData); Mesh* chunk = mChunkData[chunkIndex].meshData; @@ -1403,7 +1440,7 @@ int32_t FractureTool::islandDetectionAndRemoving(int32_t chunkId) std::vector<uint32_t> compVertexMapping(chunk->getVerticesCount(), 0); - Vertex* vrts = chunk->getVertices(); + const Vertex* vrts = chunk->getVertices(); for (uint32_t v = 0; v < chunk->getVerticesCount(); ++v) { int32_t vComp = comps[mapping[v]]; @@ -1411,8 +1448,8 @@ int32_t FractureTool::islandDetectionAndRemoving(int32_t chunkId) compVertices[vComp].push_back(vrts[v]); } - Facet* fcb = chunk->getFacetsBuffer(); - Edge* edb = chunk->getEdges(); + const Facet* fcb = chunk->getFacetsBuffer(); + const Edge* edb = chunk->getEdges(); for (uint32_t fc = 0; fc < chunk->getFacetCount(); ++fc) { @@ -1436,13 +1473,13 @@ int32_t FractureTool::islandDetectionAndRemoving(int32_t chunkId) } delete mChunkData[chunkIndex].meshData; - mChunkData[chunkIndex].meshData = new Mesh(compVertices[0].data(), compEdges[0].data(), compFacets[0].data(), static_cast<uint32_t>(compVertices[0].size()), + mChunkData[chunkIndex].meshData = new MeshImpl(compVertices[0].data(), compEdges[0].data(), compFacets[0].data(), static_cast<uint32_t>(compVertices[0].size()), static_cast<uint32_t>(compEdges[0].size()), static_cast<uint32_t>(compFacets[0].size()));; for (int32_t i = 1; i < cComp; ++i) { mChunkData.push_back(ChunkInfo(mChunkData[chunkIndex])); mChunkData.back().chunkId = mChunkIdCounter++; - mChunkData.back().meshData = new Mesh(compVertices[i].data(), compEdges[i].data(), compFacets[i].data(), static_cast<uint32_t>(compVertices[i].size()), + mChunkData.back().meshData = new MeshImpl(compVertices[i].data(), compEdges[i].data(), compFacets[i].data(), static_cast<uint32_t>(compVertices[i].size()), static_cast<uint32_t>(compEdges[i].size()), static_cast<uint32_t>(compFacets[i].size())); } @@ -1451,60 +1488,52 @@ int32_t FractureTool::islandDetectionAndRemoving(int32_t chunkId) return 0; } -void FractureTool::getBufferedBaseMeshes(std::vector<Vertex>& vertexBuffer, std::vector<std::vector<uint32_t> >& indexBuffer) +uint32_t FractureToolImpl::getBufferedBaseMeshes(Vertex*& vertexBuffer, uint32_t*& indexBuffer, + uint32_t*& indexBufferOffsets) { std::map<Vertex, uint32_t, VrtComp> vertexMapping; - vertexBuffer.clear(); - indexBuffer.clear(); - indexBuffer.resize(mChunkPostprocessors.size()); + std::vector<Vertex> _vertexBuffer; + std::vector<std::vector<uint32_t>> _indexBuffer(mChunkPostprocessors.size()); + + indexBufferOffsets = new uint32_t[mChunkPostprocessors.size() + 1]; + uint32_t totalIndices = 0; for (uint32_t ch = 0; ch < mChunkPostprocessors.size(); ++ch) { std::vector<Triangle>& trb = mChunkPostprocessors[ch]->getBaseMesh(); - weldVertices(vertexMapping, vertexBuffer, indexBuffer[ch], trb); + + weldVertices(vertexMapping, _vertexBuffer, _indexBuffer[ch], trb); + + indexBufferOffsets[ch] = totalIndices; + totalIndices += _indexBuffer[ch].size(); } - for (uint32_t i = 0; i < vertexBuffer.size(); ++i) + indexBufferOffsets[mChunkPostprocessors.size()] = totalIndices; + + for (uint32_t i = 0; i < _vertexBuffer.size(); ++i) { - vertexBuffer[i].p = vertexBuffer[i].p * mScaleFactor + mOffset; + _vertexBuffer[i].p = _vertexBuffer[i].p * mScaleFactor + mOffset; } -} -int32_t FractureTool::getChunkId(int32_t chunkIndex) -{ - if (chunkIndex < 0 || static_cast<uint32_t>(chunkIndex) >= mChunkData.size()) + vertexBuffer = new Vertex[_vertexBuffer.size()]; + indexBuffer = new uint32_t[totalIndices]; + + memcpy(vertexBuffer, _vertexBuffer.data(), _vertexBuffer.size() * sizeof(Vertex)); + for (uint32_t ch = 0; ch < _indexBuffer.size(); ++ch) { - return -1; + memcpy(indexBuffer + indexBufferOffsets[ch], _indexBuffer[ch].data(), _indexBuffer[ch].size() * sizeof(uint32_t)); } - return mChunkData[chunkIndex].chunkId; + + return _vertexBuffer.size(); } -void FractureTool::getBufferedNoiseMeshes(std::vector<Vertex>& vertexBuffer, std::vector<std::vector<uint32_t> >& indexBuffer) +int32_t FractureToolImpl::getChunkId(int32_t chunkIndex) { - std::map<Vertex, uint32_t, VrtComp> vertexMapping; - vertexBuffer.clear(); - indexBuffer.clear(); - indexBuffer.resize(mChunkPostprocessors.size()); - - for (uint32_t ch = 0; ch < mChunkPostprocessors.size(); ++ch) - { - if (ch == 0) - { - std::vector<Triangle>& trb = mChunkPostprocessors[ch]->getBaseMesh(); - weldVertices(vertexMapping, vertexBuffer, indexBuffer[ch], trb); - } - else - { - std::vector<Triangle>& trb = mChunkPostprocessors[ch]->getNoisyMesh(); - weldVertices(vertexMapping, vertexBuffer, indexBuffer[ch], trb); - } - } - for (uint32_t i = 0; i < vertexBuffer.size(); ++i) + if (chunkIndex < 0 || static_cast<uint32_t>(chunkIndex) >= mChunkData.size()) { - vertexBuffer[i].p = vertexBuffer[i].p * mScaleFactor + mOffset; + return -1; } + return mChunkData[chunkIndex].chunkId; } - } // namespace Blast } // namespace Nv - diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h new file mode 100644 index 0000000..9b656e3 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h @@ -0,0 +1,330 @@ +/* +* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#ifndef NVBLASTAUTHORINGFRACTURETOOLIMPL_H +#define NVBLASTAUTHORINGFRACTURETOOLIMPL_H + +#include "NvBlastExtAuthoringFractureTool.h" +#include "NvBlastExtAuthoringMesh.h" +#include <vector> + +namespace Nv +{ +namespace Blast +{ + +class SpatialAccelerator; +class Triangulator; + + +/** + Class for voronoi sites generation inside supplied mesh. +*/ +class VoronoiSitesGeneratorImpl : public VoronoiSitesGenerator +{ +public: + + /** + Voronoi sites should not be generated outside of the fractured mesh, so VoronoiSitesGenerator + should be supplied with fracture mesh. + \param[in] mesh Fracture mesh + \param[in] rnd User supplied random value generator. + \return + */ + VoronoiSitesGeneratorImpl(const Mesh* mesh, RandomGeneratorBase* rnd); + ~VoronoiSitesGeneratorImpl(); + + void release() override; + + /** + Set base fracture mesh + */ + void setBaseMesh(const Mesh* m) override; + + /** + Access to generated voronoi sites. + \note User should call NVBLAST_FREE for hulls and hullsOffset when it not needed anymore + \param[out] Pointer to generated voronoi sites + \return Count of generated voronoi sites. + */ + uint32_t getVoronoiSites(const physx::PxVec3*& sites) override; + + /** + Add site in particular point + \param[in] site Site coordinates + */ + void addSite(const physx::PxVec3& site) override; + /** + Uniformly generate sites inside the mesh + \param[in] numberOfSites Number of generated sites + */ + void uniformlyGenerateSitesInMesh(uint32_t numberOfSites) override; + + /** + Generate sites in clustered fashion + \param[in] numberOfClusters Number of generated clusters + \param[in] sitesPerCluster Number of sites in each cluster + \param[in] clusterRadius Voronoi cells cluster radius + */ + void clusteredSitesGeneration(uint32_t numberOfClusters, uint32_t sitesPerCluster, float clusterRadius) override; + + /** + Radial pattern of sites generation + \param[in] center Center of generated pattern + \param[in] normal Normal to plane in which sites are generated + \param[in] radius Pattern radius + \param[in] angularSteps Number of angular steps + \param[in] radialSteps Number of radial steps + \param[in] angleOffset Angle offset at each radial step + \param[in] variability Randomness of sites distribution + */ + void radialPattern(const physx::PxVec3& center, const physx::PxVec3& normal, float radius, int32_t angularSteps, int32_t radialSteps, float angleOffset = 0.0f, float variability = 0.0f) override; + + /** + Generate sites inside sphere + \param[in] count Count of generated sites + \param[in] radius Radius of sphere + \param[in] center Center of sphere + */ + void generateInSphere(const uint32_t count, const float radius, const physx::PxVec3& center) override; + /** + Set stencil mesh. With stencil mesh sites are generated only inside both of fracture and stencil meshes. + \param[in] stencil Stencil mesh. + */ + void setStencil(const Mesh* stencil) override; + /** + Removes stencil mesh + */ + void clearStencil() override; + + /** + Deletes sites inside supplied sphere + \param[in] radius Radius of sphere + \param[in] center Center of sphere + \param[in] eraserProbability Probability of removing some particular site + */ + void deleteInSphere(const float radius, const physx::PxVec3& center, const float eraserProbability = 1) override; + +private: + std::vector <physx::PxVec3> mGeneratedSites; + const Mesh* mMesh; + const Mesh* mStencil; + RandomGeneratorBase* mRnd; + SpatialAccelerator* mAccelerator; +}; + + + +/** + FractureTool class provides methods to fracture provided mesh and generate Blast asset data +*/ +class FractureToolImpl : public FractureTool +{ + +public: + + /** + FractureTool can log asset creation info if logCallback is provided. + */ + FractureToolImpl() + { + mPlaneIndexerOffset = 1; + mChunkIdCounter = 0; + mRemoveIslands = false; + } + + ~FractureToolImpl() + { + reset(); + } + + void release() override; + + /** + Reset FractureTool state. + */ + void reset() override; + + + /** + Set input mesh wich will be fractured, FractureTool will be reseted. + */ + void setSourceMesh(const Mesh* mesh) override; + + /** + Get chunk mesh in polygonal representation + */ + Mesh* createChunkMesh(int32_t chunkId) override; + + /** + Input mesh is scaled and transformed internally to fit unit cube centered in origin. + Method provides offset vector and scale parameter; + */ + void getTransformation(physx::PxVec3& offset, float& scale) override; + + + /** + Fractures specified chunk with voronoi method. + \param[in] chunkId Chunk to fracture + \param[in] cellPoints Array of voronoi sites + \param[in] replaceChunk if 'true', newly generated chunks will replace source chunk, if 'false', newly generated chunks will be at next depth level, source chunk will be parent for them. + Case replaceChunk == true && chunkId == 0 considered as wrong input parameters + \return If 0, fracturing is successful. + */ + int32_t voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPoints, bool replaceChunk) override; + + /** + Fractures specified chunk with voronoi method. Cells can be scaled along x,y,z axes. + \param[in] chunkId Chunk to fracture + \param[in] cellPoints Array of voronoi sites + \param[in] cellPoints Array of voronoi sites + \param[in] scale Voronoi cells scaling factor + \param[in] replaceChunk if 'true', newly generated chunks will replace source chunk, if 'false', newly generated chunks will be at next depth level, source chunk will be parent for them. + Case replaceChunk == true && chunkId == 0 considered as wrong input parameters + \return If 0, fracturing is successful. + */ + int32_t voronoiFracturing(uint32_t chunkId, uint32_t cellCount, const physx::PxVec3* cellPoints, const physx::PxVec3& scale, bool replaceChunk) override; + + + /** + Fractures specified chunk with slicing method. + \param[in] chunkId Chunk to fracture + \param[in] conf Slicing parameters, see SlicingConfiguration. + \param[in] replaceChunk if 'true', newly generated chunks will replace source chunk, if 'false', newly generated chunks will be at next depth level, source chunk will be parent for them. + Case replaceChunk == true && chunkId == 0 considered as wrong input parameters + \param[in] rnd User supplied random number generator + + \return If 0, fracturing is successful. + */ + int32_t slicing(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd) override; + + + /** + Creates resulting fractured mesh geometry from intermediate format + */ + void finalizeFracturing() override; + + uint32_t getChunkCount() const override; + + /** + Get chunk information + */ + const ChunkInfo& getChunkInfo(int32_t chunkIndex) override; + + /** + Get percentage of mesh overlap. + percentage computed as volume(intersection(meshA , meshB)) / volume (meshA) + \param[in] meshA Mesh A + \param[in] meshB Mesh B + \return mesh overlap percentage + */ + float getMeshOverlap(const Mesh& meshA, const Mesh& meshB) override; + + /** + Get chunk base mesh + \note User should call NVBLAST_FREE for output when it not needed anymore + \param[in] chunkIndex Chunk index + \param[out] output Array of triangles to be filled + \return number of triangles in base mesh + */ + uint32_t getBaseMesh(int32_t chunkIndex, Triangle*& output) override; + + /** + Return index of chunk with specified chunkId + \param[in] chunkId Chunk ID + \return Chunk index in internal buffer, if not exist -1 is returned. + */ + int32_t getChunkIndex(int32_t chunkId) override; + + /** + Return id of chunk with specified index. + \param[in] chunkIndex Chunk index + \return Chunk id or -1 if there is no such chunk. + */ + int32_t getChunkId(int32_t chunkIndex) override; + + /** + Return depth level of the given chunk + \param[in] chunkId Chunk ID + \return Chunk depth or -1 if there is no such chunk. + */ + int32_t getChunkDepth(int32_t chunkId) override; + + /** + Return array of chunks IDs with given depth. + \note User should call NVBLAST_FREE for chunkIds when it not needed anymore + \param[in] depth Chunk depth + \param[out] Pointer to array of chunk IDs + \return Number of chunks in array + */ + uint32_t getChunksIdAtDepth(uint32_t depth, int32_t*& chunkIds) override; + + + /** + Get result geometry without noise as vertex and index buffers, where index buffers contain series of triplets + which represent triangles. + \note User should call NVBLAST_FREE for vertexBuffer, indexBuffer and indexBufferOffsets when it not needed anymore + \param[out] vertexBuffer Array of vertices to be filled + \param[out] indexBuffer Array of indices to be filled + \param[out] indexBufferOffsets Array of offsets in indexBuffer for each base mesh. + Contains getChunkCount() + 1 elements. Last one is indexBuffer size + \return Number of vertices in vertexBuffer + */ + uint32_t getBufferedBaseMeshes(Vertex*& vertexBuffer, uint32_t*& indexBuffer, uint32_t*& indexBufferOffsets) override; + + /** + Set automatic islands removing. May cause instabilities. + \param[in] isRemoveIslands Flag whether remove or not islands. + */ + void setRemoveIslands(bool isRemoveIslands) override; + + /** + Try find islands and remove them on some specifical chunk. If chunk has childs, island removing can lead to wrong results! Apply it before further chunk splitting. + \param[in] chunkId Chunk ID which should be checked for islands + \return Number of found islands is returned + */ + int32_t islandDetectionAndRemoving(int32_t chunkId) override; + + /** + Check if input mesh contains open edges. Open edges can lead to wrong fracturing results. + \return true if mesh contains open edges + */ + bool isMeshContainOpenEdges(const Mesh* input) override; + +private: + void eraseChunk(int32_t chunkId); + bool isAncestorForChunk(int32_t ancestorId, int32_t chunkId); + void deleteAllChildsOfChunk(int32_t chunkId); + int32_t slicingNoisy(uint32_t chunkId, SlicingConfiguration conf, bool replaceChunk, RandomGeneratorBase* rnd); + +protected: + /** + Mesh scaled to unite-cube and translated to the origin + */ + float mScaleFactor; + physx::PxVec3 mOffset; + + /* Chunk mesh wrappers */ + std::vector<Triangulator*> mChunkPostprocessors; + + + + int32_t mPlaneIndexerOffset; + int32_t mChunkIdCounter; + std::vector<ChunkInfo> mChunkData; + + bool mRemoveIslands; +}; + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGFRACTURETOOLIMPL_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h index b8fb20e..862016f 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h @@ -1,16 +1,35 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #ifndef NVBLASTINTERNALCOMMON_H #define NVBLASTINTERNALCOMMON_H #include "NvBlastExtAuthoringTypes.h" +#include <algorithm> using namespace physx; @@ -74,15 +93,15 @@ Computes best direction to project points. */ NV_FORCE_INLINE ProjectionDirections getProjectionDirection(const physx::PxVec3& normal) { - float maxv = std::max(abs(normal.x), std::max(abs(normal.y), abs(normal.z))); + float maxv = std::max(std::abs(normal.x), std::max(std::abs(normal.y), std::abs(normal.z))); ProjectionDirections retVal; - if (maxv == abs(normal.x)) + if (maxv == std::abs(normal.x)) { retVal = YZ_PLANE; if (normal.x < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); return retVal; } - if (maxv == abs(normal.y)) + if (maxv == std::abs(normal.y)) { retVal = ZX_PLANE; if (normal.y > 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); @@ -187,6 +206,54 @@ NV_INLINE bool getPlaneSegmentIntersection(const PxPlane& pl, const PxVec3& a, c return true; } + +#define VEC_COMPARISON_OFFSET 1e-5f +/** +Vertex comparator for vertex welding. +*/ +struct VrtComp +{ + bool operator()(const Vertex& a, const Vertex& b) const + { + if (a.p.x + VEC_COMPARISON_OFFSET < b.p.x) return true; + if (a.p.x - VEC_COMPARISON_OFFSET > b.p.x) return false; + if (a.p.y + VEC_COMPARISON_OFFSET < b.p.y) return true; + if (a.p.y - VEC_COMPARISON_OFFSET > b.p.y) return false; + if (a.p.z + VEC_COMPARISON_OFFSET < b.p.z) return true; + if (a.p.z - VEC_COMPARISON_OFFSET > b.p.z) return false; + + if (a.n.x + 1e-3 < b.n.x) return true; + if (a.n.x - 1e-3 > b.n.x) return false; + if (a.n.y + 1e-3 < b.n.y) return true; + if (a.n.y - 1e-3 > b.n.y) return false; + if (a.n.z + 1e-3 < b.n.z) return true; + if (a.n.z - 1e-3 > b.n.z) return false; + + + if (a.uv[0].x + 1e-3 < b.uv[0].x) return true; + if (a.uv[0].x - 1e-3 > b.uv[0].x) return false; + if (a.uv[0].y + 1e-3 < b.uv[0].y) return true; + return false; + }; +}; + +/** +Vertex comparator for vertex welding (not accounts normal and uv parameters of vertice). +*/ +struct VrtPositionComparator +{ + bool operator()(const physx::PxVec3& a, const physx::PxVec3& b) const + { + if (a.x + VEC_COMPARISON_OFFSET < b.x) return true; + if (a.x - VEC_COMPARISON_OFFSET > b.x) return false; + if (a.y + VEC_COMPARISON_OFFSET < b.y) return true; + if (a.y - VEC_COMPARISON_OFFSET > b.y) return false; + if (a.z + VEC_COMPARISON_OFFSET < b.z) return true; + if (a.z - VEC_COMPARISON_OFFSET > b.z) return false; + return false; + }; +}; + } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp new file mode 100644 index 0000000..602ae75 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp @@ -0,0 +1,1626 @@ + +#include <PxVec3.h> +#include <PxVec2.h> +#include <vector> +#include <queue> +#include <map> + +#include <NvBlastExtAuthoringMeshCleanerImpl.h> +#include <NvBlastExtAuthoringMeshImpl.h> +#include <NvBlastExtAuthoringInternalCommon.h> +#include <boost/multiprecision/cpp_int.hpp> + + + + +using physx::PxVec3; +using physx::PxVec2; + +using namespace Nv::Blast; +using namespace boost::multiprecision; + +/** + Exact rational vector types. +*/ +struct RVec3 +{ + cpp_rational x, y, z; + RVec3() + { + + } + + bool isZero() + { + return x.is_zero() && y.is_zero() && z.is_zero(); + } + + RVec3(cpp_rational _x, cpp_rational _y, cpp_rational _z) + { + x = _x; + y = _y; + z = _z; + } + + RVec3(const PxVec3& p) + { + x = cpp_rational(p.x); + y = cpp_rational(p.y); + z = cpp_rational(p.z); + } + PxVec3 toVec3() + { + return PxVec3(x.convert_to<float>(), y.convert_to<float>(), z.convert_to<float>()); + } + + RVec3 operator-(const RVec3& b) const + { + return RVec3(x - b.x, y - b.y, z - b.z); + } + RVec3 operator+(const RVec3& b) const + { + return RVec3(x + b.x, y + b.y, z + b.z); + } + RVec3 cross(const RVec3& in) const + { + return RVec3(y * in.z - in.y * z, in.x * z - x * in.z, x * in.y - in.x * y); + } + cpp_rational dot(const RVec3& in) const + { + return x * in.x + y * in.y + z * in.z; + } + RVec3 operator*(const cpp_rational& in) const + { + return RVec3(x * in, y * in, z * in); + } + + +}; + +struct RVec2 +{ + cpp_rational x, y; + RVec2() + { + + } + + RVec2(cpp_rational _x, cpp_rational _y) + { + x = _x; + y = _y; + } + + RVec2(const PxVec2& p) + { + x = cpp_rational(p.x); + y = cpp_rational(p.y); + } + PxVec2 toVec2() + { + return PxVec2(x.convert_to<float>(), y.convert_to<float>()); + } + + RVec2 operator-(const RVec2& b) const + { + return RVec2(x - b.x, y - b.y); + } + RVec2 operator+(const RVec2& b) const + { + return RVec2(x + b.x, y + b.y); + } + cpp_rational cross(const RVec2& in) const + { + return x * in.y - y * in.x; + } + cpp_rational dot(const RVec2& in) const + { + return x * in.x + y * in.y; + } + RVec2 operator*(const cpp_rational& in) const + { + return RVec2(x * in, y * in); + } +}; +struct RatPlane +{ + RVec3 n; + cpp_rational d; + + RatPlane(const RVec3& a, const RVec3& b, const RVec3& c) + { + n = (b - a).cross(c - a); + d = -n.dot(a); + }; + cpp_rational distance(RVec3& in) + { + return n.dot(in) + d; + } +}; + +bool isSame(const RatPlane& a, const RatPlane& b) +{ + if (a.d != b.d) return false; + if (a.n.x != b.n.x || a.n.y != b.n.y || a.n.z != b.n.z) return false; + return true; +} + +RVec3 planeSegmInters(RVec3& a, RVec3& b, RatPlane& pl) +{ + cpp_rational t = -(a.dot(pl.n) + pl.d) / pl.n.dot(b - a); + RVec3 on = a + (b - a) * t; + return on; +} + +enum POINT_CLASS +{ + ON_AB = 0, + ON_BC = 1, + ON_AC = 2, + INSIDE_TR, + OUTSIDE_TR, + ON_VERTEX +}; + + +int32_t isPointInside(const RVec2& a, const RVec2& b, const RVec2& c, const RVec2& p) +{ + cpp_rational v1 = (b - a).cross(p - a); + cpp_rational v2 = (c - b).cross(p - b); + cpp_rational v3 = (a - c).cross(p - c); + + + + int32_t v1s = v1.sign(); + int32_t v2s = v2.sign(); + int32_t v3s = v3.sign(); + + if (v1s * v2s < 0 || v1s * v3s < 0 || v2s * v3s < 0) return OUTSIDE_TR; + + if (v1s == 0 && v2s == 0) return OUTSIDE_TR; + if (v1s == 0 && v3s == 0) return OUTSIDE_TR; + if (v2s == 0 && v3s == 0) return OUTSIDE_TR; + + if (v1s == 0) return ON_AB; + if (v2s == 0) return ON_BC; + if (v3s == 0) return ON_AC; + + return INSIDE_TR; +} + +RVec2 getProjectedPointWithWinding(const RVec3& point, ProjectionDirections dir) +{ + if (dir & YZ_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return RVec2(point.z, point.y); + } + else + return RVec2(point.y, point.z); + } + if (dir & ZX_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return RVec2(point.z, point.x); + } + return RVec2(point.x, point.z); + } + if (dir & OPPOSITE_WINDING) + { + return RVec2(point.y, point.x); + } + return RVec2(point.x, point.y); +} + +struct DelTriangle +{ + int32_t p[3]; + int32_t n[3]; + int32_t parentTriangle; + int32_t getEdWP(int32_t vrt) + { + if (p[0] == vrt) return 1; + if (p[1] == vrt) return 2; + if (p[2] == vrt) return 0; + return -1; + } + int32_t getEdId(int32_t v1, int32_t v2) + { + if (p[0] == v1 && p[1] == v2) return 0; + if (p[1] == v1 && p[2] == v2) return 1; + if (p[2] == v1 && p[0] == v2) return 2; + return -1; + } + int32_t getOppP(int32_t v1, int32_t v2) + { + if (p[0] == v1 && p[1] == v2) return 2; + if (p[1] == v1 && p[2] == v2) return 0; + if (p[2] == v1 && p[0] == v2) return 1; + return -1; + } + + int32_t getOppPoint(int32_t v1, int32_t v2) + { + if (p[0] != v1 && p[0] != v2) return p[0]; + if (p[1] != v1 && p[1] != v2) return p[1]; + if (p[2] != v1 && p[2] != v2) return p[2]; + return -1; + } + bool compare(const DelTriangle& t) const + { + if (p[0] == t.p[0] && p[1] == t.p[1] && p[2] == t.p[2]) return true; + if (p[1] == t.p[0] && p[2] == t.p[1] && p[0] == t.p[2]) return true; + if (p[2] == t.p[0] && p[0] == t.p[1] && p[1] == t.p[2]) return true; + return false; + } + +}; + +struct DelEdge +{ + int32_t s, e; + int32_t nr, nl; +}; + + +bool isIntersectsTriangle(RVec2& a, RVec2& b, RVec2& c, RVec2& s, RVec2& e) +{ + RVec2 vec = e - s; + + if ((a - s).cross(vec) * (b - s).cross(vec) < 0) + { + RVec2 vec2 = b - a; + if ((s - a).cross(vec2) * (e - a).cross(vec) < 0) return true; + } + + if ((b - s).cross(vec) * (c - s).cross(vec) < 0) + { + RVec2 vec2 = c - b; + if ((s - b).cross(vec2) * (e - b).cross(vec) < 0) return true; + } + + if ((a - s).cross(vec) * (c - s).cross(vec) < 0) + { + RVec2 vec2 = a - c; + if ((s - c).cross(vec2) * (e - c).cross(vec) < 0) return true; + } + + return false; +} + + +inline int32_t inCircumcircle(RVec2& a, RVec2& b, RVec2& c, RVec2& p) +{ + RVec2 ta = a - p; + RVec2 tb = b - p; + RVec2 tc = c - p; + cpp_rational ad = ta.dot(ta); + cpp_rational bd = tb.dot(tb); + cpp_rational cd = tc.dot(tc); + + cpp_rational pred = ta.x * (tb.y * cd - tc.y * bd) - ta.y * (tb.x * cd - tc.x * bd) + ad * (tb.x * tc.y - tc.x * tb.y); + + + if (pred > 0) return 1; + if (pred < 0) return -1; + return 0; +} + +int32_t getEdge(std::vector<DelEdge>& edges, int32_t s, int32_t e) +{ + for (uint32_t i = 0; i < edges.size(); ++i) + { + if (edges[i].s == s && edges[i].e == e) return i; + } + + edges.push_back(DelEdge()); + edges.back().s = s; + edges.back().e = e; + return edges.size() - 1; +} + +void reubildAdjacency(std::vector<DelTriangle>& state) +{ + for (uint32_t i = 0; i < state.size(); ++i) + { + state[i].n[0] = state[i].n[1] = state[i].n[2] = -1; + } + for (uint32_t i = 0; i < state.size(); ++i) + { + if (state[i].p[0] == -1) continue; + for (uint32_t j = i + 1; j < state.size(); ++j) + { + if (state[j].p[0] == -1) continue; + for (uint32_t k = 0; k < 3; ++k) + { + for (uint32_t c = 0; c < 3; ++c) + { + if (state[i].p[k] == state[j].p[(c + 1) % 3] && state[i].p[(k + 1) % 3] == state[j].p[c]) { state[i].n[k] = j; state[j].n[c] = i; } + } + } + } + } +} + +void insertPoint(std::vector<RVec2>& vertices, std::vector<DelTriangle>& state, int32_t p, const std::vector<Edge>& edges) +{ + std::queue<int32_t> triangleToCheck; + + for (uint32_t i = 0; i < state.size(); ++i) + { + if (state[i].p[0] == -1) continue; + DelTriangle ctr = state[i]; + int32_t cv = isPointInside(vertices[ctr.p[0]], vertices[ctr.p[1]], vertices[ctr.p[2]], vertices[p]); + + if (cv == OUTSIDE_TR) continue; + if (cv == INSIDE_TR) + { + uint32_t taInd = state.size(); + uint32_t tbInd = state.size() + 1; + uint32_t tcInd = state.size() + 2; + state.resize(state.size() + 3); + + state[taInd].p[0] = ctr.p[2]; + state[taInd].p[1] = ctr.p[0]; + state[taInd].p[2] = p; + + state[taInd].n[0] = ctr.n[2]; + state[taInd].n[1] = tbInd; + state[taInd].n[2] = tcInd; + + state[tbInd].p[0] = ctr.p[0]; + state[tbInd].p[1] = ctr.p[1]; + state[tbInd].p[2] = p; + + state[tbInd].n[0] = ctr.n[0]; + state[tbInd].n[1] = tcInd; + state[tbInd].n[2] = taInd; + + state[tcInd].p[0] = ctr.p[1]; + state[tcInd].p[1] = ctr.p[2]; + state[tcInd].p[2] = p; + + state[tcInd].n[0] = ctr.n[1]; + state[tcInd].n[1] = taInd; + state[tcInd].n[2] = tbInd; + + + triangleToCheck.push(taInd); + triangleToCheck.push(tbInd); + triangleToCheck.push(tcInd); + + + /** + Change neighboors + */ + int32_t nb = state[i].n[0]; + if (nb != -1) + state[nb].n[state[nb].getEdId(state[i].p[1], state[i].p[0])] = tbInd; + nb = state[i].n[1]; + if (nb != -1) + state[nb].n[state[nb].getEdId(state[i].p[2], state[i].p[1])] = tcInd; + nb = state[i].n[2]; + if (nb != -1) + state[nb].n[state[nb].getEdId(state[i].p[0], state[i].p[2])] = taInd; + + + state[i].p[0] = -1; + } + else + { + uint32_t taInd = state.size(); + uint32_t tbInd = state.size() + 1; + state.resize(state.size() + 2); + + int32_t bPoint = state[i].p[(cv + 2) % 3]; + + state[taInd].p[0] = bPoint; + state[taInd].p[1] = state[i].p[cv]; + state[taInd].p[2] = p; + + state[tbInd].p[0] = bPoint; + state[tbInd].p[1] = p; + state[tbInd].p[2] = state[i].p[(cv + 1) % 3]; + + state[taInd].n[0] = state[i].n[(cv + 2) % 3]; + state[taInd].n[1] = -1; + state[taInd].n[2] = tbInd; + + state[tbInd].n[0] = taInd; + state[tbInd].n[1] = -1; + state[tbInd].n[2] = state[i].n[(cv + 1) % 3]; + + if (state[i].n[(cv + 1) % 3] != -1) + for (int32_t k = 0; k < 3; ++k) + if (state[state[i].n[(cv + 1) % 3]].n[k] == (int32_t)i) { + state[state[i].n[(cv + 1) % 3]].n[k] = tbInd; break; + } + if (state[i].n[(cv + 2) % 3] != -1) + for (int32_t k = 0; k < 3; ++k) + if (state[state[i].n[(cv + 2) % 3]].n[k] == (int32_t)i) { + state[state[i].n[(cv + 2) % 3]].n[k] = taInd; break; + } + + triangleToCheck.push(taInd); + triangleToCheck.push(tbInd); + + int32_t total = 2; + int32_t oppositeTr = 0; + if (state[i].n[cv] != -1) + { + oppositeTr = state[i].n[cv]; + total += 2; + uint32_t tcInd = state.size(); + uint32_t tdInd = state.size() + 1; + state.resize(state.size() + 2); + + int32_t oped = state[oppositeTr].getEdId(state[i].p[(cv + 1) % 3], state[i].p[cv]); + + + state[tcInd].n[0] = state[oppositeTr].n[(oped + 2) % 3]; + state[tcInd].n[1] = tbInd; + state[tbInd].n[1] = tcInd; + state[tcInd].n[2] = tdInd; + + state[tdInd].n[0] = tcInd; + state[tdInd].n[1] = taInd; + state[taInd].n[1] = tdInd; + state[tdInd].n[2] = state[oppositeTr].n[(oped + 1) % 3]; + if (state[oppositeTr].n[(oped + 2) % 3] != -1) + for (int32_t k = 0; k < 3; ++k) + if (state[state[oppositeTr].n[(oped + 2) % 3]].n[k] == oppositeTr) { + state[state[oppositeTr].n[(oped + 2) % 3]].n[k] = tcInd; break; + } + if (state[oppositeTr].n[(oped + 1) % 3] != -1) + for (int32_t k = 0; k < 3; ++k) + if (state[state[oppositeTr].n[(oped + 1) % 3]].n[k] == oppositeTr) { + state[state[oppositeTr].n[(oped + 1) % 3]].n[k] = tdInd; break; + } + + int32_t pop = state[oppositeTr].p[(oped + 2) % 3]; + state[tcInd].p[0] = pop; + state[tcInd].p[1] = state[i].p[(cv + 1) % 3]; + state[tcInd].p[2] = p; + + state[tdInd].p[0] = pop; + state[tdInd].p[1] = p; + state[tdInd].p[2] = state[i].p[cv]; + + + state[oppositeTr].p[0] = -1; + triangleToCheck.push(tcInd); + triangleToCheck.push(tdInd); + } + state[i].p[0] = -1; + } + break; + } + + while (!triangleToCheck.empty()) + { + int32_t ctrid = triangleToCheck.front(); + triangleToCheck.pop(); + DelTriangle& ctr = state[ctrid]; + int32_t oppTr = -5; + int32_t ced = 0; + for (uint32_t i = 0; i < 3; ++i) + { + if (ctr.p[i] != p && ctr.p[(i + 1) % 3] != p) + { + ced = i; + oppTr = ctr.n[i]; + break; + } + } + if (oppTr == -1) continue; + bool toCont = false; + for (size_t i = 0; i < edges.size(); ++i) + { + if ((int32_t)edges[i].s == ctr.p[ced] && ctr.p[(ced + 1) % 3] == (int32_t)edges[i].e) { toCont = true; break; } + if ((int32_t)edges[i].e == ctr.p[ced] && ctr.p[(ced + 1) % 3] == (int32_t)edges[i].s) { toCont = true; break; } + } + if (toCont) continue; + + + DelTriangle& otr = state[oppTr]; + + if (inCircumcircle(vertices[state[oppTr].p[0]], vertices[state[oppTr].p[1]], vertices[state[oppTr].p[2]], vertices[p]) > 0) + { + int32_t notPIndx = 0; + for (; notPIndx < 3; ++notPIndx) + { + if (otr.p[notPIndx] != ctr.p[0] && otr.p[notPIndx] != ctr.p[1] && otr.p[notPIndx] != ctr.p[2]) + break; + } + + int32_t oppCed = state[oppTr].getEdId(ctr.p[(ced + 1) % 3], ctr.p[ced]); + + int32_t ntr1 = ctrid, ntr2 = oppTr; + + DelTriangle nt1, nt2; + nt1.p[0] = state[oppTr].p[notPIndx]; + nt1.p[1] = p; + nt1.n[0] = ntr2; + nt1.p[2] = ctr.p[ced]; + nt1.n[1] = ctr.n[(ced + 2) % 3]; + nt1.n[2] = otr.n[(oppCed + 1) % 3]; + + if (nt1.n[2] != -1) + for (uint32_t k = 0; k < 3; ++k) + if (state[nt1.n[2]].n[k] == oppTr) state[nt1.n[2]].n[k] = ntr1; + + nt2.p[0] = p; + nt2.p[1] = state[oppTr].p[notPIndx]; + nt2.n[0] = ntr1; + nt2.p[2] = ctr.p[(ced + 1) % 3]; + nt2.n[1] = otr.n[(oppCed + 2) % 3]; + nt2.n[2] = ctr.n[(ced + 1) % 3]; + if (nt2.n[2] != -1) + for (uint32_t k = 0; k < 3; ++k) + if (state[nt2.n[2]].n[k] == ctrid) state[nt2.n[2]].n[k] = ntr2; + state[ntr1] = nt1; + state[ntr2] = nt2; + triangleToCheck.push(ntr1); + triangleToCheck.push(ntr2); + } + } + +} + +bool edgeIsIntersected(const RVec2& a, const RVec2& b, const RVec2& es, const RVec2& ee) +{ + RVec2 t = b - a; + cpp_rational temp = (es - a).cross(t) * (ee - a).cross(t); + + if (temp < 0) + { + t = es - ee; + if ((a - ee).cross(t) * (b - ee).cross(t) <= 0) return true; + } + return false; +} + +void triangulatePseudoPolygon(std::vector<RVec2>& vertices, int32_t ba, int32_t bb, std::vector<int32_t>& pseudo, std::vector<DelTriangle>& output) +{ + if (pseudo.empty()) return; + + int32_t c = 0; + if (pseudo.size() > 1) + { + for (uint32_t i = 1; i < pseudo.size(); ++i) + { + if (inCircumcircle(vertices[ba], vertices[bb], vertices[pseudo[c]], vertices[pseudo[i]]) > 0) + { + c = i; + } + } + std::vector<int32_t> toLeft; + std::vector<int32_t> toRight; + + for (int32_t t = 0; t < c; ++t) + { + toLeft.push_back(pseudo[t]); + } + for (size_t t = c + 1; t < pseudo.size(); ++t) + { + toRight.push_back(pseudo[t]); + } + if (toLeft.size() > 0) + triangulatePseudoPolygon(vertices, ba, pseudo[c], toLeft, output); + if (toRight.size() > 0) + triangulatePseudoPolygon(vertices, pseudo[c], bb, toRight, output); + } + output.push_back(DelTriangle()); + output.back().p[0] = ba; + output.back().p[1] = bb; + output.back().p[2] = pseudo[c]; +} + + + +void insertEdge(std::vector<RVec2>& vertices, std::vector<DelTriangle>& output, int32_t edBeg, int32_t edEnd) +{ + bool hasEdge = false; + for (auto& it : output) + { + for (uint32_t i = 0; i < 3; ++i) + if ((it.p[i] == edBeg || it.p[i] == edEnd) && (it.p[(i + 1) % 3] == edBeg || it.p[(i + 1) % 3] == edEnd)) + { + hasEdge = true; + } + } + if (hasEdge) return; + + int32_t startTriangle = -1; + int32_t edg = -1; + for (uint32_t i = 0; i < output.size(); ++i) + { + if (output[i].p[0] == -1) continue; + + if (output[i].p[0] == edBeg || output[i].p[1] == edBeg || output[i].p[2] == edBeg) + { + edg = output[i].getEdWP(edBeg); + if (edgeIsIntersected(vertices[edBeg], vertices[edEnd], vertices[output[i].p[edg]], vertices[output[i].p[(edg + 1) % 3]])) + { + startTriangle = i; + break; + } + } + } + if (startTriangle == -1) + { + return; + } + int32_t cvertex = edBeg; + + std::vector<int32_t> pointsAboveEdge; + std::vector<int32_t> pointsBelowEdge; + + RVec2 vec = vertices[edEnd] - vertices[edBeg]; + + if (vec.cross(vertices[output[startTriangle].p[edg]] - vertices[edBeg]) > 0) + { + pointsAboveEdge.push_back(output[startTriangle].p[edg]); + pointsBelowEdge.push_back(output[startTriangle].p[(edg + 1) % 3]); + } + else + { + pointsBelowEdge.push_back(output[startTriangle].p[edg]); + pointsAboveEdge.push_back(output[startTriangle].p[(edg + 1) % 3]); + } + + while (1) + { + DelTriangle& ctr = output[startTriangle]; + int32_t oed = ctr.getEdWP(cvertex); + int32_t nextTriangle = ctr.n[oed]; + + if (output[nextTriangle].p[0] == edEnd || output[nextTriangle].p[1] == edEnd || output[nextTriangle].p[2] == edEnd) + { + ctr.p[0] = -1; + output[nextTriangle].p[0] = -1; + break; + } + + DelTriangle& otr = output[nextTriangle]; + int32_t opp = otr.p[otr.getOppP(ctr.p[(oed + 1) % 3], ctr.p[oed % 3])]; + + int32_t nextPoint = 0; + if (vec.cross((vertices[opp] - vertices[edBeg])) > 0) + { + pointsAboveEdge.push_back(opp); + if (vec.cross(vertices[ctr.p[(oed + 1) % 3]] - vertices[edBeg]) > 0) + { + nextPoint = ctr.p[(oed + 1) % 3]; + } + else + { + nextPoint = ctr.p[oed]; + } + } + else + { + pointsBelowEdge.push_back(opp); + + if (vec.cross(vertices[ctr.p[(oed + 1) % 3]] - vertices[edBeg]) < 0) + { + nextPoint = ctr.p[(oed + 1) % 3]; + } + else + { + nextPoint = ctr.p[oed]; + } + } + startTriangle = nextTriangle; + cvertex = nextPoint; + ctr.p[0] = -1; + } + triangulatePseudoPolygon(vertices, edBeg, edEnd, pointsAboveEdge, output); + std::reverse(pointsBelowEdge.begin(), pointsBelowEdge.end()); + triangulatePseudoPolygon(vertices, edEnd, edBeg, pointsBelowEdge, output); + reubildAdjacency(output); +} + + + + + + +void buildCDT(std::vector<RVec3>& vertices, std::vector<Edge>& edges, std::vector<DelTriangle>& output, ProjectionDirections dr) +{ + std::vector<DelTriangle> state; + + DelTriangle crt; + std::vector<bool> added(vertices.size(), false); + + for (uint32_t i = 0; i < 3; ++i) + { + crt.p[i] = edges[i].s; + added[edges[i].s] = true; + crt.n[i] = -1; // dont have neighboors; + } + state.push_back(crt); + + + std::vector<RVec2> p2d(vertices.size()); + for (uint32_t i = 0; i < vertices.size(); ++i) + { + p2d[i] = getProjectedPointWithWinding(vertices[i], dr); + } + + for (size_t i = 0; i < edges.size(); ++i) + { + if (!added[edges[i].s]) + { + insertPoint(p2d, state, edges[i].s, edges); + added[edges[i].s] = true; + } + if (!added[edges[i].e]) + { + insertPoint(p2d, state, edges[i].e, edges); + added[edges[i].e] = true; + } + if (edges[i].s != edges[i].e) + { + insertEdge(p2d, state, edges[i].s, edges[i].e); + } + } + + for (uint32_t t = 0; t < state.size(); ++t) + { + if (state[t].p[0] != -1) + { + output.push_back(state[t]); + } + } +} + +int32_t intersectSegments(RVec3& s1, RVec3& e1, RVec3& s2, RVec3& e2, ProjectionDirections dir, std::vector<cpp_rational>& t1v, std::vector<cpp_rational>& t2v); + +void getTriangleIntersectionCoplanar(uint32_t tr1, uint32_t tr2, std::vector<std::vector<RVec3>>& stencil, ProjectionDirections dr) +{ + std::vector<cpp_rational> intr1[3]; + std::vector<cpp_rational> intr2[3]; + + RVec3 p1[3]; + p1[0] = stencil[tr1][0]; + p1[1] = stencil[tr1][1]; + p1[2] = stencil[tr1][3]; + + RVec3 p2[3]; + p2[0] = stencil[tr2][0]; + p2[1] = stencil[tr2][1]; + p2[2] = stencil[tr2][3]; + + for (uint32_t i = 0; i < 3; ++i) + { + for (uint32_t j = 0; j < 3; ++j) + { + intersectSegments(p1[i], p1[(i + 1) % 3], p2[j], p2[(j + 1) % 3], dr, intr1[i], intr2[j]); + } + } + + int32_t inRel1[3]; + for (uint32_t i = 0; i < 3; ++i) + { + inRel1[i] = isPointInside(getProjectedPointWithWinding(p2[0], dr), getProjectedPointWithWinding(p2[1], dr), getProjectedPointWithWinding(p2[2], dr), getProjectedPointWithWinding(p1[i], dr)); + } + + int32_t inRel2[3]; + for (uint32_t i = 0; i < 3; ++i) + { + inRel2[i] = isPointInside(getProjectedPointWithWinding(p1[0], dr), getProjectedPointWithWinding(p1[1], dr), getProjectedPointWithWinding(p1[2], dr), getProjectedPointWithWinding(p2[i], dr)); + } + + for (uint32_t i = 0; i < 3; ++i) + { + if (inRel1[i] == INSIDE_TR && inRel1[(i + 1) % 3] == INSIDE_TR) + { + stencil[tr2].push_back(p1[i]); + stencil[tr2].push_back(p1[(i + 1) % 3]); + } + else + { + if (inRel1[i] == INSIDE_TR && intr1[i].size() == 1) + { + stencil[tr2].push_back(p1[i]); + stencil[tr2].push_back((p1[(i + 1) % 3] - p1[i]) * intr1[i][0] + p1[i]); + } + if (inRel1[(i + 1) % 3] == INSIDE_TR && intr1[i].size() == 1) + { + stencil[tr2].push_back(p1[(i + 1) % 3]); + stencil[tr2].push_back((p1[(i + 1) % 3] - p1[i]) * intr1[i][0] + p1[i]); + } + if (intr1[i].size() == 2) + { + stencil[tr2].push_back((p1[(i + 1) % 3] - p1[i]) * intr1[i][0] + p1[i]); + stencil[tr2].push_back((p1[(i + 1) % 3] - p1[i]) * intr1[i][1] + p1[i]); + } + } + } + + for (uint32_t i = 0; i < 3; ++i) + { + if (inRel2[i] == INSIDE_TR && inRel2[(i + 1) % 3] == INSIDE_TR) + { + stencil[tr1].push_back(p2[i]); + stencil[tr1].push_back(p2[(i + 1) % 3]); + } + else + { + if (inRel2[i] == INSIDE_TR && intr2[i].size() == 1) + { + stencil[tr1].push_back(p2[i]); + stencil[tr1].push_back((p2[(i + 1) % 3] - p2[i]) * intr2[i][0] + p2[i]); + } + if (inRel2[(i + 1) % 3] == INSIDE_TR && intr2[i].size() == 1) + { + stencil[tr1].push_back(p2[(i + 1) % 3]); + stencil[tr1].push_back((p2[(i + 1) % 3] - p2[i]) * intr2[i][0] + p2[i]); + } + if (intr2[i].size() == 2) + { + stencil[tr1].push_back((p2[(i + 1) % 3] - p2[i]) * intr2[i][0] + p2[i]); + stencil[tr1].push_back((p2[(i + 1) % 3] - p2[i]) * intr2[i][1] + p2[i]); + } + } + } +} + + +int32_t getTriangleIntersection3d(uint32_t tr1, uint32_t tr2, std::vector<std::vector<RVec3>>& stencil, ProjectionDirections dr) +{ + RatPlane pl1(stencil[tr1][0], stencil[tr1][1], stencil[tr1][3]); + if (pl1.n.isZero()) + { + std::swap(tr1, tr2); + pl1 = RatPlane(stencil[tr1][0], stencil[tr1][1], stencil[tr1][3]); + if (pl1.n.isZero()) return 0; + } + + + cpp_rational d1 = pl1.distance(stencil[tr2][0]); + cpp_rational d2 = pl1.distance(stencil[tr2][1]); + cpp_rational d3 = pl1.distance(stencil[tr2][3]); + + int32_t sd1 = d1.sign(); + int32_t sd2 = d2.sign(); + int32_t sd3 = d3.sign(); + + + if (sd1 == 0 && sd2 == 0 && sd3 == 0) + { + getTriangleIntersectionCoplanar(tr1, tr2, stencil, dr); + return 0; + } + /** + Never intersected + */ + if (sd1 < 0 && sd2 < 0 && sd3 < 0) + return 0; + if (sd1 > 0 && sd2 > 0 && sd3 > 0) + return 0; + + RVec3 tb0 = stencil[tr2][0]; + RVec3 tb1 = stencil[tr2][1]; + RVec3 tb2 = stencil[tr2][3]; + + if (sd1 * sd3 > 0) + { + std::swap(tb1, tb2); + std::swap(d2, d3); + } + else + { + if (sd2 * sd3 > 0) + { + std::swap(tb0, tb2); + std::swap(d1, d3); + } + else + { + if (sd3 == 0 && sd1 * sd2 < 0) + { + std::swap(tb0, tb2); + std::swap(d1, d3); + } + } + } + + RatPlane pl2(stencil[tr2][0], stencil[tr2][1], stencil[tr2][3]); + + cpp_rational d21 = pl2.distance(stencil[tr1][0]); + cpp_rational d22 = pl2.distance(stencil[tr1][1]); + cpp_rational d23 = pl2.distance(stencil[tr1][3]); + + int32_t sd21 = d21.sign(); + int32_t sd22 = d22.sign(); + int32_t sd23 = d23.sign(); + + if (sd21 < 0 && sd22 < 0 && sd23 < 0) + return 0; + if (sd21 > 0 && sd22 > 0 && sd23 > 0) + return 0; + + + RVec3 ta0 = stencil[tr1][0]; + RVec3 ta1 = stencil[tr1][1]; + RVec3 ta2 = stencil[tr1][3]; + + + if (sd21 * sd23 > 0) + { + std::swap(ta1, ta2); + std::swap(d22, d23); + } + else + { + if (sd22 * sd23 > 0) + { + std::swap(ta0, ta2); + std::swap(d21, d23); + } + else + { + if (sd23 == 0 && sd21 * sd22 < 0) + { + std::swap(ta0, ta2); + std::swap(d21, d23); + } + } + } + ////////////////////////////////////////////////// + RVec3 dir = ta2 - ta0; + + cpp_rational dirPlaneDot = dir.dot(pl2.n); + + + RVec3 pointOnIntersectionLine; + if (dirPlaneDot != 0) + { + pointOnIntersectionLine = ta0 - dir * (d21 / dirPlaneDot); + } + else + { + pointOnIntersectionLine = ta0; + } + RVec3 interLineDir = pl1.n.cross(pl2.n); + cpp_rational sqd = interLineDir.dot(interLineDir); + if (sqd.is_zero()) return 0; + + cpp_rational t1p2 = (ta1 - pointOnIntersectionLine).dot(interLineDir) / sqd; + cpp_rational t1p3 = (ta2 - pointOnIntersectionLine).dot(interLineDir) / sqd; + cpp_rational t1p2param = t1p2; + if (d22 != d23) + { + t1p2param = t1p2 + (t1p3 - t1p2) * (d22 / (d22 - d23)); + } + + t1p2 = (tb0 - pointOnIntersectionLine).dot(interLineDir) / sqd; + t1p3 = (tb2 - pointOnIntersectionLine).dot(interLineDir) / sqd; + cpp_rational t2p1param = t1p2; + if (d1 != d3) + { + t2p1param = t1p2 + (t1p3 - t1p2) * d1 / (d1 - d3); + } + + t1p2 = (tb1 - pointOnIntersectionLine).dot(interLineDir) / sqd; + cpp_rational t2p2param = t1p2; + if (d2 != d3) + { + t2p2param = t1p2 + (t1p3 - t1p2) * d2 / (d2 - d3); + } + cpp_rational beg1 = 0; + + if (t1p2param < 0) + { + std::swap(beg1, t1p2param); + } + if (t2p2param < t2p1param) + { + std::swap(t2p2param, t2p1param); + } + cpp_rational minEnd = std::min(t1p2param, t2p2param); + cpp_rational maxBeg = std::max(beg1, t2p1param); + + if (minEnd > maxBeg) + { + RVec3 p1 = pointOnIntersectionLine + interLineDir * maxBeg; + RVec3 p2 = pointOnIntersectionLine + interLineDir * minEnd; + + stencil[tr1].push_back(p1); + stencil[tr1].push_back(p2); + + stencil[tr2].push_back(p1); + stencil[tr2].push_back(p2); + return 1; + } + return 0; +} + +int32_t intersectSegments(RVec3& s1, RVec3& e1, RVec3& s2, RVec3& e2, ProjectionDirections dir, std::vector<cpp_rational>& t1v, std::vector<cpp_rational>& t2v) +{ + RVec2 s1p = getProjectedPointWithWinding(s1, dir); + RVec2 e1p = getProjectedPointWithWinding(e1, dir); + + RVec2 s2p = getProjectedPointWithWinding(s2, dir); + RVec2 e2p = getProjectedPointWithWinding(e2, dir); + + RVec2 dir1 = e1p - s1p; + RVec2 dir2 = s2p - e2p; + + cpp_rational crs = dir1.cross(dir2); + if (crs != 0) + { + cpp_rational c1 = s2p.x - s1p.x; + cpp_rational c2 = s2p.y - s1p.y; + + cpp_rational det1 = c1 * dir2.y - c2 * dir2.x; + cpp_rational det2 = dir1.x * c2 - dir1.y * c1; + + cpp_rational t1 = det1 / crs; + cpp_rational t2 = det2 / crs; + + if (t1 > 0 && t1 < 1 && (t2 >= 0 && t2 <= 1)) + { + t1v.push_back(t1); + } + if (t2 > 0 && t2 < 1 && (t1 >= 0 && t1 <= 1)) + { + t2v.push_back(t2); + } + + } + else + { + if (dir1.cross(s2p - s1p) == 0) + { + if (dir1.x != 0) + { + cpp_rational t1 = (s2p.x - s1p.x) / dir1.x; + cpp_rational t2 = (e2p.x - s1p.x) / dir1.x; + if (t1 > 0 && t1 < 1) t1v.push_back(t1); + if (t2 > 0 && t2 < 1) t1v.push_back(t2); + } + else + { + if (dir1.y != 0) + { + cpp_rational t1 = (s2p.y - s1p.y) / dir1.y; + cpp_rational t2 = (e2p.y - s1p.y) / dir1.y; + if (t1 > 0 && t1 < 1) t1v.push_back(t1); + if (t2 > 0 && t2 < 1) t1v.push_back(t2); + } + } + } + if (dir2.cross(s1p - s2p) == 0) + { + dir2 = e2p - s2p; + if (dir2.x != 0) + { + cpp_rational t1 = (s1p.x - s2p.x) / dir2.x; + cpp_rational t2 = (e1p.x - s2p.x) / dir2.x; + if (t1 > 0 && t1 < 1) t2v.push_back(t1); + if (t2 > 0 && t2 < 1) t2v.push_back(t2); + } + else + { + if (dir2.y != 0) + { + cpp_rational t1 = (s1p.y - s2p.y) / dir2.y; + cpp_rational t2 = (e1p.y - s2p.y) / dir2.y; + if (t1 > 0 && t1 < 1) t2v.push_back(t1); + if (t2 > 0 && t2 < 1) t2v.push_back(t2); + } + } + } + } + return 1; +} + +struct RVec3Comparer +{ + bool operator()(const RVec3& a, const RVec3& b) const + { + if (a.x < b.x) return true; + if (a.x > b.x) return false; + if (a.y < b.y) return true; + if (a.y > b.y) return false; + if (a.z < b.z) return true; + return false; + } +}; + +void getBarycentricCoords(PxVec2& a, PxVec2& b, PxVec2& c, PxVec2& p, float& u, float& v) +{ + PxVec3 v1(b.x - a.x, c.x - a.x, a.x - p.x); + PxVec3 v2(b.y - a.y, c.y - a.y, a.y - p.y); + + PxVec3 resl = v1.cross(v2); + u = resl.x / resl.z; + v = resl.y / resl.z; +} + + +Mesh* MeshCleanerImpl::cleanMesh(const Mesh* mesh) +{ + /** + ======= Get mesh data =========== + */ + std::vector<Vertex> vertices; + std::vector<Edge> edges; + std::vector<Facet> facets; + + vertices.resize(mesh->getVerticesCount()); + edges.resize(mesh->getEdgesCount()); + facets.resize(mesh->getFacetCount()); + + PxBounds3 bnd; + bnd.setEmpty(); + + for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) + { + vertices[i] = mesh->getVertices()[i]; + bnd.include(vertices[i].p); + } + for (uint32_t i = 0; i < mesh->getEdgesCount(); ++i) + { + edges[i] = mesh->getEdges()[i]; + } + for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) + { + facets[i] = mesh->getFacetsBuffer()[i]; + } + //====================================== + + /** + Transform vertices to fit unit cube and snap them to grid. + **/ + float scale = 1.0f / bnd.getExtents().abs().maxElement(); + + int32_t gridSize = 10000; // Grid resolution to which vertices position will be snapped. + + for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) + { + vertices[i].p = (vertices[i].p - bnd.minimum) * scale; + vertices[i].p.x = std::floor(vertices[i].p.x * gridSize) / gridSize; + vertices[i].p.y = std::floor(vertices[i].p.y * gridSize) / gridSize; + vertices[i].p.z = std::floor(vertices[i].p.z * gridSize) / gridSize; + } + + std::vector<std::vector<RVec3>> triangleStencil(facets.size()); + + std::vector<PxVec3> facetsNormals(facets.size()); + std::vector<PxBounds3> facetBound(facets.size()); + + + for (uint32_t tr1 = 0; tr1 < facets.size(); ++tr1) + { + if (facets[tr1].edgesCount != 3) + { + return nullptr; + } + int32_t fed = facets[tr1].firstEdgeNumber; + triangleStencil[tr1].push_back(vertices[edges[fed].s].p); + triangleStencil[tr1].push_back(vertices[edges[fed].e].p); + triangleStencil[tr1].push_back(vertices[edges[fed + 1].s].p); + triangleStencil[tr1].push_back(vertices[edges[fed + 1].e].p); + triangleStencil[tr1].push_back(vertices[edges[fed + 2].s].p); + triangleStencil[tr1].push_back(vertices[edges[fed + 2].e].p); + + facetBound[tr1].setEmpty(); + facetBound[tr1].include(vertices[edges[fed].s].p); + facetBound[tr1].include(vertices[edges[fed].e].p); + facetBound[tr1].include(vertices[edges[fed + 2].s].p); + facetBound[tr1].fattenFast(0.001f); + + facetsNormals[tr1] = (vertices[edges[fed + 1].s].p - vertices[edges[fed].s].p).cross(vertices[edges[fed + 2].s].p - vertices[edges[fed].s].p); + } + + /** + Build intersections between all pairs of triangles. + */ + for (uint32_t tr1 = 0; tr1 < facets.size(); ++tr1) + { + if (triangleStencil[tr1].empty()) continue; + for (uint32_t tr2 = tr1 + 1; tr2 < facets.size(); ++tr2) + { + if (triangleStencil[tr2].empty()) continue; + if (facetBound[tr1].intersects(facetBound[tr2]) == false) continue; + + getTriangleIntersection3d(tr1, tr2, triangleStencil, getProjectionDirection(facetsNormals[tr1])); + } + } + + /** + Reintersect all segments + */ + for (uint32_t tr = 0; tr < triangleStencil.size(); ++tr) + { + std::vector<RVec3>& ctr = triangleStencil[tr]; + std::vector<std::vector<cpp_rational> > perSegmentInters(ctr.size() / 2); + for (uint32_t sg1 = 6; sg1 < ctr.size(); sg1 += 2) + { + for (uint32_t sg2 = sg1 + 2; sg2 < ctr.size(); sg2 += 2) + { + intersectSegments(ctr[sg1], ctr[sg1 + 1], ctr[sg2], ctr[sg2 + 1], getProjectionDirection(facetsNormals[tr]), perSegmentInters[sg1 / 2], perSegmentInters[sg2 / 2]); + } + } + + std::vector<RVec3> newStencil; + newStencil.reserve(ctr.size()); + + for (uint32_t i = 0; i < ctr.size(); i += 2) + { + int32_t csm = i / 2; + if (perSegmentInters[csm].size() == 0) + { + newStencil.push_back(ctr[i]); + newStencil.push_back(ctr[i + 1]); + } + else + { + cpp_rational current = 0; + newStencil.push_back(ctr[i]); + std::sort(perSegmentInters[csm].begin(), perSegmentInters[csm].end()); + for (size_t j = 0; j < perSegmentInters[csm].size(); ++j) + { + if (perSegmentInters[csm][j] > current) + { + current = perSegmentInters[csm][j]; + RVec3 pnt = (ctr[i + 1] - ctr[i]) * current + ctr[i]; + newStencil.push_back(pnt); + newStencil.push_back(pnt); + } + } + newStencil.push_back(ctr[i + 1]); + } + } + ctr = newStencil; + } + + std::vector<RVec3> finalPoints; + + std::vector<std::vector<Edge>> tsten(facets.size()); + + { + std::map<RVec3, uint32_t, RVec3Comparer> mapping; + for (uint32_t tr1 = 0; tr1 < triangleStencil.size(); ++tr1) + { + for (uint32_t j = 0; j < triangleStencil[tr1].size(); j += 2) + { + + auto it = mapping.find(triangleStencil[tr1][j]); + int32_t pt = 0; + if (it == mapping.end()) + { + mapping[triangleStencil[tr1][j]] = finalPoints.size(); + pt = finalPoints.size(); + finalPoints.push_back(triangleStencil[tr1][j]); + } + else + { + pt = it->second; + } + + Edge newed; + + newed.s = pt; + + it = mapping.find(triangleStencil[tr1][j + 1]); + if (it == mapping.end()) + { + mapping[triangleStencil[tr1][j + 1]] = finalPoints.size(); + pt = finalPoints.size(); + finalPoints.push_back(triangleStencil[tr1][j + 1]); + } + else + { + pt = it->second; + } + newed.e = pt; + bool hasNewEdge = false; + for (uint32_t e = 0; e < tsten[tr1].size(); ++e) + { + if (tsten[tr1][e].s == newed.s && tsten[tr1][e].e == newed.e) + { + hasNewEdge = true; + break; + } + if (tsten[tr1][e].e == newed.s && tsten[tr1][e].s == newed.e) + { + hasNewEdge = true; + break; + } + } + if (!hasNewEdge) tsten[tr1].push_back(newed); + } + } + } + + /** + Build constrained DT + */ + std::vector<DelTriangle> trs; + for (uint32_t i = 0; i < tsten.size(); ++i) + { + + if (tsten[i].size() < 3) continue; + if (tsten[i].size() > 3) + { + int32_t oldSize = trs.size(); + buildCDT(finalPoints, tsten[i], trs, getProjectionDirection(facetsNormals[i])); + for (uint32_t k = oldSize; k < trs.size(); ++k) + trs[k].parentTriangle = i; + } + else + { + trs.push_back(DelTriangle()); + trs.back().parentTriangle = i; + for (uint32_t v = 0; v < 3; ++v) + trs.back().p[v] = tsten[i][v].s; + } + + } + + /** + Remove 'deleted' triangles from array. + */ + { + std::vector < DelTriangle > trstemp; + trstemp.reserve(trs.size()); + for (uint32_t i = 0; i < trs.size(); ++i) + { + if (trs[i].p[0] != -1) + trstemp.push_back(trs[i]); + } + trs = trstemp; + } + + /** + Filter exterior surface + */ + std::vector<bool> fillingMask(trs.size(), false); + + std::map<std::pair<int32_t, int32_t>, int32_t> edgeMap; + std::vector<std::vector<int32_t> > edgeToTriangleMapping; + + for (uint32_t i = 0; i < trs.size(); ++i) + { + if (trs[i].p[0] == -1) continue; + if (trs[i].p[0] == trs[i].p[1] || trs[i].p[2] == trs[i].p[1] || trs[i].p[2] == trs[i].p[0]) + { + trs[i].p[0] = -1; + continue; + } + #if 0 // Filter null-area triangles. + if ((finalPoints[trs[i].p[1]] - finalPoints[trs[i].p[0]]).cross(finalPoints[trs[i].p[2]] - finalPoints[trs[i].p[0]]).isZero()) + { + trs[i].p[0] = -1; + continue; + } + #endif + for (uint32_t k = 0; k < 3; ++k) + { + int32_t es = trs[i].p[k]; + int32_t ee = trs[i].p[(k + 1) % 3]; + if (es > ee) + { + std::swap(es, ee); + } + auto pr = std::make_pair(es, ee); + auto iter = edgeMap.find(pr); + if (iter == edgeMap.end()) + { + edgeMap[pr] = edgeToTriangleMapping.size(); + trs[i].n[k] = edgeToTriangleMapping.size(); + edgeToTriangleMapping.resize(edgeToTriangleMapping.size() + 1); + edgeToTriangleMapping.back().push_back(i); + } + else + { + for (uint32_t j = 0; j < edgeToTriangleMapping[iter->second].size(); ++j) + { + if (trs[edgeToTriangleMapping[iter->second][j]].compare(trs[i])) + { + trs[i].p[0] = -1; + break; + } + } + if (trs[i].p[0] != -1) + { + trs[i].n[k] = iter->second; + edgeToTriangleMapping[iter->second].push_back(i); + } + } + } + } + + std::queue<int32_t> trque; + float maxx = -1000; + int32_t best = 0; + for (uint32_t i = 0; i < trs.size(); ++i) + { + if (trs[i].p[0] == -1) continue; + float m = std::max(finalPoints[trs[i].p[0]].x.convert_to<float>(), std::max(finalPoints[trs[i].p[1]].x.convert_to<float>(), finalPoints[trs[i].p[2]].x.convert_to<float>())); + if (m > maxx && facetsNormals[trs[i].parentTriangle].x > 0) + { + maxx = m; + best = i; + } + } + + trque.push(best); + while (!trque.empty()) + { + int32_t trid = trque.front(); + fillingMask[trid] = true; + DelTriangle& tr = trs[trque.front()]; + trque.pop(); + + for (uint32_t ed = 0; ed < 3; ++ed) + { + auto& tlist = edgeToTriangleMapping[tr.n[ed]]; + if (tlist.size() == 2) + { + for (uint32_t k = 0; k < tlist.size(); ++k) + { + int32_t to = tlist[k]; + if (to != trid && !fillingMask[to] && edgeToTriangleMapping[trs[to].n[0]].size() > 0 && edgeToTriangleMapping[trs[to].n[1]].size() > 0 && edgeToTriangleMapping[trs[to].n[2]].size() > 0) + { + trque.push(tlist[k]); + fillingMask[tlist[k]] = true; + } + } + } + if (tlist.size() > 2) + { + int32_t bestPath = (tlist[0] == trid) ? tlist[1] : tlist[0]; + RVec3 start = finalPoints[trs[trid].p[ed]]; + RVec3 axis = finalPoints[trs[trid].p[(ed + 1) % 3]] - start; + RVec3 nAxis = finalPoints[trs[trid].p[(ed + 2) % 3]] - start; + RVec3 normal = axis.cross(nAxis); + + + uint32_t op = trs[bestPath].getOppPoint(trs[trid].p[ed], trs[trid].p[(ed + 1) % 3]); + + RVec3 dir2 = (finalPoints[op] - start); + RVec3 normal2 = dir2.cross(axis); + cpp_rational bestDir = normal.cross(normal2).dot(axis); + cpp_rational oldDist = normal2.dot(normal2); + for (uint32_t k = 0; k < tlist.size(); ++k) + { + if (tlist[k] == trid) continue; + op = trs[tlist[k]].getOppPoint(trs[trid].p[ed], trs[trid].p[(ed + 1) % 3]); + dir2 = (finalPoints[op] - start); + normal2 = dir2.cross(axis); + cpp_rational newOne = normal.cross(normal2).dot(axis); + + if (newOne * oldDist < bestDir * normal2.dot(normal2)) + { + oldDist = normal2.dot(normal2); + bestPath = tlist[k]; + bestDir = newOne; + } + } + if (!fillingMask[bestPath] && edgeToTriangleMapping[trs[bestPath].n[0]].size() > 0 && edgeToTriangleMapping[trs[bestPath].n[1]].size() > 0 && edgeToTriangleMapping[trs[bestPath].n[2]].size() > 0) + { + trque.push(bestPath); + fillingMask[bestPath] = true; + } + } + edgeToTriangleMapping[tr.n[ed]].clear(); + } + + } + for (uint32_t id = 0; id < trs.size(); ++id) + { + if (!fillingMask[id]) + { + trs[id].p[0] = -1; // Remove triangle + } + } + ///////////////////////////////////////////////////////////////////////////////////////////// + + std::vector<PxVec3> newVertices; + newVertices.resize(finalPoints.size()); + for (uint32_t i = 0; i < finalPoints.size(); ++i) + { + newVertices[i].x = finalPoints[i].x.convert_to<float>(); + newVertices[i].y = finalPoints[i].y.convert_to<float>(); + newVertices[i].z = finalPoints[i].z.convert_to<float>(); + } + /** + Rescale mesh to initial coordinates. + */ + for (uint32_t i = 0; i < finalPoints.size(); ++i) + { + newVertices[i] = newVertices[i] * (1.0f / scale) + bnd.minimum; + } + for (uint32_t i = 0; i < vertices.size(); ++i) + { + vertices[i].p = vertices[i].p * (1.0f / scale) + bnd.minimum; + } + + std::vector<Triangle> result; + result.reserve(trs.size()); + { + std::vector<PxVec2> projectedTriangles(facets.size() * 3); + std::vector<Vertex> normalTriangles(facets.size() * 3); + + for (uint32_t i = 0; i < facets.size(); ++i) + { + for (uint32_t k = 0; k < 3; ++k) + { + normalTriangles[i * 3 + k] = vertices[edges[facets[i].firstEdgeNumber + k].s]; + projectedTriangles[i * 3 + k] = getProjectedPointWithWinding(vertices[edges[facets[i].firstEdgeNumber + k].s].p, getProjectionDirection(facetsNormals[i])); + } + } + + for (uint32_t i = 0; i < trs.size(); ++i) + { + if (trs[i].p[0] == -1) continue; + int32_t id = 0; + int32_t parentTriangle = trs[i].parentTriangle; + float u = 0, v = 0; + result.resize(result.size() + 1); + result.back().materialId = facets[parentTriangle].materialId; + result.back().smoothingGroup = facets[parentTriangle].smoothingGroup; + for (auto vert : { &result.back().a, &result.back().b , &result.back().c }) + { + vert->p = newVertices[trs[i].p[id]]; + PxVec2 p = getProjectedPointWithWinding(vert->p, getProjectionDirection(facetsNormals[parentTriangle])); + getBarycentricCoords(projectedTriangles[parentTriangle * 3], projectedTriangles[parentTriangle * 3 + 1], projectedTriangles[parentTriangle * 3 + 2], p, u, v); + vert->uv[0] = (1 - u - v) * normalTriangles[parentTriangle * 3].uv[0] + u * normalTriangles[parentTriangle * 3 + 1].uv[0] + v * normalTriangles[parentTriangle * 3 + 2].uv[0]; + vert->n = (1 - u - v) * normalTriangles[parentTriangle * 3].n + u * normalTriangles[parentTriangle * 3 + 1].n + v * normalTriangles[parentTriangle * 3 + 2].n; + ++id; + } + } + } + + /** + Reuse old buffers to create Mesh + */ + std::vector<PxVec3> newMeshVertices(result.size() * 3); + std::vector<PxVec3> newMeshNormals(result.size() * 3); + std::vector<PxVec2> newMeshUvs(result.size() * 3); + + std::vector<int32_t> newMaterialIds(result.size()); + std::vector<int32_t> newSmoothingGroups(result.size()); + + + for (uint32_t i = 0; i < result.size(); ++i) + { + Vertex* arr[3] = { &result[i].a, &result[i].b , &result[i].c }; + for (uint32_t k = 0; k < 3; ++k) + { + newMeshVertices[i * 3 + k] = arr[k]->p; + newMeshNormals[i * 3 + k] = arr[k]->n; + newMeshUvs[i * 3 + k] = arr[k]->uv[0]; + } + } + std::vector<uint32_t> serializedIndices; + serializedIndices.reserve(result.size() * 3); + int32_t cindex = 0; + for (uint32_t i = 0; i < result.size(); ++i) + { + newMaterialIds[i] = result[i].materialId; + newSmoothingGroups[i] = result[i].smoothingGroup; + + for (uint32_t pi = 0; pi < 3; ++pi) + serializedIndices.push_back(cindex++); + } + + MeshImpl* rMesh = new MeshImpl(newMeshVertices.data(), newMeshNormals.data(), newMeshUvs.data(), static_cast<uint32_t>(newMeshVertices.size()), serializedIndices.data(), static_cast<uint32_t>(serializedIndices.size())); + rMesh->setMaterialId(newMaterialIds.data()); + rMesh->setSmoothingGroup(newSmoothingGroups.data()); + return rMesh; +} + +void MeshCleanerImpl::release() +{ + delete this; +} + diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h new file mode 100644 index 0000000..0eb1a85 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h @@ -0,0 +1,25 @@ +#include "NvBlastExtAuthoringMeshCleaner.h" + +namespace Nv +{ +namespace Blast +{ + +class Mesh; + +class MeshCleanerImpl : public MeshCleaner +{ +public: + /** + Tries to remove self intersections and open edges in interior of mesh. + \param[in] mesh Mesh to be cleaned. + \return Cleaned mesh or nullptr if failed. + */ + virtual Mesh* cleanMesh(const Nv::Blast::Mesh* mesh) override; + virtual void release() override; + + ~MeshCleanerImpl() {}; +}; + +} +}
\ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMesh.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp index a25d2fe..3497fda 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMesh.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp @@ -10,10 +10,11 @@ #define _CRT_SECURE_NO_WARNINGS -#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringMeshImpl.h" #include "NvBlastExtAuthoringTypes.h" #include <string.h> #include "NvBlastExtAuthoringPerlinNoise.h" +#include <cmath> using physx::PxVec2; using physx::PxVec3; @@ -24,7 +25,7 @@ namespace Nv namespace Blast { -Mesh::Mesh(PxVec3* position, PxVec3* normals, PxVec2* uv, uint32_t verticesCount, uint32_t* indices, uint32_t indicesCount) +MeshImpl::MeshImpl(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount) { mVertices.resize(verticesCount); @@ -81,11 +82,14 @@ Mesh::Mesh(PxVec3* position, PxVec3* normals, PxVec2* uv, uint32_t verticesCount mEdges[i + 2].e = indices[i]; mFacets[facetId].firstEdgeNumber = i; mFacets[facetId].edgesCount = 3; + mFacets[facetId].materialId = 0; + //Unassigned for now + mFacets[facetId].smoothingGroup = -1; facetId++; } } -Mesh::Mesh(Vertex* vertices, Edge* edges, Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount) +MeshImpl::MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount) { mVertices.resize(posCount); mEdges.resize(edgesCount); @@ -101,7 +105,7 @@ Mesh::Mesh(Vertex* vertices, Edge* edges, Facet* facets, uint32_t posCount, uint } } -float Mesh::getMeshVolume() +float MeshImpl::getMeshVolume() { /** Check if mesh boundary consist only of triangles @@ -124,53 +128,80 @@ float Mesh::getMeshVolume() volume += (a.x * b.y * c.z - a.x * b.z * c.y - a.y * b.x * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x); } - return (1.0f / 6.0f) * abs(volume); + return (1.0f / 6.0f) * std::abs(volume); } -uint32_t Mesh::getFacetCount() +uint32_t MeshImpl::getFacetCount() const { return static_cast<uint32_t>(mFacets.size()); } -Vertex* Mesh::getVertices() +Vertex* MeshImpl::getVerticesWritable() { return mVertices.data(); } -Edge* Mesh::getEdges() +Edge* MeshImpl::getEdgesWritable() { return mEdges.data(); } -uint32_t Mesh::getEdgesCount() +const Vertex* MeshImpl::getVertices() const +{ + return mVertices.data(); +} + +const Edge* MeshImpl::getEdges() const +{ + return mEdges.data(); +} + +uint32_t MeshImpl::getEdgesCount() const { return static_cast<uint32_t>(mEdges.size()); } -uint32_t Mesh::getVerticesCount() +uint32_t MeshImpl::getVerticesCount() const { return static_cast<uint32_t>(mVertices.size()); } -Facet* Mesh::getFacetsBuffer() +Facet* MeshImpl::getFacetsBufferWritable() { return mFacets.data(); } -Facet* Mesh::getFacet(int32_t facet) +const Facet* MeshImpl::getFacetsBuffer() const +{ + return mFacets.data(); +} +Facet* MeshImpl::getFacetWritable(int32_t facet) +{ + return &mFacets[facet]; +} +const Facet* MeshImpl::getFacet(int32_t facet) const { return &mFacets[facet]; } +MeshImpl::~MeshImpl() +{ +} + +void MeshImpl::release() +{ + delete this; +} -Mesh::~Mesh() +const PxBounds3& MeshImpl::getBoundingBox() const { + return mBounds; } -PxBounds3& Mesh::getBoundingBox() +PxBounds3& MeshImpl::getBoundingBoxWritable() { return mBounds; } -void Mesh::recalculateBoundingBox() +void MeshImpl::recalculateBoundingBox() { mBounds.setEmpty(); for (uint32_t i = 0; i < mVertices.size(); ++i) @@ -184,7 +215,7 @@ void Mesh::recalculateBoundingBox() void getTangents(PxVec3& normal, PxVec3& t1, PxVec3& t2) { - if (abs(normal.z) < 0.9) + if (std::abs(normal.z) < 0.9) { t1 = normal.cross(PxVec3(0, 0, 1)); } @@ -249,61 +280,85 @@ Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int32 edges.push_back(Edge(1, 2)); edges.push_back(Edge(2, 3)); edges.push_back(Edge(3, 0)); - facets.push_back(Facet(0, 4, id)); + facets.push_back(Facet(0, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(0, 3)); edges.push_back(Edge(3, 7)); edges.push_back(Edge(7, 4)); edges.push_back(Edge(4, 0)); - facets.push_back(Facet(4, 4, id)); + facets.push_back(Facet(4, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(3, 2)); edges.push_back(Edge(2, 6)); edges.push_back(Edge(6, 7)); edges.push_back(Edge(7, 3)); - facets.push_back(Facet(8, 4, id)); + facets.push_back(Facet(8, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(5, 6)); edges.push_back(Edge(6, 2)); edges.push_back(Edge(2, 1)); edges.push_back(Edge(1, 5)); - facets.push_back(Facet(12, 4, id)); + facets.push_back(Facet(12, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(4, 5)); edges.push_back(Edge(5, 1)); edges.push_back(Edge(1, 0)); edges.push_back(Edge(0, 4)); - facets.push_back(Facet(16, 4, id)); + facets.push_back(Facet(16, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(4, 7)); edges.push_back(Edge(7, 6)); edges.push_back(Edge(6, 5)); edges.push_back(Edge(5, 4)); - facets.push_back(Facet(20, 4, id)); - return new Mesh(positions.data(), edges.data(), facets.data(), static_cast<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); + facets.push_back(Facet(20, 4, MATERIAL_INTERIOR, id)); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); } void inverseNormalAndSetIndices(Mesh* mesh, int32_t id) { for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) { - mesh->getVertices()[i].n *= -1.0f; + mesh->getVerticesWritable()[i].n *= -1.0f; } for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { - mesh->getFacet(i)->userData = id; + mesh->getFacetWritable(i)->userData = id; } +} +void MeshImpl::setMaterialId(int32_t* materialId) +{ + if (materialId != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].materialId = *materialId; + ++materialId; + } + } } +void MeshImpl::setSmoothingGroup(int32_t* smoothingGroup) +{ + if (smoothingGroup != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].smoothingGroup = *smoothingGroup; + ++smoothingGroup; + } + } +} + + void setCuttingBox(const PxVec3& point, const PxVec3& normal, Mesh* mesh, float size, int32_t id) { PxVec3 t1, t2; PxVec3 lNormal = normal.getNormalized(); getTangents(lNormal, t1, t2); - Vertex* positions = mesh->getVertices(); + Vertex* positions = mesh->getVerticesWritable(); positions[0].p = point + (t1 + t2) * size; positions[1].p = point + (t2 - t1) * size; @@ -332,12 +387,12 @@ void setCuttingBox(const PxVec3& point, const PxVec3& normal, Mesh* mesh, float for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { - mesh->getFacet(i)->userData = id; + mesh->getFacetWritable(i)->userData = id; } mesh->recalculateBoundingBox(); } -bool Mesh::isValid() +bool MeshImpl::isValid() const { return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0; } @@ -388,7 +443,7 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no edges.push_back(Edge(i * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j + 1)); edges.push_back(Edge((i + 1) * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j)); edges.push_back(Edge((i + 1) * (resolution + 1) + j, i * (resolution + 1) + j)); - facets.push_back(Facet(start, 4, id)); + facets.push_back(Facet(start, 4, MATERIAL_INTERIOR, id)); } } uint32_t offset = (resolution + 1) * (resolution + 1); @@ -437,7 +492,7 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no edges.push_back(Edge(9 + offset, 8 + offset)); edges.push_back(Edge(8 + offset, 11 + offset)); - facets.push_back(Facet(edgeOffset, 8, id)); + facets.push_back(Facet(edgeOffset, 8, MATERIAL_INTERIOR, id)); @@ -445,34 +500,34 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no edges.push_back(Edge(3 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 4 + offset)); edges.push_back(Edge(4 + offset, 0 + offset)); - facets.push_back(Facet(8 + edgeOffset, 4, id)); + facets.push_back(Facet(8 + edgeOffset, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(3 + offset, 2 + offset)); edges.push_back(Edge(2 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 3 + offset)); - facets.push_back(Facet(12 + edgeOffset, 4, id)); + facets.push_back(Facet(12 + edgeOffset, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(5 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 2 + offset)); edges.push_back(Edge(2 + offset, 1 + offset)); edges.push_back(Edge(1 + offset, 5 + offset)); - facets.push_back(Facet(16 + edgeOffset, 4, id)); + facets.push_back(Facet(16 + edgeOffset, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(4 + offset, 5 + offset)); edges.push_back(Edge(5 + offset, 1 + offset)); edges.push_back(Edge(1 + offset, 0 + offset)); edges.push_back(Edge(0 + offset, 4 + offset)); - facets.push_back(Facet(20 + edgeOffset, 4, id)); + facets.push_back(Facet(20 + edgeOffset, 4, MATERIAL_INTERIOR, id)); edges.push_back(Edge(4 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 5 + offset)); edges.push_back(Edge(5 + offset, 4 + offset)); - facets.push_back(Facet(24 + edgeOffset, 4, id)); + facets.push_back(Facet(24 + edgeOffset, 4, MATERIAL_INTERIOR, id)); // - return new Mesh(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); + return new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); } Mesh* getBigBox(const PxVec3& point, float size) @@ -517,41 +572,41 @@ Mesh* getBigBox(const PxVec3& point, float size) edges.push_back(Edge(1, 2)); edges.push_back(Edge(2, 3)); edges.push_back(Edge(3, 0)); - facets.push_back(Facet(0, 4)); + facets.push_back(Facet(0, 4, MATERIAL_INTERIOR, 0)); edges.push_back(Edge(0, 3)); edges.push_back(Edge(3, 7)); edges.push_back(Edge(7, 4)); edges.push_back(Edge(4, 0)); - facets.push_back(Facet(4, 4)); + facets.push_back(Facet(4, 4, MATERIAL_INTERIOR, 0)); edges.push_back(Edge(3, 2)); edges.push_back(Edge(2, 6)); edges.push_back(Edge(6, 7)); edges.push_back(Edge(7, 3)); - facets.push_back(Facet(8, 4)); + facets.push_back(Facet(8, 4, MATERIAL_INTERIOR, 0)); edges.push_back(Edge(5, 6)); edges.push_back(Edge(6, 2)); edges.push_back(Edge(2, 1)); edges.push_back(Edge(1, 5)); - facets.push_back(Facet(12, 4)); + facets.push_back(Facet(12, 4, MATERIAL_INTERIOR, 0)); edges.push_back(Edge(4, 5)); edges.push_back(Edge(5, 1)); edges.push_back(Edge(1, 0)); edges.push_back(Edge(0, 4)); - facets.push_back(Facet(16, 4)); + facets.push_back(Facet(16, 4, MATERIAL_INTERIOR, 0)); edges.push_back(Edge(4, 7)); edges.push_back(Edge(7, 6)); edges.push_back(Edge(6, 5)); edges.push_back(Edge(5, 4)); - facets.push_back(Facet(20, 4)); + facets.push_back(Facet(20, 4, MATERIAL_INTERIOR, 0)); for (int i = 0; i < 8; ++i) positions[i].n = PxVec3(0, 0, 0); - return new Mesh(positions.data(), edges.data(), facets.data(), static_cast<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); } } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h new file mode 100644 index 0000000..ee36f9c --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h @@ -0,0 +1,212 @@ +/* +* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#ifndef NVBLASTAUTHORINGMESHIMPL_H +#define NVBLASTAUTHORINGMESHIMPL_H + +#include "NvBlastExtAuthoringMesh.h" +#include <vector> + +namespace Nv +{ +namespace Blast +{ + +/** + Class for internal mesh representation +*/ +class MeshImpl : public Mesh +{ +public: + + /** + Constructs mesh object from array of triangles. + \param[in] position Array of vertex positions + \param[in] normals Array of vertex normals + \param[in] uv Array of vertex uv coordinates + \param[in] verticesCount Vertices count + \param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle. + \param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3) + */ + MeshImpl(const physx::PxVec3* position, const physx::PxVec3* normals, const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount); + + /** + Constructs mesh object from array of facets. + \param[in] vertices Array of vertices + \param[in] edges Array of edges + \param[in] facets Array of facets + \param[in] posCount Vertices count + \param[in] edgesCount Edges count + \param[in] facetsCount Facets count + */ + MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount); + + ~MeshImpl(); + + virtual void release() override; + + /** + Return true if mesh is valid + */ + bool isValid() const override; + + /** + Return pointer on vertices array + */ + Vertex* getVerticesWritable() override; + + /** + Return pointer on edges array + */ + Edge* getEdgesWritable() override; + + /** + Return pointer on facets array + */ + Facet* getFacetsBufferWritable() override; + + /** + Return pointer on vertices array + */ + const Vertex* getVertices() const override; + + /** + Return pointer on edges array + */ + const Edge* getEdges() const override; + + /** + Return pointer on facets array + */ + const Facet* getFacetsBuffer() const override; + + /** + Return writable pointer on specified facet + */ + Facet* getFacetWritable(int32_t facet) override; + + /** + Return writable pointer on specified facet + */ + const Facet* getFacet(int32_t facet) const override; + + /** + Return edges count + */ + uint32_t getEdgesCount() const override; + + /** + Return vertices count + */ + uint32_t getVerticesCount() const override; + + /** + Return facet count + */ + uint32_t getFacetCount() const override; + + + /** + Return reference on mesh bounding box. + */ + const physx::PxBounds3& getBoundingBox() const override; + + /** + Return writable reference on mesh bounding box. + */ + physx::PxBounds3& getBoundingBoxWritable() override; + + /** + Recalculate bounding box + */ + void recalculateBoundingBox() override; + + /** + Compute mesh volume. Can be used only for triangulated meshes. + Return mesh volume. If mesh is not triangulated return 0. + */ + float getMeshVolume() override; + + + /** + Set per-facet material id. + */ + void setMaterialId(int32_t* materialIds) override; + + /** + Set per-facet smoothing group. + */ + void setSmoothingGroup(int32_t* smoothingGroup) override; + +private: + std::vector<Vertex> mVertices; + std::vector<Edge> mEdges; + std::vector<Facet> mFacets; + physx::PxBounds3 mBounds; +}; + + +/** + Helper functions +*/ + +/** + Set cutting box at some particular position. + \param[in] point Cutting face center + \param[in] normal Cutting face normal + \param[in] mesh Cutting box mesh + \param[in] size Cutting box size + \param[in] id Cutting box ID +*/ +void setCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, Mesh* mesh, float size, int32_t id); +/** + Create cutting box at some particular position. + \param[in] point Cutting face center + \param[in] normal Cutting face normal + \param[in] size Cutting box size + \param[in] id Cutting box ID +*/ +Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int32_t id); + +/** + Create box at some particular position. + \param[in] point Cutting face center + \param[in] size Cutting box size +*/ +Mesh* getBigBox(const physx::PxVec3& point, float size); + +/** + Create slicing box with noisy cutting surface. + \param[in] point Cutting face center + \param[in] normal Cutting face normal + \param[in] size Cutting box size + \param[in] jaggedPlaneSize Noisy surface size + \param[in] resolution Noisy surface resolution + \param[in] id Cutting box ID + \param[in] amplitude Noise amplitude + \param[in] frequency Noise frequency + \param[in] octaves Noise octaves + \param[in] seed Random generator seed, used for noise generation. +*/ +Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed); + + +/** + Inverses normals of cutting box and sets indices. + \param[in] mesh Cutting box mesh + \param[in] id Cutting box ID +*/ +void inverseNormalAndSetIndices(Mesh* mesh, int32_t id); + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGMESHIMPL_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.cpp new file mode 100644 index 0000000..72e9413 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.cpp @@ -0,0 +1,975 @@ +// 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. + + +// This warning arises when using some stl containers with older versions of VC +// c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code +#include "NvPreprocessor.h" +#if NV_VC && NV_VC < 14 +#pragma warning(disable : 4702) +#endif + +#include "NvBlastExtAuthoringMeshNoiser.h" +#include "NvBlastExtAuthoringPerlinNoise.h" +#include <set> +#include <queue> +#include <NvBlastAssert.h> + +using namespace Nv::Blast; +using namespace std; + + +void MeshNoiser::computeFalloffAndNormals() +{ + // Map newly created vertices according to positions + + computePositionedMapping(); + + mGeometryGraph.resize(mVertices.size()); + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + if (mTrMeshEdToTr[i].c == 0) + { + continue; + } + int32_t v1 = mPositionMappedVrt[mEdges[i].s]; + int32_t v2 = mPositionMappedVrt[mEdges[i].e]; + + if (std::find(mGeometryGraph[v1].begin(), mGeometryGraph[v1].end(), v2) == mGeometryGraph[v1].end()) + mGeometryGraph[v1].push_back(v2); + if (std::find(mGeometryGraph[v2].begin(), mGeometryGraph[v2].end(), v1) == mGeometryGraph[v2].end()) + mGeometryGraph[v2].push_back(v1); + } + mVerticesDistances.clear(); + mVerticesDistances.resize(mVertices.size(), 10000.0f); + + std::queue<int32_t> que; + + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + if (mTrMeshEdToTr[i].c != 0 && (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE)) + { + int32_t v1 = mPositionMappedVrt[mEdges[i].s]; + int32_t v2 = mPositionMappedVrt[mEdges[i].e]; + mVerticesDistances[v1] = 0.0f; + mVerticesDistances[v2] = 0.0f; + que.push(v1); + que.push(v2); + } + } + while (!que.empty()) + { + int32_t curr = que.front(); + que.pop(); + + for (uint32_t i = 0; i < mGeometryGraph[curr].size(); ++i) + { + int32_t to = mGeometryGraph[curr][i]; + float d = mVerticesDistances[curr] + 0.1f;// (mVertices[to].p - mVertices[curr].p).magnitudeSquared(); + if (d < mVerticesDistances[to]) + { + mVerticesDistances[to] = d; + que.push(to); + } + } + } + + for (uint32_t i = 0; i < mVerticesDistances.size(); ++i) + { + int32_t from = mPositionMappedVrt[i]; + mVerticesDistances[i] = mVerticesDistances[from]; + } +} + +bool edgeOverlapTest(PxVec3& as, PxVec3& ae, PxVec3& bs, PxVec3& be) +{ + //return false; + if (std::max(std::min(as.x, ae.x), std::min(bs.x, be.x)) > std::min(std::max(as.x, ae.x), std::max(bs.x, be.x))) return false; + if (std::max(std::min(as.y, ae.y), std::min(bs.y, be.y)) > std::min(std::max(as.y, ae.y), std::max(bs.y, be.y))) return false; + if (std::max(std::min(as.z, ae.z), std::min(bs.z, be.z)) > std::min(std::max(as.z, ae.z), std::max(bs.z, be.z))) return false; + + return ((bs - as).cross(ae - as)).magnitudeSquared() < 1e-6f && ((be - as).cross(ae - as)).magnitudeSquared() < 1e-6f; +} + +void MeshNoiser::computePositionedMapping() +{ + std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; + mPositionMappedVrt.clear(); + mPositionMappedVrt.resize(mVertices.size()); + + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + auto it = mPosMap.find(mVertices[i].p); + + if (it == mPosMap.end()) + { + mPosMap[mVertices[i].p] = i; + mPositionMappedVrt[i] = i; + } + else + { + mPositionMappedVrt[i] = it->second; + } + } +} + + + + +void MeshNoiser::relax(int32_t iteration, float factor, std::vector<Vertex>& vertices) +{ + std::vector<PxVec3> verticesTemp(vertices.size()); + std::vector<PxVec3> normalsTemp(vertices.size()); + for (int32_t iter = 0; iter < iteration; ++iter) + { + for (uint32_t i = 0; i < vertices.size(); ++i) + { + if (mRestrictionFlag[i]) + { + continue; + } + PxVec3 cps = vertices[i].p; + PxVec3 cns = mVerticesNormalsSmoothed[i]; + PxVec3 averaged(0, 0, 0); + PxVec3 averagedNormal(0, 0, 0); + + for (uint32_t p = 0; p < mGeometryGraph[mPositionMappedVrt[i]].size(); ++p) + { + int32_t to = mGeometryGraph[mPositionMappedVrt[i]][p]; + averaged += vertices[to].p; + averagedNormal += mVerticesNormalsSmoothed[to]; + + } + averaged *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); + averagedNormal *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); + verticesTemp[i] = cps + (averaged - cps) * factor; + normalsTemp[i] = cns * (1.0f - factor) + averagedNormal * factor; + } + for (uint32_t i = 0; i < vertices.size(); ++i) + { + if (mRestrictionFlag[i]) + { + continue; + } + vertices[i].p = verticesTemp[i]; + mVerticesNormalsSmoothed[i] = normalsTemp[i].getNormalized(); + + } + } + +} + +NV_FORCE_INLINE void markEdge(int32_t ui, int32_t ed, std::vector<MeshNoiser::EdgeFlag>& shortMarkup, std::vector<int32_t>& lastOwner) +{ + if (shortMarkup[ed] == MeshNoiser::NONE) + { + if (ui == 0) + { + shortMarkup[ed] = MeshNoiser::EXTERNAL_EDGE; + } + else + { + shortMarkup[ed] = MeshNoiser::INTERNAL_EDGE; + } + lastOwner[ed] = ui; + } + else + { + if (ui != 0) + { + if (shortMarkup[ed] == MeshNoiser::EXTERNAL_EDGE) + { + shortMarkup[ed] = MeshNoiser::EXTERNAL_BORDER_EDGE; + } + if ((shortMarkup[ed] == MeshNoiser::INTERNAL_EDGE) && ui != lastOwner[ed]) + { + shortMarkup[ed] = MeshNoiser::INTERNAL_BORDER_EDGE; + } + } + else + { + if (shortMarkup[ed] != MeshNoiser::EXTERNAL_EDGE) + { + shortMarkup[ed] = MeshNoiser::EXTERNAL_BORDER_EDGE; + } + } + } +} + +void MeshNoiser::prebuildEdgeFlagArray() +{ + mRestrictionFlag.clear(); + mRestrictionFlag.resize(mVertices.size()); + mEdgeFlag.clear(); + mEdgeFlag.resize(mEdges.size(), NONE); + + std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; + mPositionMappedVrt.clear(); + mPositionMappedVrt.resize(mVertices.size(), 0); + + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + auto it = mPosMap.find(mVertices[i].p); + + if (it == mPosMap.end()) + { + mPosMap[mVertices[i].p] = i; + mPositionMappedVrt[i] = i; + } + else + { + mPositionMappedVrt[i] = it->second; + } + } + + std::map<Edge, int32_t> mPositionEdgeMap; + std::vector<int32_t> mPositionBasedEdges(mEdges.size()); + + + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + Edge tmp = Edge(mPositionMappedVrt[mEdges[i].s], mPositionMappedVrt[mEdges[i].e]); + if (tmp.e < tmp.s) std::swap(tmp.e, tmp.s); + auto it = mPositionEdgeMap.find(tmp); + if (it == mPositionEdgeMap.end()) + { + mPositionEdgeMap[tmp] = i; + mPositionBasedEdges[i] = i; + } + else + { + mPositionBasedEdges[i] = it->second; + } + } + + std::vector<EdgeFlag> shortMarkup(mEdges.size(), NONE); + std::vector<int32_t> lastOwner(mEdges.size(), 0); + + std::vector<std::vector<int32_t> > edgeOverlap(mEdges.size()); + for (auto it1 = mPositionEdgeMap.begin(); it1 != mPositionEdgeMap.end(); ++it1) + { + auto it2 = it1; + it2++; + for (; it2 != mPositionEdgeMap.end(); ++it2) + { + Edge& ed1 = mEdges[it1->second]; + Edge& ed2 = mEdges[it2->second]; + + if (edgeOverlapTest(mVertices[ed1.s].p, mVertices[ed1.e].p, mVertices[ed2.s].p, mVertices[ed2.e].p)) + { + edgeOverlap[it1->second].push_back(it2->second); + } + } + } + + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + int32_t ui = mTriangles[i].userData; + int32_t ed = mPositionBasedEdges[findEdge(Edge(mTriangles[i].ea, mTriangles[i].eb))]; + + + markEdge(ui, ed, shortMarkup, lastOwner); + for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) + { + markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); + } + + ed = mPositionBasedEdges[findEdge(Edge(mTriangles[i].ea, mTriangles[i].ec))]; + markEdge(ui, ed, shortMarkup, lastOwner); + for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) + { + markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); + } + + ed = mPositionBasedEdges[findEdge(Edge(mTriangles[i].eb, mTriangles[i].ec))]; + markEdge(ui, ed, shortMarkup, lastOwner); + for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) + { + markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); + } + + } + + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + mEdgeFlag[i] = shortMarkup[mPositionBasedEdges[i]]; + } + + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].userData != 0) continue; + + int32_t ed = findEdge(Edge(mTriangles[i].ea, mTriangles[i].eb)); + mEdgeFlag[ed] = EXTERNAL_EDGE; + ed = findEdge(Edge(mTriangles[i].ec, mTriangles[i].eb)); + mEdgeFlag[ed] = EXTERNAL_EDGE; + ed = findEdge(Edge(mTriangles[i].ea, mTriangles[i].ec)); + mEdgeFlag[ed] = EXTERNAL_EDGE; + } +} + + + + +NV_FORCE_INLINE int32_t MeshNoiser::addVerticeIfNotExist(const Vertex& p) +{ + auto it = mVertMap.find(p); + if (it == mVertMap.end()) + { + mVertMap[p] = static_cast<int32_t>(mVertices.size()); + mVertices.push_back(p); + return static_cast<int32_t>(mVertices.size()) - 1; + } + else + { + return it->second; + } +} + +NV_FORCE_INLINE int32_t MeshNoiser::addEdge(const Edge& e) +{ + Edge ed = e; + if (ed.e < ed.s) std::swap(ed.s, ed.e); + auto it = mEdgeMap.find(ed); + if (it == mEdgeMap.end()) + { + mTrMeshEdToTr.push_back(EdgeToTriangles()); + mEdgeMap[ed] = (int)mEdgeMap.size(); + mEdges.push_back(ed); + mEdgeFlag.push_back(INTERNAL_EDGE); + return (int32_t)mEdges.size() - 1; + } + else + { + return it->second; + } +} + +NV_FORCE_INLINE int32_t MeshNoiser::findEdge(const Edge& e) +{ + Edge ed = e; + if (ed.e < ed.s) std::swap(ed.s, ed.e); + auto it = mEdgeMap.find(ed); + if (it == mEdgeMap.end()) + { + return -1; + } + else + { + return it->second; + } +} + + +/** + Weld input vertices, build edge and triangle buffers +*/ +void MeshNoiser::setMesh(const vector<Triangle>& mesh) +{ + uint32_t a, b, c; + PxBounds3 box; + box.setEmpty(); + for (uint32_t i = 0; i < mesh.size(); ++i) + { + const Triangle& tr = mesh[i]; + a = addVerticeIfNotExist(tr.a); + b = addVerticeIfNotExist(tr.b); + c = addVerticeIfNotExist(tr.c); + box.include(tr.a.p); + box.include(tr.b.p); + box.include(tr.c.p); + addEdge(Edge(a, b)); + addEdge(Edge(b, c)); + addEdge(Edge(a, c)); + mTriangles.push_back(TriangleIndexed(a, b, c)); + mTriangles.back().userData = tr.userData; + mTriangles.back().materialId = tr.materialId; + mTriangles.back().smoothingGroup = tr.smoothingGroup; + + } + mOffset = box.getCenter(); + mScale = max(box.getExtents(0), max(box.getExtents(1), box.getExtents(2))); + float invScale = 1.0f / mScale; + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].p = mVertices[i].p - box.getCenter(); + mVertices[i].p *= invScale; + } +} + + +void MeshNoiser::tesselateInternalSurface(float maxLenIn) +{ + if (mTriangles.empty()) + { + return; + } + + updateEdgeTriangleInfo(); + prebuildEdgeFlagArray(); + mRestrictionFlag.resize(mVertices.size(), 0); + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) + { + mRestrictionFlag[mEdges[i].s] = 1; + mRestrictionFlag[mEdges[i].e] = 1; + } + } + + + float maxLen = maxLenIn; + float mlSq = maxLen * maxLen; + float minD = maxLen * 0.5f; + minD = minD * minD; + + for (int32_t iter = 0; iter < 15; ++iter) + { + updateVertEdgeInfo(); + uint32_t oldSize = (uint32_t)mEdges.size(); + for (uint32_t i = 0; i < oldSize; ++i) + { + if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) + { + continue; + } + if ((mVertices[mEdges[i].s].p - mVertices[mEdges[i].e].p).magnitudeSquared() < minD) + { + collapseEdge(i); + } + } + oldSize = (uint32_t)mEdges.size(); + updateEdgeTriangleInfo(); + for (uint32_t i = 0; i < oldSize; ++i) + { + if (mEdgeFlag[i] == EXTERNAL_EDGE) + { + continue; + } + if ((mVertices[mEdges[i].s].p - mVertices[mEdges[i].e].p).magnitudeSquared() > mlSq) + { + divideEdge(i); + } + } + } + computeFalloffAndNormals(); + prebuildTesselatedTriangles(); + isTesselated = true; +} + +void MeshNoiser::updateEdgeTriangleInfo() +{ + mTrMeshEdToTr.clear(); + mTrMeshEdToTr.resize(mEdges.size()); + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + TriangleIndexed& tr = mTriangles[i]; + if (tr.ea == NOT_VALID_VERTEX) + continue; + int32_t ed = addEdge(Edge(tr.ea, tr.eb)); + mTrMeshEdToTr[ed].add(i); + ed = addEdge(Edge(tr.ea, tr.ec)); + mTrMeshEdToTr[ed].add(i); + ed = addEdge(Edge(tr.ec, tr.eb)); + mTrMeshEdToTr[ed].add(i); + } +} + +void MeshNoiser::updateVertEdgeInfo() +{ + mVertexToTriangleMap.clear(); + mVertexToTriangleMap.resize(mVertices.size()); + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + TriangleIndexed& tr = mTriangles[i]; + if (tr.ea == NOT_VALID_VERTEX) continue; + mVertexToTriangleMap[tr.ea].push_back(i); + mVertexToTriangleMap[tr.eb].push_back(i); + mVertexToTriangleMap[tr.ec].push_back(i); + } + mVertexValence.clear(); + mVertexValence.resize(mVertices.size(), 0); + + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + if (mTrMeshEdToTr[i].c != 0) + { + mVertexValence[mEdges[i].s]++; + mVertexValence[mEdges[i].e]++; + } + } +} + + +void MeshNoiser::collapseEdge(int32_t id) +{ + Edge cEdge = mEdges[id]; + uint32_t from = cEdge.s; + uint32_t to = cEdge.e; + + if (mRestrictionFlag[from] && mRestrictionFlag[to]) + { + return; + } + + if (mVertexValence[from] > mVertexValence[to]) + { + std::swap(from, to); + } + + if (mRestrictionFlag[from]) + { + std::swap(from, to); + } + + std::set<int32_t> connectedToBegin; + std::set<int32_t> connectedToEnd; + std::set<int32_t> neighboorTriangles; + + int32_t trWithEdge[2] = {-1, -1}; + int32_t cntr = 0; + for (uint32_t i = 0; i < mVertexToTriangleMap[from].size(); ++i) + { + if (mTriangles[mVertexToTriangleMap[from][i]].ea == NOT_VALID_VERTEX) + continue; + if (neighboorTriangles.insert(mVertexToTriangleMap[from][i]).second && mTriangles[mVertexToTriangleMap[from][i]].isContainEdge(from, to)) + { + trWithEdge[cntr] = mVertexToTriangleMap[from][i]; + cntr++; + } + } + for (uint32_t i = 0; i < mVertexToTriangleMap[to].size(); ++i) + { + if (mTriangles[mVertexToTriangleMap[to][i]].ea == NOT_VALID_VERTEX) + continue; + if (neighboorTriangles.insert(mVertexToTriangleMap[to][i]).second && mTriangles[mVertexToTriangleMap[to][i]].isContainEdge(from, to)) + { + trWithEdge[cntr] = mVertexToTriangleMap[to][i]; + cntr++; + } + } + + if (cntr == 0) + { + return; + } + if (cntr > 2) + { + return; + } + + for (uint32_t i: neighboorTriangles) + { + if (mTriangles[i].ea == from || mTriangles[i].eb == from || mTriangles[i].ec == from) + { + if (mTriangles[i].ea != to && mTriangles[i].ea != from) + connectedToBegin.insert(mTriangles[i].ea); + if (mTriangles[i].eb != to && mTriangles[i].eb != from) + connectedToBegin.insert(mTriangles[i].eb); + if (mTriangles[i].ec != to && mTriangles[i].ec != from) + connectedToBegin.insert(mTriangles[i].ec); + } + + if (mTriangles[i].ea == to || mTriangles[i].eb == to || mTriangles[i].ec == to) + { + if (mTriangles[i].ea != to && mTriangles[i].ea != from) + connectedToEnd.insert(mTriangles[i].ea); + if (mTriangles[i].eb != to && mTriangles[i].eb != from) + connectedToEnd.insert(mTriangles[i].eb); + if (mTriangles[i].ec != to && mTriangles[i].ec != from) + connectedToEnd.insert(mTriangles[i].ec); + } + } + bool canBeCollapsed = true; + for (auto it = connectedToBegin.begin(); it != connectedToBegin.end(); ++it) + { + uint32_t currV = *it; + if (connectedToEnd.find(currV) == connectedToEnd.end()) + continue; + bool found = false; + for (int32_t tr : neighboorTriangles) + { + if ((mTriangles[tr].ea == from || mTriangles[tr].eb == from || mTriangles[tr].ec == from) && + (mTriangles[tr].ea == to || mTriangles[tr].eb == to || mTriangles[tr].ec == to) && + (mTriangles[tr].ea == currV || mTriangles[tr].eb == currV || mTriangles[tr].ec == currV)) + { + found = true; + break; + } + } + if (!found) + { + canBeCollapsed = false; + break; + } + } + if (canBeCollapsed) + { + for (int32_t i : neighboorTriangles) + { + if (trWithEdge[0] == i) continue; + if (cntr == 2 && trWithEdge[1] == i) continue; + TriangleIndexed tr = mTriangles[i]; + PxVec3 oldNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); + + if (tr.ea == from) + { + tr.ea = to; + } + else + if (tr.eb == from) + { + tr.eb = to; + } + else + if (tr.ec == from) + { + tr.ec = to; + } + PxVec3 newNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); + if (newNormal.magnitude() < 1e-8f) + { + canBeCollapsed = false; + break; + } + if (oldNormal.dot(newNormal) < 0) + { + canBeCollapsed = false; + break; + } + } + mTriangles[trWithEdge[0]].ea = NOT_VALID_VERTEX; + if (cntr == 2)mTriangles[trWithEdge[1]].ea = NOT_VALID_VERTEX; + + for (int32_t i : neighboorTriangles) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + continue; + if (mTriangles[i].ea == from) + { + mTriangles[i].ea = to; + mVertexToTriangleMap[from].clear(); + mVertexToTriangleMap[to].push_back(i); + } + else + if (mTriangles[i].eb == from) + { + mTriangles[i].eb = to; + mVertexToTriangleMap[from].clear(); + mVertexToTriangleMap[to].push_back(i); + } + else + if (mTriangles[i].ec == from) + { + mTriangles[i].ec = to; + mVertexToTriangleMap[from].clear(); + mVertexToTriangleMap[to].push_back(i); + } + } + } +} + + +void MeshNoiser::divideEdge(int32_t id) +{ + + if (mTrMeshEdToTr[id].c == 0 ) + { + return; + } + + Edge cEdge = mEdges[id]; + EdgeFlag snapRestriction = mEdgeFlag[id]; + Vertex middle; + uint32_t nv = NOT_VALID_VERTEX; + for (int32_t t = 0; t < mTrMeshEdToTr[id].c; ++t) + { + int32_t oldTriangleIndex = mTrMeshEdToTr[id].tr[t]; + TriangleIndexed tr = mTriangles[mTrMeshEdToTr[id].tr[t]]; + + if (tr.ea == NOT_VALID_VERTEX) + { + continue; + } + + uint32_t pbf[3]; + pbf[0] = tr.ea; + pbf[1] = tr.eb; + pbf[2] = tr.ec; + for (int32_t p = 0; p < 3; ++p) + { + int32_t pnx = (p + 1) % 3; + int32_t opp = (p + 2) % 3; + + if ((pbf[p] == cEdge.s && pbf[pnx] == cEdge.e) || (pbf[p] == cEdge.e && pbf[pnx] == cEdge.s)) + { + if (nv == NOT_VALID_VERTEX) + { + middle.p = (mVertices[pbf[p]].p + mVertices[pbf[pnx]].p) * 0.5f; + middle.n = (mVertices[pbf[p]].n + mVertices[pbf[pnx]].n) * 0.5f; + middle.uv[0] = (mVertices[pbf[p]].uv[0] + mVertices[pbf[pnx]].uv[0]) * 0.5f; + + nv = (uint32_t)mVertices.size(); + mVertices.push_back(middle); + } + if (nv < mRestrictionFlag.size()) + { + mRestrictionFlag[nv] = ((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); + } + else + { + mRestrictionFlag.push_back((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); + } + + uint32_t ind1 = addEdge(Edge(pbf[p], nv)); + uint32_t ind2 = addEdge(Edge(nv, pbf[pnx])); + uint32_t ind3 = addEdge(Edge(nv, pbf[opp])); + + + mEdgeFlag[ind1] = snapRestriction; + mEdgeFlag[ind2] = snapRestriction; + mEdgeFlag[ind3] = INTERNAL_EDGE; + + mTrMeshEdToTr[ind1].add(mTrMeshEdToTr[id].tr[t]); + int32_t userInfo = mTriangles[mTrMeshEdToTr[id].tr[t]].userData; + int32_t matId = mTriangles[mTrMeshEdToTr[id].tr[t]].materialId; + mTriangles[mTrMeshEdToTr[id].tr[t]] = TriangleIndexed(pbf[p], nv, pbf[opp]); + mTriangles[mTrMeshEdToTr[id].tr[t]].userData = userInfo; + mTriangles[mTrMeshEdToTr[id].tr[t]].materialId = matId; + mTrMeshEdToTr[ind2].add((int32_t)mTriangles.size()); + mTrMeshEdToTr[ind3].add((int32_t)mTrMeshEdToTr[id].tr[t]); + mTrMeshEdToTr[ind3].add((int32_t)mTriangles.size()); + mTriangles.push_back(TriangleIndexed(nv,pbf[pnx], pbf[opp])); + mTriangles.back().userData = userInfo; + mTriangles.back().materialId = matId; + int32_t ed1 = findEdge(Edge(pbf[pnx], pbf[opp])); + mTrMeshEdToTr[ed1].replace(oldTriangleIndex, (int32_t)mTriangles.size() - 1); + break; + } + } + } +} + + +float falloffFunction(float x, float mx) +{ + float t = (x) / (mx + 1e-6f); + t = std::min(1.0f, t); + return t * t; +} + +void MeshNoiser::recalcNoiseDirs() +{ + /** + Compute normals direction to apply noise + */ + mVerticesNormalsSmoothed.resize(mVertices.size(), PxVec3(0, 0, 0)); + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + { + continue; + } + TriangleIndexed& tr = mTriangles[i]; + if (tr.userData == 0) continue; + + if (tr.userData < 0) + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += mVertices[tr.ea].n.getNormalized(); + else + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] -= mVertices[tr.ea].n.getNormalized(); + + if (tr.userData < 0) + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += mVertices[tr.eb].n.getNormalized(); + else + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] -= mVertices[tr.eb].n.getNormalized(); + + if (tr.userData < 0) + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += mVertices[tr.ec].n.getNormalized(); + else + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] -= mVertices[tr.ec].n.getNormalized(); + + } + for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) + { + + mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; + mVerticesNormalsSmoothed[i].normalize(); + } +} + + + +void MeshNoiser::applyNoise(SimplexNoise& noise, float falloff, int32_t /*relaxIterations*/, float /*relaxFactor*/) +{ + NVBLAST_ASSERT(isTesselated); + if (isTesselated == false) + { + return; + } + mRestrictionFlag.clear(); + mRestrictionFlag.resize(mVertices.size(), false); + + for (uint32_t i = 0; i < mEdges.size(); ++i) + { + if (mTrMeshEdToTr[i].c != 0) + { + if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE) + { + mRestrictionFlag[mEdges[i].e] = true; + mRestrictionFlag[mEdges[i].s] = true; + } + } + } + std::vector<Vertex> localVertices = mVertices; + + recalcNoiseDirs(); + + //relax(relaxIterations, relaxFactor, localVertices); + + + /** + Apply noise + */ + for (uint32_t i = 0; i < localVertices.size(); ++i) + { + + if (!mRestrictionFlag[i]) + { + + float d = noise.sample(localVertices[i].p); + localVertices[i].p += (falloffFunction(mVerticesDistances[i], falloff)) * mVerticesNormalsSmoothed[i] * d; + } + } + + + /* Recalculate smoothed normals*/ + mVerticesNormalsSmoothed.assign(mVerticesNormalsSmoothed.size(), PxVec3(0, 0, 0)); + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + { + continue; + } + TriangleIndexed& tr = mTriangles[i]; + if (tr.userData == 0) continue; + + Triangle pTr(localVertices[tr.ea], localVertices[tr.eb], localVertices[tr.ec]); + PxVec3 nrm = pTr.getNormal().getNormalized(); + + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += nrm; + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += nrm; + mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += nrm; + } + for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) + { + mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; + mVerticesNormalsSmoothed[i].normalize(); + } + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + { + continue; + } + TriangleIndexed& tr = mTriangles[i]; + if (tr.userData == 0) continue; + + localVertices[tr.ea].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]]; + localVertices[tr.eb].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]]; + localVertices[tr.ec].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]]; + } + + mResultTriangles.clear(); + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + { + continue; + } + mResultTriangles.push_back(Triangle(localVertices[mTriangles[i].ea], localVertices[mTriangles[i].eb], localVertices[mTriangles[i].ec])); + mResultTriangles.back().userData = mTriangles[i].userData; + mResultTriangles.back().materialId = mTriangles[i].materialId; + mResultTriangles.back().smoothingGroup = mTriangles[i].smoothingGroup; + + } +} + + +void MeshNoiser::prebuildTesselatedTriangles() +{ + mResultTriangles.clear(); + + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].p = mVertices[i].p * mScale + mOffset; + } + + for (uint32_t i = 0; i < mTriangles.size(); ++i) + { + if (mTriangles[i].ea == NOT_VALID_VERTEX) + { + continue; + } + mResultTriangles.push_back(Triangle(mVertices[mTriangles[i].ea], mVertices[mTriangles[i].eb], mVertices[mTriangles[i].ec])); + mResultTriangles.back().userData = mTriangles[i].userData; + mResultTriangles.back().materialId = mTriangles[i].materialId; + mResultTriangles.back().smoothingGroup = mTriangles[i].smoothingGroup; + + } + +} + + +std::vector<Triangle> MeshNoiser::getMesh() +{ + return mResultTriangles; +} + + +void MeshNoiser::reset() +{ + mVertices.clear(); + mTriangles.clear(); + mEdges.clear(); + mVertMap.clear(); + mEdgeMap.clear(); + mResultTriangles.clear(); + mRestrictionFlag.clear(); + mEdgeFlag.clear(); + mTrMeshEdToTr.clear(); + mVertexValence.clear(); + mVertexToTriangleMap.clear(); + + mVerticesDistances.clear(); + mVerticesNormalsSmoothed.clear(); + mPositionMappedVrt.clear(); + mGeometryGraph.clear(); + + isTesselated = false; + mOffset = PxVec3(0, 0, 0); + mScale = 1.0f; +}
\ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.h new file mode 100644 index 0000000..893cf63 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshNoiser.h @@ -0,0 +1,193 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTAUTHORINGMESHNOISER_H +#define NVBLASTEXTAUTHORINGMESHNOISER_H +#include <vector> +#include <map> +#include "NvBlastExtAuthoringInternalCommon.h" + +namespace Nv +{ + namespace Blast + { + class SimplexNoise; + + /** + Structure used on tesselation stage. Maps edge to two neighboor triangles + */ + struct EdgeToTriangles + { + int32_t tr[2]; + int32_t c; + EdgeToTriangles() + { + c = 0; + } + /** + Add triangle to edge. Should not be called more than twice for one edge!!!!. + */ + void add(int32_t t) + { + tr[c] = t; + ++c; + } + /** + Replaces mapping from one triangle to another. + */ + void replace(int32_t from, int32_t to) + { + if (tr[0] == from) + { + tr[0] = to; + } + else + { + if (c == 2 && tr[1] == from) + { + tr[1] = to; + } + } + } + /** + Get triangle which is mapped by this edge and which index is different than provided. + */ + int32_t getNot(int32_t id) + { + if (tr[0] != id) + { + return tr[0]; + } + if (c == 2 && tr[1] != id) + { + return tr[1]; + } + return -1; + } + + }; + + /** + Tool for graphic mesh tesselation and adding noise to internal surface. Each triangle must have initialized + Triangle::userInfo field (0 for external surface triangles and != 0 for internal) + */ + class MeshNoiser + { + public: + MeshNoiser() + { + reset(); + } + + void reset(); + + /** + Edge flags + */ + enum EdgeFlag { INTERNAL_EDGE, EXTERNAL_BORDER_EDGE, INTERNAL_BORDER_EDGE, EXTERNAL_EDGE, NONE }; + + + /** + Set mesh to tesselate and apply noise + */ + void setMesh(const std::vector<Triangle>& mesh); + + /** + Tesselate internal surface. + \param[in] maxLen - maximal length of edge on internal surface. + */ + void tesselateInternalSurface(float maxLen); + + /** + Apply noise to internal surface. Must be called only after tesselation!!! + \param[in] noise - noise generator + \param[in] falloff - damping of noise around of external surface + \param[in] relaxIterations - number of smoothing iterations before applying noise + \param[in] relaxFactor - amount of smooting before applying noise. + */ + void applyNoise(SimplexNoise& noise, float falloff, int32_t relaxIterations, float relaxFactor); + + std::vector<Triangle> getMesh(); + + private: + PxVec3 mOffset; + float mScale; + bool isTesselated; + /** + Mesh data + */ + std::vector<Vertex> mVertices; + std::vector<TriangleIndexed> mTriangles; + std::vector<Edge> mEdges; + std::map<Vertex, int32_t, VrtComp> mVertMap; + std::map<Edge, int32_t> mEdgeMap; + + + /** + Final triangles. + */ + std::vector<Triangle> mResultTriangles; + + + int32_t addVerticeIfNotExist(const Vertex& p); + int32_t addEdge(const Edge& e); + int32_t findEdge(const Edge& e); + + + + void collapseEdge(int32_t id); + void divideEdge(int32_t id); + void updateVertEdgeInfo(); + void updateEdgeTriangleInfo(); + void relax(int32_t iterations, float factor, std::vector<Vertex>& vertices); + void recalcNoiseDirs(); + + + std::vector<bool> mRestrictionFlag; + std::vector<EdgeFlag> mEdgeFlag; + std::vector<EdgeToTriangles> mTrMeshEdToTr; + std::vector<int32_t> mVertexValence; + std::vector<std::vector<int32_t> > mVertexToTriangleMap; + + + + std::vector<float> mVerticesDistances; + std::vector<physx::PxVec3> mVerticesNormalsSmoothed; + std::vector<int32_t> mPositionMappedVrt; + std::vector<std::vector<int32_t> > mGeometryGraph; + + void prebuildEdgeFlagArray(); + void computePositionedMapping(); + void computeFalloffAndNormals(); + + void prebuildTesselatedTriangles(); + }; + + } // namespace Blast +} // namespace Nv +#endif // ! NVBLASTEXTAUTHORINGMESHNOISER_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringPerlinNoise.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringPerlinNoise.h index 95308c2..2b17f0c 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringPerlinNoise.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringPerlinNoise.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #ifndef NVBLASTEXTAUTHORINGPERLINNOISE_H #define NVBLASTEXTAUTHORINGPERLINNOISE_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp index 0b7187f..cc2442c 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + // This warning arises when using some stl containers with older versions of VC // c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code @@ -24,13 +42,11 @@ #include <set> #include "NvBlastExtAuthoringBooleanTool.h" #include <queue> -#include "NvBlastExtAuthoringPerlinNoise.h" #include <NvBlastAssert.h> using physx::PxVec3; using physx::PxVec2; -#define VEC_COMPARISON_OFFSET 1e-5f #define TWO_VERTICES_THRESHOLD 1e-7 namespace Nv @@ -38,40 +54,6 @@ namespace Nv namespace Blast { -bool VrtComp::operator()(const Vertex& a, const Vertex& b) const -{ - if (a.p.x + VEC_COMPARISON_OFFSET < b.p.x) return true; - if (a.p.x - VEC_COMPARISON_OFFSET > b.p.x) return false; - if (a.p.y + VEC_COMPARISON_OFFSET < b.p.y) return true; - if (a.p.y - VEC_COMPARISON_OFFSET > b.p.y) return false; - if (a.p.z + VEC_COMPARISON_OFFSET < b.p.z) return true; - if (a.p.z - VEC_COMPARISON_OFFSET > b.p.z) return false; - - if (a.n.x + 1e-3 < b.n.x) return true; - if (a.n.x - 1e-3 > b.n.x) return false; - if (a.n.y + 1e-3 < b.n.y) return true; - if (a.n.y - 1e-3 > b.n.y) return false; - if (a.n.z + 1e-3 < b.n.z) return true; - if (a.n.z - 1e-3 > b.n.z) return false; - - - if (a.uv[0].x + 1e-3 < b.uv[0].x) return true; - if (a.uv[0].x - 1e-3 > b.uv[0].x) return false; - if (a.uv[0].y + 1e-3 < b.uv[0].y) return true; - return false; -} - -bool VrtPositionComparator::operator()(const PxVec3& a, const PxVec3& b) const -{ - if (a.x + VEC_COMPARISON_OFFSET < b.x) return true; - if (a.x - VEC_COMPARISON_OFFSET > b.x) return false; - if (a.y + VEC_COMPARISON_OFFSET < b.y) return true; - if (a.y - VEC_COMPARISON_OFFSET > b.y) return false; - if (a.z + VEC_COMPARISON_OFFSET < b.z) return true; - if (a.z - VEC_COMPARISON_OFFSET > b.z) return false; - return false; -} - NV_FORCE_INLINE bool compareTwoVertices(const PxVec3& a, const PxVec3& b) { return std::abs(b.x - a.x) < TWO_VERTICES_THRESHOLD && std::abs(b.y - a.y) < TWO_VERTICES_THRESHOLD && std::abs(b.z - a.z) < TWO_VERTICES_THRESHOLD; @@ -100,7 +82,7 @@ inline bool pointInside(PxVec2 a, PxVec2 b, PxVec2 c, PxVec2 pnt) (v1 <= 0.0f && v2 <= 0.0f && v3 <= 0.0f); } -void ChunkPostProcessor::triangulatePolygonWithEarClipping(std::vector<uint32_t>& inputPolygon, Vertex* vert, ProjectionDirections dir) +void Triangulator::triangulatePolygonWithEarClipping(std::vector<uint32_t>& inputPolygon, Vertex* vert, ProjectionDirections dir) { // return; //for (uint32_t i = 0; i < inputPolygon.size(); ++i) @@ -144,10 +126,6 @@ void ChunkPostProcessor::triangulatePolygonWithEarClipping(std::vector<uint32_t> } if (good) { - addEdgeTr(Edge(inputPolygon[curr], inputPolygon[prev])); - addEdgeTr(Edge(inputPolygon[next], inputPolygon[prev])); - addEdgeTr(Edge(inputPolygon[curr], inputPolygon[next])); - mBaseMeshTriangles.push_back(TriangleIndexed(inputPolygon[curr], inputPolygon[prev], inputPolygon[next])); vCount--; inputPolygon.erase(inputPolygon.begin() + curr); @@ -321,7 +299,7 @@ int32_t unitePolygons(std::vector<uint32_t>& externalLoop, std::vector<uint32_t> return 0; } -void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData) +void Triangulator::buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData, int32_t materialId, int32_t smoothingGroup) { std::vector<std::vector<uint32_t> > serializedLoops; @@ -439,7 +417,7 @@ void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Ve int32_t baseLoop = loopsInfo[extPoly].index; for (uint32_t intPoly = 0; intPoly < loopsInfo.size(); ++intPoly) { - if (loopsInfo[intPoly].area > 0 || loopsInfo[intPoly].used || abs(loopsInfo[intPoly].area) > loopsInfo[extPoly].area) + if (loopsInfo[intPoly].area > 0 || loopsInfo[intPoly].used || std::abs(loopsInfo[intPoly].area) > loopsInfo[extPoly].area) { continue; } @@ -454,11 +432,13 @@ void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Ve } for (uint32_t i = oldSize; i < mBaseMeshTriangles.size(); ++i) { - mBaseMeshTriangles[i].userInfo = userData; + mBaseMeshTriangles[i].userData = userData; + mBaseMeshTriangles[i].materialId = materialId; + mBaseMeshTriangles[i].smoothingGroup = smoothingGroup; } } -NV_FORCE_INLINE int32_t ChunkPostProcessor::addVerticeIfNotExist(Vertex& p) +NV_FORCE_INLINE int32_t Triangulator::addVerticeIfNotExist(const Vertex& p) { auto it = mVertMap.find(p); if (it == mVertMap.end()) @@ -473,7 +453,7 @@ NV_FORCE_INLINE int32_t ChunkPostProcessor::addVerticeIfNotExist(Vertex& p) } } -NV_FORCE_INLINE void ChunkPostProcessor::addEdgeIfValid(EdgeWithParent& ed) +NV_FORCE_INLINE void Triangulator::addEdgeIfValid(EdgeWithParent& ed) { if (ed.s == ed.e) return; @@ -497,14 +477,14 @@ NV_FORCE_INLINE void ChunkPostProcessor::addEdgeIfValid(EdgeWithParent& ed) -void ChunkPostProcessor::prepare(Mesh* mesh) +void Triangulator::prepare(const Mesh* mesh) { - Edge* ed = mesh->getEdges(); - Vertex* vr = mesh->getVertices(); + const Edge* ed = mesh->getEdges(); + const Vertex* vr = mesh->getVertices(); mBaseMapping.resize(mesh->getVerticesCount()); for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { - Facet* fc = mesh->getFacet(i); + const Facet* fc = mesh->getFacet(i); for (uint32_t j = fc->firstEdgeNumber; j < fc->firstEdgeNumber + fc->edgesCount; ++j) { int32_t a = addVerticeIfNotExist(vr[ed[j].s]); @@ -527,29 +507,17 @@ void ChunkPostProcessor::prepare(Mesh* mesh) } -void ChunkPostProcessor::reset() +void Triangulator::reset() { - isTesselated = false; mVertices.clear(); mBaseMeshEdges.clear(); mVertMap.clear(); mEdgeMap.clear(); - mTrMeshEdgeMap.clear(); - mTrMeshEdges.clear(); - mTrMeshEdToTr.clear(); mBaseMeshTriangles.clear(); - mEdgeFlag.clear(); - mVertexValence.clear(); - mRestrictionFlag.clear(); - mVerticesDistances.clear(); - mVerticesNormalsSmoothed.clear(); - mBaseMeshResultTriangles.clear(); - mTesselatedMeshResultTriangles.clear(); - mTesselatedMeshTriangles.clear(); } -void ChunkPostProcessor::triangulate(Mesh* mesh) +void Triangulator::triangulate(const Mesh* mesh) { reset(); if (mesh == nullptr || !mesh->isValid()) @@ -569,17 +537,16 @@ void ChunkPostProcessor::triangulate(Mesh* mesh) { if (temp.empty() == false) { - buildPolygonAndTriangulate(temp, &mVertices[0], mesh->getFacet(fP)->userData); + buildPolygonAndTriangulate(temp, mVertices.data(), mesh->getFacet(fP)->userData, mesh->getFacet(fP)->materialId, mesh->getFacet(fP)->smoothingGroup); } temp.clear(); fP = mBaseMeshEdges[i].parent; } temp.push_back(Edge(mBaseMeshEdges[i].s, mBaseMeshEdges[i].e)); } - buildPolygonAndTriangulate(temp, &mVertices[0], mesh->getFacet(fP)->userData); + buildPolygonAndTriangulate(temp, mVertices.data(), mesh->getFacet(fP)->userData, mesh->getFacet(fP)->materialId, mesh->getFacet(fP)->smoothingGroup); /* Build final triangles */ - mBaseMeshResultTriangles.clear(); for (uint32_t i = 0; i < mBaseMeshTriangles.size(); ++i) { @@ -588,683 +555,19 @@ void ChunkPostProcessor::triangulate(Mesh* mesh) continue; } mBaseMeshResultTriangles.push_back(Triangle(mVertices[mBaseMeshTriangles[i].ea], mVertices[mBaseMeshTriangles[i].eb], mVertices[mBaseMeshTriangles[i].ec])); - mBaseMeshResultTriangles.back().userInfo = mBaseMeshTriangles[i].userInfo; - } - - computePositionedMapping(); -} - -void ChunkPostProcessor::prebuildTesselatedTriangles() -{ - mTesselatedMeshResultTriangles.clear(); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - mTesselatedMeshResultTriangles.push_back(Triangle(mVertices[mTesselatedMeshTriangles[i].ea], mVertices[mTesselatedMeshTriangles[i].eb], mVertices[mTesselatedMeshTriangles[i].ec])); - mTesselatedMeshResultTriangles.back().userInfo = mTesselatedMeshTriangles[i].userInfo; - } - -} - - -int32_t ChunkPostProcessor::addEdgeTr(const Edge& e) -{ - Edge ed = e; - if (ed.e < ed.s) std::swap(ed.s, ed.e); - auto it = mTrMeshEdgeMap.find(ed); - if (it == mTrMeshEdgeMap.end()) - { - mTrMeshEdToTr.push_back(EdgeToTriangles()); - mTrMeshEdgeMap[ed] = (int)mTrMeshEdToTr.size() - 1; - mTrMeshEdges.push_back(ed); - mEdgeFlag.push_back(INTERNAL_EDGE); - return (int32_t)mTrMeshEdToTr.size() - 1; - } - else - { - return it->second; - } -} - -int32_t ChunkPostProcessor::findEdge(const Edge& e) -{ - Edge ed = e; - if (ed.e < ed.s) std::swap(ed.s, ed.e); - auto it = mTrMeshEdgeMap.find(ed); - if (it == mTrMeshEdgeMap.end()) - { - return -1; - } - return it->second; -} - -void ChunkPostProcessor::updateEdgeTriangleInfo() -{ - mTrMeshEdToTr.clear(); - mTrMeshEdToTr.resize(mTrMeshEdges.size()); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.ea == NOT_VALID_VERTEX) - continue; - int32_t ed = addEdgeTr(Edge(tr.ea, tr.eb)); - mTrMeshEdToTr[ed].add(i); - ed = addEdgeTr(Edge(tr.ea, tr.ec)); - mTrMeshEdToTr[ed].add(i); - ed = addEdgeTr(Edge(tr.ec, tr.eb)); - mTrMeshEdToTr[ed].add(i); - } -} - -void ChunkPostProcessor::updateVertEdgeInfo() -{ - mVertexToTriangleMap.clear(); - mVertexToTriangleMap.resize(mVertices.size()); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.ea == NOT_VALID_VERTEX) continue; - mVertexToTriangleMap[tr.ea].push_back(i); - mVertexToTriangleMap[tr.eb].push_back(i); - mVertexToTriangleMap[tr.ec].push_back(i); - } - mVertexValence.clear(); - mVertexValence.resize(mVertices.size(), 0); - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0) - { - mVertexValence[mTrMeshEdges[i].s]++; - mVertexValence[mTrMeshEdges[i].e]++; - } - } -} - - -void ChunkPostProcessor::collapseEdge(int32_t id) -{ - Edge cEdge = mTrMeshEdges[id]; - uint32_t from = cEdge.s; - uint32_t to = cEdge.e; - - - if (mRestrictionFlag[from] && mRestrictionFlag[to]) - { - return; - } - - if (mVertexValence[from] > mVertexValence[to]) - { - std::swap(from, to); - } - - if (mRestrictionFlag[from]) - { - std::swap(from, to); - } - - std::set<int32_t> connectedToBegin; - std::set<int32_t> connectedToEnd; - std::set<int32_t> neighboorTriangles; - - int32_t trWithEdge[2] = {-1, -1}; - int32_t cntr = 0; - for (uint32_t i = 0; i < mVertexToTriangleMap[from].size(); ++i) - { - if (mTesselatedMeshTriangles[mVertexToTriangleMap[from][i]].ea == NOT_VALID_VERTEX) - continue; - if (neighboorTriangles.insert(mVertexToTriangleMap[from][i]).second && mTesselatedMeshTriangles[mVertexToTriangleMap[from][i]].isContainEdge(from, to)) - { - trWithEdge[cntr] = mVertexToTriangleMap[from][i]; - cntr++; - } - } - for (uint32_t i = 0; i < mVertexToTriangleMap[to].size(); ++i) - { - if (mTesselatedMeshTriangles[mVertexToTriangleMap[to][i]].ea == NOT_VALID_VERTEX) - continue; - if (neighboorTriangles.insert(mVertexToTriangleMap[to][i]).second && mTesselatedMeshTriangles[mVertexToTriangleMap[to][i]].isContainEdge(from, to)) - { - trWithEdge[cntr] = mVertexToTriangleMap[to][i]; - cntr++; - } - } - - if (cntr == 0) - { - return; - } - if (cntr > 2) - { - return; - } - - for (uint32_t i: neighboorTriangles) - { - if (mTesselatedMeshTriangles[i].ea == from || mTesselatedMeshTriangles[i].eb == from || mTesselatedMeshTriangles[i].ec == from) - { - if (mTesselatedMeshTriangles[i].ea != to && mTesselatedMeshTriangles[i].ea != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].ea); - if (mTesselatedMeshTriangles[i].eb != to && mTesselatedMeshTriangles[i].eb != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].eb); - if (mTesselatedMeshTriangles[i].ec != to && mTesselatedMeshTriangles[i].ec != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].ec); - } - - if (mTesselatedMeshTriangles[i].ea == to || mTesselatedMeshTriangles[i].eb == to || mTesselatedMeshTriangles[i].ec == to) - { - if (mTesselatedMeshTriangles[i].ea != to && mTesselatedMeshTriangles[i].ea != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].ea); - if (mTesselatedMeshTriangles[i].eb != to && mTesselatedMeshTriangles[i].eb != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].eb); - if (mTesselatedMeshTriangles[i].ec != to && mTesselatedMeshTriangles[i].ec != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].ec); - } - } - bool canBeCollapsed = true; - for (auto it = connectedToBegin.begin(); it != connectedToBegin.end(); ++it) - { - uint32_t currV = *it; - if (connectedToEnd.find(currV) == connectedToEnd.end()) - continue; - bool found = false; - for (int32_t tr : neighboorTriangles) - { - if ((mTesselatedMeshTriangles[tr].ea == from || mTesselatedMeshTriangles[tr].eb == from || mTesselatedMeshTriangles[tr].ec == from) && - (mTesselatedMeshTriangles[tr].ea == to || mTesselatedMeshTriangles[tr].eb == to || mTesselatedMeshTriangles[tr].ec == to) && - (mTesselatedMeshTriangles[tr].ea == currV || mTesselatedMeshTriangles[tr].eb == currV || mTesselatedMeshTriangles[tr].ec == currV)) - { - found = true; - break; - } - } - if (!found) - { - canBeCollapsed = false; - break; - } - } - - if (canBeCollapsed) - { - for (int32_t i : neighboorTriangles) - { - if (trWithEdge[0] == i) continue; - if (cntr == 2 && trWithEdge[1] == i) continue; - TriangleIndexed tr = mTesselatedMeshTriangles[i]; - PxVec3 oldNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); - - if (tr.ea == from) - { - tr.ea = to; - } - else - if (tr.eb == from) - { - tr.eb = to; - } - else - if (tr.ec == from) - { - tr.ec = to; - } - PxVec3 newNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); - if (newNormal.magnitude() < 1e-8f) - { - canBeCollapsed = false; - break; - } - if (oldNormal.dot(newNormal) < 0) - { - canBeCollapsed = false; - break; - } - } - } - - if (canBeCollapsed) - { - mTesselatedMeshTriangles[trWithEdge[0]].ea = NOT_VALID_VERTEX; - if (cntr == 2)mTesselatedMeshTriangles[trWithEdge[1]].ea = NOT_VALID_VERTEX; - - for (int32_t i : neighboorTriangles) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - continue; - if (mTesselatedMeshTriangles[i].ea == from) - { - mTesselatedMeshTriangles[i].ea = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - else - if (mTesselatedMeshTriangles[i].eb == from) - { - mTesselatedMeshTriangles[i].eb = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - else - if (mTesselatedMeshTriangles[i].ec == from) - { - mTesselatedMeshTriangles[i].ec = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - } - } -} - - -void ChunkPostProcessor::divideEdge(int32_t id) -{ - - if (mTrMeshEdToTr[id].c == 0 ) - { - return; - } - - Edge cEdge = mTrMeshEdges[id]; - EdgeFlag snapRestriction = mEdgeFlag[id]; - Vertex middle; - uint32_t nv = NOT_VALID_VERTEX; - for (int32_t t = 0; t < mTrMeshEdToTr[id].c; ++t) - { - int32_t oldTriangleIndex = mTrMeshEdToTr[id].tr[t]; - TriangleIndexed tr = mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]]; - - if (tr.ea == NOT_VALID_VERTEX) - { - continue; - } - - uint32_t pbf[3]; - pbf[0] = tr.ea; - pbf[1] = tr.eb; - pbf[2] = tr.ec; - for (int32_t p = 0; p < 3; ++p) - { - int32_t pnx = (p + 1) % 3; - int32_t opp = (p + 2) % 3; - - if ((pbf[p] == cEdge.s && pbf[pnx] == cEdge.e) || (pbf[p] == cEdge.e && pbf[pnx] == cEdge.s)) - { - if (nv == NOT_VALID_VERTEX) - { - middle.p = (mVertices[pbf[p]].p + mVertices[pbf[pnx]].p) * 0.5f; - middle.n = (mVertices[pbf[p]].n + mVertices[pbf[pnx]].n) * 0.5f; - middle.uv[0] = (mVertices[pbf[p]].uv[0] + mVertices[pbf[pnx]].uv[0]) * 0.5f; - - nv = (uint32_t)mVertices.size(); - mVertices.push_back(middle); - } - if (nv < mRestrictionFlag.size()) - { - mRestrictionFlag[nv] = ((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); - } - else - { - mRestrictionFlag.push_back((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); - } - - uint32_t ind1 = addEdgeTr(Edge(pbf[p], nv)); - uint32_t ind2 = addEdgeTr(Edge(nv, pbf[pnx])); - uint32_t ind3 = addEdgeTr(Edge(nv, pbf[opp])); - - - mEdgeFlag[ind1] = snapRestriction; - mEdgeFlag[ind2] = snapRestriction; - mEdgeFlag[ind3] = INTERNAL_EDGE; - - mTrMeshEdToTr[ind1].add(mTrMeshEdToTr[id].tr[t]); - int32_t userInfo = mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]].userInfo; - mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]] = TriangleIndexed(pbf[p], nv, pbf[opp]); - mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]].userInfo = userInfo; - mTrMeshEdToTr[ind2].add((int32_t)mTesselatedMeshTriangles.size()); - mTrMeshEdToTr[ind3].add((int32_t)mTrMeshEdToTr[id].tr[t]); - mTrMeshEdToTr[ind3].add((int32_t)mTesselatedMeshTriangles.size()); - mTesselatedMeshTriangles.push_back(TriangleIndexed(nv,pbf[pnx], pbf[opp])); - mTesselatedMeshTriangles.back().userInfo = userInfo; - int32_t ed1 = findEdge(Edge(pbf[pnx], pbf[opp])); - mTrMeshEdToTr[ed1].replace(oldTriangleIndex, (int32_t)mTesselatedMeshTriangles.size() - 1); - break; - } - } - } -} - + mBaseMeshResultTriangles.back().userData = mBaseMeshTriangles[i].userData; + mBaseMeshResultTriangles.back().materialId = mBaseMeshTriangles[i].materialId; + mBaseMeshResultTriangles.back().smoothingGroup = mBaseMeshTriangles[i].smoothingGroup; -NV_FORCE_INLINE void markEdge(int32_t ui, int32_t ed, std::vector<ChunkPostProcessor::EdgeFlag>& shortMarkup, std::vector<int32_t>& lastOwner) -{ - if (shortMarkup[ed] == ChunkPostProcessor::NONE) - { - if (ui == 0) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_EDGE; - } - else - { - shortMarkup[ed] = ChunkPostProcessor::INTERNAL_EDGE; - } - lastOwner[ed] = ui; } - else - { - if (ui != 0) - { - if (shortMarkup[ed] == ChunkPostProcessor::EXTERNAL_EDGE) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_BORDER_EDGE; - } - if ((shortMarkup[ed] == ChunkPostProcessor::INTERNAL_EDGE) && ui != lastOwner[ed]) - { - shortMarkup[ed] = ChunkPostProcessor::INTERNAL_BORDER_EDGE; - } - } - else - { - if (shortMarkup[ed] != ChunkPostProcessor::EXTERNAL_EDGE) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_BORDER_EDGE; - } - } - } -} - -float falloffFunction(float x, float mx) -{ - float t = (x) / (mx + 1e-6f); - t = std::min(1.0f, t); - return t * t; -} - -void ChunkPostProcessor::recalcNoiseDirs() -{ - /** - Compute normals direction to apply noise - */ - mVerticesNormalsSmoothed.resize(mVertices.size(), PxVec3(0, 0, 0)); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += mVertices[tr.ea].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] -= mVertices[tr.ea].n.getNormalized(); - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += mVertices[tr.eb].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] -= mVertices[tr.eb].n.getNormalized(); - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += mVertices[tr.ec].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] -= mVertices[tr.ec].n.getNormalized(); - - } - for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) - { - - mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; - mVerticesNormalsSmoothed[i].normalize(); - } -} - - - -void ChunkPostProcessor::applyNoise(SimplexNoise& noise, float falloff, int32_t relaxIterations, float relaxFactor) -{ - NVBLAST_ASSERT(isTesselated); - if (isTesselated == false) - { - return; - } - mRestrictionFlag.clear(); - mRestrictionFlag.resize(mVertices.size(), false); - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE) - { - mRestrictionFlag[mTrMeshEdges[i].e] = true; - mRestrictionFlag[mTrMeshEdges[i].s] = true; - } - } - } - std::vector<Vertex> localVertices = mVertices; - - recalcNoiseDirs(); - - relax(relaxIterations, relaxFactor, localVertices); - - - /** - Apply noise - */ - for (uint32_t i = 0; i < localVertices.size(); ++i) - { - - if (!mRestrictionFlag[i]) - { - - float d = noise.sample(localVertices[i].p); - localVertices[i].p += (falloffFunction(mVerticesDistances[i], falloff)) * mVerticesNormalsSmoothed[i] * d; - } - } - - - /* Recalculate smoothed normals*/ - mVerticesNormalsSmoothed.assign(mVerticesNormalsSmoothed.size(), PxVec3(0, 0, 0)); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - Triangle pTr(localVertices[tr.ea], localVertices[tr.eb], localVertices[tr.ec]); - PxVec3 nrm = pTr.getNormal().getNormalized(); - - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += nrm; - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += nrm; - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += nrm; - } - for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) - { - mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; - mVerticesNormalsSmoothed[i].normalize(); - } - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - localVertices[tr.ea].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]]; - localVertices[tr.eb].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]]; - localVertices[tr.ec].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]]; - } - - mTesselatedMeshResultTriangles.clear(); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - mTesselatedMeshResultTriangles.push_back(Triangle(localVertices[mTesselatedMeshTriangles[i].ea], localVertices[mTesselatedMeshTriangles[i].eb], localVertices[mTesselatedMeshTriangles[i].ec])); - mTesselatedMeshResultTriangles.back().userInfo = mTesselatedMeshTriangles[i].userInfo; - } - - -} - - -void ChunkPostProcessor::computePositionedMapping() -{ - std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; - mPositionMappedVrt.clear(); - mPositionMappedVrt.resize(mVertices.size()); - - for (uint32_t i = 0; i < mVertices.size(); ++i) - { - auto it = mPosMap.find(mVertices[i].p); - - if (it == mPosMap.end()) - { - mPosMap[mVertices[i].p] = i; - mPositionMappedVrt[i] = i; - } - else - { - mPositionMappedVrt[i] = it->second; - } - } -} - -void ChunkPostProcessor::computeFalloffAndNormals() -{ - // Map newly created vertices according to positions - computePositionedMapping(); - - mGeometryGraph.resize(mVertices.size()); - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c == 0) - { - continue; - } - int32_t v1 = mPositionMappedVrt[mTrMeshEdges[i].s]; - int32_t v2 = mPositionMappedVrt[mTrMeshEdges[i].e]; - - if (std::find(mGeometryGraph[v1].begin(), mGeometryGraph[v1].end(), v2) == mGeometryGraph[v1].end()) - mGeometryGraph[v1].push_back(v2); - if (std::find(mGeometryGraph[v2].begin(), mGeometryGraph[v2].end(), v1) == mGeometryGraph[v2].end()) - mGeometryGraph[v2].push_back(v1); - } - mVerticesDistances.clear(); - mVerticesDistances.resize(mVertices.size(), 10000.0f); - - std::queue<int32_t> que; - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0 && (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE)) - { - int32_t v1 = mPositionMappedVrt[mTrMeshEdges[i].s]; - int32_t v2 = mPositionMappedVrt[mTrMeshEdges[i].e]; - mVerticesDistances[v1] = 0.0f; - mVerticesDistances[v2] = 0.0f; - que.push(v1); - que.push(v2); - } - } - while (!que.empty()) - { - int32_t curr = que.front(); - que.pop(); - - for (uint32_t i = 0; i < mGeometryGraph[curr].size(); ++i) - { - int32_t to = mGeometryGraph[curr][i]; - float d = mVerticesDistances[curr] + 0.1f;// (mVertices[to].p - mVertices[curr].p).magnitudeSquared(); - if (d < mVerticesDistances[to]) - { - mVerticesDistances[to] = d; - que.push(to); - } - } - } - - for (uint32_t i = 0; i < mVerticesDistances.size(); ++i) - { - int32_t from = mPositionMappedVrt[i]; - mVerticesDistances[i] = mVerticesDistances[from]; - } -} - -bool edgeOverlapTest(PxVec3& as, PxVec3& ae, PxVec3& bs, PxVec3& be) -{ - //return false; - if (std::max(std::min(as.x, ae.x), std::min(bs.x, be.x)) > std::min(std::max(as.x, ae.x), std::max(bs.x, be.x))) return false; - if (std::max(std::min(as.y, ae.y), std::min(bs.y, be.y)) > std::min(std::max(as.y, ae.y), std::max(bs.y, be.y))) return false; - if (std::max(std::min(as.z, ae.z), std::min(bs.z, be.z)) > std::min(std::max(as.z, ae.z), std::max(bs.z, be.z))) return false; - - return ((bs - as).cross(ae - as)).magnitudeSquared() < 1e-12f && ((be - as).cross(ae - as)).magnitudeSquared() < 1e-12f; } -void ChunkPostProcessor::relax(int32_t iteration, float factor, std::vector<Vertex>& vertices) +void Triangulator::computePositionedMapping() { - std::vector<PxVec3> verticesTemp(vertices.size()); - std::vector<PxVec3> normalsTemp(vertices.size()); - for (int32_t iter = 0; iter < iteration; ++iter) - { - for (uint32_t i = 0; i < vertices.size(); ++i) - { - if (mRestrictionFlag[i]) - { - continue; - } - PxVec3 cps = vertices[i].p; - PxVec3 cns = mVerticesNormalsSmoothed[i]; - PxVec3 averaged(0, 0, 0); - PxVec3 averagedNormal(0, 0, 0); - - for (uint32_t p = 0; p < mGeometryGraph[mPositionMappedVrt[i]].size(); ++p) - { - int32_t to = mGeometryGraph[mPositionMappedVrt[i]][p]; - averaged += vertices[to].p; - averagedNormal += mVerticesNormalsSmoothed[to]; - - } - averaged *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); - averagedNormal *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); - verticesTemp[i] = cps + (averaged - cps) * factor; - normalsTemp[i] = cns * (1.0f - factor) + averagedNormal * factor; - } - for (uint32_t i = 0; i < vertices.size(); ++i) - { - if (mRestrictionFlag[i]) - { - continue; - } - vertices[i].p = verticesTemp[i]; - mVerticesNormalsSmoothed[i] = normalsTemp[i].getNormalized(); - - } - } - -} - -void ChunkPostProcessor::prebuildEdgeFlagArray() -{ - mRestrictionFlag.clear(); - mRestrictionFlag.resize(mVertices.size()); - mEdgeFlag.clear(); - mEdgeFlag.resize(mTrMeshEdges.size(), NONE); - std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; mPositionMappedVrt.clear(); - mPositionMappedVrt.resize(mVertices.size(), 0); + mPositionMappedVrt.resize(mVertices.size()); for (uint32_t i = 0; i < mVertices.size(); ++i) { @@ -1280,159 +583,6 @@ void ChunkPostProcessor::prebuildEdgeFlagArray() mPositionMappedVrt[i] = it->second; } } - - std::map<Edge, int32_t> mPositionEdgeMap; - std::vector<int32_t> mPositionBasedEdges(mTrMeshEdges.size()); - - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - Edge tmp = Edge(mPositionMappedVrt[mTrMeshEdges[i].s], mPositionMappedVrt[mTrMeshEdges[i].e]); - if (tmp.e < tmp.s) std::swap(tmp.e, tmp.s); - auto it = mPositionEdgeMap.find(tmp); - if (it == mPositionEdgeMap.end()) - { - mPositionEdgeMap[tmp] = i; - mPositionBasedEdges[i] = i; - } - else - { - mPositionBasedEdges[i] = it->second; - } - } - - std::vector<EdgeFlag> shortMarkup(mTrMeshEdges.size(), NONE); - std::vector<int32_t> lastOwner(mTrMeshEdges.size(), 0); - - std::vector<std::vector<int32_t> > edgeOverlap(mTrMeshEdges.size()); - for (auto it1 = mPositionEdgeMap.begin(); it1 != mPositionEdgeMap.end(); ++it1) - { - auto it2 = it1; - it2++; - for (; it2 != mPositionEdgeMap.end(); ++it2) - { - Edge& ed1 = mTrMeshEdges[it1->second]; - Edge& ed2 = mTrMeshEdges[it2->second]; - - if (edgeOverlapTest(mVertices[ed1.s].p, mVertices[ed1.e].p, mVertices[ed2.s].p, mVertices[ed2.e].p)) - { - edgeOverlap[it1->second].push_back(it2->second); - } - } - } - - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - int32_t ui = mTesselatedMeshTriangles[i].userInfo; - int32_t ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].eb))]; - - - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].ec))]; - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].eb, mTesselatedMeshTriangles[i].ec))]; - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - } - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - mEdgeFlag[i] = shortMarkup[mPositionBasedEdges[i]]; - } - - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].userInfo != 0) continue; - - int32_t ed = findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].eb)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - ed = findEdge(Edge(mTesselatedMeshTriangles[i].ec, mTesselatedMeshTriangles[i].eb)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - ed = findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].ec)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - } -} - - - -void ChunkPostProcessor::tesselateInternalSurface(float maxLenIn) -{ - mTesselatedMeshTriangles = mBaseMeshTriangles; - if (mTesselatedMeshTriangles.empty()) - { - return; - } - - updateEdgeTriangleInfo(); - prebuildEdgeFlagArray(); - mRestrictionFlag.resize(mVertices.size(), 0); - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) - { - mRestrictionFlag[mTrMeshEdges[i].s] = 1; - mRestrictionFlag[mTrMeshEdges[i].e] = 1; - } - } - - - float maxLen = std::max(0.1f, maxLenIn); - while (maxLen > maxLenIn) - { - float mlSq = maxLen * maxLen; - float minD = maxLen * 0.5f; - minD = minD * minD; - - for (int32_t iter = 0; iter < 15; ++iter) - { - updateVertEdgeInfo(); - uint32_t oldSize = (uint32_t)mTrMeshEdges.size(); - for (uint32_t i = 0; i < oldSize; ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) - { - continue; - } - if ((mVertices[mTrMeshEdges[i].s].p - mVertices[mTrMeshEdges[i].e].p).magnitudeSquared() < minD) - { - collapseEdge(i); - } - } - - oldSize = (uint32_t)mTrMeshEdges.size(); - updateEdgeTriangleInfo(); - for (uint32_t i = 0; i < oldSize; ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE) - { - continue; - } - if ((mVertices[mTrMeshEdges[i].s].p - mVertices[mTrMeshEdges[i].e].p).magnitudeSquared() > mlSq) - { - divideEdge(i); - } - } - } - maxLen *= 0.3; - maxLen = std::max(maxLen, maxLenIn); - } - computeFalloffAndNormals(); - prebuildTesselatedTriangles(); - isTesselated = true; } } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.h index 83942f4..c5cb5b1 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAUTHORINGTRIANGULATOR_H #define NVBLASTEXTAUTHORINGTRIANGULATOR_H @@ -22,95 +40,19 @@ namespace Nv { namespace Blast { -class SimplexNoise; - -/** - Vertex comparator for vertex welding. -*/ -struct VrtComp -{ - bool operator()(const Vertex& a, const Vertex& b) const; -}; - -/** - Vertex comparator for vertex welding (not accounts normal and uv parameters of vertice). -*/ -struct VrtPositionComparator -{ - bool operator()(const physx::PxVec3& a, const physx::PxVec3& b) const; -}; - -/** - Structure used on tesselation stage. Maps edge to two neighboor triangles -*/ -struct EdgeToTriangles -{ - int32_t tr[2]; - int32_t c; - EdgeToTriangles() - { - c = 0; - } - /** - Add triangle to edge. Should not be called more than twice for one edge!!!!. - */ - void add(int32_t t) - { - tr[c] = t; - ++c; - } - /** - Replaces mapping from one triangle to another. - */ - void replace(int32_t from, int32_t to) - { - if (tr[0] == from) - { - tr[0] = to; - } - else - { - if (c == 2 && tr[1] == from) - { - tr[1] = to; - } - } - } - /** - Get triangle which is mapped by this edge and which index is different than provided. - */ - int32_t getNot(int32_t id) - { - if (tr[0] != id) - { - return tr[0]; - } - if (c == 2 && tr[1] != id) - { - return tr[1]; - } - return -1; - } - -}; /** Tool for doing all post processing steps of authoring. */ -class ChunkPostProcessor +class Triangulator { public: /** - Edge flags - */ - enum EdgeFlag{ INTERNAL_EDGE, EXTERNAL_BORDER_EDGE, INTERNAL_BORDER_EDGE, EXTERNAL_EDGE, NONE }; - - /** Triangulates provided mesh and saves result internally. Uses Ear-clipping algorithm. \param[in] mesh Mesh for triangulation */ - void triangulate(Mesh* mesh); + void triangulate(const Mesh* mesh); /** \return Return array of triangles of base mesh. @@ -127,8 +69,6 @@ public: { return mBaseMeshTriangles; } - - /** \return Return mapping from vertices of input Mesh to internal vertices buffer. Used for island detection. */ @@ -143,7 +83,6 @@ public: { return mPositionMappedVrt; }; - /** \return Return internal vertex buffer size. Vertices internally are welded with some threshold. */ @@ -151,44 +90,15 @@ public: { return static_cast<uint32_t>(mVertices.size()); } - /** - Tesselate internal surface. - \param[in] maxLen - maximal length of edge on internal surface. - */ - void tesselateInternalSurface(float maxLen); - - /** - Apply noise to internal surface. Must be called only after tesselation!!! - \param[in] noise - noise generator - \param[in] falloff - damping of noise around of external surface - \param[in] relaxIterations - number of smoothing iterations before applying noise - \param[in] relaxFactor - amount of smooting before applying noise. - */ - void applyNoise(SimplexNoise& noise, float falloff, int32_t relaxIterations, float relaxFactor); - - /** - \return Return array of noised mesh triangles. - */ - std::vector<Triangle>& getNoisyMesh() - { - return mTesselatedMeshResultTriangles; - }; /** - Removes all information about mesh triangulation, tesselation, etc. + Removes all information about mesh triangulation. */ void reset(); private: - - - void collapseEdge(int32_t id); - void divideEdge(int32_t id); - void updateVertEdgeInfo(); - void updateEdgeTriangleInfo(); - - int32_t addVerticeIfNotExist(Vertex& p); + int32_t addVerticeIfNotExist(const Vertex& p); void addEdgeIfValid(EdgeWithParent& ed); /* Data used before triangulation to build polygon loops*/ @@ -198,60 +108,26 @@ private: std::map<Vertex, int32_t, VrtComp> mVertMap; std::map<EdgeWithParent, int32_t, EdgeComparator> mEdgeMap; std::vector<uint32_t> mBaseMapping; - + std::vector<int32_t> mPositionMappedVrt; + /* ------------------------------------------------------------ */ /** Unite all almost similar vertices, update edges according to this changes */ - void prepare(Mesh* mesh); - - /* ------------------------------------------------------------ */ - - /* Triangulation and tesselation stage data */ - bool isTesselated; - - std::map<Edge, int32_t> mTrMeshEdgeMap; - std::vector<Edge> mTrMeshEdges; - std::vector<EdgeToTriangles> mTrMeshEdToTr; - std::vector<int32_t> mVertexValence; - std::vector<std::vector<int32_t> > mVertexToTriangleMap; - - std::vector<bool> mRestrictionFlag; - std::vector<EdgeFlag> mEdgeFlag; - - std::vector<float> mVerticesDistances; - std::vector<physx::PxVec3> mVerticesNormalsSmoothed; - std::vector<int32_t> mPositionMappedVrt; - std::vector<std::vector<int32_t> > mGeometryGraph; - - - int32_t addEdgeTr(const Edge& ed); - int32_t findEdge(const Edge& e); - - void prebuildEdgeFlagArray(); - void computePositionedMapping(); - - void computeFalloffAndNormals(); - + void prepare(const Mesh* mesh); + void triangulatePolygonWithEarClipping(std::vector<uint32_t>& inputPolygon, Vertex* vert, ProjectionDirections dir); - void buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData); + void buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData, int32_t materialId, int32_t smoothingGroup); + void computePositionedMapping(); - void relax(int32_t iterations, float factor, std::vector<Vertex>& vertices); - void recalcNoiseDirs(); - - std::vector<TriangleIndexed> mBaseMeshTriangles; - std::vector<TriangleIndexed> mTesselatedMeshTriangles; - + std::vector<TriangleIndexed> mBaseMeshTriangles; /** Final triangles */ - void prebuildTesselatedTriangles(); - std::vector<Triangle> mBaseMeshResultTriangles; - std::vector<Triangle> mTesselatedMeshResultTriangles; }; } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringVSA.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringVSA.h index fd0c9c9..62d73c1 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringVSA.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringVSA.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAUTHORINGVSA_H #define NVBLASTEXTAUTHORINGVSA_H diff --git a/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.cpp b/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.cpp index 3c3e540..0ec4c20 100644 --- a/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtTriangleProcessor.h" #include "NvBlastExtAuthoringInternalCommon.h" diff --git a/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.h b/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.h index db9f682..0b32218 100644 --- a/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.h +++ b/sdk/extensions/authoring/source/NvBlastExtTriangleProcessor.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTTRIANGLEPROCESSOR_H #define NVBLASTEXTTRIANGLEPROCESSOR_H diff --git a/sdk/extensions/common/source/NvBlastExtAllocator.h b/sdk/extensions/common/source/NvBlastExtAllocator.h deleted file mode 100644 index d917cbf..0000000 --- a/sdk/extensions/common/source/NvBlastExtAllocator.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTALLOCATOR_H -#define NVBLASTEXTALLOCATOR_H - -#include "NvBlastTkFramework.h" -#include "PxAllocatorCallback.h" - - -namespace Nv -{ -namespace Blast -{ - -/** -ExtAllocator uses TkFramework allocator -*/ -class ExtAllocator -{ -public: - ExtAllocator(const char* = 0) - { - } - - void* allocate(size_t size, const char* filename, int line) - { - return NvBlastTkFrameworkGet()->getAllocatorCallback().allocate(size, nullptr, filename, line); - } - - void deallocate(void* ptr) - { - NvBlastTkFrameworkGet()->getAllocatorCallback().deallocate(ptr); - } - - - /** - Aligned allocation. - - Example using 16-byte alignment: - - // b will lie on a 16-byte boundary and point to 50 bytes of usable memory - void* b = alignedAlloc<16>(50); - */ - template<int A> - static void* alignedAlloc(size_t size, const char* filename, int line) - { - NV_COMPILE_TIME_ASSERT(A > 0 && A <= 256); - unsigned char* mem = (unsigned char*)ExtAllocator().allocate(size + A, filename, line); - const unsigned char offset = (unsigned char)((uintptr_t)A - (uintptr_t)mem % A - 1); - mem += offset; - *mem++ = offset; - return mem; - } - - template<int A> - static void* alignedAlloc(size_t size) - { - return alignedAlloc<A>(size, __FILE__, __LINE__); - } - - - /** - Version of alignedAlloc specialized 16-byte aligned allocation. - */ - static void* alignedAlloc16(size_t size) - { - return alignedAlloc<16>(size); - } - - - /** - Aligned deallocation. - - Memory freed using this function MUST have been allocated using alignedAlloc. - - Example using free: - - // Using the memory pointer b from the example above (for alignedAlloc) - alignedFree(b); - */ - static void alignedFree(void* block) - { - if (block != nullptr) - { - unsigned char* mem = (unsigned char*)block; - const unsigned char offset = *--mem; - ExtAllocator().deallocate(mem - offset); - } - }; -}; - - -/** -ExtAlignedAllocator uses ExtAllocator -*/ -template<int A> -class ExtAlignedAllocator -{ -public: - ExtAlignedAllocator(const char* = 0) - { - } - - void* allocate(size_t size, const char* filename, int line) - { - return ExtAllocator::alignedAlloc<A>(size, filename, line); - } - - void deallocate(void* ptr) - { - return ExtAllocator::alignedFree(ptr); - } -}; - -} // namespace Blast -} // namespace Nv - - -#endif // #ifndef NVBLASTEXTALLOCATOR_H diff --git a/sdk/extensions/common/source/NvBlastExtArray.h b/sdk/extensions/common/source/NvBlastExtArray.h deleted file mode 100644 index 9ea4777..0000000 --- a/sdk/extensions/common/source/NvBlastExtArray.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTARRAY_H -#define NVBLASTEXTARRAY_H - - -#include "NvBlastExtAllocator.h" -#include "PsInlineArray.h" - - -namespace Nv -{ -namespace Blast -{ - -template <class T> -struct ExtArray -{ - typedef physx::shdfnd::Array<T, ExtAllocator> type; -}; - - -template <class T, uint32_t N> -struct ExtInlineArray -{ - typedef physx::shdfnd::InlineArray<T, N, ExtAllocator> type; -}; - -} // namespace Blast -} // namespace Nv - - -#endif // #ifndef NVBLASTEXTARRAY_H diff --git a/sdk/extensions/common/source/NvBlastExtDefs.h b/sdk/extensions/common/source/NvBlastExtDefs.h deleted file mode 100644 index 72b6c1d..0000000 --- a/sdk/extensions/common/source/NvBlastExtDefs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTDEFS_H -#define NVBLASTEXTDEFS_H - -#include "NvBlastTkFramework.h" -#include "PxAllocatorCallback.h" -#include <new> - - -//////// Log macros that use the ExtContext log function //////// - -#define NVBLASTEXT_LOG_ERROR(_msg) NVBLAST_LOG_ERROR(NvBlastTkFrameworkGet()->getLogFn(), _msg) -#define NVBLASTEXT_LOG_WARNING(_msg) NVBLAST_LOG_WARNING(NvBlastTkFrameworkGet()->getLogFn(), _msg) -#define NVBLASTEXT_LOG_INFO(_msg) NVBLAST_LOG_INFO(NvBlastTkFrameworkGet()->getLogFn(), _msg) -#define NVBLASTEXT_LOG_DEBUG(_msg) NVBLAST_LOG_DEBUG(NvBlastTkFrameworkGet()->getLogFn(), _msg) - -#define NVBLASTEXT_CHECK(_expr, _messageType, _msg, _onFail) \ - { \ - if(!(_expr)) \ - { \ - (*NvBlastTkFrameworkGet()->getLogFn())(_messageType, _msg, __FILE__, __LINE__); \ - { _onFail; }; \ - } \ - } - -#define NVBLASTEXT_CHECK_ERROR(_expr, _msg, _onFail) NVBLASTEXT_CHECK(_expr, NvBlastMessage::Error, _msg, _onFail) -#define NVBLASTEXT_CHECK_WARNING(_expr, _msg, _onFail) NVBLASTEXT_CHECK(_expr, NvBlastMessage::Warning, _msg, _onFail) -#define NVBLASTEXT_CHECK_INFO(_expr, _msg, _onFail) NVBLASTEXT_CHECK(_expr, NvBlastMessage::Info, _msg, _onFail) -#define NVBLASTEXT_CHECK_DEBUG(_expr, _msg, _onFail) NVBLASTEXT_CHECK(_expr, NvBlastMessage::Debug, _msg, _onFail) - - -//////// Allocator macros //////// - -/** -Placement new with ExtContext allocation. -Example: Foo* foo = NVBLASTEXT_NEW(Foo, context) (params); -*/ -#define NVBLASTEXT_NEW(T) new (NvBlastTkFrameworkGet()->getAllocatorCallback().allocate(sizeof(T), #T, __FILE__, __LINE__)) T - -/** -Respective delete to NVBLASTEXT_NEW -Example: NVBLASTEXT_DELETE(foo, Foo, context); -*/ -#define NVBLASTEXT_DELETE(obj, T) \ - (obj)->~T(); \ - NvBlastTkFrameworkGet()->getAllocatorCallback().deallocate(obj) - - -//////// Util macros //////// - -// Macro to load a uint32_t (or larger) with four characters -#define NVBLASTEXT_FOURCC(_a, _b, _c, _d) ( (uint32_t)(_a) | (uint32_t)(_b)<<8 | (uint32_t)(_c)<<16 | (uint32_t)(_d)<<24 ) - - -#endif // #ifndef NVBLASTEXTDEFS_H diff --git a/sdk/extensions/common/source/NvBlastExtHashMap.h b/sdk/extensions/common/source/NvBlastExtHashMap.h deleted file mode 100644 index 0fa094e..0000000 --- a/sdk/extensions/common/source/NvBlastExtHashMap.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTHASHMAP_H -#define NVBLASTEXTHASHMAP_H - - -#include "NvBlastExtAllocator.h" -#include "PsHashMap.h" - - -namespace Nv -{ -namespace Blast -{ - -template <class Key, class Value, class HashFn = physx::shdfnd::Hash<Key>> -struct ExtHashMap -{ - typedef physx::shdfnd::HashMap<Key, Value, HashFn, ExtAllocator> type; -}; - -} // namespace Blast -} // namespace Nv - - -#endif // #ifndef NVBLASTEXTHASHMAP_H diff --git a/sdk/extensions/common/source/NvBlastExtHashSet.h b/sdk/extensions/common/source/NvBlastExtHashSet.h deleted file mode 100644 index 97fc0a9..0000000 --- a/sdk/extensions/common/source/NvBlastExtHashSet.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTHASHSET_H -#define NVBLASTEXTHASHSET_H - - -#include "NvBlastExtAllocator.h" -#include "PsHashSet.h" - -namespace Nv -{ -namespace Blast -{ - -template <class Key, class HashFn = physx::shdfnd::Hash<Key>> -struct ExtHashSet -{ - typedef physx::shdfnd::HashSet<Key, HashFn, ExtAllocator> type; -}; - -} // namespace Blast -} // namespace Nv - - -#endif // #ifndef NVBLASTEXTHASHSET_H diff --git a/sdk/extensions/converter/include/NvBlastExtDataConverter.h b/sdk/extensions/converter/include/NvBlastExtDataConverter.h deleted file mode 100644 index b251518..0000000 --- a/sdk/extensions/converter/include/NvBlastExtDataConverter.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTDATACONVERTER_H -#define NVBLASTEXTDATACONVERTER_H - - -#include "NvBlast.h" -#include <vector> - -namespace Nv -{ -namespace Blast -{ - /** - Generic version conversion function for Blast data blocks. - - Automatically determines block type (one of NvBlastDataBlock::Type) and uses appropriate converter. - - \param[out] outBlock User-supplied memory block to fill with new data. - \param[in] inBlock Data block to convert. - \param[in] outBlockVersion Version to convert too, pass 'nullptr' to convert to the latest version. - - \return true iff conversion was successful. - */ - NVBLAST_API bool convertDataBlock(std::vector<char>& outBlock, const std::vector<char>& inBlock, uint32_t* outBlockVersion = nullptr); - - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTEXTDATACONVERTER_H diff --git a/sdk/extensions/converter/source/conversion/NvBlastExtAssetBlockVersionConverter_v0_v1.h b/sdk/extensions/converter/source/conversion/NvBlastExtAssetBlockVersionConverter_v0_v1.h deleted file mode 100644 index 44a0b54..0000000 --- a/sdk/extensions/converter/source/conversion/NvBlastExtAssetBlockVersionConverter_v0_v1.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTASSETBLOCKVERSIONCONVERTER_V0_V1_H -#define NVBLASTEXTASSETBLOCKVERSIONCONVERTER_V0_V1_H - - -#include "NvBlastExtBinaryBlockConverter.h" - - -namespace Nv -{ -namespace Blast -{ - -/* - WARNING: THIS CLASS IS AN EXAMPLE. - REPLACE WITH ACTUAL CONVERSION CODE ONCE NEEDED. -*/ -class NvBlastAssetBlockVersionConverter_v0_v1 : public BinaryBlockConverter::VersionConverter -{ -public: - virtual uint32_t getVersionFrom() const { return NvBlastAssetDataFormat::Initial; } - - virtual uint32_t getVersionTo() const { return 1/*NvBlastAssetDataFormat::BondCountSwap*/; } - - // remains the same - struct SupportGraph - { - uint32_t m_nodeCount; - uint32_t m_chunkIndicesOffset; - uint32_t m_adjacencyPartitionOffset; - uint32_t m_adjacentNodeIndicesOffset; - uint32_t m_adjacentBondIndicesOffset; - }; - - // prev version - struct AssetDataHeaderPrev - { - uint32_t m_formatVersion; - uint32_t m_size; - NvBlastID m_ID; - uint32_t m_totalChunkCount; - SupportGraph m_graph; - uint32_t m_leafChunkCount; - uint32_t m_firstSubsupportChunkIndex; // 0 - uint32_t m_bondCount; // 1 - }; - - // new version - struct AssetDataHeaderNew - { - uint32_t m_formatVersion; - uint32_t m_size; - NvBlastID m_ID; - uint32_t m_totalChunkCount; - SupportGraph m_graph; - uint32_t m_leafChunkCount; - uint32_t m_bondCount; // 1 - uint32_t m_firstSubsupportChunkIndex; // 0 - }; - - bool convert(const std::vector<char>& from, std::vector<char>& to) const - { - to = from; - - const AssetDataHeaderPrev* headerPrev = reinterpret_cast<const AssetDataHeaderPrev*>(from.data()); - AssetDataHeaderNew* headerNew = reinterpret_cast<AssetDataHeaderNew*>(to.data()); - headerNew->m_bondCount = headerPrev->m_bondCount; - headerNew->m_firstSubsupportChunkIndex = headerPrev->m_firstSubsupportChunkIndex; - headerNew->m_formatVersion = (uint32_t)getVersionTo(); - - return true; - } -}; - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTEXTASSETBLOCKVERSIONCONVERTER_V0_V1_H diff --git a/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.cpp b/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.cpp deleted file mode 100644 index a606b70..0000000 --- a/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtBinaryBlockConverter.h" -#include <iostream> -#include <algorithm> -#include <queue> -#include <limits> - - -namespace Nv -{ -namespace Blast -{ - -bool BinaryBlockConverter::convertBinaryBlock(std::vector<char>& outBlock, const std::vector<VersionConverterPtr>& converters, const std::vector<char>& inBlock, uint32_t outBlockVersion, uint32_t inBlockVersion) -{ - if (inBlock.empty()) - { - std::cerr << "Conversion failed: empty input block." << std::endl; - return false; - } - - // starting version - uint32_t version; - version = inBlockVersion; - std::cout << "Input block version: " << version << std::endl; - - // target version - const uint32_t targetVersion = outBlockVersion; - std::cout << "Target version: " << targetVersion << std::endl; - - // search conversion path - std::vector<VersionConverterPtr> conversionPath; - if (!findShortestPath(conversionPath, converters, version, targetVersion)) - { - std::cerr << "Conversion failed: can't find conversion path." << std::endl; - return false; - } - - // starting convertion loop - std::vector<char> blockFrom(inBlock.begin(), inBlock.end()); - std::vector<char> blockTo(inBlock.size()); - for (const VersionConverterPtr converter : conversionPath) - { - // actual conversion call - std::cout << "Converting from version: " << converter->getVersionFrom() << " -> " << converter->getVersionTo() << " Result: "; - if (!converter->convert(blockFrom, blockTo)) - { - std::cout << "Fail." << std::endl; - std::cerr << "Conversion failed: inside converter for version: " << version << std::endl; - return false; - } - else - { - std::cout << "Success." << std::endl; - blockFrom.swap(blockTo); - version = converter->getVersionTo(); - } - } - - // copy result - outBlock = blockFrom; - - return true; -} - - -/** -Finds shortest path form versionFrom to verstionTo using breadth-first search with DP -*/ -bool BinaryBlockConverter::findShortestPath(std::vector<VersionConverterPtr>& conversionPath, const std::vector<VersionConverterPtr>& converters, uint32_t versionFrom, uint32_t versionTo) -{ - // find max version - uint32_t versionMax = 0; - for (VersionConverterPtr c : converters) - { - versionMax = std::max(versionMax, c->getVersionFrom()); - versionMax = std::max(versionMax, c->getVersionTo()); - } - - // dynamic programming data - struct Node - { - uint32_t distance; - VersionConverterPtr converter; - - Node() : distance(std::numeric_limits<uint32_t>::max()), converter(nullptr) {} - }; - std::vector<Node> nodes(versionMax + 1); - - // initial state (start from versionTo) - std::queue<uint32_t> q; - q.emplace(versionTo); - nodes[versionTo].distance = 0; - nodes[versionTo].converter = nullptr; - - // breadth-first search - bool found = false; - while (!q.empty() && !found) - { - uint32_t v0 = q.front(); - q.pop(); - - for (const VersionConverterPtr c : converters) - { - if (c->getVersionTo() == v0) - { - uint32_t v1 = c->getVersionFrom(); - if (nodes[v1].distance > nodes[v0].distance + 1) - { - nodes[v1].distance = nodes[v0].distance + 1; - nodes[v1].converter = c; - q.emplace(v1); - } - - if (c->getVersionFrom() == versionFrom) - { - found = true; - break; - } - } - } - } - - if (found) - { - // unfold found path to result conversionPath - uint32_t v = versionFrom; - conversionPath.clear(); - while (nodes[v].converter.get() != nullptr) - { - conversionPath.push_back(nodes[v].converter); - v = nodes[v].converter->getVersionTo(); - } - return true; - } - else - { - return false; - } -} - -} // namespace Blast -} // namespace Nv diff --git a/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.h b/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.h deleted file mode 100644 index 83eb6b3..0000000 --- a/sdk/extensions/converter/source/conversion/NvBlastExtBinaryBlockConverter.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTBINARYBLOCKCONVERTER_H -#define NVBLASTEXTBINARYBLOCKCONVERTER_H - - -#include "NvBlast.h" -#include <vector> -#include <memory> - - -namespace Nv -{ -namespace Blast -{ - -/** -Generic binary block converter class. - -BinaryBlockConverter is an abstract class, as well as it's member class VersionConverter. In order to implement your own -binary converter - implement for every version conversion BinaryBlockConverter::VersionConverter. Then implement BinaryBlockConverter -where getVersionConverters() should return all your implemented BinaryBlockConverter::VersionConverter's. - -*/ -class BinaryBlockConverter -{ -public: - class VersionConverter - { - public: - virtual uint32_t getVersionFrom() const = 0; - virtual uint32_t getVersionTo() const = 0; - virtual bool convert(const std::vector<char>& from, std::vector<char>& to) const = 0; - }; - - typedef std::shared_ptr<VersionConverter> VersionConverterPtr; - - static bool convertBinaryBlock(std::vector<char>& outBlock, const std::vector<VersionConverterPtr>& converters, const std::vector<char>& inBlock, uint32_t outBlockVersion, uint32_t inBlockVersion); -protected: - -private: - static bool findShortestPath(std::vector<VersionConverterPtr>& conversionPath, const std::vector<VersionConverterPtr>& converters, uint32_t versionFrom, uint32_t versionTo); -}; - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTEXTBINARYBLOCKCONVERTER_H diff --git a/sdk/extensions/converter/source/conversion/NvBlastExtDataConverter.cpp b/sdk/extensions/converter/source/conversion/NvBlastExtDataConverter.cpp deleted file mode 100644 index fe8c745..0000000 --- a/sdk/extensions/converter/source/conversion/NvBlastExtDataConverter.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtDataConverter.h" -#include "NvBlastExtBinaryBlockConverter.h" - -#include <iostream> - -// asset converters -#include "NvBlastExtAssetBlockVersionConverter_v0_v1.h" - - -namespace Nv -{ -namespace Blast -{ - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Asset Block Converter -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -NV_INLINE std::vector<BinaryBlockConverter::VersionConverterPtr> getAssetConverters() -{ - /** - +==========================================+ - | HINT: ADD NEW VERSION CONVERTERS THERE | - +==========================================+ - */ - BinaryBlockConverter::VersionConverterPtr converters[] = - { - std::make_shared<NvBlastAssetBlockVersionConverter_v0_v1>() - }; - - return std::vector<BinaryBlockConverter::VersionConverterPtr>(converters, converters + sizeof(converters) / sizeof(converters[0])); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Family Converter -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -NV_INLINE std::vector<BinaryBlockConverter::VersionConverterPtr> getFamilyConverters() -{ - /** - +==========================================+ - | HINT: ADD NEW VERSION CONVERTERS THERE | - +==========================================+ - */ - BinaryBlockConverter::VersionConverterPtr converters[] = - { - nullptr //std::make_shared<NvBlastFamilyVersionConverter_v0_v1>() - }; - - return std::vector<BinaryBlockConverter::VersionConverterPtr>(converters, converters + sizeof(converters) / sizeof(converters[0])); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Generic Block Converter -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -bool convertDataBlock(std::vector<char>& outBlock, const std::vector<char>& inBlock, uint32_t* outBlockVersion) -{ - // Pick header to determine dataType and version - if (inBlock.size() < sizeof(NvBlastDataBlock)) - { - std::cerr << "Conversion failed: invalid block, passed block is too small." << std::endl; - return false; - } - const NvBlastDataBlock* dataBlock = reinterpret_cast<const NvBlastDataBlock*>(inBlock.data()); - - // Select appropriate converters and version based on dataType - std::vector<BinaryBlockConverter::VersionConverterPtr> converters; - uint32_t version; - switch (dataBlock->dataType) - { - case NvBlastDataBlock::AssetDataBlock: - std::cout << "Input block dataType: NvBlastDataBlock::Asset" << std::endl; - converters = getAssetConverters(); - version = (outBlockVersion == nullptr ? static_cast<uint32_t>(NvBlastAssetDataFormat::Current) : *outBlockVersion); - break; - case NvBlastDataBlock::FamilyDataBlock: - std::cout << "Input block dataType: NvBlastDataBlock::Family" << std::endl; - converters = getFamilyConverters(); - version = (outBlockVersion == nullptr ? static_cast<uint32_t>(NvBlastFamilyDataFormat::Current) : *outBlockVersion); - break; - default: - std::cerr << "Conversion failed: unsupported dataType: " << dataBlock->dataType << std::endl; - return false; - } - - return BinaryBlockConverter::convertBinaryBlock(outBlock, converters, inBlock, version, dataBlock->formatVersion); -} - -} // namespace Blast -} // namespace Nv diff --git a/sdk/extensions/exporter/include/NvBlastExtExporter.h b/sdk/extensions/exporter/include/NvBlastExtExporter.h new file mode 100644 index 0000000..5432ec7 --- /dev/null +++ b/sdk/extensions/exporter/include/NvBlastExtExporter.h @@ -0,0 +1,257 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTER_H +#define NVBLASTEXTEXPORTER_H + +#include "NvBlastTypes.h" + +struct NvBlastAsset; + +namespace physx +{ +class PxVec2; +class PxVec3; +} + +namespace Nv +{ +namespace Blast +{ +struct AuthoringResult; +struct CollisionHull; + +struct ExporterMeshData +{ + NvBlastAsset* asset; //Blast asset + + uint32_t positionsCount; //Number of positions + + uint32_t normalsCount; //Number of normals + + uint32_t uvsCount; //Number of textures uv + + physx::PxVec3* positions; //Array of positions + + physx::PxVec3* normals; //Array of normals + + physx::PxVec2* uvs; //Array of textures uv + + uint32_t meshCount; //Number of meshes (chunks) + + uint32_t submeshCount; //Number of submeshes + + const char** submeshNames; //Equal to material names + + + /** + Indices offsets for posIndex, normIndex and texIndex + First position index: posIndex[submeshOffsets[meshId * submeshCount + submeshId]] + Total number of indices: submeshOffsets[meshCount * submeshCount] + */ + uint32_t* submeshOffsets; + + uint32_t* posIndex; //Array of position indices + + uint32_t* normIndex; //Array of normals indices + + uint32_t* texIndex; //Array of texture indices + + + /** + Hull offsets. Contains meshCount + 1 element. + First hull for i-th mesh: hulls[hullsOffsets[i]] + hullsOffsets[meshCount+1] is total number of hulls + */ + uint32_t* hullsOffsets; + + CollisionHull** hulls; //Array of pointers to hull for all meshes +}; + +/** + An interface for Blast mesh file reader +*/ +class IMeshFileReader +{ +public: + + /** + Delete this object + */ + virtual void release() = 0; + + /* + Load from the specified file path + */ + virtual void loadFromFile(const char* filename) = 0; + + /** + Number of loaded vertices + */ + virtual uint32_t getVerticesCount() const = 0; + + /** + Number of loaded indices + */ + virtual uint32_t getIdicesCount() const = 0; + + /** + Get loaded vertex positions + */ + virtual physx::PxVec3* getPositionArray() = 0; + + /** + Get loaded vertex normals + */ + virtual physx::PxVec3* getNormalsArray() = 0; + + /** + Get loaded vertex uv-coordinates + */ + virtual physx::PxVec2* getUvArray() = 0; + + /** + Get loaded per triangle material ids. + */ + virtual int32_t* getMaterialIds() = 0; + + /** + Get loaded per triangle smoothing groups. + */ + virtual int32_t* getSmoothingGroups() = 0; + + /** + Get material name. + */ + virtual char* getMaterialName(int32_t id) = 0; + + /** + Get material count. + */ + virtual int32_t getMaterialCount() = 0; + + + + /** + Get loaded triangle indices + */ + virtual uint32_t* getIndexArray() = 0; + + + /** + Check whether file contained an collision geometry + */ + virtual bool isCollisionLoaded() = 0; + + /** + Retrieve collision geometry if it exist + \note User should call NVBLAST_FREE for hulls and hullsOffset when it not needed anymore + + \param[out] hullsOffset Array of hull offsets for hulls array. The size is meshCount + 1. + \param[out] hulls Array of hull. The first i-th mesh hull: hulls[hullsOffset[i]]. The size is written to hullsOffset[meshCount] + \return Number of meshes (meshCount) + */ + virtual uint32_t getCollision(uint32_t*& hullsOffset, CollisionHull** hulls) = 0; + +}; + +/** + An interface for fbx file reader +*/ +class IFbxFileReader : public IMeshFileReader +{ +public: + /** + Retrieve bone influence if it exist + \note User should call NVBLAST_FREE for out when it not needed anymore + + \param[out] out Array of bone influences. + \return Number of bones influences (boneCount) + */ + virtual uint32_t getBoneInfluences(uint32_t*& out) = 0; + + /** + Return number of bones in fbx file + */ + virtual uint32_t getBoneCount() = 0; +}; + +/** + An interface for Blast mesh file writer +*/ +class IMeshFileWriter +{ +public: + + /** + Delete this object + */ + virtual void release() = 0; + + /** + Append rendermesh to scene. Meshes constructed from arrays of triangles. + */ + virtual bool appendMesh(const AuthoringResult& aResult, const char* assetName, bool nonSkinned = false) = 0; + + /** + Append rendermesh to scene. Meshes constructed from arrays of vertices and indices + */ + virtual bool appendMesh(const ExporterMeshData& meshData, const char* assetName, bool nonSkinned = false) = 0; + + /** + Save scene to file. + */ + virtual bool saveToFile(const char* assetName, const char* outputPath) = 0; +}; + +} +} + +/** + Creates an instance of IMeshFileReader for reading obj file. +*/ +NVBLAST_API Nv::Blast::IMeshFileReader* NvBlastExtExporterCreateObjFileReader(); + +/** + Creates an instance of IFbxFileReader for reading fbx file. +*/ +NVBLAST_API Nv::Blast::IFbxFileReader* NvBlastExtExporterCreateFbxFileReader(); + +/** + Creates an instance of IMeshFileWriter for writing obj file. +*/ +NVBLAST_API Nv::Blast::IMeshFileWriter* NvBlastExtExporterCreateObjFileWriter(); + +/** + Creates an instance of IMeshFileWriter for writing fbx file. + + \param[in] outputFBXAscii If true writes fbx in ascii format otherwise write in binary. +*/ +NVBLAST_API Nv::Blast::IMeshFileWriter* NvBlastExtExporterCreateFbxFileWriter(bool outputFBXAscii = false); + +#endif //NVBLASTEXTEXPORTER_H
\ No newline at end of file diff --git a/sdk/extensions/exporter/include/NvBlastExtExporterJsonCollision.h b/sdk/extensions/exporter/include/NvBlastExtExporterJsonCollision.h new file mode 100644 index 0000000..5cda025 --- /dev/null +++ b/sdk/extensions/exporter/include/NvBlastExtExporterJsonCollision.h @@ -0,0 +1,62 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTERJSONCOLLISION_H +#define NVBLASTEXTEXPORTERJSONCOLLISION_H + +#include "NvBlastTypes.h" + +namespace Nv +{ +namespace Blast +{ + + +struct CollisionHull; + +/** + Serializes collision geometry to JSON format. +*/ +class JsonCollisionExporter +{ +public: + JsonCollisionExporter(){}; + + /** + Method creates file with given path and serializes given array of arrays of convex hulls to it in JSON format. + \param[in] path Output file path + \param[in] hulls Array of arrays of convex hull descriptors. Each array contain array of convex hulls for chunk (hulls[0] - convexes for chunk 0, etc.) + */ + bool writeCollision(const char* path, uint32_t meshCount, const uint32_t* meshOffsets, const CollisionHull* hulls); +}; + + +} // namespace Blast +} // namespace Nv + +#endif //NVBLASTEXTEXPORTERJSONCOLLISION_H
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporter.cpp b/sdk/extensions/exporter/source/NvBlastExtExporter.cpp new file mode 100644 index 0000000..d74a1ee --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporter.cpp @@ -0,0 +1,58 @@ +// 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 "NvBlastExtExporter.h" +#include "NvBlastExtExporterFbxReader.h" +#include "NvBlastExtExporterObjReader.h" +#include "NvBlastExtExporterFbxWriter.h" +#include "NvBlastExtExporterObjWriter.h" + +using namespace Nv::Blast; + +IMeshFileReader* NvBlastExtExporterCreateObjFileReader() +{ + return new ObjFileReader; +} + +IFbxFileReader* NvBlastExtExporterCreateFbxFileReader() +{ + return new FbxFileReader; +} + +IMeshFileWriter* NvBlastExtExporterCreateObjFileWriter() +{ + return new ObjFileWriter; +} + +IMeshFileWriter* NvBlastExtExporterCreateFbxFileWriter(bool outputFBXAscii) +{ + auto ret = new FbxFileWriter; + ret->bOutputFBXAscii = outputFBXAscii; + return ret; +} + diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp new file mode 100644 index 0000000..df0500e --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp @@ -0,0 +1,505 @@ +// 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 "NvBlastExtExporterFbxReader.h" +#include "NvBlastExtExporterFbxUtils.h" +#include "NvBlastGlobals.h" +#include "fileio/fbxiosettings.h" +#include "fileio/fbxiosettingspath.h" +#include "core/base/fbxstringlist.h" +#include <iostream> +#include <algorithm> +#include <cctype> +#include <sstream> +#include "scene/geometry/fbxmesh.h" + +#include "PxVec3.h" +#include "PxVec2.h" +#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringBondGenerator.h" +#include "NvBlastExtAuthoringCollisionBuilder.h" + +using physx::PxVec3; +using physx::PxVec2; + +using namespace Nv::Blast; + +FbxFileReader::FbxFileReader() +{ + mBoneCount = 0; +} + +void FbxFileReader::release() +{ + delete this; +} + +FbxAMatrix FbxFileReader::getTransformForNode(FbxNode* node) +{ + //The geometry transform contains the information about the pivots in the mesh node relative to the node's transform + FbxAMatrix geometryTransform(node->GetGeometricTranslation(FbxNode::eSourcePivot), + node->GetGeometricRotation(FbxNode::eSourcePivot), + node->GetGeometricScaling(FbxNode::eSourcePivot)); + FbxAMatrix nodeTransform = node->EvaluateGlobalTransform(); + + return nodeTransform * geometryTransform; +} + +void FbxFileReader::loadFromFile(const char* filename) +{ + // Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak. + std::shared_ptr<FbxManager> sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager) + { + std::cout << "Deleting FbxManager" << std::endl; + manager->Destroy(); + }); + + mBoneCount = 0; + mCollisionNodes.clear(); + FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT); + // Set some properties on the io settings + + sdkManager->SetIOSettings(ios); + + + FbxImporter* importer = FbxImporter::Create(sdkManager.get(), ""); + + bool importStatus = importer->Initialize(filename, -1, sdkManager->GetIOSettings()); + + if (!importStatus) + { + std::cerr << "Call to FbxImporter::Initialize failed." << std::endl; + std::cerr << "Error returned: " << importer->GetStatus().GetErrorString() << std::endl; + + return; + } + + FbxScene* scene = FbxScene::Create(sdkManager.get(), "importScene"); + + + + + importStatus = importer->Import(scene); + + if (!importStatus) + { + std::cerr << "Call to FbxImporter::Import failed." << std::endl; + std::cerr << "Error returned: " << importer->GetStatus().GetErrorString() << std::endl; + + return; + } + + int32_t matCount = scene->GetMaterialCount(); + + for (int32_t i = 0; i < matCount; ++i) + { + mMaterialNames.push_back(std::string(scene->GetMaterial(i)->GetName())); + } + + //This removes axis and unit conversion nodes so it converts the entire scene to the header specified axis and units + FbxRootNodeUtility::RemoveAllFbxRoots(scene); + + FbxAxisSystem blastAxisSystem = FbxUtils::getBlastFBXAxisSystem(); + FbxAxisSystem sourceSetup = scene->GetGlobalSettings().GetAxisSystem(); + if (sourceSetup != blastAxisSystem) + { + std::cout << "Converting to Blast coordinates" << std::endl; + std::cout << "Existing axis: " << FbxUtils::FbxAxisSystemToString(sourceSetup) << std::endl; + blastAxisSystem.ConvertScene(scene); + } + + FbxSystemUnit blastUnits = FbxUtils::getBlastFBXUnit(); + FbxSystemUnit sourceUnits = scene->GetGlobalSettings().GetSystemUnit(); + if (sourceUnits != blastUnits) + { + std::cout << "Converting to Blast units" << std::endl; + std::cout << "Existing units: " << FbxUtils::FbxSystemUnitToString(sourceUnits) << std::endl; + blastUnits.ConvertScene(scene); + } + + FbxDisplayLayer* collisionDisplayLayer = scene->FindMember<FbxDisplayLayer>(FbxUtils::getCollisionGeometryLayerName().c_str()); + + // Recurse the fbx tree and find all meshes + std::vector<FbxNode*> meshNodes; + getFbxMeshes(collisionDisplayLayer, scene->GetRootNode(), meshNodes); + + if (isCollisionLoaded()) + { + std::cout << "Collision geometry is found."; + getCollisionInternal(); + } + + std::cout << "Found " << meshNodes.size() << " meshes." << std::endl; + + // Process just 0, because dumb. Fail out if more than 1? + if (meshNodes.size() > 1) + { + std::cerr << "Can't load more that one graphics mesh." << std::endl; + return; + } + + if (meshNodes.empty()) + { + return; + } + + FbxNode* meshNode = meshNodes[0]; + FbxMesh* mesh = meshNode->GetMesh(); + + int polyCount = mesh->GetPolygonCount(); + + + bool bAllTriangles = true; + // Verify that the mesh is triangulated. + for (int i = 0; i < polyCount; i++) + { + if (mesh->GetPolygonSize(i) != 3) + { + bAllTriangles = false; + } + } + + if (!bAllTriangles) + { + std::cerr << "Mesh 0 has " << polyCount << " but not all polygons are triangles. Mesh must be triangulated." << std::endl; + return; + } + + FbxStringList uvSetNames; + + mesh->GetUVSetNames(uvSetNames); + + const char * uvSetName = uvSetNames.GetStringAt(0); + + std::vector<PxVec3> positions; + std::vector<PxVec3> normals; + std::vector<PxVec2> uv; + std::vector<uint32_t> indices; + + int* polyVertices = mesh->GetPolygonVertices(); + + uint32_t vertIndex = 0; + + FbxAMatrix trans = getTransformForNode(meshNode); + FbxVector4 rotation = trans.GetR(); + FbxVector4 scale = trans.GetS(); + FbxAMatrix normalTransf; + normalTransf.SetR(rotation); + normalTransf.SetS(scale); + normalTransf = normalTransf.Inverse().Transpose(); + + int32_t matElements = mesh->GetElementMaterialCount(); + if (matElements > 1) + { + std::cerr << "Mesh has more than 1 material mappings, first one will be used. " << std::endl; + } + auto matLayer = mesh->GetElementMaterial(0); + + + for (int i = 0; i < polyCount; i++) + { + for (int vi = 0; vi < 3; vi++) + { + int polyCPIdx = polyVertices[i*3+vi]; + + FbxVector4 vert = mesh->GetControlPointAt(polyCPIdx); + FbxVector4 normVec; + FbxVector2 uvVec; + + bool bUnmapped; + mesh->GetPolygonVertexNormal(i, vi, normVec); + mesh->GetPolygonVertexUV(i, vi, uvSetName, uvVec, bUnmapped); + vert = trans.MultT(vert); + normVec = normalTransf.MultT(normVec); + + positions.push_back(PxVec3((float) vert[0], (float)vert[1], (float)vert[2])); + normals.push_back(PxVec3((float)normVec[0], (float)normVec[1], (float)normVec[2])); + uv.push_back(PxVec2((float)uvVec[0], (float)uvVec[1])); + indices.push_back(vertIndex++); + } + if (matLayer != nullptr) + { + mMaterialIds.push_back(matLayer->GetIndexArray().GetAt(i)); + } + } + + mVertexPositions = positions; + mVertexNormals = normals; + mVertexUv = uv; + mIndices = indices; + + getBoneInfluencesInternal(mesh); +} + +int32_t FbxFileReader::getMaterialCount() +{ + return mMaterialNames.size(); +} + +void FbxFileReader::getFbxMeshes(FbxDisplayLayer* collisionDisplayLayer, FbxNode* node, std::vector<FbxNode*>& meshNodes) +{ + FbxMesh* mesh = node->GetMesh(); + + if (mesh != nullptr) + { + if (collisionDisplayLayer == nullptr && node->FindProperty("ParentalChunkIndex").IsValid()) + { + //Old-style file + uint32_t chunkIndex = node->FindProperty("ParentalChunkIndex").Get<int32_t>(); + mCollisionNodes.emplace(chunkIndex, node); + } + else if (collisionDisplayLayer != nullptr && collisionDisplayLayer->IsMember(node)) + { + uint32_t chunkIndex = FbxUtils::getChunkIndexForNode(node); + if (chunkIndex != UINT32_MAX) + { + mCollisionNodes.emplace(chunkIndex, node); + } + else + { + std::cerr << "Warning: Not sure what to do about collision geo " << node->GetName() << ". No corresponding chunk." << std::endl; + } + } + else + { + meshNodes.push_back(node); + } + } + int childCount = node->GetChildCount(); + + for (int i = 0; i < childCount; i++) + { + FbxNode * childNode = node->GetChild(i); + + getFbxMeshes(collisionDisplayLayer, childNode, meshNodes); + } +} + +bool FbxFileReader::isCollisionLoaded() +{ + return !mCollisionNodes.empty(); +} + +uint32_t FbxFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) +{ + if (!isCollisionLoaded()) + { + return 0; + } + hullsOffset = new uint32_t[mMeshCount + 1]; + hulls = new Nv::Blast::CollisionHull*[mMeshCount]; + memcpy(hullsOffset, mHullsOffset.data(), sizeof(uint32_t) * (mMeshCount + 1)); + memcpy(hulls, mHulls.data(), sizeof(Nv::Blast::CollisionHull*) * mMeshCount); + return mMeshCount; +} + +struct CollisionHullImpl : public Nv::Blast::CollisionHull +{ + void release() override + { + + } +}; + +bool FbxFileReader::getCollisionInternal() +{ + for (auto hull : mHulls) + { + hull->release(); + } + int32_t maxParentIndex = 0; + + for (auto p : mCollisionNodes) + { + int32_t parentIndex = p.first; + maxParentIndex = std::max(maxParentIndex, parentIndex); + } + mMeshCount = maxParentIndex + 1; + mHullsOffset.resize(mMeshCount + 1); + mHulls.resize(mCollisionNodes.size()); + mHullsOffset[0] = 0; + + for (auto p : mCollisionNodes) // it should be sorted by chunk id + { + int32_t parentIndex = p.first; + //hulls[parentIndex].push_back(Nv::Blast::CollisionHull()); + mHulls[mHullsOffset[parentIndex]] = new CollisionHullImpl(); + Nv::Blast::CollisionHull& chull = *mHulls[mHullsOffset[parentIndex]]; + FbxMesh* meshNode = p.second->GetMesh(); + + FbxAMatrix nodeTransform = getTransformForNode(p.second); + FbxAMatrix nodeTransformNormal = nodeTransform.Inverse().Transpose(); + + chull.points = new PxVec3[meshNode->GetControlPointsCount()]; + FbxVector4* vpos = meshNode->GetControlPoints(); + /** + Copy control points from FBX. + */ + for (int32_t i = 0; i < meshNode->GetControlPointsCount(); ++i) + { + FbxVector4 worldVPos = nodeTransform.MultT(*vpos); + chull.points[i].x = (float)worldVPos[0]; + chull.points[i].y = (float)worldVPos[1]; + chull.points[i].z = (float)worldVPos[2]; + vpos++; + } + + uint32_t polyCount = meshNode->GetPolygonCount(); + chull.polygonData = new Nv::Blast::CollisionHull::HullPolygon[polyCount]; + FbxGeometryElementNormal* nrm = meshNode->GetElementNormal(); + FbxLayerElementArray& narr = nrm->GetDirectArray(); + + for (uint32_t poly = 0; poly < polyCount; ++poly) + { + int32_t vInPolyCount = meshNode->GetPolygonSize(poly); + auto& pd = chull.polygonData[poly]; + pd.mIndexBase = (uint16_t)chull.indicesCount; + pd.mNbVerts = (uint16_t)vInPolyCount; + int32_t* ind = &meshNode->GetPolygonVertices()[meshNode->GetPolygonVertexIndex(poly)]; + chull.indices = new uint32_t[vInPolyCount]; + memcpy(chull.indices, ind, sizeof(uint32_t) * vInPolyCount); + + FbxVector4 normal; + narr.GetAt(poly, &normal); + + normal = nodeTransformNormal.MultT(normal); + + pd.mPlane[0] = (float)normal[0]; + pd.mPlane[1] = (float)normal[1]; + pd.mPlane[2] = (float)normal[2]; + PxVec3 polyLastVertex = chull.points[chull.indices[vInPolyCount - 1]]; + pd.mPlane[3] = -((float)(polyLastVertex.x * normal[0] + polyLastVertex.y * normal[1] + polyLastVertex.z * normal[2])); + } + mHullsOffset[parentIndex + 1] = mHullsOffset[parentIndex] + 1; + } + + + return false; +} + + +/** + To work properly export tool should give bone names as bone_@chunkIndex (e.g. bone_1, bone_2) +**/ +bool FbxFileReader::getBoneInfluencesInternal(FbxMesh* meshNode) +{ + + if (meshNode->GetDeformerCount() != 1) + { + std::cout << "Can't create bone mapping: There is no mesh deformers...: " << std::endl; + return false; + } + mVertexToParentBoneMap.clear(); + mVertexToParentBoneMap.resize(mVertexPositions.size()); + std::vector<uint32_t> controlToParentBoneMap; + controlToParentBoneMap.resize(meshNode->GetControlPointsCount()); + FbxSkin* def = (FbxSkin *)meshNode->GetDeformer(0, FbxDeformer::EDeformerType::eSkin); + + if (def->GetClusterCount() == 0) + { + std::cout << "Can't create bone mapping: There is no vertex clusters...: " << std::endl; + return false; + } + mBoneCount = def->GetClusterCount(); + for (int32_t i = 0; i < def->GetClusterCount(); ++i) + { + FbxCluster* cls = def->GetCluster(i); + FbxNode* bone = cls->GetLink(); + int32_t parentChunk = atoi(bone->GetName() + 5); + int32_t* cpIndx = cls->GetControlPointIndices(); + for (int32_t j = 0; j < cls->GetControlPointIndicesCount(); ++j) + { + controlToParentBoneMap[*cpIndx] = parentChunk; + ++cpIndx; + } + } + int* polyVertices = meshNode->GetPolygonVertices(); + uint32_t lv = 0; + for (int i = 0; i < meshNode->GetPolygonCount(); i++) + { + for (int vi = 0; vi < 3; vi++) + { + mVertexToParentBoneMap[lv] = controlToParentBoneMap[*polyVertices]; + polyVertices++; + lv++; + } + } + return true; +}; + +physx::PxVec3* FbxFileReader::getPositionArray() +{ + return mVertexPositions.data(); +}; + +physx::PxVec3* FbxFileReader::getNormalsArray() +{ + return mVertexNormals.data(); +}; + +physx::PxVec2* FbxFileReader::getUvArray() +{ + return mVertexUv.data(); +}; + +uint32_t* FbxFileReader::getIndexArray() +{ + return mIndices.data(); +}; + +uint32_t FbxFileReader::getBoneInfluences(uint32_t*& out) +{ + out = static_cast<uint32_t*>(NVBLAST_ALLOC(sizeof(uint32_t) * mVertexToParentBoneMap.size())); + memcpy(out, mVertexToParentBoneMap.data(), sizeof(uint32_t) * mVertexToParentBoneMap.size()); + return mVertexToParentBoneMap.size(); +} + +uint32_t FbxFileReader::getBoneCount() +{ + return mBoneCount; +} + +char* FbxFileReader::getMaterialName(int32_t id) +{ + if (id < int32_t(mMaterialNames.size()) && id >= 0) + { + return &mMaterialNames[id][0]; + } + else + { + return nullptr; + } +} + +int32_t* FbxFileReader::getMaterialIds() +{ + if (mMaterialIds.empty()) + { + return nullptr; + } + return mMaterialIds.data(); +}
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h new file mode 100644 index 0000000..4155b25 --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h @@ -0,0 +1,144 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTERFBXREADER_H +#define NVBLASTEXTEXPORTERFBXREADER_H + +#include <memory> +#include "fbxsdk.h" +#include <vector> +#include <map> +#include "NvBlastExtExporter.h" +#include "NvBlastExtAuthoringTypes.h" + +namespace Nv +{ +namespace Blast +{ +class Mesh; + +class FbxFileReader : public IFbxFileReader +{ +public: + FbxFileReader(); + ~FbxFileReader() = default; + + virtual void release() override; + + /* + Load from the specified file path, returning a mesh or nullptr if failed + */ + virtual void loadFromFile(const char* filename) override; + + virtual uint32_t getVerticesCount() const override + { + return mVertexPositions.size(); + } + + virtual uint32_t getIdicesCount() const override + { + return mIndices.size(); + } + + /** + Check whether file contained an collision geometry + */ + virtual bool isCollisionLoaded() override; + + /** + Retrieve collision geometry if it exist + */ + virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) override; + + virtual uint32_t getBoneInfluences(uint32_t*& out) override; + + virtual uint32_t getBoneCount() override; + + /** + Get loaded vertex positions + */ + virtual physx::PxVec3* getPositionArray() override; + /** + Get loaded vertex normals + */ + virtual physx::PxVec3* getNormalsArray() override; + /** + Get loaded vertex uv-coordinates + */ + virtual physx::PxVec2* getUvArray() override; + /** + Get loaded triangle indices + */ + virtual uint32_t* getIndexArray() override; + + /** + Get loaded per triangle material ids. + */ + int32_t* getMaterialIds() override; + + /** + Get loaded per triangle smoothing groups. Currently not supported. + */ + int32_t* getSmoothingGroups() override { return nullptr; }; + + /** + Get material name. + */ + char* getMaterialName(int32_t id) override; + + + int32_t getMaterialCount() override; + +private: + + uint32_t mMeshCount; + std::vector<uint32_t> mHullsOffset; + std::vector<Nv::Blast::CollisionHull*> mHulls; + std::vector<uint32_t> mVertexToParentBoneMap; + std::multimap<uint32_t, FbxNode*> mCollisionNodes; + std::vector<physx::PxVec3> mVertexPositions; + std::vector<physx::PxVec3> mVertexNormals; + std::vector<physx::PxVec2> mVertexUv; + std::vector<uint32_t> mIndices; + std::vector<int32_t> mSmoothingGroups; + std::vector<int32_t> mMaterialIds; + std::vector<std::string> mMaterialNames; + + uint32_t mBoneCount; + + FbxAMatrix getTransformForNode(FbxNode* node); + void getFbxMeshes(FbxDisplayLayer* collisionDisplayLayer, FbxNode* node, std::vector<FbxNode*>& meshNodes); + bool getCollisionInternal(); + bool getBoneInfluencesInternal(FbxMesh* meshNode); + +}; + +} +} + +#endif
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp new file mode 100644 index 0000000..95a757f --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp @@ -0,0 +1,192 @@ +// 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 "fbxsdk.h" +#include "NvBlastExtExporterFbxUtils.h" +#include "PxVec3.h" +#include "PxVec2.h" +#include "NvBlastExtAuthoringTypes.h" +#include <sstream> +#include <cctype> + +using physx::PxVec3; +using physx::PxVec2; + + +void FbxUtils::VertexToFbx(const Nv::Blast::Vertex& vert, FbxVector4& outVertex, FbxVector4& outNormal, FbxVector2& outUV) +{ + PxVec3ToFbx(vert.p, outVertex); + PxVec3ToFbx(vert.n, outNormal); + PxVec2ToFbx(vert.uv[0], outUV); +} + +void FbxUtils::PxVec3ToFbx(const physx::PxVec3& inVector, FbxVector4& outVector) +{ + outVector[0] = inVector.x; + outVector[1] = inVector.y; + outVector[2] = inVector.z; + outVector[3] = 0; +} + +void FbxUtils::PxVec2ToFbx(const physx::PxVec2& inVector, FbxVector2& outVector) +{ + outVector[0] = inVector.x; + outVector[1] = inVector.y; +} + +FbxAxisSystem FbxUtils::getBlastFBXAxisSystem() +{ + const FbxAxisSystem::EUpVector upVector = FbxAxisSystem::eZAxis; + //From the documentation: If the up axis is Z, the remain two axes will X And Y, so the ParityEven is X, and the ParityOdd is Y + const FbxAxisSystem::EFrontVector frontVector = FbxAxisSystem::eParityOdd; + const FbxAxisSystem::ECoordSystem rightVector = FbxAxisSystem::eRightHanded; + return FbxAxisSystem(upVector, frontVector, rightVector); +} + +FbxSystemUnit FbxUtils::getBlastFBXUnit() +{ + return FbxSystemUnit::cm; +} + +std::string FbxUtils::FbxAxisSystemToString(const FbxAxisSystem& axisSystem) +{ + std::stringstream ss; + int upSign, frontSign; + FbxAxisSystem::EUpVector upVector = axisSystem.GetUpVector(upSign); + FbxAxisSystem::EFrontVector frontVector = axisSystem.GetFrontVector(frontSign); + FbxAxisSystem::ECoordSystem coordSystem = axisSystem.GetCoorSystem(); + ss << "Predefined Type: "; + if (axisSystem == FbxAxisSystem::MayaZUp) + { + ss << "MayaZUP"; + } + else if (axisSystem == FbxAxisSystem::MayaYUp) + { + ss << "MayaYUp"; + } + else if (axisSystem == FbxAxisSystem::Max) + { + ss << "Max"; + } + else if (axisSystem == FbxAxisSystem::Motionbuilder) + { + ss << "Motionbuilder"; + } + else if (axisSystem == FbxAxisSystem::OpenGL) + { + ss << "OpenGL"; + } + else if (axisSystem == FbxAxisSystem::DirectX) + { + ss << "OpenGL"; + } + else if (axisSystem == FbxAxisSystem::Lightwave) + { + ss << "OpenGL"; + } + else + { + ss << "<Other>"; + } + ss << " UpVector: " << (upSign > 0 ? "+" : "-"); + switch (upVector) + { + case FbxAxisSystem::eXAxis: ss << "eXAxis"; break; + case FbxAxisSystem::eYAxis: ss << "eYAxis"; break; + case FbxAxisSystem::eZAxis: ss << "eZAxis"; break; + default: ss << "<unknown>"; break; + } + + ss << " FrontVector: " << (frontSign > 0 ? "+" : "-"); + switch (frontVector) + { + case FbxAxisSystem::eParityEven: ss << "eParityEven"; break; + case FbxAxisSystem::eParityOdd: ss << "eParityOdd"; break; + default: ss << "<unknown>"; break; + } + + ss << " CoordSystem: "; + switch (coordSystem) + { + case FbxAxisSystem::eLeftHanded: ss << "eLeftHanded"; break; + case FbxAxisSystem::eRightHanded: ss << "eRightHanded"; break; + default: ss << "<unknown>"; break; + } + + return ss.str(); +} + +std::string FbxUtils::FbxSystemUnitToString(const FbxSystemUnit& systemUnit) +{ + return std::string(systemUnit.GetScaleFactorAsString()); +} + +const static std::string chunkPrefix = "chunk_"; + +uint32_t FbxUtils::getChunkIndexForNode(FbxNode* node, bool includeParents /*= true*/) +{ + std::string nodeName(node->GetNameOnly()); + for (char& c : nodeName) + c = (char)std::tolower(c); + + if (nodeName.substr(0, chunkPrefix.size()) == chunkPrefix) + { + std::istringstream iss(nodeName.substr(chunkPrefix.size())); + uint32_t ret = UINT32_MAX; + iss >> ret; + if (!iss.fail()) + { + return ret; + } + } + + if (includeParents && node->GetParent()) + { + return getChunkIndexForNode(node->GetParent(), true); + } + //Found nothing + return UINT32_MAX; +} + +std::string FbxUtils::getChunkNodeName(uint32_t chunkIndex) +{ + //This naming is required for the UE4 plugin to find them + std::ostringstream namestream; + namestream << chunkPrefix << chunkIndex; + return namestream.str(); +} + +std::string FbxUtils::getCollisionGeometryLayerName() +{ + return "Collision"; +} + +std::string FbxUtils::getRenderGeometryLayerName() +{ + return "Render"; +} diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h new file mode 100644 index 0000000..d26a9e9 --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h @@ -0,0 +1,67 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTERFBXUTILS_H +#define NVBLASTEXTEXPORTERFBXUTILS_H + +#include "fbxsdk.h" +#include "PxVec3.h" +#include "PxVec2.h" +#include <string> + +namespace Nv +{ + namespace Blast + { + struct Vertex; + } +} + +class FbxUtils +{ +public: + static void VertexToFbx(const Nv::Blast::Vertex& vert, FbxVector4& outVertex, FbxVector4& outNormal, FbxVector2& outUV); + + static void PxVec3ToFbx(const physx::PxVec3& inVector, FbxVector4& outVector); + static void PxVec2ToFbx(const physx::PxVec2& inVector, FbxVector2& outVector); + + static FbxAxisSystem getBlastFBXAxisSystem(); + static FbxSystemUnit getBlastFBXUnit(); + + static std::string FbxAxisSystemToString(const FbxAxisSystem& axisSystem); + static std::string FbxSystemUnitToString(const FbxSystemUnit& systemUnit); + + //returns UINT32_MAX if not a chunk + static uint32_t getChunkIndexForNode(FbxNode* node, bool includeParents = true); + static std::string getChunkNodeName(uint32_t chunkIndex); + + static std::string getCollisionGeometryLayerName(); + static std::string getRenderGeometryLayerName(); +}; + +#endif //NVBLASTEXTEXPORTERFBXUTILS_H
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp new file mode 100644 index 0000000..b5fd04b --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp @@ -0,0 +1,1095 @@ +// 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 "fbxsdk.h" +#include <iostream> +#include <sstream> +#include <iomanip> +#include "NvBlastTypes.h" +#include "NvBlastGlobals.h" +#include "NvBlastTkFramework.h" +#include "NvBlast.h" +#include "PxVec3.h" +#include "NvBlastAssert.h" +#include <unordered_set> +#include <functional> +#include "NvBlastExtExporterFbxWriter.h" +#include "NvBlastExtExporterFbxUtils.h" +#include "NvBlastExtAuthoringCollisionBuilder.h" +#include "NvBlastExtAuthoring.h" +#include "NvBlastExtAuthoringMesh.h" + +using namespace Nv::Blast; + +FbxFileWriter::FbxFileWriter(): + bOutputFBXAscii(false) +{ + // Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak. + sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager) + { + std::cout << "Deleting FbxManager" << std::endl; + manager->Destroy(); + }); + + mScene = FbxScene::Create(sdkManager.get(), "Export Scene"); + + mScene->GetGlobalSettings().SetAxisSystem(FbxUtils::getBlastFBXAxisSystem()); + mScene->GetGlobalSettings().SetSystemUnit(FbxUtils::getBlastFBXUnit()); + mScene->GetGlobalSettings().SetOriginalUpAxis(FbxUtils::getBlastFBXAxisSystem()); + mScene->GetGlobalSettings().SetOriginalSystemUnit(FbxUtils::getBlastFBXUnit()); + + //We don't actually check for membership in this layer, but it's useful to show and hide the geo to look at the collision geo + mRenderLayer = FbxDisplayLayer::Create(mScene, FbxUtils::getRenderGeometryLayerName().c_str()); + mRenderLayer->Show.Set(true); + mRenderLayer->Color.Set(FbxDouble3(0.0f, 1.0f, 0.0f)); +} + +void FbxFileWriter::release() +{ + //sdkManager->Destroy(); + delete this; +} + +FbxScene* FbxFileWriter::getScene() +{ + return mScene; +} + + +void FbxFileWriter::createMaterials(const ExporterMeshData& aResult) +{ + mMaterials.clear(); + + for (uint32_t i = 0; i < aResult.submeshCount; ++i) + { + FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), aResult.submeshNames[i]); + material->Diffuse.Set(FbxDouble3(float(rand()) / RAND_MAX , float(rand()) / RAND_MAX, float(rand()) / RAND_MAX)); + material->DiffuseFactor.Set(1.0); + mMaterials.push_back(material); + } +} + +void FbxFileWriter::createMaterials(const AuthoringResult& aResult) +{ + mMaterials.clear(); + for (uint32_t i = 0; i < aResult.materialCount; ++i) + { + FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), aResult.materialNames[i]); + material->Diffuse.Set(FbxDouble3(float(rand()) / RAND_MAX, float(rand()) / RAND_MAX, float(rand()) / RAND_MAX)); + material->DiffuseFactor.Set(1.0); + mMaterials.push_back(material); + } + if (mMaterials.size() == 0) + { + FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), "Base_mat"); + material->Diffuse.Set(FbxDouble3(0.3, 1.0, 0)); + material->DiffuseFactor.Set(1.0); + mMaterials.push_back(material); + } + FbxSurfacePhong* interiorMat = FbxSurfacePhong::Create(sdkManager.get(), "Interior_Material"); + interiorMat->Diffuse.Set(FbxDouble3(1.0, 0.0, 0.5)); + interiorMat->DiffuseFactor.Set(1.0); + mMaterials.push_back(interiorMat); +} + + +bool FbxFileWriter::appendMesh(const AuthoringResult& aResult, const char* assetName, bool nonSkinned) +{ + createMaterials(aResult); + + if (nonSkinned) + { + return appendNonSkinnedMesh(aResult, assetName); + } + std::string meshName(assetName); meshName.append("_rendermesh"); + + FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), meshName.c_str()); + + FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal(); + geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geNormal->SetReferenceMode(FbxGeometryElement::eDirect); + + FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement"); + geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geUV->SetReferenceMode(FbxGeometryElement::eDirect); + + FbxGeometryElementSmoothing* smElement = nullptr; + size_t triangleCount = aResult.geometryOffset[aResult.chunkCount]; + + for (size_t triangle = 0; triangle < triangleCount; triangle++) + { + if (aResult.geometry[triangle].smoothingGroup >= 0) + { + //Found a valid smoothing group + smElement = mesh->CreateElementSmoothing(); + smElement->SetMappingMode(FbxGeometryElement::eByPolygon); + smElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + break; + } + } + + mesh->InitControlPoints((int)triangleCount * 3); + + + FbxNode* meshNode = FbxNode::Create(mScene, assetName); + meshNode->SetNodeAttribute(mesh); + meshNode->SetShadingMode(FbxNode::eTextureShading); + + mRenderLayer->AddMember(meshNode); + + for (uint32_t i = 0; i < mMaterials.size(); ++i) + { + meshNode->AddMaterial(mMaterials[i]); + } + + FbxNode* lRootNode = mScene->GetRootNode(); + + //In order for Maya to correctly convert the axis of a skinned model there must be a common root node between the skeleton and the model + FbxNode* sceneRootNode = FbxNode::Create(sdkManager.get(), "sceneRoot"); + lRootNode->AddChild(sceneRootNode); + sceneRootNode->AddChild(meshNode); + + //UE4 cannot hide the root bone, so add a dummy chunk so chunk0 is not the root + FbxNode* skelRootNode = FbxNode::Create(sdkManager.get(), "root"); + FbxSkeleton* skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib"); + skelAttrib->SetSkeletonType(FbxSkeleton::eRoot); + skelRootNode->SetNodeAttribute(skelAttrib); + + sceneRootNode->AddChild(skelRootNode); + + FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing"); + skin->SetGeometry(mesh); + mesh->AddDeformer(skin); + + // Add a material otherwise UE4 freaks out on import + + FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial(); + matElement->SetMappingMode(FbxGeometryElement::eByPolygon); + matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + // Now walk the tree and create a skeleton with geometry at the same time + // Find a "root" chunk and walk the tree from there. + uint32_t chunkCount = aResult.chunkCount; + auto chunks = aResult.chunkDescs; + + uint32_t cpIdx = 0; + for (uint32_t i = 0; i < chunkCount; i++) + { + auto& chunk = chunks[i]; + + if (chunk.parentChunkIndex == UINT32_MAX) + { + uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, skelRootNode, skin, aResult); + cpIdx += addedCps; + } + } + + if (!smElement) + { + //If no smoothing groups, generate them + FbxGeometryConverter fbxConv(mesh->GetFbxManager()); + if (fbxConv.ComputeEdgeSmoothingFromNormals(mesh)) + { + fbxConv.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0); + } + } + + if (aResult.collisionHull != nullptr) + { + return appendCollisionMesh(chunkCount, aResult.collisionHullOffset, aResult.collisionHull, assetName); + } + + return true; +}; + + +bool FbxFileWriter::appendNonSkinnedMesh(const AuthoringResult& aResult, const char* assetName) +{ + FbxNode* lRootNode = mScene->GetRootNode(); + + //UE4 cannot hide the root bone, so add a dummy chunk so chunk0 is not the root + FbxNode* skelRootNode = FbxNode::Create(sdkManager.get(), "root"); + //UE4 needs this to be a skeleton node, null node, or mesh node to get used + FbxNull* nullAttr = FbxNull::Create(sdkManager.get(), "SkelRootAttrib"); + skelRootNode->SetNodeAttribute(nullAttr); + lRootNode->AddChild(skelRootNode); + + // Now walk the tree and create a skeleton with geometry at the same time + // Find a "root" chunk and walk the tree from there. + uint32_t chunkCount = aResult.chunkCount; + + auto chunks = aResult.chunkDescs; + + for (uint32_t i = 0; i < chunkCount; i++) + { + auto& chunk = chunks[i]; + + if (chunk.parentChunkIndex == UINT32_MAX) + { + createChunkRecursiveNonSkinned(assetName, i, skelRootNode, mMaterials, aResult); + } + } + + if (aResult.collisionHull != nullptr) + { + return appendCollisionMesh(chunkCount, aResult.collisionHullOffset, aResult.collisionHull, assetName); + } + + return true; +} + + +bool FbxFileWriter::appendNonSkinnedMesh(const ExporterMeshData& meshData, const char* assetName) +{ + FbxNode* lRootNode = mScene->GetRootNode(); + + //UE4 cannot hide the root bone, so add a dummy chunk so chunk0 is not the root + FbxNode* skelRootNode = FbxNode::Create(sdkManager.get(), "root"); + //UE4 needs this to be a skeleton node, null node, or mesh node to get used + FbxNull* nullAttr = FbxNull::Create(sdkManager.get(), "SkelRootAttrib"); + skelRootNode->SetNodeAttribute(nullAttr); + lRootNode->AddChild(skelRootNode); + + // Now walk the tree and create a skeleton with geometry at the same time + // Find a "root" chunk and walk the tree from there. + uint32_t chunkCount = NvBlastAssetGetChunkCount(meshData.asset, Nv::Blast::logLL); + + auto chunks = NvBlastAssetGetChunks(meshData.asset, Nv::Blast::logLL); + + for (uint32_t i = 0; i < chunkCount; i++) + { + const NvBlastChunk* chunk = &chunks[i]; + + if (chunk->parentChunkIndex == UINT32_MAX) + { + createChunkRecursiveNonSkinned("chunk", i, skelRootNode, mMaterials, meshData); + } + } + if (meshData.hulls != nullptr) + { + return appendCollisionMesh(chunkCount, meshData.hullsOffsets, meshData.hulls, assetName); + } + return true; +} + +bool FbxFileWriter::appendCollisionMesh(uint32_t meshCount, uint32_t* offsets, CollisionHull** hulls, const char* assetName) +{ + FbxDisplayLayer* displayLayer = FbxDisplayLayer::Create(mScene, FbxUtils::getCollisionGeometryLayerName().c_str()); + //Hide by default + displayLayer->Show.Set(false); + displayLayer->Color.Set(FbxDouble3(0.0f, 0.0f, 1.0f)); + + // Now walk the tree and create a skeleton with geometry at the same time + // Find a "root" chunk and walk the tree from there. + + for (uint32_t i = 0; i < meshCount; i++) + { + auto findIt = chunkNodes.find(i); + if (findIt == chunkNodes.end()) + { + std::cerr << "Warning: No chunk node for chunk " << i << ". Ignoring collision geo" << std::endl; + continue; + } + addCollisionHulls(i, displayLayer, findIt->second, offsets[i+1] - offsets[i], hulls + offsets[i]); + } + return true; +} + +/* + Recursive method that creates this chunk and all it's children. + + This creates a FbxNode with an FbxCluster, and all of the geometry for this chunk. + + Returns the number of added control points +*/ +uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const AuthoringResult& aResult) +{ + + auto chunks = NvBlastAssetGetChunks(aResult.asset, Nv::Blast::logLL); + const NvBlastChunk* chunk = &chunks[chunkIndex]; + physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]); + + //mesh->InitTextureUV(triangles.size() * 3); + + std::string boneName = FbxUtils::getChunkNodeName(chunkIndex); + + FbxSkeleton* skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str()); + if (chunk->parentChunkIndex == UINT32_MAX) + { + skelAttrib->SetSkeletonType(FbxSkeleton::eRoot); + + // Change the centroid to origin + centroid = physx::PxVec3(0.0f); + } + else + { + skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode); + worldChunkPivots[chunkIndex] = centroid; + } + + skelAttrib->Size.Set(1.0); // What's this for? + + + FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str()); + boneNode->SetNodeAttribute(skelAttrib); + + chunkNodes[chunkIndex] = boneNode; + + auto mat = parentNode->EvaluateGlobalTransform().Inverse(); + + FbxVector4 vec(0, 0, 0, 0); + FbxVector4 c2 = mat.MultT(vec); + + boneNode->LclTranslation.Set(c2); + + parentNode->AddChild(boneNode); + + std::ostringstream namestream; + namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex; + std::string clusterName = namestream.str(); + + FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str()); + cluster->SetTransformMatrix(FbxAMatrix()); + cluster->SetLink(boneNode); + cluster->SetLinkMode(FbxCluster::eTotalOne); + + skin->AddCluster(cluster); + + FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute()); + + FbxVector4* controlPoints = mesh->GetControlPoints(); + auto geNormal = mesh->GetElementNormal(); + auto geUV = mesh->GetElementUV("diffuseElement"); + FbxGeometryElementMaterial* matElement = mesh->GetElementMaterial(); + FbxGeometryElementSmoothing* smElement = mesh->GetElementSmoothing(); + + auto addVert = [&](Nv::Blast::Vertex vert, int controlPointIdx) + { + FbxVector4 vertex; + FbxVector4 normal; + FbxVector2 uv; + + FbxUtils::VertexToFbx(vert, vertex, normal, uv); + + controlPoints[controlPointIdx] = vertex; + geNormal->GetDirectArray().Add(normal); + geUV->GetDirectArray().Add(uv); + // Add this control point to the bone with weight 1.0 + cluster->AddControlPointIndex(controlPointIdx, 1.0); + }; + + uint32_t cpIdx = 0; + uint32_t polyCount = mesh->GetPolygonCount(); + for (uint32_t i = aResult.geometryOffset[chunkIndex]; i < aResult.geometryOffset[chunkIndex + 1]; i++) + { + Triangle& tri = aResult.geometry[i]; + addVert(tri.a, currentCpIdx + cpIdx + 0); + addVert(tri.b, currentCpIdx + cpIdx + 1); + addVert(tri.c, currentCpIdx + cpIdx + 2); + + mesh->BeginPolygon(); + mesh->AddPolygon(currentCpIdx + cpIdx + 0); + mesh->AddPolygon(currentCpIdx + cpIdx + 1); + mesh->AddPolygon(currentCpIdx + cpIdx + 2); + mesh->EndPolygon(); + int32_t material = (tri.materialId != MATERIAL_INTERIOR) ? ((tri.materialId < int32_t(mMaterials.size() - 1)) ? tri.materialId : 0) : int32_t(mMaterials.size() - 1); + matElement->GetIndexArray().SetAt(polyCount, material); + if (smElement) + { + if (tri.userData == 0) + { + smElement->GetIndexArray().SetAt(polyCount, tri.smoothingGroup); + } + else + { + smElement->GetIndexArray().SetAt(polyCount, SMOOTHING_GROUP_INTERIOR); + } + } + + polyCount++; + cpIdx += 3; + } + + mat = meshNode->EvaluateGlobalTransform(); + cluster->SetTransformMatrix(mat); + + mat = boneNode->EvaluateGlobalTransform(); + cluster->SetTransformLinkMatrix(mat); + + uint32_t addedCps = static_cast<uint32_t>((aResult.geometryOffset[chunkIndex + 1] - aResult.geometryOffset[chunkIndex]) * 3); + + for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++) + { + addedCps += createChunkRecursive(currentCpIdx + addedCps, i, meshNode, boneNode, skin, aResult); + } + + return addedCps; +} + + +void FbxFileWriter::createChunkRecursiveNonSkinned(const std::string& meshName, uint32_t chunkIndex, FbxNode* parentNode, + const std::vector<FbxSurfaceMaterial*>& materials, const ExporterMeshData& meshData) +{ + auto chunks = NvBlastAssetGetChunks(meshData.asset, Nv::Blast::logLL); + const NvBlastChunk* chunk = &chunks[chunkIndex]; + physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]); + + std::string chunkName = FbxUtils::getChunkNodeName(chunkIndex); + + FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), (chunkName + "_mesh").c_str()); + + FbxNode* meshNode = FbxNode::Create(mScene, chunkName.c_str()); + meshNode->SetNodeAttribute(mesh); + meshNode->SetShadingMode(FbxNode::eTextureShading); + mRenderLayer->AddMember(meshNode); + + chunkNodes[chunkIndex] = meshNode; + + auto mat = parentNode->EvaluateGlobalTransform().Inverse(); + + FbxVector4 c2 = mat.MultT(FbxVector4(centroid.x, centroid.y, centroid.z, 1.0f)); + if (chunk->parentChunkIndex != UINT32_MAX) + { + //Don't mess with the root chunk pivot + meshNode->LclTranslation.Set(c2); + worldChunkPivots[chunkIndex] = centroid; + } + + parentNode->AddChild(meshNode); + FbxAMatrix finalXForm = meshNode->EvaluateGlobalTransform(); + + //Set the geo transform to inverse so we can use the world mesh coordinates + FbxAMatrix invFinalXForm = finalXForm.Inverse(); + meshNode->SetGeometricTranslation(FbxNode::eSourcePivot, invFinalXForm.GetT()); + meshNode->SetGeometricRotation(FbxNode::eSourcePivot, invFinalXForm.GetR()); + meshNode->SetGeometricScaling(FbxNode::eSourcePivot, invFinalXForm.GetS()); + + auto geNormal = mesh->CreateElementNormal(); + auto geUV = mesh->CreateElementUV("diffuseElement"); + auto matr = mesh->CreateElementMaterial(); + + uint32_t* firstIdx = meshData.submeshOffsets + chunkIndex * meshData.submeshCount; + uint32_t* lastIdx = meshData.submeshOffsets + (chunkIndex + 1) * meshData.submeshCount; + uint32_t cpCount = *lastIdx - *firstIdx; + mesh->InitControlPoints(cpCount); + + geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geNormal->SetReferenceMode(FbxGeometryElement::eDirect); + + geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geUV->SetReferenceMode(FbxGeometryElement::eDirect); + + matr->SetMappingMode(FbxGeometryElement::eByPolygon); + matr->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + for (auto m : materials) + { + meshNode->AddMaterial(m); + } + + uint32_t cPolygCount = 0; + int32_t addedVertices = 0; + + for (uint32_t subMesh = 0; subMesh < meshData.submeshCount; ++subMesh) + { + for (uint32_t tr = *(firstIdx + subMesh); tr < *(firstIdx + subMesh + 1); tr += 3) + { + mesh->BeginPolygon(subMesh); + for (uint32_t k = 0; k < 3; ++k) + { + mesh->AddPolygon(tr - *firstIdx + k); + + FbxVector4 temp; + FbxUtils::PxVec3ToFbx(meshData.positions[meshData.posIndex[tr + k]], temp); + mesh->SetControlPointAt(temp, tr - *firstIdx + k); + + FbxUtils::PxVec3ToFbx(meshData.normals[meshData.normIndex[tr + k]], temp); + geNormal->GetDirectArray().Add(temp); + + FbxVector2 temp2; + FbxUtils::PxVec2ToFbx(meshData.uvs[meshData.texIndex[tr + k]], temp2); + geUV->GetDirectArray().Add(temp2); + } + mesh->EndPolygon(); + cPolygCount++; + addedVertices += 3; + } + } + + if (!mesh->GetElementSmoothing()) + { + //If no smoothing groups, generate them + FbxGeometryConverter fbxConv(mesh->GetFbxManager()); + if (fbxConv.ComputeEdgeSmoothingFromNormals(mesh)) + { + fbxConv.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0); + } + } + + for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++) + { + createChunkRecursiveNonSkinned(meshName, i, meshNode, materials, meshData); + } +} + + +void FbxFileWriter::createChunkRecursiveNonSkinned(const std::string& meshName, uint32_t chunkIndex, FbxNode* parentNode, const std::vector<FbxSurfaceMaterial*>& materials, const AuthoringResult& aResult) +{ + auto chunks = NvBlastAssetGetChunks(aResult.asset, Nv::Blast::logLL); + const NvBlastChunk* chunk = &chunks[chunkIndex]; + physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]); + + std::string chunkName = FbxUtils::getChunkNodeName(chunkIndex).c_str(); + + FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), (chunkName + "_mesh").c_str()); + + FbxNode* meshNode = FbxNode::Create(mScene, chunkName.c_str()); + meshNode->SetNodeAttribute(mesh); + meshNode->SetShadingMode(FbxNode::eTextureShading); + mRenderLayer->AddMember(meshNode); + + chunkNodes[chunkIndex] = meshNode; + + auto mat = parentNode->EvaluateGlobalTransform().Inverse(); + + FbxVector4 c2 = mat.MultT(FbxVector4(centroid.x, centroid.y, centroid.z, 1.0f)); + + if (chunk->parentChunkIndex != UINT32_MAX) + { + //Don't mess with the root chunk pivot + meshNode->LclTranslation.Set(c2); + worldChunkPivots[chunkIndex] = centroid; + } + + parentNode->AddChild(meshNode); + FbxAMatrix finalXForm = meshNode->EvaluateGlobalTransform(); + + //Set the geo transform to inverse so we can use the world mesh coordinates + FbxAMatrix invFinalXForm = finalXForm.Inverse(); + meshNode->SetGeometricTranslation(FbxNode::eSourcePivot, invFinalXForm.GetT()); + meshNode->SetGeometricRotation(FbxNode::eSourcePivot, invFinalXForm.GetR()); + meshNode->SetGeometricScaling(FbxNode::eSourcePivot, invFinalXForm.GetS()); + + + auto geNormal = mesh->CreateElementNormal(); + auto geUV = mesh->CreateElementUV("diffuseElement"); + auto matr = mesh->CreateElementMaterial(); + + uint32_t firstIdx = aResult.geometryOffset[chunkIndex]; + uint32_t lastIdx = aResult.geometryOffset[chunkIndex + 1]; + + FbxGeometryElementSmoothing* smElement = nullptr; + for (uint32_t triangle = firstIdx; triangle < lastIdx; triangle++) + { + if (aResult.geometry[triangle].smoothingGroup >= 0) + { + //Found a valid smoothing group + smElement = mesh->CreateElementSmoothing(); + smElement->SetMappingMode(FbxGeometryElement::eByPolygon); + smElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + break; + } + } + + mesh->InitControlPoints((int)(lastIdx - firstIdx) * 3); + + geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geNormal->SetReferenceMode(FbxGeometryElement::eDirect); + + geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geUV->SetReferenceMode(FbxGeometryElement::eDirect); + + matr->SetMappingMode(FbxGeometryElement::eByPolygon); + matr->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + for (auto m : materials) + { + meshNode->AddMaterial(m); + } + + FbxGeometryElementMaterial* matElement = mesh->GetElementMaterial(); + int32_t polyCount = 0; + for (uint32_t tr = firstIdx; tr < lastIdx; tr++) + { + auto& geo = aResult.geometry[tr]; + const Nv::Blast::Vertex triVerts[3] = { geo.a, geo.b, geo.c }; + mesh->BeginPolygon(); + for (uint32_t k = 0; k < 3; ++k) + { + mesh->AddPolygon(tr * 3 + k); + FbxVector4 v, n; + FbxVector2 uv; + FbxUtils::VertexToFbx(triVerts[k], v, n, uv); + mesh->SetControlPointAt(v, tr * 3 + k); + + geNormal->GetDirectArray().Add(n); + geUV->GetDirectArray().Add(uv); + } + mesh->EndPolygon(); + int32_t material = (geo.materialId != MATERIAL_INTERIOR) ? ((geo.materialId < int32_t(mMaterials.size() - 1))? geo.materialId : 0) : int32_t(mMaterials.size() - 1); + matElement->GetIndexArray().SetAt(polyCount, material); + + if (smElement) + { + if (geo.userData == 0) + { + smElement->GetIndexArray().SetAt(polyCount, geo.smoothingGroup); + } + else + { + smElement->GetIndexArray().SetAt(polyCount, SMOOTHING_GROUP_INTERIOR); + } + } + + polyCount++; + + } + + if (!smElement) + { + //If no smoothing groups, generate them + FbxGeometryConverter fbxConv(mesh->GetFbxManager()); + if (fbxConv.ComputeEdgeSmoothingFromNormals(mesh)) + { + fbxConv.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0); + } + } + + for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++) + { + createChunkRecursiveNonSkinned(meshName, i, meshNode, materials, aResult); + } +} + +uint32_t FbxFileWriter::addCollisionHulls(uint32_t chunkIndex, FbxDisplayLayer* displayLayer, FbxNode* parentNode, uint32_t hullsCount, CollisionHull** hulls) +{ + for (uint32_t hullId = 0; hullId < hullsCount; ++hullId) + { + std::stringstream namestream; + namestream.clear(); + namestream << "collisionHull_" << chunkIndex << "_" << hullId; + + FbxNode* collisionNode = FbxNode::Create(sdkManager.get(), namestream.str().c_str()); + + displayLayer->AddMember(collisionNode); + + //TODO: Remove this when tools are converted over + FbxProperty::Create(collisionNode, FbxIntDT, "ParentalChunkIndex"); + collisionNode->FindProperty("ParentalChunkIndex").Set(chunkIndex); + // + + namestream.clear(); + namestream << "collisionHullGeom_" << chunkIndex << "_" << hullId; + FbxMesh* meshAttr = FbxMesh::Create(sdkManager.get(), namestream.str().c_str()); + collisionNode->SetNodeAttribute(meshAttr); + parentNode->AddChild(collisionNode); + + auto mat = parentNode->EvaluateGlobalTransform().Inverse(); + auto centroid = worldChunkPivots.find(chunkIndex); + + if (centroid != worldChunkPivots.end()) + { + FbxVector4 c2 = mat.MultT(FbxVector4(centroid->second.x, centroid->second.y, centroid->second.z, 1.0f)); + //Don't mess with the root chunk pivot + collisionNode->LclTranslation.Set(c2); + } + parentNode->AddChild(collisionNode); + FbxAMatrix finalXForm = collisionNode->EvaluateGlobalTransform(); + + //Set the geo transform to inverse so we can use the world mesh coordinates + FbxAMatrix invFinalXForm = finalXForm.Inverse(); + collisionNode->SetGeometricTranslation(FbxNode::eSourcePivot, invFinalXForm.GetT()); + collisionNode->SetGeometricRotation(FbxNode::eSourcePivot, invFinalXForm.GetR()); + collisionNode->SetGeometricScaling(FbxNode::eSourcePivot, invFinalXForm.GetS()); + + + meshAttr->InitControlPoints(hulls[hullId]->pointsCount); + meshAttr->CreateElementNormal(); + FbxVector4* controlPoints = meshAttr->GetControlPoints(); + auto geNormal = meshAttr->GetElementNormal(); + geNormal->SetMappingMode(FbxGeometryElement::eByPolygon); + geNormal->SetReferenceMode(FbxGeometryElement::eDirect); + for (uint32_t i = 0; i < hulls[hullId]->pointsCount; ++i) + { + auto& pnts = hulls[hullId]->points[i]; + controlPoints->Set(pnts.x, pnts.y, pnts.z, 0.0); + controlPoints++; + } + + for (uint32_t i = 0; i < hulls[hullId]->polygonDataCount; ++i) + { + auto& poly = hulls[hullId]->polygonData[i]; + meshAttr->BeginPolygon(); + for (uint32_t j = 0; j < poly.mNbVerts; ++j) + { + meshAttr->AddPolygon(hulls[hullId]->indices[poly.mIndexBase + j]); + } + meshAttr->EndPolygon(); + FbxVector4 plane(poly.mPlane[0], poly.mPlane[1], poly.mPlane[2], 0); + geNormal->GetDirectArray().Add(plane); + } + } + return 1; +} + +uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const ExporterMeshData& meshData) +{ + auto chunks = NvBlastAssetGetChunks(meshData.asset, Nv::Blast::logLL); + const NvBlastChunk* chunk = &chunks[chunkIndex]; + physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]); + + std::string boneName = FbxUtils::getChunkNodeName(chunkIndex).c_str(); + + FbxSkeleton* skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str()); + if (chunk->parentChunkIndex == UINT32_MAX) + { + skelAttrib->SetSkeletonType(FbxSkeleton::eRoot); + + // Change the centroid to origin + centroid = physx::PxVec3(0.0f); + } + else + { + skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode); + worldChunkPivots[chunkIndex] = centroid; + } + + FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str()); + boneNode->SetNodeAttribute(skelAttrib); + + chunkNodes[chunkIndex] = boneNode; + + auto mat = parentNode->EvaluateGlobalTransform().Inverse(); + + FbxVector4 vec(0, 0, 0, 0); + FbxVector4 c2 = mat.MultT(vec); + + boneNode->LclTranslation.Set(c2); + + parentNode->AddChild(boneNode); + + std::ostringstream namestream; + namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex; + std::string clusterName = namestream.str(); + + FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str()); + cluster->SetTransformMatrix(FbxAMatrix()); + cluster->SetLink(boneNode); + cluster->SetLinkMode(FbxCluster::eTotalOne); + + skin->AddCluster(cluster); + + FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute()); + + auto geNormal = mesh->GetElementNormal(); + auto geUV = mesh->GetElementUV("diffuseElement"); + auto matr = mesh->GetElementMaterial(); + + std::vector<bool> addedVerticesFlag(mesh->GetControlPointsCount(), false); + + uint32_t* firstIdx = meshData.submeshOffsets + chunkIndex * meshData.submeshCount; + uint32_t cPolygCount = mesh->GetPolygonCount(); + int32_t addedVertices = 0; + for (uint32_t subMesh = 0; subMesh < meshData.submeshCount; ++subMesh) + { + for (uint32_t tr = *(firstIdx + subMesh); tr < *(firstIdx + subMesh + 1); tr += 3) + { + mesh->BeginPolygon(subMesh); + mesh->AddPolygon(meshData.posIndex[tr + 0]); + mesh->AddPolygon(meshData.posIndex[tr + 1]); + mesh->AddPolygon(meshData.posIndex[tr + 2]); + mesh->EndPolygon(); + for (uint32_t k = 0; k < 3; ++k) + { + geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices + k, meshData.normIndex[tr + k]); + geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices + k, meshData.texIndex[tr + k]); + } + if (subMesh == 0) + { + matr->GetIndexArray().SetAt(cPolygCount, 0); + } + else + { + matr->GetIndexArray().SetAt(cPolygCount, 1); + } + cPolygCount++; + addedVertices += 3; + for (uint32_t k = 0; k < 3; ++k) + { + if (!addedVerticesFlag[meshData.posIndex[tr + k]]) + { + cluster->AddControlPointIndex(meshData.posIndex[tr + k], 1.0); + addedVerticesFlag[meshData.posIndex[tr + k]] = true; + } + } + } + } + mat = meshNode->EvaluateGlobalTransform(); + cluster->SetTransformMatrix(mat); + + mat = boneNode->EvaluateGlobalTransform(); + cluster->SetTransformLinkMatrix(mat); + + + for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++) + { + addedVertices += createChunkRecursive(currentCpIdx + addedVertices, i, meshNode, boneNode, skin, meshData); + } + + return addedVertices; + +} + +void FbxFileWriter::addControlPoints(FbxMesh* mesh, const ExporterMeshData& meshData) +{ + std::vector<uint32_t> vertices; + std::cout << "Adding control points" << std::endl; + std::vector<int32_t> mapping(meshData.positionsCount, -1); + for (uint32_t ch = 0; ch < meshData.meshCount; ++ch) + { + mapping.assign(meshData.positionsCount, -1); + for (uint32_t sb = 0; sb < meshData.submeshCount; ++sb) + { + uint32_t* first = meshData.submeshOffsets + ch * meshData.submeshCount + sb; + for (uint32_t pi = *first; pi < *(first+1); ++pi) + { + uint32_t p = meshData.posIndex[pi]; + if (mapping[p] == -1) + { + mapping[p] = (int)vertices.size(); + vertices.push_back(p); + meshData.posIndex[pi] = mapping[p]; + } + else + { + meshData.posIndex[pi] = mapping[p]; + } + } + } + } + mesh->InitControlPoints((int)vertices.size()); + FbxVector4* controlPoints = mesh->GetControlPoints(); + for (auto v : vertices) + { + auto& p = meshData.positions[v]; + *controlPoints = FbxVector4(p.x, p.y, p.z, 0); + ++controlPoints; + } + std::cout << "Adding control points: done" << std::endl; +} + +void FbxFileWriter::addBindPose() +{ + // Store the bind pose + //Just add all the nodes, it doesn't seem to do any harm and it stops Maya complaining about incomplete bind poses + FbxPose* pose = FbxPose::Create(sdkManager.get(), "BindPose"); + pose->SetIsBindPose(true); + + int nodeCount = mScene->GetNodeCount(); + for (int i = 0; i < nodeCount; i++) + { + FbxNode* node = mScene->GetNode(i); + FbxMatrix bindMat = node->EvaluateGlobalTransform(); + + pose->Add(node, bindMat); + } + + mScene->AddPose(pose); +} + +bool FbxFileWriter::saveToFile(const char* assetName, const char* outputPath) +{ + + addBindPose(); + + FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT); + // Set some properties on the io settings + + sdkManager->SetIOSettings(ios); + + sdkManager->GetIOSettings()->SetBoolProp(EXP_ASCIIFBX, bOutputFBXAscii); + + + FbxExporter* exporter = FbxExporter::Create(sdkManager.get(), "Scene Exporter"); + exporter->SetFileExportVersion(FBX_2012_00_COMPATIBLE); + + int lFormat; + + if (bOutputFBXAscii) + { + lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)"); + } + else + { + lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX binary (*.fbx)"); + } + + auto path = std::string(outputPath) + "\\" + assetName + ".fbx"; + bool exportStatus = exporter->Initialize(path.c_str(), lFormat, sdkManager->GetIOSettings()); + + if (!exportStatus) + { + std::cerr << "Call to FbxExporter::Initialize failed" << std::endl; + std::cerr << "Error returned: " << exporter->GetStatus().GetErrorString() << std::endl; + return false; + } + + exportStatus = exporter->Export(mScene); + + if (!exportStatus) + { + auto fbxStatus = exporter->GetStatus(); + + std::cerr << "Call to FbxExporter::Export failed" << std::endl; + std::cerr << "Error returned: " << fbxStatus.GetErrorString() << std::endl; + return false; + } + return true; +} + + + +bool FbxFileWriter::appendMesh(const ExporterMeshData& meshData, const char* assetName, bool nonSkinned) +{ + createMaterials(meshData); + + if (nonSkinned) + { + return appendNonSkinnedMesh(meshData, assetName); + } + + /** + Get polygon count + */ + uint32_t polygCount = meshData.submeshOffsets[meshData.meshCount * meshData.submeshCount] / 3; + + FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), "meshgeo"); + + FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal(); + geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geNormal->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement"); + geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex); + geUV->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + + FbxNode* meshNode = FbxNode::Create(mScene, "meshnode"); + meshNode->SetNodeAttribute(mesh); + meshNode->SetShadingMode(FbxNode::eTextureShading); + + FbxNode* lRootNode = mScene->GetRootNode(); + + mRenderLayer->AddMember(meshNode); + + for (uint32_t i = 0; i < mMaterials.size(); ++i) + { + meshNode->AddMaterial(mMaterials[i]); + } + + FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing"); + skin->SetGeometry(mesh); + + mesh->AddDeformer(skin); + + /** + Create control points, copy data to buffers + */ + addControlPoints(mesh, meshData); + + auto normalsElem = mesh->GetElementNormal(); + for (uint32_t i = 0; i < meshData.normalsCount; ++i) + { + auto& n = meshData.normals[i]; + normalsElem->GetDirectArray().Add(FbxVector4(n.x, n.y, n.z, 0)); + } + auto uvsElem = mesh->GetElementUV("diffuseElement"); + for (uint32_t i = 0; i < meshData.uvsCount; ++i) + { + auto& uvs = meshData.uvs[i]; + uvsElem->GetDirectArray().Add(FbxVector2(uvs.x, uvs.y)); + } + + FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial(); + matElement->SetMappingMode(FbxGeometryElement::eByPolygon); + matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); + + + matElement->GetIndexArray().SetCount(polygCount); + normalsElem->GetIndexArray().SetCount(polygCount * 3); + uvsElem->GetIndexArray().SetCount(polygCount * 3); + + + std::cout << "Create chunks recursive" << std::endl; + + //In order for Maya to correctly convert the axis of a skinned model there must be a common root node between the skeleton and the model + FbxNode* sceneRootNode = FbxNode::Create(sdkManager.get(), "sceneRoot"); + lRootNode->AddChild(sceneRootNode); + sceneRootNode->AddChild(meshNode); + + //UE4 cannot hide the root bone, so add a dummy chunk so chunk0 is not the root + FbxNode* skelRootNode = FbxNode::Create(sdkManager.get(), "root"); + FbxSkeleton* skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib"); + skelAttrib->SetSkeletonType(FbxSkeleton::eRoot); + skelRootNode->SetNodeAttribute(skelAttrib); + + sceneRootNode->AddChild(skelRootNode); + + // Now walk the tree and create a skeleton with geometry at the same time + // Find a "root" chunk and walk the tree from there. + uint32_t chunkCount = NvBlastAssetGetChunkCount(meshData.asset, Nv::Blast::logLL); + auto chunks = NvBlastAssetGetChunks(meshData.asset, Nv::Blast::logLL); + uint32_t cpIdx = 0; + for (uint32_t i = 0; i < chunkCount; i++) + { + const NvBlastChunk* chunk = &chunks[i]; + + if (chunk->parentChunkIndex == UINT32_MAX) + { + uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, skelRootNode, skin, meshData); + cpIdx += addedCps; + } + } + + if (!mesh->GetElementSmoothing()) + { + //If no smoothing groups, generate them + FbxGeometryConverter fbxConv(mesh->GetFbxManager()); + if (fbxConv.ComputeEdgeSmoothingFromNormals(mesh)) + { + fbxConv.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0); + } + } + + if (meshData.hulls != nullptr) + { + return appendCollisionMesh(chunkCount, meshData.hullsOffsets, meshData.hulls, assetName); + } + return true; +} + diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.h b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.h new file mode 100644 index 0000000..985b32c --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.h @@ -0,0 +1,134 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTERFBXWRITER_H +#define NVBLASTEXTEXPORTERFBXWRITER_H + +#include "NvBlastExtExporter.h" +#include <memory> +#include <vector> +#include <map> + +namespace fbxsdk +{ + class FbxScene; + class FbxNode; + class FbxMesh; + class FbxSkin; + class FbxManager; + class FbxSurfaceMaterial; + class FbxDisplayLayer; +} + +struct NvBlastAsset; + +namespace Nv +{ +namespace Blast +{ +class Mesh; +struct Triangle; +struct CollisionHull; + +class FbxFileWriter : public IMeshFileWriter +{ +public: + + /** + Initialize FBX sdk and create scene. + */ + FbxFileWriter(); + //~FbxFileWriter() = default; + + virtual void release() override; + + /** + Get current scene; + */ + fbxsdk::FbxScene* getScene(); + + /** + Append rendermesh to scene. Meshes constructed from arrays of triangles. + */ + virtual bool appendMesh(const AuthoringResult& aResult, const char* assetName, bool nonSkinned) override; + + /** + Append rendermesh to scene. Meshes constructed from arrays of vertex data (position, normal, uvs) and indices. + Position, normal and uv has separate index arrays. + */ + virtual bool appendMesh(const ExporterMeshData& meshData, const char* assetName, bool nonSkinned) override; + + /** + Save scene to file. + */ + virtual bool saveToFile(const char* assetName, const char* outputPath) override; + + /** + Set true if FBX should be saved in ASCII mode. + */ + bool bOutputFBXAscii; + +private: + std::vector<fbxsdk::FbxSurfaceMaterial*> mMaterials; + fbxsdk::FbxScene* mScene; + fbxsdk::FbxDisplayLayer* mRenderLayer; + + //TODO we should track for every memory allocation and deallocate it not only for sdkManager + std::shared_ptr<fbxsdk::FbxManager> sdkManager; + std::map<uint32_t, fbxsdk::FbxNode*> chunkNodes; + std::map<uint32_t, physx::PxVec3> worldChunkPivots; + + bool appendNonSkinnedMesh(const AuthoringResult& aResult, const char* assetName); + bool appendNonSkinnedMesh(const ExporterMeshData& meshData, const char* assetName); + void createMaterials(const ExporterMeshData& meshData); + void createMaterials(const AuthoringResult& aResult); + + /** + Append collision geometry to scene. Each node with collision geometry has "ParentalChunkIndex" property, which contain index of chunk + which this collision geometry belongs to. + */ + bool appendCollisionMesh(uint32_t meshCount, uint32_t* offsets, CollisionHull** hulls, const char* assetName); + + uint32_t addCollisionHulls(uint32_t chunkIndex, fbxsdk::FbxDisplayLayer* displayLayer, fbxsdk::FbxNode* parentNode, uint32_t hullsCount, CollisionHull** hulls); + uint32_t createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, fbxsdk::FbxNode *meshNode, fbxsdk::FbxNode* parentNode, fbxsdk::FbxSkin* skin, const AuthoringResult& aResult); + uint32_t createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, fbxsdk::FbxNode *meshNode, fbxsdk::FbxNode* parentNode, fbxsdk::FbxSkin* skin, const ExporterMeshData& meshData); + + void createChunkRecursiveNonSkinned(const std::string& meshName, uint32_t chunkIndex, fbxsdk::FbxNode* parentNode, + const std::vector<fbxsdk::FbxSurfaceMaterial*>& materials, const AuthoringResult& aResult); + + void createChunkRecursiveNonSkinned(const std::string& meshName, uint32_t chunkIndex, fbxsdk::FbxNode* parentNode, + const std::vector<fbxsdk::FbxSurfaceMaterial*>& materials, const ExporterMeshData& meshData); + + void addControlPoints(fbxsdk::FbxMesh* mesh, const ExporterMeshData& meshData); + void addBindPose(); +}; + +} +} + +#endif // NVBLASTEXTEXPORTERFBXWRITER_H
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterJsonCollision.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterJsonCollision.cpp new file mode 100644 index 0000000..c19c931 --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterJsonCollision.cpp @@ -0,0 +1,107 @@ +// 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 "NvBlastExtExporterJsonCollision.h" +#include "NvBlastExtAuthoringTypes.h" +#include <PxVec3.h> +#include <iostream> +#include <sstream> +#include <fstream> +#include <iomanip> + +#define JS_NAME(name) "\"" << name << "\": " + +using namespace Nv::Blast; + + +void serializaHullPolygon(std::ofstream& stream, const CollisionHull::HullPolygon& p, uint32_t indent) +{ + std::string sindent(indent, '\t'); + std::string bindent(indent + 1, '\t'); + stream << sindent << "{\n" << + bindent << JS_NAME("mIndexBase") << p.mIndexBase << ",\n" << + bindent << JS_NAME("mPlane") << "[" << p.mPlane[0] << ", " << p.mPlane[1] << ", " << p.mPlane[2] << ", " << p.mPlane[3] << "],\n" << + bindent << JS_NAME("mNbVerts") << p.mNbVerts << "\n" << + sindent << "}"; +} +void serializeCollisionHull(std::ofstream& stream, const CollisionHull& hl, uint32_t indent) +{ + std::string sindent(indent, '\t'); + std::string bindent(indent + 1, '\t'); + + stream << sindent << "{\n" << bindent << JS_NAME("indices") << "["; + for (uint32_t i = 0; i < hl.indicesCount; ++i) + { + stream << hl.indices[i]; + if (i < hl.indicesCount - 1) stream << ", "; + } + stream << "],\n"; + stream << bindent << JS_NAME("points") << "["; + for (uint32_t i = 0; i < hl.pointsCount; ++i) + { + auto& p = hl.points[i]; + stream << p.x << ", " << p.y << ", " << p.z; + if (i < hl.pointsCount - 1) stream << ", "; + } + stream << "],\n"; + stream << bindent << JS_NAME("polygonData") << "[\n"; + for (uint32_t i = 0; i < hl.polygonDataCount; ++i) + { + serializaHullPolygon(stream, hl.polygonData[i], indent + 1); + if (i < hl.polygonDataCount - 1) stream << ", "; + stream << "\n"; + } + stream << bindent << "]\n"; + stream << sindent << "}"; +} + +bool JsonCollisionExporter::writeCollision(const char* path, uint32_t meshCount, const uint32_t* meshOffsets, const CollisionHull* hulls) +{ + std::ofstream stream(path, std::ios::out); + stream << std::fixed << std::setprecision(8); + if (!stream.is_open()) + { + std::cout << "Can't open output stream" << std::endl; + return false; + } + + stream << "{\n" << "\t" << JS_NAME("CollisionData") << "[\n"; + for (uint32_t i = 0; i < meshCount; ++i) + { + stream << "\t\t" << "[\n"; + for (uint32_t j = meshOffsets[i]; j < meshOffsets[i + 1]; ++j) + { + serializeCollisionHull(stream, hulls[j], 3); + stream << ((j < meshOffsets[i + 1] - 1) ? ",\n" : "\n"); + } + stream << "\t\t" << ((i < meshCount - 1) ? "], \n" : "]\n"); + } + stream << "\t]\n}"; + stream.close(); + return true; +}; diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp new file mode 100644 index 0000000..95efb3e --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp @@ -0,0 +1,130 @@ +// 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 "NvBlastExtExporterObjReader.h" + +#pragma warning(push) +#pragma warning(disable:4706) +#pragma warning(disable:4702) +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" +#pragma warning(pop) + + +#include <iostream> +#include "PxVec3.h" +#include "PxVec2.h" +#include "NvBlastExtAuthoringMesh.h" + +using physx::PxVec3; +using physx::PxVec2; +using namespace Nv::Blast; + +ObjFileReader::ObjFileReader() +{ +} + +void ObjFileReader::release() +{ + delete this; +} + +void ObjFileReader::loadFromFile(const char* filename) +{ + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> mats; + std::string err; + std::string mtlPath; + bool ret = tinyobj::LoadObj(shapes, mats, err, filename); + // can't load? + if (!ret) + { + return; + } + if (shapes.size() > 1) + { + std::cout << "Can load only one object per mesh" << std::endl; + } + + mVertexPositions.clear(); + mVertexNormals.clear(); + mVertexUv.clear(); + mIndices.clear(); + + auto& psVec = shapes[0].mesh.positions; + for (uint32_t i = 0; i < psVec.size() / 3; ++i) + { + mVertexPositions.push_back(PxVec3(psVec[i * 3], psVec[i * 3 + 1], psVec[i * 3 + 2])); + } + auto& nmVec = shapes[0].mesh.normals; + for (uint32_t i = 0; i < nmVec.size() / 3; ++i) + { + mVertexNormals.push_back(PxVec3(nmVec[i * 3], nmVec[i * 3 + 1], nmVec[i * 3 + 2])); + } + auto& txVec = shapes[0].mesh.texcoords; + for (uint32_t i = 0; i < txVec.size() / 2; ++i) + { + mVertexUv.push_back(PxVec2(txVec[i * 2], txVec[i * 2 + 1])); + } + + mIndices = shapes[0].mesh.indices; + +} + + +bool ObjFileReader::isCollisionLoaded() +{ + return false; +}; + + +uint32_t ObjFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) +{ + NV_UNUSED(hulls); + return false; +}; + +physx::PxVec3* ObjFileReader::getPositionArray() +{ + return mVertexPositions.data(); +}; + +physx::PxVec3* ObjFileReader::getNormalsArray() +{ + return mVertexNormals.data(); +}; + +physx::PxVec2* ObjFileReader::getUvArray() +{ + return mVertexUv.data(); +}; + +uint32_t* ObjFileReader::getIndexArray() +{ + return mIndices.data(); +};
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h new file mode 100644 index 0000000..f80f8f9 --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h @@ -0,0 +1,122 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTEROBJREADER_H +#define NVBLASTEXTEXPORTEROBJREADER_H +#include <memory> +#include <string> +#include <vector> +#include "NvBlastExtExporter.h" + +namespace Nv +{ +namespace Blast +{ +class Mesh; + +class ObjFileReader : public IMeshFileReader +{ +public: + ObjFileReader(); + ~ObjFileReader() = default; + + virtual void release() override; + + /* + Load from the specified file path, returning a mesh or nullptr if failed + */ + virtual void loadFromFile(const char* filename) override; + + virtual uint32_t getVerticesCount() const override + { + return mVertexPositions.size(); + } + + virtual uint32_t getIdicesCount() const override + { + return mIndices.size(); + } + + /** + Check whether file contained an collision geometry + */ + virtual bool isCollisionLoaded() override; + + /** + Retrieve collision geometry if it exist + */ + virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) override; + + /** + Get loaded vertex positions + */ + virtual physx::PxVec3* getPositionArray() override; + /** + Get loaded vertex normals + */ + virtual physx::PxVec3* getNormalsArray() override; + /** + Get loaded vertex uv-coordinates + */ + virtual physx::PxVec2* getUvArray() override; + /** + Get loaded triangle indices + */ + virtual uint32_t* getIndexArray() override; + + /** + Get loaded per triangle material ids. Currently not supported by OBJ. + */ + int32_t* getMaterialIds() override { return nullptr; }; + + /** + Get loaded per triangle smoothing groups. Currently not supported by OBJ. + */ + int32_t* getSmoothingGroups() override { return nullptr; }; + + /** + Get material name. Currently not supported by OBJ. + */ + char* getMaterialName(int32_t id) override { return nullptr; } + + /** + Get material count. + */ + int32_t getMaterialCount() { return 0; }; + +private: + std::vector<physx::PxVec3> mVertexPositions; + std::vector<physx::PxVec3> mVertexNormals; + std::vector<physx::PxVec2> mVertexUv; + std::vector<uint32_t> mIndices; +}; + +} +} + +#endif // NVBLASTEXTEXPORTEROBJREADER_H
\ No newline at end of file diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.cpp new file mode 100644 index 0000000..a49e28f --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.cpp @@ -0,0 +1,188 @@ +// 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 "NvBlastExtExporterObjWriter.h" +#include <PxVec3.h> +#include <sstream> +#include "NvBlastExtAuthoringTypes.h" +#include "NvBlastExtAuthoringMesh.h" + + +using namespace physx; +using namespace Nv::Blast; + +char* gTexPath = ""; + +void ObjFileWriter::release() +{ + delete this; +} + +bool ObjFileWriter::appendMesh(const AuthoringResult& aResult, const char* /*assetName*/, bool /*nonSkinned*/) +{ + mMeshData = std::shared_ptr<ExporterMeshData>(new ExporterMeshData(), [](ExporterMeshData* md) + { + //delete[] md->hulls; + //delete[] md->hullsOffsets; + delete[] md->normals; + //delete[] md->normIndex; + delete[] md->posIndex; + delete[] md->positions; + delete[] md->submeshOffsets; + //delete[] md->texIndex; + delete[] md->submeshNames; + delete[] md->uvs; + delete md; + }); + ExporterMeshData& md = *mMeshData.get(); + uint32_t triCount = aResult.geometryOffset[aResult.chunkCount]; + md.meshCount = aResult.chunkCount; + md.submeshOffsets = new uint32_t[md.meshCount + 1]; + for (uint32_t i = 0; i < md.meshCount + 1; i++) + { + md.submeshOffsets[i] = aResult.geometryOffset[i] * 3; + } + //md.submeshOffsets = md.meshOffsets; + md.submeshCount = 1; + //md.indicesCount = triCount * 3; + md.positionsCount = triCount * 3; + md.normalsCount = md.positionsCount; + md.uvsCount = md.positionsCount; + md.positions = new PxVec3[md.positionsCount]; + md.normals = new PxVec3[md.normalsCount]; + md.uvs = new PxVec2[md.uvsCount]; + md.posIndex = new uint32_t[triCount * 3]; + md.normIndex = md.posIndex; + md.texIndex = md.posIndex; + md.submeshNames = new const char*[1]{ gTexPath }; + for (uint32_t vc = 0; vc < triCount; ++vc) + { + Triangle& tri = aResult.geometry[vc]; + uint32_t i = vc * 3; + md.positions[i+0] = tri.a.p; + md.positions[i+1] = tri.b.p; + md.positions[i+2] = tri.c.p; + + md.normals[i+0] = tri.a.n; + md.normals[i+1] = tri.b.n; + md.normals[i+2] = tri.c.n; + + md.uvs[i+0] = tri.a.uv[0]; + md.uvs[i+1] = tri.b.uv[0]; + md.uvs[i+2] = tri.c.uv[0]; + + md.posIndex[i + 0] = i + 0; + md.posIndex[i + 1] = i + 1; + md.posIndex[i + 2] = i + 2; + } + return true; +} + +bool ObjFileWriter::appendMesh(const ExporterMeshData& meshData, const char* /*assetName*/, bool /*nonSkinned*/) +{ + mMeshData = std::shared_ptr<ExporterMeshData>(new ExporterMeshData(meshData)); + return true; +} + +bool ObjFileWriter::saveToFile(const char* assetName, const char* outputPath) +{ + if (mMeshData.get() == nullptr) + { + return false; + } + const ExporterMeshData& md = *mMeshData.get(); + + uint32_t chunkCount = md.meshCount; + + // export materials (mtl file) + { + std::ostringstream mtlFilePath; + mtlFilePath << outputPath << "\\" << assetName << ".mtl"; + FILE* f = fopen(mtlFilePath.str().c_str(), "w"); + if (!f) + return false; + + for (uint32_t submeshIndex = 0; submeshIndex < md.submeshCount; ++submeshIndex) + { + fprintf(f, "newmtl mat%d\n", submeshIndex); + fprintf(f, "\tmap_Kd %s\n", md.submeshNames[submeshIndex]); + fprintf(f, "\n"); + } + + fclose(f); + } + + /// Export geometry to *.obj file + { + std::ostringstream objFilePath; + objFilePath << outputPath << "\\" << assetName << ".obj"; + FILE* f = fopen(objFilePath.str().c_str(), "w"); + if (!f) + return false; + + fprintf(f, "mtllib %s.mtl\n", assetName); + fprintf(f, "o frac \n"); + + + /// Write compressed vertices + for (uint32_t i = 0; i < md.positionsCount; ++i) + { + fprintf(f, "v %.4f %.4f %.4f\n", md.positions[i].x, md.positions[i].y, md.positions[i].z); + } + for (uint32_t i = 0; i < md.normalsCount; ++i) + { + fprintf(f, "vn %.4f %.4f %.4f\n", md.normals[i].x, md.normals[i].y, md.normals[i].z); + } + for (uint32_t i = 0; i < md.uvsCount; ++i) + { + fprintf(f, "vt %.4f %.4f\n", md.uvs[i].x, md.uvs[i].y); + } + + for (uint32_t chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) + { + for (uint32_t submeshIndex = 0; submeshIndex < md.submeshCount; ++submeshIndex) + { + uint32_t firstIdx = md.submeshOffsets[chunkIndex * md.submeshCount + submeshIndex]; + uint32_t lastIdx = md.submeshOffsets[chunkIndex * md.submeshCount + submeshIndex + 1]; + fprintf(f, "g %d_%d \n", chunkIndex, submeshIndex); + fprintf(f, "usemtl mat%d\n", submeshIndex); + + for (uint32_t i = firstIdx; i < lastIdx; i += 3) + { + fprintf(f, "f %d/%d/%d ", md.posIndex[i] + 1, md.texIndex[i] + 1, md.normIndex[i] + 1); + fprintf(f, "%d/%d/%d ", md.posIndex[i + 1] + 1, md.texIndex[i + 1] + 1, md.normIndex[i + 1] + 1); + fprintf(f, "%d/%d/%d \n", md.posIndex[i + 2] + 1, md.texIndex[i + 2] + 1, md.normIndex[i + 2] + 1); + } + } + } + fclose(f); + } + return true; + +} + diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.h b/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.h new file mode 100644 index 0000000..3152d42 --- /dev/null +++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjWriter.h @@ -0,0 +1,73 @@ +// 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. + + +#ifndef NVBLASTEXTEXPORTEROBJWRITER_H +#define NVBLASTEXTEXPORTEROBJWRITER_H + +#include "NvBlastExtExporter.h" +#include <memory> +#include <vector> +#include <PxVec2.h> +#include <PxVec3.h> + +struct NvBlastAsset; + +namespace Nv +{ +namespace Blast +{ + +class ObjFileWriter : public IMeshFileWriter +{ +public: + + ObjFileWriter() {}; + ~ObjFileWriter() = default; + + virtual void release() override; + + virtual bool appendMesh(const AuthoringResult& aResult, const char* assetName, bool nonSkinned) override; + + /** + Append rendermesh to scene. Meshes constructed from arrays of vertices and indices + */ + virtual bool appendMesh(const ExporterMeshData& meshData, const char* assetName, bool nonSkinned) override; + + /** + Save scene to file. + */ + virtual bool saveToFile(const char* assetName, const char* outputPath) override; + +private: + std::shared_ptr<ExporterMeshData> mMeshData; +}; + +} +} + +#endif // NVBLASTEXTEXPORTEROBJWRITER_H
\ No newline at end of file diff --git a/sdk/extensions/import/include/NvBlastExtApexImportTool.h b/sdk/extensions/import/include/NvBlastExtApexImportTool.h index bbfcfce..788ec40 100644 --- a/sdk/extensions/import/include/NvBlastExtApexImportTool.h +++ b/sdk/extensions/import/include/NvBlastExtApexImportTool.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAPEXIMPORTTOOL_H #define NVBLASTEXTAPEXIMPORTTOOL_H @@ -18,8 +36,6 @@ namespace physx { -class PxErrorCallback; -class PxAllocatorCallback; namespace general_PxIOStream2 { class PxFileBuf; @@ -87,9 +103,8 @@ public: /** Constructor should be provided with user defined allocator and massage function: - \param[in] logFn User - supplied message function(see NvBlastLog definition).May be NULL. */ - ApexImportTool(NvBlastLog logFn = NULL); + ApexImportTool(); ~ApexImportTool(); ////////////////////////////////////////////////////////////////////////////// @@ -168,11 +183,12 @@ public: \param[in] apexChunkFlags Chunk flags array \param[out] physicsChunks Chunk physics info output array \param[out] physicsSubchunks Chunk collision geometry and transformation data output array + \param[out] hullsDescs Chunk collision geometry descriptors, can be used to save to some third party format \return If true - success, output arrays are filled. */ bool getCollisionGeometry(const nvidia::apex::DestructibleAsset* apexAsset, uint32_t chunkCount, std::vector<uint32_t>& chunkReorderInvMap, const std::vector<uint32_t>& apexChunkFlags, std::vector<ExtPxAssetDesc::ChunkDesc>& physicsChunks, - std::vector<ExtPxAssetDesc::SubchunkDesc>& physicsSubchunks); + std::vector<ExtPxAssetDesc::SubchunkDesc>& physicsSubchunks, std::vector<std::vector<CollisionHull*> >& hullsDesc); ApexDestruction* m_apexDestruction; ////////////////////////////////////////////////////////////////////////////// @@ -184,9 +200,6 @@ private: protected: - NvBlastLog m_log; - -protected: ApexImportTool(const ApexImportTool&); ApexImportTool& operator=(const ApexImportTool&); }; diff --git a/sdk/extensions/import/source/NvBlastExtApexDestruction.cpp b/sdk/extensions/import/source/NvBlastExtApexDestruction.cpp index 889a8c8..3f8451e 100644 --- a/sdk/extensions/import/source/NvBlastExtApexDestruction.cpp +++ b/sdk/extensions/import/source/NvBlastExtApexDestruction.cpp @@ -1,18 +1,37 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtApexDestruction.h" #include "PxPhysicsAPI.h" #include "Apex.h" +#include "NvBlastPxCallbacks.h" #include <ModuleDestructible.h> #include <DestructibleAsset.h> #include "NullRenderer.h" @@ -23,8 +42,6 @@ using namespace apex; ////////////////////////////////////////////////////////////////////////////// -PxDefaultAllocator gPxAllocator; -PxDefaultErrorCallback gErrorCallback; NullRenderResourceManager gNullRenderer; ///////////////////////////////////////////////////////////////////////////// @@ -74,7 +91,7 @@ bool ApexDestruction::initialize() ////////////////////////////////////////////////////////////////////////////// - m_Foundation.reset(PxCreateFoundation(PX_FOUNDATION_VERSION, gPxAllocator, gErrorCallback)); + m_Foundation.reset(PxCreateFoundation(PX_FOUNDATION_VERSION, NvBlastGetPxAllocatorCallback(), NvBlastGetPxErrorCallback())); if (!m_Foundation) { if (m_log) diff --git a/sdk/extensions/import/source/NvBlastExtApexDestruction.h b/sdk/extensions/import/source/NvBlastExtApexDestruction.h index 6560aed..3a3b313 100644 --- a/sdk/extensions/import/source/NvBlastExtApexDestruction.h +++ b/sdk/extensions/import/source/NvBlastExtApexDestruction.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTAPEXDESTRUCTION_H #define NVBLASTEXTAPEXDESTRUCTION_H diff --git a/sdk/extensions/import/source/NvBlastExtApexImportTool.cpp b/sdk/extensions/import/source/NvBlastExtApexImportTool.cpp index d2def6f..e0fe7bd 100644 --- a/sdk/extensions/import/source/NvBlastExtApexImportTool.cpp +++ b/sdk/extensions/import/source/NvBlastExtApexImportTool.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtApexImportTool.h" @@ -16,19 +34,21 @@ #endif #include "PxFoundation.h" -#include "PxErrorCallback.h" -#include "PxAllocatorCallback.h" #include "NvBlastIndexFns.h" +#include "NvBlastGlobals.h" #include "DestructibleAsset.h" #include "NvBlastExtApexDestruction.h" #include <PxConvexMesh.h> #include "PxPhysics.h" #include "NvBlastExtAuthoringCollisionBuilder.h" #include "NvBlastExtPxAsset.h" -#include "NvBlastExtAuthoringTypes.h" +#include "NvBlastExtAuthoring.h" #include "NvBlastExtAuthoringBondGenerator.h" +#include <algorithm> +#include <memory> + using namespace nvidia; using namespace apex; @@ -59,8 +79,8 @@ namespace ApexImporter } }; -ApexImportTool::ApexImportTool(NvBlastLog log) - : m_apexDestruction(NULL), m_log(log) +ApexImportTool::ApexImportTool() + : m_apexDestruction(NULL) { } @@ -77,8 +97,8 @@ bool ApexImportTool::initialize() { return true; } - m_log(NvBlastMessage::Info, "APEX initialization \n", __FILE__, __LINE__); - m_apexDestruction = new ApexDestruction(m_log); + NVBLAST_LOG_INFO("APEX initialization"); + m_apexDestruction = new ApexDestruction(); return isValid(); } @@ -89,8 +109,8 @@ bool ApexImportTool::initialize(nvidia::apex::ApexSDK* apexSdk, nvidia::apex::Mo { return true; } - m_log(NvBlastMessage::Info, "APEX initialization \n", __FILE__, __LINE__); - m_apexDestruction = new ApexDestruction(apexSdk, moduleDestructible, m_log); + NVBLAST_LOG_INFO("APEX initialization"); + m_apexDestruction = new ApexDestruction(apexSdk, moduleDestructible); return isValid(); } @@ -102,12 +122,15 @@ DestructibleAsset* ApexImportTool::loadAssetFromFile(physx::PxFileBuf* stream) bool ApexImportTool::getCollisionGeometry(const nvidia::apex::DestructibleAsset* apexAsset, uint32_t chunkCount, std::vector<uint32_t>& chunkReorderInvMap, const std::vector<uint32_t>& apexChunkFlags, std::vector<ExtPxAssetDesc::ChunkDesc>& physicsChunks, - std::vector<ExtPxAssetDesc::SubchunkDesc>& physicsSubchunks) + std::vector<ExtPxAssetDesc::SubchunkDesc>& physicsSubchunks, std::vector<std::vector<CollisionHull*> >& hullsDesc) { physicsChunks.clear(); physicsChunks.resize(chunkCount); // prepare physics asset desc (convexes, transforms) - ConvexMeshBuilder collisionBuilder(m_apexDestruction->cooking(), &m_apexDestruction->apexSDK()->getPhysXSDK()->getPhysicsInsertionCallback()); + std::shared_ptr<ConvexMeshBuilder> collisionBuilder( + NvBlastExtAuthoringCreateConvexMeshBuilder(m_apexDestruction->cooking(), &m_apexDestruction->apexSDK()->getPhysXSDK()->getPhysicsInsertionCallback()), + [](ConvexMeshBuilder* cmb) { cmb->release(); }); + int32_t apexHullCount = 0; const uint32_t apexChunkCount = apexAsset->getChunkCount(); for (uint32_t chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) @@ -121,6 +144,8 @@ bool ApexImportTool::getCollisionGeometry(const nvidia::apex::DestructibleAsset* } physicsSubchunks.reserve(chunkCount); { + hullsDesc.clear(); + hullsDesc.resize(chunkCount); for (uint32_t chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { uint32_t apexChunkIndex = chunkReorderInvMap[chunkIndex]; @@ -138,9 +163,10 @@ bool ApexImportTool::getCollisionGeometry(const nvidia::apex::DestructibleAsset* paramHandle.getArraySize(verticesCount); std::vector<PxVec3> vertexData(verticesCount); paramHandle.getParamVec3Array(vertexData.data(), verticesCount); - - PxConvexMesh* convexMesh = collisionBuilder.buildConvexMesh(vertexData); - + hullsDesc[chunkIndex].push_back(nullptr); + hullsDesc[chunkIndex].back() = collisionBuilder.get()->buildCollisionGeometry(verticesCount, vertexData.data()); + PxConvexMesh* convexMesh = collisionBuilder.get()->buildConvexMesh(verticesCount, vertexData.data()); + const ExtPxAssetDesc::SubchunkDesc subchunk = { PxTransform(PxIdentity), @@ -155,8 +181,7 @@ bool ApexImportTool::getCollisionGeometry(const nvidia::apex::DestructibleAsset* } else { - // this is earth chunk - physicsChunks[chunkIndex].isStatic = true; + NVBLAST_LOG_ERROR("Error: chunk index is invalid."); } } } @@ -164,7 +189,7 @@ bool ApexImportTool::getCollisionGeometry(const nvidia::apex::DestructibleAsset* // check that vector didn't grow if (static_cast<int32_t>(physicsSubchunks.size()) > apexHullCount) { - m_log(NvBlastMessage::Error, "Error: sub chunk count seems to be wrong. \n", __FILE__, __LINE__); + NVBLAST_LOG_ERROR("Error: sub chunk count seems to be wrong."); return false; } return true; @@ -189,13 +214,14 @@ void gatherChunkHullPoints(const DestructibleAsset* apexAsset, std::vector<std:: } } } -PxBounds3 gatherChunkTriangles(const DestructibleAsset* apexAsset, std::vector<std::vector<Nv::Blast::Triangle> >& chunkTriangles, int32_t posBufferIndex, float scale, PxVec3 offset ) +PxBounds3 gatherChunkTriangles(const DestructibleAsset* apexAsset, std::vector<uint32_t>& chunkTrianglesOffsets, std::vector<Nv::Blast::Triangle>& chunkTriangles, int32_t posBufferIndex, float scale, PxVec3 offset ) { PxBounds3 bnd; bnd.setEmpty(); - chunkTriangles.clear(); - chunkTriangles.resize(apexAsset->getChunkCount()); + chunkTrianglesOffsets.clear(); + chunkTrianglesOffsets.resize(apexAsset->getChunkCount() + 1); + chunkTrianglesOffsets[0] = 0; for (uint32_t chunkIndex = 0; chunkIndex < apexAsset->getChunkCount(); ++chunkIndex) { uint32_t part = apexAsset->getPartIndex(chunkIndex); @@ -223,9 +249,10 @@ PxBounds3 gatherChunkTriangles(const DestructibleAsset* apexAsset, std::vector<s a.p *= scale; b.p *= scale; c.p *= scale; - chunkTriangles[chunkIndex].push_back(Nv::Blast::Triangle(a, b, c)); + chunkTriangles.push_back(Nv::Blast::Triangle(a, b, c)); } } + chunkTrianglesOffsets[chunkIndex + 1] = chunkTriangles.size(); } return bnd; } @@ -252,10 +279,7 @@ bool ApexImportTool::importApexAssetInternal(std::vector<uint32_t>& chunkReorder if (!apexAsset) { - if (m_log != NULL) - { - m_log(NvBlastMessage::Error, "Error: attempting to import NULL Apex asset.\n", __FILE__, __LINE__); - } + NVBLAST_LOG_ERROR("Error: attempting to import NULL Apex asset."); return false; } @@ -339,14 +363,18 @@ bool ApexImportTool::importApexAssetInternal(std::vector<uint32_t>& chunkReorder bondsDescriptors.clear(); bondsDescriptors.resize(overlapsBuffer.size()); - Nv::Blast::BlastBondGenerator bondGenTool(GetApexSDK()->getCookingInterface(), &GetApexSDK()->getPhysXSDK()->getPhysicsInsertionCallback()); - std::vector<std::vector<Nv::Blast::Triangle> > chunkTriangles; + std::shared_ptr<Nv::Blast::BlastBondGenerator> bondGenTool( + NvBlastExtAuthoringCreateBondGenerator(GetApexSDK()->getCookingInterface(), &GetApexSDK()->getPhysXSDK()->getPhysicsInsertionCallback()), + [](Nv::Blast::BlastBondGenerator* bg) {bg->release(); }); + + std::vector<uint32_t> chunkTrianglesOffsets; + std::vector<Nv::Blast::Triangle> chunkTriangles; PxBounds3 bnds = apexAsset->getRenderMeshAsset()->getBounds(); PxVec3 offset = bnds.getCenter(); float scale = 1.0f / PxMax(PxAbs(bnds.getExtents(0)), PxMax(PxAbs(bnds.getExtents(1)), PxAbs(bnds.getExtents(2)))); - bnds = gatherChunkTriangles(apexAsset, chunkTriangles, 0, scale, offset); + bnds = gatherChunkTriangles(apexAsset, chunkTrianglesOffsets, chunkTriangles, 0, scale, offset); BondGenerationConfig cf; @@ -355,9 +383,17 @@ bool ApexImportTool::importApexAssetInternal(std::vector<uint32_t>& chunkReorder { cf.bondMode = BondGenerationConfig::EXACT; } - - bondGenTool.createBondBetweenMeshes(chunkTriangles, bondsDescriptors, overlapsBuffer, cf); - + NvBlastBondDesc* bondsDesc; + std::vector<uint32_t> overlapsA, overlapsB; + for (auto it : overlapsBuffer) + { + overlapsA.push_back(it.first); + overlapsB.push_back(it.second); + } + bondGenTool.get()->createBondBetweenMeshes(chunkTrianglesOffsets.size() - 1, chunkTrianglesOffsets.data(), chunkTriangles.data(), + overlapsBuffer.size(), overlapsA.data(), overlapsB.data(), bondsDesc, cf); + memcpy(bondsDescriptors.data(), bondsDesc, sizeof(NvBlastBondDesc) * bondsDescriptors.size()); + delete[] bondsDesc; float inverScale = 1.0f / scale; @@ -392,16 +428,8 @@ bool ApexImportTool::importApexAssetInternal(std::vector<uint32_t>& chunkReorder apexChunkFlags.clear(); apexChunkFlags.resize(chunkDescriptors.size()); - // special 'earth chunk' + // externally supported chunks { - uint32_t earthChunkIndex = (uint32_t)chunkDescriptors.size(); - NvBlastChunkDesc earthChunk; - memset(earthChunk.centroid, 0, 3 * sizeof(float)); - earthChunk.volume = 0.0f; - earthChunk.parentChunkIndex = rootChunkIndex; - earthChunk.flags = NvBlastChunkDesc::SupportFlag; - earthChunk.userData = earthChunkIndex; - uint32_t chunksConnectedToEarth = 0; for (uint32_t i = 0; i < chunkDescriptors.size(); i++) { uint32_t chunkID = i; @@ -420,29 +448,24 @@ bool ApexImportTool::importApexAssetInternal(std::vector<uint32_t>& chunkReorder { NvBlastBondDesc bond; bond.chunkIndices[0] = i; - bond.chunkIndices[1] = earthChunkIndex; + bond.chunkIndices[1] = UINT32_MAX; // invalid index for "world" bond.bond.area = 0.1f; // ??? PxVec3 center = apexAsset->getChunkActorLocalBounds(chunkID).getCenter(); memcpy(&bond.bond.centroid, ¢er.x, sizeof(PxVec3)); PxVec3 normal = PxVec3(0, 0, 1); memcpy(&bond.bond.normal, &normal.x, sizeof(PxVec3)); bondsDescriptors.push_back(bond); - chunksConnectedToEarth++; } } - if (chunksConnectedToEarth > 0) - { - chunkDescriptors.push_back(earthChunk); - } } const uint32_t chunkCount = static_cast<uint32_t>(chunkDescriptors.size()); const uint32_t bondCount = static_cast<uint32_t>(bondsDescriptors.size()); std::vector<uint32_t> chunkReorderMap(chunkCount); std::vector<NvBlastChunkDesc> scratch(chunkCount); - NvBlastEnsureAssetExactSupportCoverage(chunkDescriptors.data(), chunkCount, scratch.data(), m_log); - NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDescriptors.data(), chunkCount, scratch.data(), m_log); - NvBlastApplyAssetDescChunkReorderMapInplace(chunkDescriptors.data(), chunkCount, bondsDescriptors.data(), bondCount, chunkReorderMap.data(), scratch.data(), m_log); + NvBlastEnsureAssetExactSupportCoverage(chunkDescriptors.data(), chunkCount, scratch.data(), logLL); + NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDescriptors.data(), chunkCount, scratch.data(), logLL); + NvBlastApplyAssetDescChunkReorderMapInPlace(chunkDescriptors.data(), chunkCount, bondsDescriptors.data(), bondCount, chunkReorderMap.data(), true, scratch.data(), logLL); chunkReorderInvMap.resize(chunkReorderMap.size()); Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<uint32_t>(chunkReorderMap.size())); return true; @@ -453,28 +476,19 @@ bool ApexImportTool::saveAsset(const NvBlastAsset* asset, PxFileBuf* stream) { if (!asset) { - if (m_log != NULL) - { - m_log(NvBlastMessage::Error, "Error: attempting to serialize NULL asset.\n", __FILE__, __LINE__); - } + NVBLAST_LOG_ERROR("Error: attempting to serialize NULL asset."); return false; } if (!stream) { - if (m_log != NULL) - { - m_log(NvBlastMessage::Error, "Error: bad output stream.\n", __FILE__, __LINE__); - } + NVBLAST_LOG_ERROR("Error: bad output stream."); return false; } const void* assetData = asset; - uint32_t assetDataSize = NvBlastAssetGetSize(asset, m_log); + uint32_t assetDataSize = NvBlastAssetGetSize(asset, logLL); stream->write(assetData, assetDataSize); stream->close(); - if (m_log != NULL) - { - m_log(NvBlastMessage::Info, "Saving finished... \n", __FILE__, __LINE__); - } + NVBLAST_LOG_INFO("Saving finished."); return true; } diff --git a/sdk/extensions/import/source/NvBlastExtScopedResource.cpp b/sdk/extensions/import/source/NvBlastExtScopedResource.cpp index 7cf7492..4f16b36 100644 --- a/sdk/extensions/import/source/NvBlastExtScopedResource.cpp +++ b/sdk/extensions/import/source/NvBlastExtScopedResource.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtScopedResource.h" diff --git a/sdk/extensions/import/source/NvBlastExtScopedResource.h b/sdk/extensions/import/source/NvBlastExtScopedResource.h index e0d35b7..6ab2980 100644 --- a/sdk/extensions/import/source/NvBlastExtScopedResource.h +++ b/sdk/extensions/import/source/NvBlastExtScopedResource.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTSCOPEDRESOURCE_H #define NVBLASTEXTSCOPEDRESOURCE_H diff --git a/sdk/extensions/physx/include/NvBlastExtCustomProfiler.h b/sdk/extensions/physx/include/NvBlastExtCustomProfiler.h new file mode 100644 index 0000000..4130964 --- /dev/null +++ b/sdk/extensions/physx/include/NvBlastExtCustomProfiler.h @@ -0,0 +1,143 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTDEFAULTPROFILER_H +#define NVBLASTDEFAULTPROFILER_H + +#include "NvBlastProfiler.h" +#include "PxProfiler.h" + +#if NV_NVTX +#include "nvToolsExt.h" +NV_INLINE void platformZoneStart(const char* name) { nvtxRangePushA(name); } +NV_INLINE void platformZoneEnd() { nvtxRangePop(); } + +#elif NV_XBOXONE +#include "xboxone/NvBlastProfilerXB1.h" + +#elif NV_PS4 +#include "ps4/NvBlastProfilerPS4.h" + +#else +NV_INLINE void platformZoneStart(const char*) { } +NV_INLINE void platformZoneEnd() { } + +#endif + +#define SUPPORTS_THREAD_LOCAL (!NV_VC || NV_VC > 12) + +namespace Nv +{ +namespace Blast +{ + +struct ExtProfileData +{ + const char* name; + void* data; +}; + +#if SUPPORTS_THREAD_LOCAL +static const int32_t PROFILER_MAX_NESTED_DEPTH = 64; +static thread_local ExtProfileData th_ProfileData[PROFILER_MAX_NESTED_DEPTH]; +static thread_local int32_t th_depth = 0; +#endif + +class ExtCustomProfiler : public ProfilerCallback +{ +public: + ExtCustomProfiler() : m_platformEnabled(false) {} + + virtual void zoneStart(const char* name) override + { + +#if SUPPORTS_THREAD_LOCAL + if (PxGetProfilerCallback()) + { + void* data = PxGetProfilerCallback()->zoneStart(name, false, 0xb1a57); + + if (th_depth < PROFILER_MAX_NESTED_DEPTH && th_depth >= 0) + { + th_ProfileData[th_depth].name = name; + th_ProfileData[th_depth].data = data; + th_depth++; + } + else + { + assert(th_depth < PROFILER_MAX_NESTED_DEPTH && th_depth >= 0); + } + } +#endif + + if (m_platformEnabled) + { + platformZoneStart(name); + } + } + + virtual void zoneEnd() override + { + +#if SUPPORTS_THREAD_LOCAL + if (PxGetProfilerCallback()) + { + th_depth--; + + if (th_depth >= 0) + { + ExtProfileData& pd = th_ProfileData[th_depth]; + PxGetProfilerCallback()->zoneEnd(pd.data, pd.name, false, 0xb1a57); + } + else + { + assert(th_depth >= 0); + } + } +#endif + + if (m_platformEnabled) + { + platformZoneEnd(); + } + } + + + void setPlatformEnabled(bool enabled) + { + m_platformEnabled = enabled; + } + +private: + bool m_platformEnabled; +}; + +} // namespace Blast +} // namespace Nv + + +#endif diff --git a/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h b/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h index ac3576d..28d0947 100644 --- a/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h +++ b/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTIMPACTDAMAGEMANAGER_H #define NVBLASTEXTIMPACTDAMAGEMANAGER_H @@ -43,16 +61,27 @@ Impact Damage Manager Settings. */ struct ExtImpactSettings { - bool isSelfCollissionEnabled; //!< family's self collision enabled - float fragility; //!< global fragility factor + bool isSelfCollissionEnabled; //!< family's self collision enabled. + bool shearDamage; //!< use shear damage program (otherwise simple radial damage is used) + float impulseMinThreshold; //!< min impulse value to apply impact damage. + float impulseMaxThreshold; //!< max impulse value, damage is interpolated value between min and max impulses. + float damageMax; //!< max damage to be applied (if impulse is >= impulseMaxThreshold). + float damageRadiusMax; //!< max penetration depth (if impulse is >= impulseMaxThreshold). + float damageAttenuation; //!< penetration attenuation ([0..1], where 1 means damage attenuates linearly from 0 to max penetration depth). ExtImpactDamageFunction damageFunction; //!< custom damage function, can be nullptr, default internal one will be used in that case. - void* damageFunctionData; //!< data to be passed in custom damage function + void* damageFunctionData; //!< data to be passed in custom damage function. ExtImpactSettings() : isSelfCollissionEnabled(false), - fragility(1.0f), - damageFunction(nullptr) + shearDamage(true), + impulseMinThreshold(0.0f), + impulseMaxThreshold(1000000.0f), + damageMax(100.f), + damageRadiusMax(5.0f), + damageAttenuation(1.f), + damageFunction(nullptr), + damageFunctionData(nullptr) {} }; diff --git a/sdk/extensions/physx/include/NvBlastExtPx.h b/sdk/extensions/physx/include/NvBlastExtPx.h index b2d938b..a34182a 100644 --- a/sdk/extensions/physx/include/NvBlastExtPx.h +++ b/sdk/extensions/physx/include/NvBlastExtPx.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPX_H #define NVBLASTEXTPX_H diff --git a/sdk/extensions/physx/include/NvBlastExtPxActor.h b/sdk/extensions/physx/include/NvBlastExtPxActor.h index 994ace7..79d6404 100644 --- a/sdk/extensions/physx/include/NvBlastExtPxActor.h +++ b/sdk/extensions/physx/include/NvBlastExtPxActor.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXACTOR_H #define NVBLASTEXTPXACTOR_H diff --git a/sdk/extensions/physx/include/NvBlastExtPxAsset.h b/sdk/extensions/physx/include/NvBlastExtPxAsset.h index a4dbe0e..136f0d2 100644 --- a/sdk/extensions/physx/include/NvBlastExtPxAsset.h +++ b/sdk/extensions/physx/include/NvBlastExtPxAsset.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXASSET_H #define NVBLASTEXTPXASSET_H @@ -114,6 +132,16 @@ public: */ static ExtPxAsset* create(const ExtPxAssetDesc& desc, TkFramework& framework); + /** + Create a new ExtPxAsset. + + \param[in] desc The ExtPxAssetDesc descriptor to be used, @see ExtPxAssetDesc. + \param[in] framework The TkFramework instance to be used to create TkAsset. + + \return the new ExtPxAsset if successful, NULL otherwise. + */ + static ExtPxAsset* create(const TkAssetDesc& desc, ExtPxChunk* pxChunks, ExtPxSubchunk* pxSubchunks, TkFramework& framework); + /* Factory method for deserialization @@ -123,17 +151,18 @@ public: */ static ExtPxAsset* create(TkAsset* asset); + /* + Create a new ExtPxAsset. - /** - Deserialize an ExtPxAsset object from the given stream. + \param[in] asset TkAsset from which ExtPxAsset will be created + \param[in] chunks Array of physics chunks descriptors + \param[in] chunkCount Size of chunks descriptors array - \param[in] stream User-defined stream object. - \param[in] framework The TkFramework instance to be used to deserialize TkAsset. - \param[in] physics The PxPhysics instance to be to deserialize PxConvexMesh(s). - \return pointer the deserialized ExtPxAsset object if successful, or NULL if unsuccessful. + \return the new ExtPxAsset if successful, NULL otherwise. + */ - static ExtPxAsset* deserialize(physx::general_PxIOStream2::PxFileBuf& stream, TkFramework& framework, physx::PxPhysics& physics); + static ExtPxAsset* create(TkAsset* asset, ExtPxAssetDesc::ChunkDesc* chunks, uint32_t chunkCount); /** Release this ExtPxAsset. @@ -141,16 +170,6 @@ public: virtual void release() = 0; /** - Write the asset's data to the user-defined PxFileBuf stream. Underlying TkAsset would be also serialized. - - \param[in] stream User-defined stream object. - \param[in] cooking The PxCooking instance to be used to serialize PxConvexMesh(s). - - \return true if serialization was successful, false otherwise. - */ - virtual bool serialize(physx::general_PxIOStream2::PxFileBuf& stream, physx::PxCooking& cooking) const = 0; - - /** Every ExtPxAsset has corresponding TkAsset. /return a pointer to TkAsset actor. @@ -187,6 +206,28 @@ public: virtual const ExtPxSubchunk* getSubchunks() const = 0; /** + Get the default NvBlastActorDesc to be used when creating family from this asset. It is called 'default', + because it can be overwritten in ExtPxManager::createFamily(...) function. + + Initially default NvBlastActorDesc contains only uniform health values, and 'nullptr' is set in arrays of health. + Call setUniformHealth(false) in order to set health per bond/chunk. You can then access directly values stored in NvBlastActorDesc, + change them and they will be serialized/deserialized as withing asset itself. + + NOTE: do not change actual pointers in NvBlastActorDesc: initialBondHealths and initialSupportChunkHealths. You can change actual values + in those arrays or if they are 'nullptr' call setUniformHealth(false) before. Or call setUniformHealth(true) to make them 'nullptr'. + + \return the default NvBlastActorDesc. + */ + virtual NvBlastActorDesc& getDefaultActorDesc() = 0; + + virtual const NvBlastActorDesc& getDefaultActorDesc() const = 0; + + /** + Set if uniform health values should be used in NvBlastActorDesc or per bond/chunk ones. @see getDefaultActorDesc. + */ + virtual void setUniformHealth(bool enabled) = 0; + + /** Pointer field available to the user. */ void* userData; diff --git a/sdk/extensions/physx/include/NvBlastExtPxFamily.h b/sdk/extensions/physx/include/NvBlastExtPxFamily.h index 7805c15..ae48769 100644 --- a/sdk/extensions/physx/include/NvBlastExtPxFamily.h +++ b/sdk/extensions/physx/include/NvBlastExtPxFamily.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXFAMILY_H #define NVBLASTEXTPXFAMILY_H diff --git a/sdk/extensions/physx/include/NvBlastExtPxListener.h b/sdk/extensions/physx/include/NvBlastExtPxListener.h index 4c43283..f3a52a3 100644 --- a/sdk/extensions/physx/include/NvBlastExtPxListener.h +++ b/sdk/extensions/physx/include/NvBlastExtPxListener.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXLISTENER_H #define NVBLASTEXTPXLISTENER_H diff --git a/sdk/extensions/physx/include/NvBlastExtPxManager.h b/sdk/extensions/physx/include/NvBlastExtPxManager.h index 9d73898..d4dd50c 100644 --- a/sdk/extensions/physx/include/NvBlastExtPxManager.h +++ b/sdk/extensions/physx/include/NvBlastExtPxManager.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXMANAGER_H #define NVBLASTEXTPXMANAGER_H @@ -54,9 +72,9 @@ Used to create Physics Family. */ struct ExtPxFamilyDesc { - const ExtPxAsset* pxAsset; //!< px asset to create from, pointer will be stored in family. - NvBlastActorDesc actorDesc; //!< actor descriptor to be used when creating TkActor. - TkGroup* group; //!< if not nullptr, created TkActor will be placed in group + const ExtPxAsset* pxAsset; //!< px asset to create from, pointer will be stored in family. + const NvBlastActorDesc* actorDesc; //!< actor descriptor to be used when creating TkActor. If nullptr, default NvBlastActorDesc from ExtPxAsset will be used. + TkGroup* group; //!< if not nullptr, created TkActor will be placed in group }; diff --git a/sdk/extensions/physx/include/NvBlastExtPxStressSolver.h b/sdk/extensions/physx/include/NvBlastExtPxStressSolver.h new file mode 100644 index 0000000..fcf4d85 --- /dev/null +++ b/sdk/extensions/physx/include/NvBlastExtPxStressSolver.h @@ -0,0 +1,98 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTPXSTRESSSOLVER_H +#define NVBLASTEXTPXSTRESSSOLVER_H + +#include "NvBlastExtStressSolver.h" +#include "common/PxRenderBuffer.h" + + +namespace Nv +{ +namespace Blast +{ + +// forward declarations +class ExtPxFamily; + + +/** +Px Stress Solver. Px wrapper over ExtStressSolver. + +Uses ExtPxFamily and ExtStressSolver. see #ExtStressSolver for more details. +Works on both dynamic and static actor's within family. +For static actors it applies gravity. +For dynamic actors it applies centrifugal force. +*/ +class NV_DLL_EXPORT ExtPxStressSolver +{ +public: + //////// creation //////// + + /** + Create a new ExtStressSolver. + + \param[in] family The ExtPxFamily instance to calculate stress on. + \param[in] settings The settings to be set on ExtStressSolver. + + \return the new ExtStressSolver if successful, NULL otherwise. + */ + static ExtPxStressSolver* create(ExtPxFamily& family, ExtStressSolverSettings settings = ExtStressSolverSettings()); + + + //////// interface //////// + + /** + Release this stress solver. + */ + virtual void release() = 0; + + /** + Get actual ExtStressSolver used. + + \return the pointer to ExtStressSolver used internally. + */ + virtual ExtStressSolver& getSolver() const = 0; + + /** + Update stress solver. + + Calculate stress and optionally apply damage. + + \param[in] doDamage If 'true' damage will be applied after stress solver. + */ + virtual void update(bool doDamage = true) = 0; +}; + + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTEXTPXSTRESSSOLVER_H diff --git a/sdk/extensions/physx/include/NvBlastExtPxTask.h b/sdk/extensions/physx/include/NvBlastExtPxTask.h new file mode 100644 index 0000000..b692ce8 --- /dev/null +++ b/sdk/extensions/physx/include/NvBlastExtPxTask.h @@ -0,0 +1,97 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTPXTASK_H +#define NVBLASTEXTPXTASK_H + +#include "NvBlastTypes.h" + + +// Forward declarations +namespace physx +{ +class PxTaskManager; +} + + +namespace Nv +{ +namespace Blast +{ + + +// Forward declarations +class TkGroup; + + +/** +Uses a physx::PxTaskManager to process a TkGroup concurrently. +*/ +class NV_DLL_EXPORT ExtGroupTaskManager +{ +protected: + virtual ~ExtGroupTaskManager() {} + +public: + static ExtGroupTaskManager* create(physx::PxTaskManager&); + static ExtGroupTaskManager* create(physx::PxTaskManager&, TkGroup&); + + /** + Change the group to process. Cannot be changed while the group being processed. + */ + virtual void setGroup(TkGroup*) = 0; + + /** + Start processing the group. + The parallelizing strategy is to have all worker tasks running concurrently. + The number of started tasks may be smaller than the requested value, + when the task manager's dispatcher thread count or the number of group jobs are + smaller. + + \param[in] workerCount The number of worker tasks to start, + 0 uses the dispatcher's worker thread count. + \return The number of worker tasks started. + */ + virtual uint32_t process(uint32_t workerCount = 0) = 0; + + /** + Wait for the group to end processing. + */ + virtual bool wait(bool block = true) = 0; + + /** + Release this object. + */ + virtual void release() = 0; +}; + + +} // namespace Blast +} // namespace Nv + +#endif // NVBLASTEXTPXTASK_H diff --git a/sdk/extensions/physx/include/NvBlastExtStressSolver.h b/sdk/extensions/physx/include/NvBlastExtStressSolver.h deleted file mode 100644 index 2fd389d..0000000 --- a/sdk/extensions/physx/include/NvBlastExtStressSolver.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTSTRESSSOLVER_H -#define NVBLASTEXTSTRESSSOLVER_H - -#include "common/PxRenderBuffer.h" -#include <vector> -#include "NvPreprocessor.h" - - -namespace Nv -{ -namespace Blast -{ - -// forward declarations -class ExtPxFamily; -class ExtPxActor; - -/** -Stress Solver Settings - -Stress on every bond is calculated as -stress = bond.linearStress * stressLinearFactor + bond.angularStress * stressAngularFactor -where: -bond.linearStress - is linear stress force on particular bond -bond.angularStress - is angular stress force on particular bond -stressLinearFactor, stressAngularFactor - are a multiplier parameter set by this struct - -Support graph reduction: -2 ^ reduction level = max node count to be aggregated during graph reduction, so 0 is 2 % 0 = 1, basically use support graph. -So N nodes graph will be simplified to contain ~ N / (2 ^ reduction level) -*/ -struct ExtStressSolverSettings -{ - float stressLinearFactor; //!< linear stress on bond multiplier - float stressAngularFactor; //!< angular stress on bond multiplier - uint32_t bondIterationsPerFrame; //!< number of bond iterations to perform per frame, @see getIterationsPerFrame() below - uint32_t graphReductionLevel; //!< graph reduction level - - ExtStressSolverSettings() : - stressLinearFactor(0.00004f), - stressAngularFactor(0.00007f), - bondIterationsPerFrame(18000), - graphReductionLevel(3) - {} -}; - - -/** -Stress Solver. - -Uses ExtPxFamily, allocates and prepares it's graph once when it's created. Then it's being quickly updated on every -actor split. -Works on both dynamic and static actor's within family. -For static actors it applies gravity. -For dynamic actors it applies centrifugal force. -Additionally applyImpulse() method can be used to apply external impulse (like impact damage). -*/ -class NV_DLL_EXPORT ExtStressSolver -{ -public: - //////// creation //////// - - /** - Create a new ExtStressSolver. - - \param[in] family The ExtPxFamily instance to calculate stress on. - \param[in] settings The settings to be set on ExtStressSolver. - - \return the new ExtStressSolver if successful, NULL otherwise. - */ - static ExtStressSolver* create(ExtPxFamily& family, ExtStressSolverSettings settings = ExtStressSolverSettings()); - - - //////// interface //////// - - /** - Release this stress solver. - */ - virtual void release() = 0; - - /** - Set stress solver settings. - Changing graph reduction level will lead to graph being rebuilt (which is fast, but still not recommended). - All other settings are applied instantly and can be changed every frame. - - \param[in] settings The settings to be set on ExtStressSolver. - */ - virtual void setSettings(const ExtStressSolverSettings& settings) = 0; - - /** - Get stress solver settings. - - \return the pointer to stress solver settings currently set. - */ - virtual const ExtStressSolverSettings& getSettings() const = 0; - - /** - Apply external impulse on particular actor of family - - \param[in] actor The ExtPxActor to apply impulse on. - \param[in] position Local position in actor's coordinates to apply impulse on. - \param[in] force Impulse to apply (kg * m / s). - */ - virtual void applyImpulse(ExtPxActor& actor, physx::PxVec3 position, physx::PxVec3 force) = 0; - - /** - Update stress solver. - - Calculate stress and optionally apply damage. - - \param[in] doDamage If 'true' damage will be applied after stress solver. - */ - virtual void update(bool doDamage = true) = 0; - - /** - Reset stress solver. - - Stress solver uses warm start internally, calling this function will flush all previous data calculated and also zeros frame count. - This function is to be used for debug purposes. - */ - virtual void reset() = 0; - - /** - Debug Render Mode - */ - enum DebugRenderMode - { - STRESS_GRAPH = 0, //!< render only stress graph - STRESS_GRAPH_NODES_IMPULSES = 1, //!< render stress graph + nodes impulses after solving stress - STRESS_GRAPH_BONDS_IMPULSES = 2 //!< render stress graph + bonds impulses after solving stress - }; - - /** - Fill debug render for passed array of support graph nodes. - - \param[in] nodes Node indices of support graph to debug render for. - \param[out] lines Lines array to fill. - \param[in] mode Debug render mode. - \param[in] scale Scale to be applied on impulses. - */ - virtual void fillDebugRender(const std::vector<uint32_t>& nodes, std::vector<physx::PxDebugLine>& lines, DebugRenderMode mode, float scale = 1.0f) = 0; - - /** - Get stress solver linear error. - - \return the total linear error of stress calculation. - */ - virtual float getStressErrorLinear() const = 0; - - /** - Get stress solver angular error. - - \return the total angular error of stress calculation. - */ - virtual float getStressErrorAngular() const = 0; - - /** - Get stress solver total iterations count since it was created (or reset). - - \return the iterations count. - */ - virtual uint32_t getIterationCount() const = 0; - - /** - Get stress solver total frames count (update() calls) since it was created (or reset). - - \return the frames count. - */ - virtual uint32_t getFrameCount() const = 0; - - /** - Get stress solver bonds count, after graph reduction was applied. - - \return the bonds count. - */ - virtual uint32_t getBondCount() const = 0; - - - //////// helpers //////// - - /** - Get iteration per frame (update() call). - - Helper method to know how many solver iterations are made per frame. - - \return the iterations per frame count. - */ - uint32_t getIterationsPerFrame() const - { - uint32_t perFrame = getSettings().bondIterationsPerFrame / (getBondCount() + 1); - return perFrame > 0 ? perFrame : 1; - } -}; - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTEXTSTRESSSOLVER_H diff --git a/sdk/extensions/physx/include/NvBlastExtSync.h b/sdk/extensions/physx/include/NvBlastExtSync.h index 805378a..170a386 100644 --- a/sdk/extensions/physx/include/NvBlastExtSync.h +++ b/sdk/extensions/physx/include/NvBlastExtSync.h @@ -1,20 +1,38 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTSYNC_H #define NVBLASTEXTSYNC_H #include "NvBlastTk.h" #include "foundation/PxTransform.h" -#include "foundation/PxAllocatorCallback.h" #include "NvPreprocessor.h" +#include "NvBlastGlobals.h" namespace Nv @@ -80,7 +98,7 @@ struct ExtSyncEventInstance : public ExtSyncEvent ExtSyncEvent* clone() const override { - return new (NvBlastTkFrameworkGet()->getAllocatorCallback().allocate(sizeof(T), nullptr, __FILE__, __LINE__)) T(*(T*)this); + return NVBLAST_NEW (T) (*(T*)this); } }; diff --git a/sdk/extensions/physx/include/NvBlastPxCallbacks.h b/sdk/extensions/physx/include/NvBlastPxCallbacks.h new file mode 100644 index 0000000..323f298 --- /dev/null +++ b/sdk/extensions/physx/include/NvBlastPxCallbacks.h @@ -0,0 +1,73 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTPXCALLBACKS_H +#define NVBLASTPXCALLBACKS_H + +#include "NvBlastGlobals.h" +#include "PxErrorCallback.h" +#include "PxAllocatorCallback.h" + +/** +This file contains helper functions to get PxShared compatible versions of global AllocatorCallback and ErrorCallback. +*/ + + +NV_INLINE physx::PxErrorCallback& NvBlastGetPxErrorCallback() +{ + class PxErrorCallbackWrapper : public physx::PxErrorCallback + { + virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) override + { + NvBlastGlobalGetErrorCallback()->reportError((Nv::Blast::ErrorCode::Enum)code, message, file, line); + } + }; + static PxErrorCallbackWrapper wrapper; + return wrapper; +} + +NV_INLINE physx::PxAllocatorCallback& NvBlastGetPxAllocatorCallback() +{ + class PxAllocatorCallbackWrapper : public physx::PxAllocatorCallback + { + virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) override + { + return NvBlastGlobalGetAllocatorCallback()->allocate(size, typeName, filename, line); + } + + virtual void deallocate(void* ptr) override + { + NvBlastGlobalGetAllocatorCallback()->deallocate(ptr); + } + }; + static PxAllocatorCallbackWrapper wrapper; + return wrapper; +} + + +#endif // #ifndef NVBLASTPXCALLBACKS_H diff --git a/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp b/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp index 54d2696..fc1f514 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp +++ b/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtImpactDamageManager.h" #include "NvBlastExtPxManager.h" @@ -17,8 +35,7 @@ #include "NvBlastAssert.h" #include "NvBlastExtDamageShaders.h" -#include "NvBlastExtArray.h" -#include "NvBlastExtDefs.h" +#include "NvBlastArray.h" #include "PxRigidDynamic.h" #include "PxSimulationEventCallback.h" @@ -59,7 +76,7 @@ public: virtual void release() override { - NVBLASTEXT_DELETE(this, ExtImpactDamageManagerImpl); + NVBLAST_DELETE(this, ExtImpactDamageManagerImpl); } @@ -124,7 +141,7 @@ private: ExtPxManager* m_pxManager; ExtImpactSettings m_settings; PxManagerListener m_listener; - ExtArray<PxContactPairPoint>::type m_pairPointBuffer; + Array<PxContactPairPoint>::type m_pairPointBuffer; bool m_usePxUserData; struct ImpactDamageData @@ -135,10 +152,10 @@ private: PxShape* shape; }; - ExtArray<ImpactDamageData>::type m_impactDamageBuffer; + Array<ImpactDamageData>::type m_impactDamageBuffer; NvBlastFractureBuffers m_fractureBuffers; - ExtArray<uint8_t>::type m_fractureData; + Array<uint8_t>::type m_fractureData; }; @@ -148,7 +165,7 @@ private: ExtImpactDamageManager* ExtImpactDamageManager::create(ExtPxManager* pxManager, ExtImpactSettings settings) { - return NVBLASTEXT_NEW(ExtImpactDamageManagerImpl) (pxManager, settings); + return NVBLAST_NEW(ExtImpactDamageManagerImpl) (pxManager, settings); } @@ -310,12 +327,6 @@ void ExtImpactDamageManagerImpl::onContact(const PxContactPairHeader& pairHeader // ExtImpactDamageManager damage processing /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float clampedLerp(float from, float to, float t) -{ - t = PxClamp(t, 0.0f, 1.0f); - return (1 - t) * from + to * t; -} - void ExtImpactDamageManagerImpl::applyDamage() { const auto damageFn = m_settings.damageFunction; @@ -323,10 +334,7 @@ void ExtImpactDamageManagerImpl::applyDamage() for (const ImpactDamageData& data : m_impactDamageBuffer) { - float forceMag = data.force.magnitude(); - float acceleration = forceMag / data.actor->getPhysXActor().getMass(); - float factor = acceleration * m_settings.fragility * 0.001f; - if (factor > 0.05f) + if (data.force.magnitudeSquared() > m_settings.impulseMinThreshold * m_settings.impulseMinThreshold) { PxTransform t(data.actor->getPhysXActor().getGlobalPose().getInverse()); PxVec3 force = t.rotate(data.force); @@ -334,7 +342,7 @@ void ExtImpactDamageManagerImpl::applyDamage() if (!damageFn || !damageFn(damageFnData, data.actor, data.shape, position, force)) { - damageActor(data.actor, data.shape, position, force*.00001f); + damageActor(data.actor, data.shape, position, force); } } } @@ -358,32 +366,73 @@ void ExtImpactDamageManagerImpl::damageActor(ExtPxActor* actor, PxShape* /*shape { ensureBuffersSize(actor); - NvBlastExtShearDamageDesc damage[] = { - { - { force[0], force[1], force[2] }, // shear - { position[0], position[1], position[2] } // position - } - }; + const float f0 = m_settings.impulseMinThreshold; + const float f1 = m_settings.impulseMaxThreshold; + const float impulse01 = PxClamp<float>((force.magnitude() - f0) / PxMax<float>(f1 - f0, 1.0f), 0, 1); + const float damage = m_settings.damageMax * impulse01; - const void* familyMaterial = actor->getTkActor().getFamily().getMaterial(); + const void* material = actor->getTkActor().getFamily().getMaterial(); + if (!material) + { + return; + } - // default material params settings - const NvBlastExtMaterial defaultMaterial = { 3.0f, 0.1f, 0.2f, 1.5f + 1e-5f, 0.95f }; + const float normalizedDamage = reinterpret_cast<const NvBlastExtMaterial*>(material)->getNormalizedDamage(damage); + if (normalizedDamage == 0.f) + { + return; + } + + const PxVec3 normal = force.getNormalized(); + const float maxDistance = m_settings.damageRadiusMax * impulse01; + const float minDistance = maxDistance * PxClamp<float>(1 - m_settings.damageAttenuation, 0, 1); NvBlastProgramParams programParams; programParams.damageDescCount = 1; - programParams.damageDescBuffer = &damage; - programParams.material = familyMaterial == nullptr ? &defaultMaterial : familyMaterial; + programParams.material = nullptr; + NvBlastDamageProgram program; - NvBlastDamageProgram program = { - NvBlastExtShearGraphShader, - NvBlastExtShearSubgraphShader - }; + if (m_settings.shearDamage) + { + NvBlastExtShearDamageDesc desc[] = { + { + normalizedDamage, + { normal[0], normal[1], normal[2] }, // shear + { position[0], position[1], position[2] }, // position + minDistance, + maxDistance + } + }; + + programParams.damageDescBuffer = &desc; + + program.graphShaderFunction = NvBlastExtShearGraphShader; + program.subgraphShaderFunction = NvBlastExtShearSubgraphShader; + + NvBlastFractureBuffers fractureEvents = m_fractureBuffers; + actor->getTkActor().generateFracture(&fractureEvents, program, &programParams); + actor->getTkActor().applyFracture(nullptr, &fractureEvents); + } + else + { + NvBlastExtRadialDamageDesc desc[] = { + { + normalizedDamage, + { position[0], position[1], position[2] }, // position + minDistance, + maxDistance + } + }; + + programParams.damageDescBuffer = &desc; - NvBlastFractureBuffers fractureEvents = m_fractureBuffers; + program.graphShaderFunction = NvBlastExtFalloffGraphShader; + program.subgraphShaderFunction = NvBlastExtFalloffSubgraphShader; - actor->getTkActor().generateFracture(&fractureEvents, program, &programParams); - actor->getTkActor().applyFracture(nullptr, &fractureEvents); + NvBlastFractureBuffers fractureEvents = m_fractureBuffers; + actor->getTkActor().generateFracture(&fractureEvents, program, &programParams); + actor->getTkActor().applyFracture(nullptr, &fractureEvents); + } } diff --git a/sdk/extensions/physx/source/physics/NvBlastExtImpulseStressSolver.h b/sdk/extensions/physx/source/physics/NvBlastExtImpulseStressSolver.h deleted file mode 100644 index d274789..0000000 --- a/sdk/extensions/physx/source/physics/NvBlastExtImpulseStressSolver.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#ifndef NVBLASTEXTIMPULSESTRESSSOLVER_H -#define NVBLASTEXTIMPULSESTRESSSOLVER_H - -#include "NvBlastExtStressSolver.h" -#include "NvBlastExtPxManager.h" -#include "NvBlastExtPxListener.h" -#include "NvBlastTypes.h" -#include <NvBlastExtArray.h> -#include <NvBlastExtHashSet.h> -#include <NvBlastExtHashMap.h> - -namespace Nv -{ -namespace Blast -{ - - -struct ExtStressNodeCachedData -{ - physx::PxVec3 localPos; - bool isStatic; -}; - - -struct ExtStressBondCachedData -{ - uint32_t bondIndex; -}; - -class SupportGraphProcessor; - -/** -*/ -class ExtImpulseStressSolver : public ExtStressSolver, ExtPxListener -{ - NV_NOCOPY(ExtImpulseStressSolver) - -public: - ExtImpulseStressSolver(ExtPxFamily& family, ExtStressSolverSettings settings); - virtual void release() override; - - - //////// ExtStressSolver interface //////// - - virtual void setSettings(const ExtStressSolverSettings& settings) override - { - m_settings = settings; - } - - virtual const ExtStressSolverSettings& getSettings() const override - { - return m_settings; - } - - virtual void applyImpulse(ExtPxActor& actor, physx::PxVec3 position, physx::PxVec3 force) override; - - virtual void update(bool doDamage) override; - - void reset() override - { - m_reset = true; - } - - virtual float getStressErrorLinear() const override - { - return m_errorLinear; - } - - virtual float getStressErrorAngular() const override - { - return m_errorAngular; - } - - virtual uint32_t getIterationCount() const override; - - virtual uint32_t getFrameCount() const override - { - return m_framesCount; - } - - virtual uint32_t getBondCount() const override; - - virtual void fillDebugRender(const std::vector<uint32_t>& nodes, std::vector<physx::PxDebugLine>& lines, DebugRenderMode mode, float scale) override; - - - //////// ExtPxListener interface //////// - - virtual void onActorCreated(ExtPxFamily& family, ExtPxActor& actor) final; - - virtual void onActorDestroyed(ExtPxFamily& family, ExtPxActor& actor) final; - - -private: - ~ExtImpulseStressSolver(); - - - //////// private methods //////// - - void solve(); - - void applyDamage(); - - void initialize(); - - NV_INLINE void iterate(); - - void syncSolver(); - - template<class T> - NV_INLINE T* getScratchArray(uint32_t size); - - - //////// data //////// - - struct ImpulseData - { - physx::PxVec3 position; - physx::PxVec3 impulse; - }; - - ExtPxFamily& m_family; - ExtHashSet<ExtPxActor*>::type m_actors; - ExtStressSolverSettings m_settings; - NvBlastSupportGraph m_graph; - bool m_isDirty; - bool m_reset; - const float* m_bondHealths; - SupportGraphProcessor* m_graphProcessor; - float m_errorAngular; - float m_errorLinear; - uint32_t m_framesCount; - ExtArray<NvBlastBondFractureData>::type m_bondFractureBuffer; - ExtHashMap<const ExtPxActor*, ExtArray<ImpulseData>::type>::type m_impulseBuffer; - ExtArray<uint8_t>::type m_scratch; -}; - - -template<class T> -NV_INLINE T* ExtImpulseStressSolver::getScratchArray(uint32_t size) -{ - const uint32_t scratchSize = sizeof(T) * size; - if (m_scratch.size() < scratchSize) - { - m_scratch.resize(scratchSize); - } - return reinterpret_cast<T*>(m_scratch.begin()); -} - - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTEXTIMPULSESTRESSSOLVER_H diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp index 7732d18..c298e07 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtPxActorImpl.h" #include "NvBlastExtPxAsset.h" @@ -16,6 +34,8 @@ #include "PxRigidDynamic.h" #include "PxPhysics.h" +#include "NvBlastAssert.h" + #include "NvBlastTkActor.h" #include "NvBlastTkAsset.h" @@ -57,7 +77,7 @@ ExtPxActorImpl::ExtPxActorImpl(ExtPxFamilyImpl* family, TkActor* tkActor, const // Single lower-support chunk actors might be leaf actors, check for this and disable contact callbacks if so if (nodeCount <= 1) { - PX_ASSERT(chunkIndices.size() == 1); + NVBLAST_ASSERT(chunkIndices.size() == 1); if (chunkIndices.size() > 0) { const NvBlastChunk& chunk = chunks[chunkIndices[0]]; @@ -106,23 +126,23 @@ ExtPxActorImpl::ExtPxActorImpl(ExtPxFamilyImpl* family, TkActor* tkActor, const m_rigidDynamic->attachShape(*shape); - PX_ASSERT_WITH_MESSAGE(m_family->m_subchunkShapes[subchunkIndex] == nullptr, "Chunk has some shapes(live)."); + NVBLAST_ASSERT_WITH_MESSAGE(m_family->m_subchunkShapes[subchunkIndex] == nullptr, "Chunk has some shapes(live)."); m_family->m_subchunkShapes[subchunkIndex] = shape; } } // search for static chunk in actor's graph (make actor static if it contains static chunk) - bool staticFound = false; + bool staticFound = m_tkActor->isBoundToWorld(); if (nodeCount > 0) { - auto& graphChunkIndices = m_family->m_indicesScratch; - graphChunkIndices.resize(nodeCount); - m_tkActor->getGraphNodeIndices(graphChunkIndices.begin(), static_cast<uint32_t>(graphChunkIndices.size())); + auto& graphNodeIndices = m_family->m_indicesScratch; + graphNodeIndices.resize(nodeCount); + m_tkActor->getGraphNodeIndices(graphNodeIndices.begin(), static_cast<uint32_t>(graphNodeIndices.size())); const NvBlastSupportGraph graph = m_tkActor->getAsset()->getGraph(); - for (uint32_t i = 0; !staticFound && i < graphChunkIndices.size(); ++i) + for (uint32_t i = 0; !staticFound && i < graphNodeIndices.size(); ++i) { - uint32_t chunkIndex = graph.chunkIndices[graphChunkIndices[i]]; + const uint32_t chunkIndex = graph.chunkIndices[graphNodeIndices[i]]; const ExtPxChunk& chunk = pxChunks[chunkIndex]; staticFound = chunk.isStatic; } diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h index a592293..5635591 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h @@ -1,18 +1,36 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXACTORIMPL_H #define NVBLASTEXTPXACTORIMPL_H #include "NvBlastExtPxActor.h" -#include "NvBlastExtArray.h" +#include "NvBlastArray.h" #include "PxTransform.h" @@ -82,7 +100,7 @@ private: ExtPxFamilyImpl* m_family; TkActor* m_tkActor; PxRigidDynamic* m_rigidDynamic; - ExtInlineArray<uint32_t, 4>::type m_chunkIndices; + InlineArray<uint32_t, 4>::type m_chunkIndices; }; diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp index a0f75fc..948cd84 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp @@ -1,15 +1,33 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtPxAssetImpl.h" -#include "NvBlastExtHashMap.h" +#include "NvBlastHashMap.h" #include "NvBlastAssert.h" #include "NvBlastIndexFns.h" @@ -30,65 +48,106 @@ namespace Blast /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Helpers/Wrappers +// ExtPxAssetImpl Implementation /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class FileBufToPxInputStream final : public PxInputStream +ExtPxAssetImpl::ExtPxAssetImpl(const ExtPxAssetDesc& desc, TkFramework& framework) +#if !defined(NV_VC) || NV_VC >= 14 + : m_defaultActorDesc { 1.0f, nullptr, 1.0f, nullptr } { -public: - FileBufToPxInputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {} - - virtual uint32_t read(void* dest, uint32_t count) - { - return m_filebuf.read(dest, count); - } +#else +{ + m_defaultActorDesc.uniformInitialBondHealth = m_defaultActorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; + m_defaultActorDesc.initialBondHealths = m_defaultActorDesc.initialSupportChunkHealths = nullptr; +#endif + m_tkAsset = framework.createAsset(desc); + fillPhysicsChunks(desc.pxChunks, desc.chunkCount); +} -private: - FileBufToPxInputStream& operator=(const FileBufToPxInputStream&); +ExtPxAssetImpl::ExtPxAssetImpl(const TkAssetDesc& desc, ExtPxChunk* pxChunks, ExtPxSubchunk* pxSubchunks, TkFramework& framework) +#if !defined(NV_VC) || NV_VC >= 14 + : m_defaultActorDesc{ 1.0f, nullptr, 1.0f, nullptr } +{ +#else +{ + m_defaultActorDesc.uniformInitialBondHealth = m_defaultActorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; + m_defaultActorDesc.initialBondHealths = m_defaultActorDesc.initialSupportChunkHealths = nullptr; +#endif + m_tkAsset = framework.createAsset(desc); + fillPhysicsChunks(pxChunks, pxSubchunks, desc.chunkCount); +} - PxFileBuf& m_filebuf; -}; +ExtPxAssetImpl::ExtPxAssetImpl(TkAsset* asset, ExtPxAssetDesc::ChunkDesc* chunks, uint32_t chunkCount) + : m_tkAsset(asset) +#if !defined(NV_VC) || NV_VC >= 14 + , m_defaultActorDesc{ 1.0f, nullptr, 1.0f, nullptr } +{ +#else +{ + m_defaultActorDesc.uniformInitialBondHealth = m_defaultActorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; + m_defaultActorDesc.initialBondHealths = m_defaultActorDesc.initialSupportChunkHealths = nullptr; +#endif + m_tkAsset = asset; + fillPhysicsChunks(chunks, chunkCount); +} -class FileBufToPxOutputStream final : public PxOutputStream +ExtPxAssetImpl::ExtPxAssetImpl(TkAsset* asset) + : m_tkAsset(asset) +#if !defined(NV_VC) || NV_VC >= 14 + , m_defaultActorDesc { 1.0f, nullptr, 1.0f, nullptr } { -public: - FileBufToPxOutputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {} +#else +{ + m_defaultActorDesc.uniformInitialBondHealth = m_defaultActorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; + m_defaultActorDesc.initialBondHealths = m_defaultActorDesc.initialSupportChunkHealths = nullptr; +#endif +} - virtual uint32_t write(const void* src, uint32_t count) override +ExtPxAssetImpl::~ExtPxAssetImpl() +{ + if (m_tkAsset) { - return m_filebuf.write(src, count); + m_tkAsset->release(); } +} -private: - FileBufToPxOutputStream& operator=(const FileBufToPxOutputStream&); - - PxFileBuf& m_filebuf; -}; - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ExtPxAssetImpl Implementation -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ExtPxAssetImpl::release() +{ + NVBLAST_DELETE(this, ExtPxAssetImpl); +} -ExtPxAssetImpl::ExtPxAssetImpl(const ExtPxAssetDesc& desc, TkFramework& framework) +void ExtPxAssetImpl::fillPhysicsChunks(ExtPxChunk* pxChunks, ExtPxSubchunk* pxSuchunks, uint32_t chunkCount) { - m_tkAsset = framework.createAsset(desc); + // count subchunks and reserve memory + uint32_t subchunkCount = 0; + for (uint32_t i = 0; i < chunkCount; ++i) + { + const auto& chunk = pxChunks[i]; + subchunkCount += static_cast<uint32_t>(chunk.subchunkCount); + } + m_subchunks.resize(subchunkCount); + m_chunks.resize(chunkCount); + memcpy(&m_subchunks.front(), pxSuchunks, sizeof(ExtPxSubchunk) * subchunkCount); + memcpy(&m_chunks.front(), pxChunks, sizeof(ExtPxChunk) * chunkCount); +} +void ExtPxAssetImpl::fillPhysicsChunks(ExtPxAssetDesc::ChunkDesc* pxChunks, uint32_t chunkCount) +{ // count subchunks and reserve memory uint32_t subchunkCount = 0; - for (uint32_t i = 0; i < desc.chunkCount; ++i) + for (uint32_t i = 0; i < chunkCount; ++i) { - const auto& chunk = desc.pxChunks[i]; + const auto& chunk = pxChunks[i]; subchunkCount += static_cast<uint32_t>(chunk.subchunkCount); } m_subchunks.reserve(subchunkCount); // fill chunks and subchunks - m_chunks.resize(desc.chunkCount); - for (uint32_t i = 0; i < desc.chunkCount; ++i) + m_chunks.resize(chunkCount); + for (uint32_t i = 0; i < chunkCount; ++i) { - const auto& chunk = desc.pxChunks[i]; + const auto& chunk = pxChunks[i]; m_chunks[i].isStatic = chunk.isStatic; m_chunks[i].firstSubchunkIndex = m_subchunks.size(); m_chunks[i].subchunkCount = chunk.subchunkCount; @@ -104,27 +163,9 @@ ExtPxAssetImpl::ExtPxAssetImpl(const ExtPxAssetDesc& desc, TkFramework& framewor } } -ExtPxAssetImpl::ExtPxAssetImpl(TkAsset* tkAsset): - m_tkAsset(tkAsset) -{ - -} -ExtPxAssetImpl::~ExtPxAssetImpl() -{ - if (m_tkAsset) - { - m_tkAsset->release(); - } -} - -void ExtPxAssetImpl::release() -{ - NVBLASTEXT_DELETE(this, ExtPxAssetImpl); -} - -NV_INLINE bool serializeConvexMesh(const PxConvexMesh& convexMesh, PxCooking& cooking, ExtArray<uint32_t>::type& indicesScratch, - ExtArray<PxHullPolygon>::type hullPolygonsScratch, PxOutputStream& stream) +NV_INLINE bool serializeConvexMesh(const PxConvexMesh& convexMesh, PxCooking& cooking, Array<uint32_t>::type& indicesScratch, + Array<PxHullPolygon>::type hullPolygonsScratch, PxOutputStream& stream) { PxConvexMeshDesc desc; desc.points.data = convexMesh.getVertices(); @@ -168,64 +209,25 @@ NV_INLINE bool serializeConvexMesh(const PxConvexMesh& convexMesh, PxCooking& co return cooking.cookConvexMesh(desc, stream); } -bool ExtPxAssetImpl::serialize(PxFileBuf& stream, PxCooking& cooking) const -{ - // Header data - stream.storeDword(ClassID); - stream.storeDword(Version::Current); - - m_tkAsset->serialize(stream); - // Chunks - const uint32_t chunkCount = m_tkAsset->getChunkCount(); - for (uint32_t i = 0; i < chunkCount; ++i) - { - const ExtPxChunk& chunk = m_chunks[i]; - stream.storeDword(chunk.firstSubchunkIndex); - stream.storeDword(chunk.subchunkCount); - stream.storeDword(chunk.isStatic ? 1 : 0); - } - - stream.storeDword(m_subchunks.size()); - - ExtArray<uint32_t>::type indicesScratch(512); - ExtArray<PxHullPolygon>::type hullPolygonsScratch(512); - ExtHashMap<PxConvexMesh*, uint32_t>::type convexReuseMap; - - FileBufToPxOutputStream outputStream(stream); - for (uint32_t i = 0; i < m_subchunks.size(); ++i) +void ExtPxAssetImpl::setUniformHealth(bool enabled) +{ + if (m_bondHealths.empty() != enabled) { - auto& subchunk = m_subchunks[i]; - - // Subchunk transform - stream.storeFloat(subchunk.transform.q.x); stream.storeFloat(subchunk.transform.q.y); stream.storeFloat(subchunk.transform.q.z); stream.storeFloat(subchunk.transform.q.w); - stream.storeFloat(subchunk.transform.p.x); stream.storeFloat(subchunk.transform.p.y); stream.storeFloat(subchunk.transform.p.z); - - // Subchunk scale - stream.storeFloat(subchunk.geometry.scale.scale.x); stream.storeFloat(subchunk.geometry.scale.scale.y); stream.storeFloat(subchunk.geometry.scale.scale.z); - stream.storeFloat(subchunk.geometry.scale.rotation.x); stream.storeFloat(subchunk.geometry.scale.rotation.y); stream.storeFloat(subchunk.geometry.scale.rotation.z); stream.storeFloat(subchunk.geometry.scale.rotation.w); - - auto convexMesh = subchunk.geometry.convexMesh; - NVBLASTEXT_CHECK_ERROR(convexMesh != nullptr, "ExtPxAssetImpl::serialize: subchunk convexMesh is nullptr.", return false); - - auto entry = convexReuseMap.find(convexMesh); - if (entry) + if (enabled) { - stream.storeDword(entry->second); + m_bondHealths.resizeUninitialized(0); + m_supportChunkHealths.resizeUninitialized(0); } else { - stream.storeDword(invalidIndex<uint32_t>()); - if (!serializeConvexMesh(*convexMesh, cooking, indicesScratch, hullPolygonsScratch, outputStream)) - { - NVBLASTEXT_LOG_ERROR("ExtPxAssetImpl::serialize: subchunk convexMesh cooking/serialization failed."); - return false; - } - convexReuseMap[convexMesh] = i; + m_bondHealths.resize(m_tkAsset->getBondCount()); + m_supportChunkHealths.resize(m_tkAsset->getGraph().nodeCount); } } - return true; + m_defaultActorDesc.initialBondHealths = enabled ? nullptr : m_bondHealths.begin(); + m_defaultActorDesc.initialSupportChunkHealths = enabled ? nullptr : m_supportChunkHealths.begin(); } @@ -235,81 +237,30 @@ bool ExtPxAssetImpl::serialize(PxFileBuf& stream, PxCooking& cooking) const ExtPxAsset* ExtPxAsset::create(const ExtPxAssetDesc& desc, TkFramework& framework) { - ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(desc, framework); + ExtPxAssetImpl* asset = NVBLAST_NEW(ExtPxAssetImpl)(desc, framework); return asset; } +ExtPxAsset* ExtPxAsset::create(const TkAssetDesc& desc, ExtPxChunk* pxChunks, ExtPxSubchunk* pxSubchunks, TkFramework& framework) +{ + ExtPxAssetImpl* asset = NVBLAST_NEW(ExtPxAssetImpl)(desc, pxChunks, pxSubchunks, framework); + return asset; +} Nv::Blast::ExtPxAsset* ExtPxAsset::create(TkAsset* tkAsset) { - ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(tkAsset); + ExtPxAssetImpl* asset = NVBLAST_NEW(ExtPxAssetImpl)(tkAsset); // Don't populate the chunks or subchunks! return asset; } -ExtPxAsset* ExtPxAsset::deserialize(PxFileBuf& stream, TkFramework& framework, PxPhysics& physics) +Nv::Blast::ExtPxAsset* ExtPxAsset::create(TkAsset* tkAsset, ExtPxAssetDesc::ChunkDesc* chunks, uint32_t chunkCount) { - ExtPxAssetImpl::DataHeader header; - header.dataType = stream.readDword(); - header.version = stream.readDword(); - NVBLASTEXT_CHECK_ERROR(header.dataType == ExtPxAssetImpl::ClassID, "ExtPxAsset::deserialize: wrong data type in filebuf stream.", return nullptr); - NVBLASTEXT_CHECK_ERROR(header.version == ExtPxAssetImpl::Version::Current, "ExtPxAsset::deserialize: wrong data version in filebuf stream.", return nullptr); - - TkAsset* tkAsset = static_cast<TkAsset*>(framework.deserialize(stream)); - NVBLASTEXT_CHECK_ERROR(tkAsset != nullptr, "ExtPxAsset::deserialize: failed to deserialize TkAsset.", return nullptr); - - ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(tkAsset); - - asset->m_chunks.resize(asset->m_tkAsset->getChunkCount()); - - const uint32_t chunkCount = asset->m_chunks.size(); - for (uint32_t i = 0; i < chunkCount; ++i) - { - ExtPxChunk& chunk = asset->m_chunks[i]; - chunk.firstSubchunkIndex = stream.readDword(); - chunk.subchunkCount = stream.readDword(); - chunk.isStatic = 0 != stream.readDword(); - } - - const uint32_t subchunkCount = stream.readDword(); - asset->m_subchunks.resize(subchunkCount); - - FileBufToPxInputStream inputStream(stream); - for (uint32_t i = 0; i < asset->m_subchunks.size(); ++i) - { - ExtPxSubchunk& subChunk = asset->m_subchunks[i]; - - // Subchunk transform - subChunk.transform.q.x = stream.readFloat(); subChunk.transform.q.y = stream.readFloat(); subChunk.transform.q.z = stream.readFloat(); subChunk.transform.q.w = stream.readFloat(); - subChunk.transform.p.x = stream.readFloat(); subChunk.transform.p.y = stream.readFloat(); subChunk.transform.p.z = stream.readFloat(); - - // Subchunk scale - subChunk.geometry.scale.scale.x = stream.readFloat(); subChunk.geometry.scale.scale.y = stream.readFloat(); subChunk.geometry.scale.scale.z = stream.readFloat(); - subChunk.geometry.scale.rotation.x = stream.readFloat(); subChunk.geometry.scale.rotation.y = stream.readFloat(); subChunk.geometry.scale.rotation.z = stream.readFloat(); subChunk.geometry.scale.rotation.w = stream.readFloat(); - - const uint32_t convexReuseIndex = stream.readDword(); - if (isInvalidIndex(convexReuseIndex)) - { - subChunk.geometry.convexMesh = physics.createConvexMesh(inputStream); - } - else - { - NVBLAST_ASSERT_WITH_MESSAGE(convexReuseIndex < i, "ExtPxAsset::deserialize: wrong convexReuseIndex."); - subChunk.geometry.convexMesh = asset->m_subchunks[convexReuseIndex].geometry.convexMesh; - } - if (!subChunk.geometry.convexMesh) - { - NVBLASTEXT_LOG_ERROR("ExtPxAsset::deserialize: failed to deserialize convex mesh."); - asset->release(); - return nullptr; - } - } - + ExtPxAssetImpl* asset = NVBLAST_NEW(ExtPxAssetImpl)(tkAsset, chunks, chunkCount); return asset; } - } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.h index fd95293..11a36b3 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.h +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.h @@ -1,19 +1,36 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXASSETIMPL_H #define NVBLASTEXTPXASSETIMPL_H #include "NvBlastExtPxAsset.h" -#include "NvBlastExtArray.h" -#include "NvBlastExtDefs.h" +#include "NvBlastArray.h" namespace Nv @@ -26,6 +43,10 @@ using namespace physx; using namespace general_PxIOStream2; +// Macro to load a uint32_t (or larger) with four characters (move it in some shared header if it's used anywhere else in Ext) +#define NVBLASTEXT_FOURCC(_a, _b, _c, _d) ( (uint32_t)(_a) | (uint32_t)(_b)<<8 | (uint32_t)(_c)<<16 | (uint32_t)(_d)<<24 ) + + class ExtPxAssetImpl final : public ExtPxAsset { NV_NOCOPY(ExtPxAssetImpl) @@ -33,27 +54,12 @@ class ExtPxAssetImpl final : public ExtPxAsset public: friend class ExtPxAsset; - /** - Enum which keeps track of the serialized data format. - */ - enum Version - { - /** Initial version */ - Initial, - - // New formats must come before Count. They should be given descriptive names with more information in comments. - - /** The number of serialized formats. */ - Count, - - /** The current version. This should always be Count-1 */ - Current = Count - 1 - }; - //////// ctor //////// ExtPxAssetImpl(const ExtPxAssetDesc& desc, TkFramework& framework); - ExtPxAssetImpl(TkAsset* tkAsset); + ExtPxAssetImpl(const TkAssetDesc& desc, ExtPxChunk* pxChunks, ExtPxSubchunk* pxSubchunks, TkFramework& framework); + ExtPxAssetImpl(TkAsset* asset, ExtPxAssetDesc::ChunkDesc* chunks, uint32_t chunkCount); + ExtPxAssetImpl(TkAsset* asset); ~ExtPxAssetImpl(); @@ -87,36 +93,56 @@ public: return m_subchunks.begin(); } - virtual bool serialize(PxFileBuf& stream, PxCooking& cooking) const override; + virtual NvBlastActorDesc& getDefaultActorDesc() override + { + return m_defaultActorDesc; + } + + virtual const NvBlastActorDesc& getDefaultActorDesc() const override + { + return m_defaultActorDesc; + } + + virtual void setUniformHealth(bool enabled) override; + //////// internal public methods //////// + /* Get the underlying array for the chunks. Used for serialization. */ - ExtArray<ExtPxChunk>::type& getChunksArray() { return m_chunks; } + Array<ExtPxChunk>::type& getChunksArray() { return m_chunks; } /* Get the underlying array for the subchunks. Used for serialization. */ - ExtArray<ExtPxSubchunk>::type& getSubchunksArray() { return m_subchunks; } + Array<ExtPxSubchunk>::type& getSubchunksArray() { return m_subchunks; } -private: - //////// serialization data //////// + /* + Get the underlying array for the bond healths. Used for serialization. + */ + Array<float>::type& getBondHealthsArray() { return m_bondHealths; } - struct DataHeader - { - uint32_t dataType; - uint32_t version; - }; + /* + Get the underlying array for the support chunk healths. Used for serialization. + */ + Array<float>::type& getSupportChunkHealthsArray() { return m_supportChunkHealths; } + +private: - enum { ClassID = NVBLASTEXT_FOURCC('B', 'P', 'X', 'A') }; // Blast PhysX Asset + //////// initialization ///////// + void fillPhysicsChunks(ExtPxChunk* pxChunks, ExtPxSubchunk* pxSuchunk, uint32_t chunkCount); + void fillPhysicsChunks(ExtPxAssetDesc::ChunkDesc* desc, uint32_t count); //////// data //////// - TkAsset* m_tkAsset; - ExtArray<ExtPxChunk>::type m_chunks; - ExtArray<ExtPxSubchunk>::type m_subchunks; + TkAsset* m_tkAsset; + Array<ExtPxChunk>::type m_chunks; + Array<ExtPxSubchunk>::type m_subchunks; + Array<float>::type m_bondHealths; + Array<float>::type m_supportChunkHealths; + NvBlastActorDesc m_defaultActorDesc; }; } // namespace Blast diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp index b2d3a47..530bbe3 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtPxFamilyImpl.h" #include "NvBlastExtPxActorImpl.h" @@ -65,14 +83,14 @@ ExtPxFamilyImpl::~ExtPxFamilyImpl() void ExtPxFamilyImpl::release() { - NVBLASTEXT_DELETE(this, ExtPxFamilyImpl); + NVBLAST_DELETE(this, ExtPxFamilyImpl); } bool ExtPxFamilyImpl::spawn(const physx::PxTransform& pose, const physx::PxVec3& scale, const ExtPxSpawnSettings& settings) { - NVBLASTEXT_CHECK_ERROR(!m_isSpawned, "Family spawn: family already spawned. Was spawn() called twice?", return false); - NVBLASTEXT_CHECK_ERROR(settings.scene != nullptr, "Family creation: desc.scene is nullptr", return false); - NVBLASTEXT_CHECK_ERROR(settings.material != nullptr, "Family creation: desc.material is nullptr", return false); + NVBLAST_CHECK_ERROR(!m_isSpawned, "Family spawn: family already spawned. Was spawn() called twice?", return false); + NVBLAST_CHECK_ERROR(settings.scene != nullptr, "Family creation: desc.scene is nullptr", return false); + NVBLAST_CHECK_ERROR(settings.material != nullptr, "Family creation: desc.material is nullptr", return false); m_initialTransform = pose; m_spawnSettings = settings; @@ -119,7 +137,7 @@ bool ExtPxFamilyImpl::spawn(const physx::PxTransform& pose, const physx::PxVec3& bool ExtPxFamilyImpl::despawn() { - NVBLASTEXT_CHECK_ERROR(m_spawnSettings.scene != nullptr, "Family despawn: desc.scene is nullptr", return false); + NVBLAST_CHECK_ERROR(m_spawnSettings.scene != nullptr, "Family despawn: desc.scene is nullptr", return false); auto& actors = m_actorsBuffer; actors.resize(m_actors.size()); @@ -228,7 +246,7 @@ void ExtPxFamilyImpl::createActors(TkActor** tkActors, const PxActorCreateInfo* auto actorsToAdd = m_physXActorsBuffer.begin(); for (uint32_t i = 0; i < count; ++i) { - ExtPxActorImpl* actor = NVBLASTEXT_NEW(ExtPxActorImpl)(this, tkActors[i], pxActorInfos[i]); + ExtPxActorImpl* actor = NVBLAST_NEW(ExtPxActorImpl)(this, tkActors[i], pxActorInfos[i]); m_actors.insert(actor); actorsToAdd[i] = &actor->getPhysXActor(); dispatchActorCreated(*actor); @@ -237,7 +255,7 @@ void ExtPxFamilyImpl::createActors(TkActor** tkActors, const PxActorCreateInfo* auto e = m_manager.m_incompleteJointMultiMap.find(tkActors[i]); if (e != nullptr) { - ExtArray<TkJoint*>::type joints = e->second; // Copying the array + Array<TkJoint*>::type joints = e->second; // Copying the array m_manager.m_incompleteJointMultiMap.erase(tkActors[i]); for (uint32_t j = 0; j < joints.size(); ++j) { @@ -262,7 +280,7 @@ void ExtPxFamilyImpl::destroyActors(ExtPxActor** actors, uint32_t count) ExtPxActorImpl* actor = (ExtPxActorImpl*)actors[i]; m_actors.erase(actor); dispatchActorDestroyed(*actor); - NVBLASTEXT_DELETE(actor, ExtPxActorImpl); + NVBLAST_DELETE(actor, ExtPxActorImpl); } } diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.h index 5c90346..356e2c7 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.h +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.h @@ -1,19 +1,37 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXFAMILYIMPL_H #define NVBLASTEXTPXFAMILYIMPL_H #include "NvBlastExtPxFamily.h" -#include "NvBlastExtArray.h" -#include "NvBlastExtHashSet.h" +#include "NvBlastArray.h" +#include "NvBlastHashSet.h" #include "PxTransform.h" #include "NvBlastTkEvent.h" @@ -150,15 +168,15 @@ private: bool m_isSpawned; PxTransform m_initialTransform; PxVec3 m_initialScale; - ExtHashSet<ExtPxActor*>::type m_actors; - ExtArray<TkActor*>::type m_culledActors; - ExtInlineArray<ExtPxListener*, 4>::type m_listeners; - ExtArray<PxShape*>::type m_subchunkShapes; - ExtArray<TkActor*>::type m_newActorsBuffer; - ExtArray<PxActorCreateInfo>::type m_newActorCreateInfo; - ExtArray<PxActor*>::type m_physXActorsBuffer; - ExtArray<ExtPxActor*>::type m_actorsBuffer; - ExtArray<uint32_t>::type m_indicesScratch; + HashSet<ExtPxActor*>::type m_actors; + Array<TkActor*>::type m_culledActors; + InlineArray<ExtPxListener*, 4>::type m_listeners; + Array<PxShape*>::type m_subchunkShapes; + Array<TkActor*>::type m_newActorsBuffer; + Array<PxActorCreateInfo>::type m_newActorCreateInfo; + Array<PxActor*>::type m_physXActorsBuffer; + Array<ExtPxActor*>::type m_actorsBuffer; + Array<uint32_t>::type m_indicesScratch; }; } // namespace Blast diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.cpp index 42266ee..bb2c64d 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.cpp +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #include "NvBlastExtPxManagerImpl.h" #include "NvBlastExtPxAssetImpl.h" @@ -32,26 +50,30 @@ namespace Blast ExtPxManager* ExtPxManager::create(PxPhysics& physics, TkFramework& framework, ExtPxCreateJointFunction createFn, bool useUserData) { - return NVBLASTEXT_NEW(ExtPxManagerImpl)(physics, framework, createFn, useUserData); + return NVBLAST_NEW(ExtPxManagerImpl)(physics, framework, createFn, useUserData); } void ExtPxManagerImpl::release() { - NVBLASTEXT_DELETE(this, ExtPxManagerImpl); + NVBLAST_DELETE(this, ExtPxManagerImpl); } ExtPxFamily* ExtPxManagerImpl::createFamily(const ExtPxFamilyDesc& desc) { - NVBLASTEXT_CHECK_ERROR(desc.pxAsset != nullptr, "Family creation: pxAsset is nullptr.", return nullptr); + NVBLAST_CHECK_ERROR(desc.pxAsset != nullptr, "Family creation: pxAsset is nullptr.", return nullptr); - // create tk family + // prepare TkActorDesc (take NvBlastActorDesc from ExtPxFamilyDesc if it's not null, otherwise take from PxAsset) TkActorDesc tkActorDesc; - (&tkActorDesc)->NvBlastActorDesc::operator=(desc.actorDesc); + const NvBlastActorDesc& actorDesc = desc.actorDesc ? *desc.actorDesc : desc.pxAsset->getDefaultActorDesc(); + (&tkActorDesc)->NvBlastActorDesc::operator=(actorDesc); tkActorDesc.asset = &desc.pxAsset->getTkAsset(); + + // create tk actor TkActor* actor = m_framework.createActor(tkActorDesc); - NVBLASTEXT_CHECK_ERROR(actor != nullptr, "Family creation: tk actor creation failed.", return nullptr); + NVBLAST_CHECK_ERROR(actor != nullptr, "Family creation: tk actor creation failed.", return nullptr); - ExtPxFamilyImpl* family = NVBLASTEXT_NEW(ExtPxFamilyImpl)(*this, actor->getFamily(), *desc.pxAsset); + // create px family + ExtPxFamilyImpl* family = NVBLAST_NEW(ExtPxFamilyImpl)(*this, actor->getFamily(), *desc.pxAsset); if (desc.group) { @@ -68,7 +90,17 @@ bool ExtPxManagerImpl::createJoint(TkJoint& joint) const TkJointData data = joint.getData(); ExtPxActorImpl* pxActor0 = data.actors[0] != nullptr ? reinterpret_cast<ExtPxActorImpl*>(data.actors[0]->userData) : nullptr; ExtPxActorImpl* pxActor1 = data.actors[1] != nullptr ? reinterpret_cast<ExtPxActorImpl*>(data.actors[1]->userData) : nullptr; - NVBLAST_ASSERT(pxActor0 || pxActor1); + if (!pxActor0 && !pxActor1) + { + for (int i = 0; i < 2; ++i) + { + if (data.actors[i] != nullptr) + { + m_incompleteJointMultiMap[data.actors[i]].pushBack(&joint); + } + } + return false; + } PxTransform lf0(data.attachPositions[0]); PxTransform lf1(data.attachPositions[1]); PxJoint* pxJoint = m_createJointFn(pxActor0, lf0, pxActor1, lf1, m_physics, joint); @@ -83,9 +115,9 @@ bool ExtPxManagerImpl::createJoint(TkJoint& joint) void ExtPxManagerImpl::updateJoint(TkJoint& joint) { + const TkJointData& data = joint.getData(); if (joint.userData) { - const TkJointData& data = joint.getData(); ExtPxActorImpl* pxActors[2]; for (int i = 0; i < 2; ++i) { @@ -94,7 +126,7 @@ void ExtPxManagerImpl::updateJoint(TkJoint& joint) pxActors[i] = reinterpret_cast<ExtPxActorImpl*>(data.actors[i]->userData); if (pxActors[i] == nullptr) { - ExtArray<TkJoint*>::type& joints = m_incompleteJointMultiMap[data.actors[i]]; + Array<TkJoint*>::type& joints = m_incompleteJointMultiMap[data.actors[i]]; NVBLAST_ASSERT(joints.find(&joint) == joints.end()); joints.pushBack(&joint); return; // Wait until the TkActor is received to create this joint @@ -109,6 +141,18 @@ void ExtPxManagerImpl::updateJoint(TkJoint& joint) PxJoint* pxJoint = reinterpret_cast<PxJoint*>(joint.userData); pxJoint->setActors(pxActors[0] ? &pxActors[0]->getPhysXActor() : nullptr, pxActors[1] ? &pxActors[1]->getPhysXActor() : nullptr); } + else + { + ExtPxActorImpl* pxActor0 = data.actors[0] != nullptr ? reinterpret_cast<ExtPxActorImpl*>(data.actors[0]->userData) : nullptr; + ExtPxActorImpl* pxActor1 = data.actors[1] != nullptr ? reinterpret_cast<ExtPxActorImpl*>(data.actors[1]->userData) : nullptr; + PxTransform lf0(data.attachPositions[0]); + PxTransform lf1(data.attachPositions[1]); + PxJoint* pxJoint = m_createJointFn(pxActor0, lf0, pxActor1, lf1, m_physics, joint); + if (pxJoint) + { + joint.userData = pxJoint; + } + } } void ExtPxManagerImpl::destroyJoint(TkJoint& joint) diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.h index 1f5e510..9c74bdb 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.h +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxManagerImpl.h @@ -1,19 +1,37 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTPXMANAGERIMPL_H #define NVBLASTEXTPXMANAGERIMPL_H #include "NvBlastExtPxManager.h" -#include "NvBlastExtArray.h" -#include "NvBlastExtHashMap.h" +#include "NvBlastArray.h" +#include "NvBlastHashMap.h" #include "NvBlastExtPxListener.h" #include "NvBlastExtPxFamily.h" @@ -188,10 +206,10 @@ private: TkFramework& m_framework; ExtPxCreateJointFunction m_createJointFn; bool m_usePxUserData; - ExtInlineArray<ExtPxListener*, 8>::type m_listeners; - ExtHashMap<const PxRigidDynamic*, ExtPxActor*>::type m_physXActorsMap; - ExtHashMap<TkFamily*, ExtPxFamily*>::type m_tkFamiliesMap; - ExtHashMap<TkActor*, ExtArray<TkJoint*>::type >::type m_incompleteJointMultiMap; + InlineArray<ExtPxListener*, 8>::type m_listeners; + HashMap<const PxRigidDynamic*, ExtPxActor*>::type m_physXActorsMap; + HashMap<TkFamily*, ExtPxFamily*>::type m_tkFamiliesMap; + HashMap<TkActor*, Array<TkJoint*>::type >::type m_incompleteJointMultiMap; uint32_t m_actorCountLimit; }; diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.cpp new file mode 100644 index 0000000..2b331d3 --- /dev/null +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.cpp @@ -0,0 +1,229 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastExtPxStressSolverImpl.h" +#include "NvBlastExtPxAsset.h" +#include "NvBlastExtPxFamily.h" +#include "NvBlastExtPxActor.h" +#include "NvBlastAssert.h" +#include "NvBlastIndexFns.h" + +#include "NvBlastTkAsset.h" +#include "NvBlastTkActor.h" +#include "NvBlastTkFamily.h" + +#include "PxScene.h" +#include "PxRigidDynamic.h" + +#define USE_PHYSX_NODE_INFO 1 + + +namespace Nv +{ +namespace Blast +{ + +using namespace physx; + + +ExtPxStressSolverImpl::ExtPxStressSolverImpl(ExtPxFamily& family, ExtStressSolverSettings settings) + : m_family(family) +{ + NvBlastFamily* familyLL = const_cast<NvBlastFamily*>(family.getTkFamily().getFamilyLL()); + NVBLAST_ASSERT(familyLL); + m_solver = ExtStressSolver::create(*familyLL, settings); + + const TkAsset* tkAsset = m_family.getTkFamily().getAsset(); + const ExtPxAsset& asset = m_family.getPxAsset(); + const ExtPxChunk* chunks = asset.getChunks(); + const ExtPxSubchunk* subChunks = asset.getSubchunks(); + const NvBlastSupportGraph graph = tkAsset->getGraph(); + const uint32_t chunkCount = tkAsset->getChunkCount(); + + TkActor* tkActor; + m_family.getTkFamily().getActors(&tkActor, 1); + const float* bondHealths = tkActor->getBondHealths(); + +#if USE_PHYSX_NODE_INFO + // traverse graph and fill node info, + // essentially it does the same as m_solver->setAllNodesInfoFromLL() but fills mass, volume, transform from physx + // and it also uses ExtPxChunk isStatic flag in addition to 'world' node in LL + for (uint32_t node0 = 0; node0 < graph.nodeCount; ++node0) + { + uint32_t chunkIndex0 = graph.chunkIndices[node0]; + const ExtPxChunk* chunk0 = chunkIndex0 < chunkCount ? &chunks[chunkIndex0] : nullptr; + bool isChunkStatic = true; + + if (chunk0) + { + isChunkStatic = chunk0->isStatic; + for (uint32_t adjacencyIndex = graph.adjacencyPartition[node0]; adjacencyIndex < graph.adjacencyPartition[node0 + 1]; adjacencyIndex++) + { + uint32_t bondIndex = graph.adjacentBondIndices[adjacencyIndex]; + if (bondHealths[bondIndex] <= 0.0f) + continue; + uint32_t node1 = graph.adjacentNodeIndices[adjacencyIndex]; + uint32_t chunkIndex1 = graph.chunkIndices[node1]; + if (chunkIndex1 < chunkCount) + { + const ExtPxChunk& chunk1 = chunks[chunkIndex1]; + + if (chunk1.subchunkCount == 0 || chunk1.isStatic) + { + isChunkStatic |= chunk1.isStatic; + continue; + } + } + else + { + isChunkStatic = true; + break; + } + } + } + + // fill node info + float mass; + float volume; + PxVec3 localPos; + if (chunk0 && chunk0->subchunkCount > 0) + { + const ExtPxSubchunk& subChunk = subChunks[chunk0->firstSubchunkIndex]; + PxVec3 localCenterOfMass; + PxMat33 intertia; + PxVec3 scale = subChunk.geometry.scale.scale; + subChunk.geometry.convexMesh->getMassInformation(mass, intertia, localCenterOfMass); + mass *= scale.x * scale.y * scale.z; + const PxTransform& chunk0LocalTransform = subChunk.transform; + localPos = chunk0LocalTransform.transform(localCenterOfMass); + volume = mass / 1.0f; // unit density + } + else + { + mass = 0.0f; + volume = 0.0f; + localPos = PxVec3(PxZero); + isChunkStatic = true; + } + m_solver->setNodeInfo(node0, mass, volume, localPos, isChunkStatic); + } +#else + m_solver->setAllNodesInfoFromLL(); +#endif + + // notify initial actor's created + InlineArray<ExtPxActor*, 4>::type actors;; + actors.resize(m_family.getActorCount()); + m_family.getActors(actors.begin(), actors.size()); + for (const auto actor : actors) + { + onActorCreated(m_family, *actor); + } + + m_family.subscribe(*this); +} + +ExtPxStressSolverImpl::~ExtPxStressSolverImpl() +{ + m_family.unsubscribe(*this); + m_solver->release(); +} + +ExtPxStressSolver* ExtPxStressSolver::create(ExtPxFamily& family, ExtStressSolverSettings settings) +{ + return NVBLAST_NEW(ExtPxStressSolverImpl) (family, settings); +} + +void ExtPxStressSolverImpl::release() +{ + NVBLAST_DELETE(this, ExtPxStressSolverImpl); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Update Wrapper +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ExtPxStressSolverImpl::update(bool doDamage) +{ + for (auto it = m_actors.getIterator(); !it.done(); ++it) + { + const ExtPxActor* actor = *it; + + PxRigidDynamic& rigidDynamic = actor->getPhysXActor(); + const bool isStatic = rigidDynamic.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC; + if (isStatic) + { + PxVec3 gravity = rigidDynamic.getScene()->getGravity(); + PxVec3 localGravity = rigidDynamic.getGlobalPose().rotateInv(gravity); + + m_solver->addGravityForce(*actor->getTkActor().getActorLL(), localGravity); + } + else + { + PxVec3 localCenterMass = rigidDynamic.getCMassLocalPose().p; + PxVec3 localAngularVelocity = rigidDynamic.getGlobalPose().rotateInv(rigidDynamic.getAngularVelocity()); + m_solver->addAngularVelocity(*actor->getTkActor().getActorLL(), localCenterMass, localAngularVelocity); + } + } + + m_solver->update(); + + if (doDamage && m_solver->getOverstressedBondCount() > 0) + { + NvBlastFractureBuffers commands; + m_solver->generateFractureCommands(commands); + if (commands.bondFractureCount > 0) + { + m_family.getTkFamily().applyFracture(&commands); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Actors +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ExtPxStressSolverImpl::onActorCreated(ExtPxFamily& /*family*/, ExtPxActor& actor) +{ + if (m_solver->notifyActorCreated(*actor.getTkActor().getActorLL())) + { + m_actors.insert(&actor); + } +} + +void ExtPxStressSolverImpl::onActorDestroyed(ExtPxFamily& /*family*/, ExtPxActor& actor) +{ + m_solver->notifyActorDestroyed(*actor.getTkActor().getActorLL()); + m_actors.erase(&actor); +} + + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.h new file mode 100644 index 0000000..f27fe6c --- /dev/null +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxStressSolverImpl.h @@ -0,0 +1,86 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTPXSTRESSSOLVERIMPL_H +#define NVBLASTEXTPXSTRESSSOLVERIMPL_H + +#include "NvBlastExtPxStressSolver.h" +#include "NvBlastExtPxListener.h" +#include "NvBlastArray.h" +#include "NvBlastHashSet.h" + +namespace Nv +{ +namespace Blast +{ + + +class ExtPxStressSolverImpl final : public ExtPxStressSolver, ExtPxListener +{ + NV_NOCOPY(ExtPxStressSolverImpl) + +public: + ExtPxStressSolverImpl(ExtPxFamily& family, ExtStressSolverSettings settings); + + + //////// ExtPxStressSolver interface //////// + + virtual void release() override; + + virtual ExtStressSolver& getSolver() const override + { + return *m_solver; + } + + virtual void update(bool doDamage) override; + + + //////// ExtPxListener interface //////// + + virtual void onActorCreated(ExtPxFamily& family, ExtPxActor& actor) final; + + virtual void onActorDestroyed(ExtPxFamily& family, ExtPxActor& actor) final; + + +private: + ~ExtPxStressSolverImpl(); + + + //////// data //////// + + ExtPxFamily& m_family; + ExtStressSolver* m_solver; + HashSet<ExtPxActor*>::type m_actors; +}; + + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTEXTPXSTRESSSOLVERIMPL_H diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.cpp new file mode 100644 index 0000000..55a6eae --- /dev/null +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.cpp @@ -0,0 +1,126 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastGlobals.h" +#include "NvBlastExtPxTaskImpl.h" + +#include "NvBlastTkGroup.h" + +using namespace Nv::Blast; + + +uint32_t ExtGroupTaskManagerImpl::process(uint32_t workerCount) +{ + NVBLAST_CHECK_WARNING(m_group != nullptr, "ExtGroupTaskManager::process cannot process, no group set.", return 0); + NVBLAST_CHECK_WARNING(m_sync.isDone(), "ExtGroupTaskManager::process group is already being processed.", return 0); + + // at least one task must start, even when dispatcher has none specified + uint32_t dispatcherThreads = m_taskManager.getCpuDispatcher()->getWorkerCount(); + dispatcherThreads = dispatcherThreads > 0 ? dispatcherThreads : 1; + + // not expecting an arbitrary amount of tasks + uint32_t availableTasks = TASKS_MAX_COUNT; + + // use workerCount tasks, unless dispatcher has less threads or less tasks are available + uint32_t requestedTasks = workerCount > 0 ? workerCount : dispatcherThreads; + requestedTasks = requestedTasks > dispatcherThreads ? dispatcherThreads : requestedTasks; + requestedTasks = requestedTasks > availableTasks ? availableTasks : requestedTasks; + + // ensure the group has enough memory allocated for concurrent processing + m_group->setWorkerCount(requestedTasks); + + // check if there is work to do + uint32_t jobCount = m_group->startProcess(); + + if (jobCount) + { + // don't start more tasks than jobs are available + requestedTasks = requestedTasks > jobCount ? jobCount : requestedTasks; + + // common counter for all tasks + m_counter.reset(jobCount); + + // set to busy state + m_sync.setCount(requestedTasks); + + // set up tasks + for (uint32_t i = 0; i < requestedTasks; i++) + { + m_tasks[i].setup(m_group, &m_counter, &m_sync); + m_tasks[i].setContinuation(m_taskManager, nullptr); + m_tasks[i].removeReference(); + } + + return requestedTasks; + } + + // there was no work to be done + return 0; +} + + +bool ExtGroupTaskManagerImpl::wait(bool block) +{ + if (block && !m_sync.isDone()) + { + m_sync.wait(); + } + if (m_sync.isDone()) + { + return m_group->endProcess(); + } + return false; +} + + +void ExtGroupTaskManagerImpl::setGroup(TkGroup* group) +{ + NVBLAST_CHECK_WARNING(m_sync.isDone(), "ExtGroupTaskManager::setGroup trying to change group while processing.", return); + + m_group = group; +} + + +ExtGroupTaskManager* ExtGroupTaskManager::create(physx::PxTaskManager& taskManager) +{ + return NVBLAST_NEW(ExtGroupTaskManagerImpl) (taskManager); +} + + +ExtGroupTaskManager* ExtGroupTaskManager::create(physx::PxTaskManager& taskManager, TkGroup& group) +{ + return NVBLAST_NEW(ExtGroupTaskManagerImpl) (taskManager, group); +} + + +void ExtGroupTaskManagerImpl::release() +{ + NVBLAST_CHECK_WARNING(m_sync.isDone(), "ExtGroupTaskManager::release group is still being processed.", return); + + NVBLAST_DELETE(this, ExtGroupTaskManagerImpl); +} diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.h new file mode 100644 index 0000000..f705e71 --- /dev/null +++ b/sdk/extensions/physx/source/physics/NvBlastExtPxTaskImpl.h @@ -0,0 +1,212 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTPXTASKIMPL_H +#define NVBLASTEXTPXTASKIMPL_H + +#include "NvBlastExtPxTask.h" +#include "PxTask.h" +#include "NvBlastTkGroup.h" + +#include <atomic> +#include <mutex> +#include <condition_variable> + +namespace Nv +{ +namespace Blast +{ + +/** +Counting synchronization object for waiting on TkWorkers to finish. +*/ +class ExtTaskSync +{ +public: + /** + Initializes with an expected number of notifications. + */ + ExtTaskSync(uint32_t count) : m_count(count) {} + + /** + Blocks until the expected number of notifications happened. + */ + void wait() + { + std::unique_lock<std::mutex> lk(m_mutex); + m_cv.wait(lk, [&] { return m_count == 0; }); + } + + /** + Decrement the wait() count by one. + */ + void notify() + { + //PERF_SCOPE_H("TaskSync::notify"); + std::unique_lock<std::mutex> lk(m_mutex); + if (m_count > 0) + { + m_count--; + } + if (m_count == 0) + { + lk.unlock(); + m_cv.notify_one(); + } + } + + /** + Peek if notifications are pending. + */ + bool isDone() + { + std::unique_lock<std::mutex> lk(m_mutex); + return m_count == 0; + } + + /** + Sets the expected number of notifications for wait() to unblock. + */ + void setCount(uint32_t count) + { + m_count = count; + } + +private: + std::mutex m_mutex; + std::condition_variable m_cv; + uint32_t m_count; +}; + + +/** +Common job counter for all tasks. +*/ +class ExtAtomicCounter +{ +public: + ExtAtomicCounter() : m_current(0), m_maxCount(0) {} + + bool isValid(uint32_t val) + { + return val < m_maxCount; + } + + uint32_t next() + { + return m_current.fetch_add(1); + } + + void reset(uint32_t maxCount) + { + m_maxCount = maxCount; + m_current = 0; + } +private: + std::atomic<uint32_t> m_current; + uint32_t m_maxCount; +}; + + +/** +A task running one group job after the other until done. Synchronizes atomically with its siblings. +*/ +class ExtGroupWorkerTask : public physx::PxLightCpuTask +{ +public: + ExtGroupWorkerTask() : PxLightCpuTask(), m_group(nullptr), m_counter(nullptr), m_sync(nullptr) + { + } + + void setup(TkGroup* group, ExtAtomicCounter* counter, ExtTaskSync* sync) + { + m_group = group; + m_counter = counter; + m_sync = sync; + } + + virtual void run() override + { + Nv::Blast::TkGroupWorker* worker = m_group->acquireWorker(); + uint32_t jobID = m_counter->next(); + while (m_counter->isValid(jobID)) + { + worker->process(jobID); + jobID = m_counter->next(); + } + m_group->returnWorker(worker); + } + + virtual void release() override + { + PxLightCpuTask::release(); + + // release the sync last + m_sync->notify(); + } + + virtual const char* getName() const override { return "BlastGroupWorkerTask"; } + +private: + TkGroup* m_group; + ExtAtomicCounter* m_counter; + ExtTaskSync* m_sync; +}; + + +/** +Implements ExtGroupTaskManager +*/ +class ExtGroupTaskManagerImpl : public ExtGroupTaskManager +{ +public: + ExtGroupTaskManagerImpl(physx::PxTaskManager& taskManager) + : m_taskManager(taskManager), m_sync(0), m_group(nullptr) {} + + ExtGroupTaskManagerImpl(physx::PxTaskManager& taskManager, TkGroup& group) + : m_taskManager(taskManager), m_sync(0), m_group(&group) {} + + // public API + virtual void setGroup(TkGroup*) override; + virtual uint32_t process(uint32_t) override; + virtual void release() override; + virtual bool wait(bool block) override; + +private: + static const uint32_t TASKS_MAX_COUNT = 16; + physx::PxTaskManager& m_taskManager; + ExtAtomicCounter m_counter; + ExtGroupWorkerTask m_tasks[TASKS_MAX_COUNT]; + ExtTaskSync m_sync; + TkGroup* m_group; +}; + +} // namespace Blast +} // namespace Nv + +#endif // NVBLASTEXTPXTASKIMPL_H
\ No newline at end of file diff --git a/sdk/extensions/physx/source/sync/NvBlastExtSync.cpp b/sdk/extensions/physx/source/sync/NvBlastExtSync.cpp index 5f018d9..a74f3e7 100644 --- a/sdk/extensions/physx/source/sync/NvBlastExtSync.cpp +++ b/sdk/extensions/physx/source/sync/NvBlastExtSync.cpp @@ -1,18 +1,34 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. #include "NvBlastExtSync.h" #include "NvBlastAssert.h" #include "NvBlast.h" -#include "NvBlastExtDefs.h" #include "NvBlastExtPxManager.h" #include "NvBlastExtPxFamily.h" #include "NvBlastExtPxActor.h" @@ -39,7 +55,7 @@ public: ExtSyncImpl(); - ~ExtSyncImpl(); + virtual ~ExtSyncImpl(); //////// TkEventListener interface //////// @@ -74,7 +90,7 @@ private: void ExtSyncEvent::release() { - NVBLASTEXT_DELETE(this, ExtSyncEvent); + NVBLAST_DELETE(this, ExtSyncEvent); } @@ -84,12 +100,12 @@ void ExtSyncEvent::release() ExtSync* ExtSync::create() { - return NVBLASTEXT_NEW(ExtSyncImpl) (); + return NVBLAST_NEW(ExtSyncImpl) (); } void ExtSyncImpl::release() { - NVBLASTEXT_DELETE(this, ExtSyncImpl); + NVBLAST_DELETE(this, ExtSyncImpl); } ExtSyncImpl::ExtSyncImpl() @@ -109,7 +125,7 @@ void ExtSyncImpl::receive(const TkEvent* events, uint32_t eventCount) if (tkEvent.type == TkEvent::FractureCommand) { const TkFractureCommands* fracEvent = tkEvent.getPayload<TkFractureCommands>(); - ExtSyncEventFracture* e = NVBLASTEXT_NEW(ExtSyncEventFracture) (); + ExtSyncEventFracture* e = NVBLAST_NEW(ExtSyncEventFracture) (); e->timestamp = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count(); e->familyID = fracEvent->tkActorData.family->getID(); e->bondFractures.resize(fracEvent->buffers.bondFractureCount); @@ -123,11 +139,11 @@ void ExtSyncImpl::receive(const TkEvent* events, uint32_t eventCount) void ExtSyncImpl::syncFamily(const TkFamily& family) { - ExtSyncEventFamilySync* e = NVBLASTEXT_NEW(ExtSyncEventFamilySync) (); + ExtSyncEventFamilySync* e = NVBLAST_NEW(ExtSyncEventFamilySync) (); e->timestamp = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count(); e->familyID = family.getID(); const NvBlastFamily* familyLL = family.getFamilyLL(); - const uint32_t size = NvBlastFamilyGetSize(familyLL, NvBlastTkFrameworkGet()->getLogFn()); + const uint32_t size = NvBlastFamilyGetSize(familyLL, logLL); e->family = std::vector<char>((char*)familyLL, (char*)familyLL + size); m_syncEvents.push_back(e); } @@ -138,7 +154,7 @@ void ExtSyncImpl::syncFamily(const ExtPxFamily& family) syncFamily(tkFamily); - ExtSyncEventPhysicsSync* e = NVBLASTEXT_NEW(ExtSyncEventPhysicsSync) (); + ExtSyncEventPhysicsSync* e = NVBLAST_NEW(ExtSyncEventPhysicsSync) (); e->timestamp = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count(); e->familyID = tkFamily.getID(); std::vector<ExtPxActor*> actors(family.getActorCount()); @@ -170,7 +186,7 @@ void ExtSyncImpl::releaseSyncBuffer() { for (uint32_t i = 0; i < m_syncEvents.size(); ++i) { - NVBLASTEXT_DELETE(m_syncEvents[i], ExtSyncEvent); + NVBLAST_DELETE(m_syncEvents[i], ExtSyncEvent); } m_syncEvents.clear(); } diff --git a/sdk/extensions/serialization/include/NvBlastExtLlSerialization.h b/sdk/extensions/serialization/include/NvBlastExtLlSerialization.h new file mode 100644 index 0000000..db90a1a --- /dev/null +++ b/sdk/extensions/serialization/include/NvBlastExtLlSerialization.h @@ -0,0 +1,113 @@ +// 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. + + +#pragma once + +#include "NvBlastGlobals.h" + + +/** +Blast Low-level serialization support. Contains serializers which can be used by the ExtSerialization manager. +*/ + + +// Forward declarations +struct NvBlastAsset; +struct NvBlastFamily; + + +namespace Nv +{ +namespace Blast +{ + +// Forward declarations +class ExtSerialization; + + +/** Standard Object Type IDs */ +struct LlObjectTypeID +{ + enum Enum + { + Asset = NVBLAST_FOURCC('L', 'L', 'A', 'S'), + Family = NVBLAST_FOURCC('L', 'L', 'F', 'A'), + }; +}; + +} // namespace Blast +} // namespace Nv + + +/** +Load all low-level serializers into the ExtSerialization manager. *N.B.* This is done automatically when +the ExtSerialization manager is created via NvBlastExtSerializationCreate(), so currently this public function +is unnecessary. Note also that other modules' serializers (ExtTkSerialization and ExtPxSerialization) are +_not_ loaded automatically, and need to be explicitly loaded by the user using their respective load functions. + +It does no harm to call this function more than once; serializers already loaded will not be loaded again. + +\param[in] serialization Serialization manager into which to load serializers. + +\return the number of serializers loaded. +*/ +NVBLAST_API size_t NvBlastExtLlSerializerLoadSet(Nv::Blast::ExtSerialization& serialization); + + +/** +Utility wrapper function to serialize an NvBlastAsset. Allocates the buffer internally using the +callack set in ExtSerialization::setBufferProvider. + +Equivalent to: + + serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::LlObjectTypeID::Asset); + +\param[out] buffer Pointer to the buffer created. +\param[in] serialization Serialization manager. +\param[in] asset Pointer to the NvBlastAsset to serialize. + +\return the number of bytes serialized into the buffer (zero if unsuccessful). +*/ +NVBLAST_API uint64_t NvBlastExtSerializationSerializeAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const NvBlastAsset* asset); + + +/** +Utility wrapper function to serialize an NvBlastFamily. Allocates the buffer internally using the +callack set in ExtSerialization::setBufferProvider. + +Equivalent to: + + serialization.serializeIntoBuffer(buffer, family, Nv::Blast::LlObjectTypeID::Family); + +\param[out] buffer Pointer to the buffer created. +\param[in] serialization Serialization manager. +\param[in] family Pointer to the NvBlastFamily to serialize. + +\return the number of bytes serialized into the buffer (zero if unsuccessful). +*/ +NVBLAST_API uint64_t NvBlastExtSerializationSerializeFamilyIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const NvBlastFamily* family); diff --git a/sdk/extensions/serialization/include/NvBlastExtPxSerialization.h b/sdk/extensions/serialization/include/NvBlastExtPxSerialization.h new file mode 100644 index 0000000..d3457ab --- /dev/null +++ b/sdk/extensions/serialization/include/NvBlastExtPxSerialization.h @@ -0,0 +1,99 @@ +// 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. + + +#pragma once + +#include "NvBlastGlobals.h" + + +/** +Blast serialization support for the ExtPhysX extension. Contains serializers which can be used by the ExtSerialization manager. +*/ + + +namespace Nv +{ +namespace Blast +{ + +// Forward declarations +class TkFramework; +class ExtSerialization; +class ExtPxAsset; + + +/** Standard Object Type IDs */ +struct ExtPxObjectTypeID +{ + enum Enum + { + Asset = NVBLAST_FOURCC('P', 'X', 'A', 'S'), + }; +}; + +} // namespace Blast +} // namespace Nv + + +namespace physx +{ + +// Forward declarations +class PxPhysics; +class PxCooking; + +} // namespace physx + + +/** +Load all ExtPhysX extension serializers into the ExtSerialization manager. + +It does no harm to call this function more than once; serializers already loaded will not be loaded again. + +\param[in] serialization Serialization manager into which to load serializers. + +\return the number of serializers loaded. +*/ +NVBLAST_API size_t NvBlastExtPxSerializerLoadSet(Nv::Blast::TkFramework& framework, physx::PxPhysics& physics, physx::PxCooking& cooking, Nv::Blast::ExtSerialization& serialization); + + +/** +Utility wrapper function to serialize an ExtPxAsset. Allocates the buffer internally using the +callack set in ExtSerialization::setBufferProvider. + +Equivalent to: + + serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::ExtPxObjectTypeID::Asset); + +\param[out] buffer Pointer to the buffer created. +\param[in] serialization Serialization manager. +\param[in] asset Pointer to the ExtPxAsset to serialize. + +\return the number of bytes serialized into the buffer (zero if unsuccessful). +*/ +NVBLAST_API uint64_t NvBlastExtSerializationSerializeExtPxAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const Nv::Blast::ExtPxAsset* asset); diff --git a/sdk/extensions/serialization/include/NvBlastExtSerialization.h b/sdk/extensions/serialization/include/NvBlastExtSerialization.h new file mode 100644 index 0000000..4225625 --- /dev/null +++ b/sdk/extensions/serialization/include/NvBlastExtSerialization.h @@ -0,0 +1,156 @@ +// 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. + + +#pragma once + +#include "NvBlastGlobals.h" + + +namespace Nv +{ +namespace Blast +{ + +/** + Serialization manager interface +*/ +class ExtSerialization +{ +public: + /** Standard Encoding IDs */ + struct EncodingID + { + enum Enum + { + CapnProtoBinary = NVBLAST_FOURCC('C', 'P', 'N', 'B'), + RawBinary = NVBLAST_FOURCC('R', 'A', 'W', ' '), + }; + }; + + /** Buffer provider API, used to request a buffer for serialization. */ + class BufferProvider + { + public: + virtual void* requestBuffer(size_t size) = 0; + }; + + /** + Set the serialization encoding to use. (See EncodingID.) + + \return true iff successful. + */ + virtual bool setSerializationEncoding(uint32_t encodingID) = 0; + + /** + Retrieve the current serialization encoding being used. Note, by default this is set to the encoding of the first + serializer registered by a module. Currently this is done automatically by the NvBlastExtLlExtension module. + + \return the current serialization encoding (zero if none is set). + */ + virtual uint32_t getSerializationEncoding() const = 0; + + /** + Set the buffer provider callback to use. (See BufferProvider.) If not set, a default provider using NVBLAST_ALLOC (see + NvBlastGlobals.h) is used, which may be freed using NvBLAST_FREE. + + \param[in] bufferProvider Buffer provider callback to use. If NULL, uses the default provider using the allocator given + in NvBlastGlobals. + */ + virtual void setBufferProvider(BufferProvider* bufferProvider) = 0; + + /** + Reads information from a buffer, returning the contained object type ID, encoding ID, and data size. + \param[out] objectTypeID If not NULL, the object type ID is written to *objectTypeID. + \param[out] encodingID If not NULL, the encoding ID is written to *encodingID. + \param[out] dataSize If not NULL, the data size is written to *dataSize. (Does not include the size of the header.) + \param[in] buffer Pointer to the buffer to read. + \param[in] bufferSize Size of the buffer to read. + + \return true iff the header is successfully read. + */ + virtual bool peekHeader(uint32_t* objectTypeID, uint32_t* encodingID, uint64_t* dataSize, const void* buffer, uint64_t bufferSize) = 0; + + /** + Determines the current object in the buffer and returns the position in the buffer immediately after the object. + + \param[in, out] bufferSize Size of the buffer to read on input, on output the remaining buffer size given the return buffer value. + \param[in] buffer Pointer to the buffer to read. + + \return a pointer to the new position in the buffer after the skipped object if successful, NULL otherwise. The bufferSize field is only updated if a valid pointer is returned. + */ + virtual const void* skipObject(uint64_t& bufferSize, const void* buffer) = 0; + + /** + Deserialize from a buffer into a newly allocated object. + + \param[in] buffer Pointer to the buffer to read. + \param[in] bufferSize Size of the buffer to read. + \param[out] objectTypeIDPtr Optional, if not NULL then *objectTypeIDPtr will be filled with the deserialized object's + type ID if deserialization is successful, or 0 if unsuccessful. + + \return object pointer; returns null if failed to deserialize. + */ + virtual void* deserializeFromBuffer(const void* buffer, uint64_t bufferSize, uint32_t* objectTypeIDPtr = nullptr) = 0; + + /** + Serialize into a buffer. Allocates the buffer internally using the callack set in setBufferProvider. + + \param[out] buffer Pointer to the buffer created. + \param[in] object Object pointer. + \param[in] objectTypeID Object type ID. + + \return the number of bytes serialized into the buffer (zero if unsuccessful). + */ + virtual uint64_t serializeIntoBuffer(void*& buffer, const void* object, uint32_t objectTypeID) = 0; + + /** + Release the serialization manager and all contained objects. + */ + virtual void release() = 0; + +protected: + /** + Destructor is virtual and not public - use the release() method instead of explicitly deleting the serialization manager + */ + virtual ~ExtSerialization() {} +}; + +} // namespace Blast +} // namespace Nv + + +//////// Global API to create serialization //////// + +/** +Create a new serialization manager. To release it, use its release() method. + +This uses the global allocator set in NvBlastGlobals.h. + +\return a new serialization manager. +*/ +NVBLAST_API Nv::Blast::ExtSerialization* NvBlastExtSerializationCreate(); diff --git a/sdk/extensions/serialization/include/NvBlastExtSerializationInterface.h b/sdk/extensions/serialization/include/NvBlastExtSerializationInterface.h deleted file mode 100644 index e4f27e0..0000000 --- a/sdk/extensions/serialization/include/NvBlastExtSerializationInterface.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -/* - Include this file to get the C interface to serialization for all asset types (LL, Tk and Ext) -*/ -#pragma once -#include <ostream> -#include "NvBlastTkAsset.h" -#include "NvBlastExtPxAsset.h" - -#include "NvBlastExtSerializationLLInterface.h" - -namespace physx -{ - class PxPhysics; -} - -NVBLAST_API void setPhysXSDK(physx::PxPhysics* physXSDK); - -NVBLAST_API Nv::Blast::TkAsset* deserializeTkAsset(const unsigned char* input, uint32_t size); -NVBLAST_API Nv::Blast::TkAsset* deserializeTkAssetFromStream(std::istream &inputStream); -NVBLAST_API bool serializeTkAssetIntoStream(const Nv::Blast::TkAsset *asset, std::ostream &outputStream); -NVBLAST_API bool serializeTkAssetIntoNewBuffer(const Nv::Blast::TkAsset *asset, unsigned char **outBuffer, uint32_t &outSize); -NVBLAST_API bool serializeTkAssetIntoExistingBuffer(const Nv::Blast::TkAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize); - -NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAsset(const unsigned char* input, uint32_t size); -NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAssetFromStream(std::istream &inputStream); -NVBLAST_API bool serializeExtPxAssetIntoStream(const Nv::Blast::ExtPxAsset *asset, std::ostream &outputStream); -NVBLAST_API bool serializeExtPxAssetIntoNewBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char **outBuffer, uint32_t &outSize); -NVBLAST_API bool serializeExtPxAssetIntoExistingBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize); diff --git a/sdk/extensions/serialization/include/NvBlastExtSerializationLLInterface.h b/sdk/extensions/serialization/include/NvBlastExtSerializationLLInterface.h deleted file mode 100644 index d21c7ca..0000000 --- a/sdk/extensions/serialization/include/NvBlastExtSerializationLLInterface.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -/* -Include this file to access the C API for serialization, for Low Level assets only. - -For Serialization of Tk and Ext assets, include only NvBlastExtSerializationInterface.h, which will include this file as well. - -*/ -#pragma once -#include <ostream> -#include "NvBlastPreprocessor.h" -#include "NvBlastTypes.h" - -#include "NvBlastExtGlobals.h" - -/* - Set a global NvBlastAlloc signature allocation function that the deserialization will use when required. - - NOTE: This will NOT be used when using the combined serialization library, as it will use the TkFramework's allocation and logging -*/ -NVBLAST_API void setAllocator(NvBlastExtAlloc alloc); - -/* - Set a global NvBlastLog signature allocation function that the library will use when required. - - NOTE: This will NOT be used when using the combined serialization library, as it will use the TkFramework's allocation and logging -*/ -NVBLAST_API void setLog(NvBlastLog log); - - -NVBLAST_API NvBlastAsset* deserializeAsset(const unsigned char* input, uint32_t size); -NVBLAST_API NvBlastAsset* deserializeAssetFromStream(std::istream &inputStream); -NVBLAST_API bool serializeAssetIntoStream(const NvBlastAsset *asset, std::ostream &outputStream); -NVBLAST_API bool serializeAssetIntoNewBuffer(const NvBlastAsset *asset, unsigned char **outBuffer, uint32_t &outSize); -NVBLAST_API bool serializeAssetIntoExistingBuffer(const NvBlastAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize); diff --git a/sdk/extensions/serialization/include/NvBlastExtTkSerialization.h b/sdk/extensions/serialization/include/NvBlastExtTkSerialization.h new file mode 100644 index 0000000..2db4f4f --- /dev/null +++ b/sdk/extensions/serialization/include/NvBlastExtTkSerialization.h @@ -0,0 +1,89 @@ +// 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. + + +#pragma once + +#include "NvBlastGlobals.h" + + +/** +Blast High-level serialization support. Contains serializers which can be used by the ExtSerialization manager. +*/ + + +namespace Nv +{ +namespace Blast +{ + +// Forward declarations +class ExtSerialization; +class TkFramework; +class TkAsset; + + +/** Standard Object Type IDs */ +struct TkObjectTypeID +{ + enum Enum + { + Asset = NVBLAST_FOURCC('T', 'K', 'A', 'S'), + }; +}; + +} // namespace Blast +} // namespace Nv + + +/** +Load all high-level serializers into the ExtSerialization manager. + +It does no harm to call this function more than once; serializers already loaded will not be loaded again. + +\param[in] serialization Serialization manager into which to load serializers. + +\return the number of serializers loaded. +*/ +NVBLAST_API size_t NvBlastExtTkSerializerLoadSet(Nv::Blast::TkFramework& framework, Nv::Blast::ExtSerialization& serialization); + + +/** +Utility wrapper function to serialize a TkAsset. Allocates the buffer internally using the +callack set in ExtSerialization::setBufferProvider. + +Equivalent to: + + serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::TkObjectTypeID::Asset); + +\param[out] buffer Pointer to the buffer created. +\param[in] serialization Serialization manager. +\param[in] asset Pointer to the TkAsset to serialize. + +\return the number of bytes serialized into the buffer (zero if unsuccessful). +*/ +NVBLAST_API uint64_t NvBlastExtSerializationSerializeTkAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const Nv::Blast::TkAsset* asset); diff --git a/sdk/extensions/serialization/source/BlastSerialization.capn b/sdk/extensions/serialization/source/BlastSerialization.capn deleted file mode 100644 index 49b1dbb..0000000 --- a/sdk/extensions/serialization/source/BlastSerialization.capn +++ /dev/null @@ -1,162 +0,0 @@ -@0xaffe4498f275ee58; - -using Cxx = import "/capnp/c++.capnp"; - -$Cxx.namespace("Nv::Blast::Serialization"); - -struct Asset -{ - header @0 :NvBlastDataBlock; - - iD @1 :UUID; - - chunkCount @2 :UInt32; - - graph @3 :NvBlastSupportGraph; - - leafChunkCount @4 :UInt32; - - firstSubsupportChunkIndex @5 :UInt32; - - bondCount @6 :UInt32; - - chunks @7: List(NvBlastChunk); - - bonds @8: List(NvBlastBond); - - subtreeLeafChunkCounts @9: List(UInt32); - - chunkToGraphNodeMap @10: List(UInt32); -} - -struct TkAsset -{ - assetLL @0 :Asset; - - jointDescs @1 :List(TkAssetJointDesc); - -} - -struct ExtPxAsset -{ - asset @0 :TkAsset; - chunks @1 :List(ExtPxChunk); - subchunks @2 :List(ExtPxSubchunk); -} - -struct ExtPxChunk -{ - firstSubchunkIndex @0 :UInt32; - subchunkCount @1 :UInt32; - isStatic @2 :Bool; -} - -struct ExtPxSubchunk -{ - transform @0 :PxTransform; - geometry @1 :PxConvexMeshGeometry; -} - -struct PxConvexMeshGeometry -{ - scale @0 :PxMeshScale; - convexMesh @1 :Data; - meshFlags @2 :UInt8; - - enum Type - { - eSPHERE @0; - ePLANE @1; - eCAPSULE @2; - eBOX @3; - eCONVEXMESH @4; - eTRIANGLEMESH @5; - eHEIGHTFIELD @6; - } - - type @3 :Type; -} - -struct NvBlastDataBlock -{ - enum Type - { - assetDataBlock @0; - instanceDataBlock @1; - } - - dataType @0 :Type; - - formatVersion @1 :UInt32; - - size @2 :UInt32; -} - -struct NvBlastChunk -{ - centroid @0 :List(Float32); - - volume @1 :Float32; - - parentChunkIndex @2 :UInt32; - firstChildIndex @3 :UInt32; - childIndexStop @4 :UInt32; - userData @5 :UInt32; -} - -struct NvBlastBond -{ - normal @0 :List(Float32); - area @1 :Float32; - centroid @2 :List(Float32); - userData @3 :UInt32; -} - -struct TkAssetJointDesc -{ - nodeIndices @0 :List(UInt32); - attachPositions @1 :List(PxVec3); -} - -struct PxVec3 -{ - x @0 :Float32; - y @1 :Float32; - z @2 :Float32; -} - -struct PxQuat -{ - x @0 :Float32; - y @1 :Float32; - z @2 :Float32; - w @3 :Float32; -} - -struct PxMeshScale -{ - scale @0 :PxVec3; - rotation @1 :PxQuat; -} - -struct PxTransform -{ - q @0 :PxQuat; - p @1 :PxVec3; -} - -struct NvBlastSupportGraph -{ - nodeCount @0 : UInt32; - - chunkIndices @1 : List(UInt32); - adjacencyPartition @2 : List(UInt32); - adjacentNodeIndices @3 : List(UInt32); - adjacentBondIndices @4 : List(UInt32); -} - -struct UUID -{ - value @0 : Data; -} - diff --git a/sdk/extensions/serialization/source/DTO/AssetDTO.cpp b/sdk/extensions/serialization/source/DTO/AssetDTO.cpp index 8d035fc..b500fe6 100644 --- a/sdk/extensions/serialization/source/DTO/AssetDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/AssetDTO.cpp @@ -1,187 +1,202 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "AssetDTO.h" +#include "NvBlastGlobals.h" #include "NvBlastIDDTO.h" #include "NvBlastChunkDTO.h" #include "NvBlastBondDTO.h" #include "NvBlastAsset.h" -#include "NvBlastExtSerializationLLImpl.h" -#include "NvBlastExtGlobals.h" -#if !defined(BLAST_LL_ALLOC) -#include "NvBlastExtAllocator.h" -#endif namespace Nv { - namespace Blast +namespace Blast +{ + +bool AssetDTO::serialize(Nv::Blast::Serialization::Asset::Builder builder, const Nv::Blast::Asset * poco) +{ + NvBlastIDDTO::serialize(builder.initID(), &poco->m_ID); + + builder.setLeafChunkCount(poco->m_leafChunkCount); + + builder.setFirstSubsupportChunkIndex(poco->m_firstSubsupportChunkIndex); + + capnp::List<Nv::Blast::Serialization::NvBlastChunk>::Builder chunks = builder.initChunks(poco->m_chunkCount); + + builder.setChunkCount(poco->m_chunkCount); + + NVBLAST_ASSERT_WITH_MESSAGE(builder.getChunkCount() == poco->m_chunkCount, "WTF"); + + for (uint32_t i = 0; i < poco->m_chunkCount; i++) + { + NvBlastChunk& chunk = poco->getChunks()[i]; + + NvBlastChunkDTO::serialize(chunks[i], &chunk); + } + + NVBLAST_ASSERT_WITH_MESSAGE(builder.getChunkCount() == poco->m_chunkCount, "WTF"); + + capnp::List<Nv::Blast::Serialization::NvBlastBond>::Builder bonds = builder.initBonds(poco->m_bondCount); + + builder.setBondCount(poco->m_bondCount); + + for (uint32_t i = 0; i < poco->m_bondCount; i++) + { + NvBlastBond& bond = poco->getBonds()[i]; + + NvBlastBondDTO::serialize(bonds[i], &bond); + } + + kj::ArrayPtr<uint32_t> stlcArray(poco->getSubtreeLeafChunkCounts(), poco->m_chunkCount); + builder.initSubtreeLeafChunkCounts(poco->m_chunkCount); + builder.setSubtreeLeafChunkCounts(stlcArray); + + kj::ArrayPtr<uint32_t> ctgnArray(poco->getChunkToGraphNodeMap(), poco->m_chunkCount); + builder.setChunkToGraphNodeMap(ctgnArray); + + Nv::Blast::Serialization::NvBlastSupportGraph::Builder graphBulder = builder.initGraph(); + + graphBulder.setNodeCount(poco->m_graph.m_nodeCount); + + uint32_t* ciPtr = poco->m_graph.getChunkIndices(); + + kj::ArrayPtr<const uint32_t> ciArray(ciPtr, poco->m_graph.m_nodeCount); + graphBulder.setChunkIndices(ciArray); + + kj::ArrayPtr<const uint32_t> adjPart(poco->m_graph.getAdjacencyPartition(), poco->m_graph.m_nodeCount + 1); + graphBulder.setAdjacencyPartition(adjPart); + + NVBLAST_ASSERT(graphBulder.getAdjacencyPartition().size() == poco->m_graph.m_nodeCount + 1); + + kj::ArrayPtr<const uint32_t> nodeIndices(poco->m_graph.getAdjacentNodeIndices(), poco->m_bondCount * 2); + graphBulder.setAdjacentNodeIndices(nodeIndices); + + NVBLAST_ASSERT(graphBulder.getAdjacentNodeIndices().size() == poco->m_bondCount * 2); + + kj::ArrayPtr<const uint32_t> bondIndices(poco->m_graph.getAdjacentBondIndices(), poco->m_bondCount * 2); + graphBulder.setAdjacentBondIndices(bondIndices); + + return true; +} + + +Nv::Blast::Asset* AssetDTO::deserialize(Nv::Blast::Serialization::Asset::Reader reader) +{ + NvBlastID EmptyId; + memset(EmptyId.data, 0, sizeof(NvBlastID)); + + void* mem = NVBLAST_ALLOC(reader.totalSize().wordCount * sizeof(uint64_t)); + + auto asset = Nv::Blast::initializeAsset(mem, EmptyId, reader.getChunkCount(), reader.getGraph().getNodeCount(), reader.getLeafChunkCount(), reader.getFirstSubsupportChunkIndex(), reader.getBondCount(), logLL); + + bool result = deserializeInto(reader, asset); + + return result ? asset : nullptr; +} + + +bool AssetDTO::deserializeInto(Nv::Blast::Serialization::Asset::Reader reader, Nv::Blast::Asset * poco) +{ + NvBlastIDDTO::deserializeInto(reader.getID(), &poco->m_ID); + + NvBlastBond* bonds = poco->getBonds(); + + uint32_t bondCount = reader.getBondCount(); + auto readerBonds = reader.getBonds(); + for (uint32_t i = 0; i < bondCount; i++) + { + auto bondReader = readerBonds[i]; + + NvBlastBondDTO::deserializeInto(bondReader, &bonds[i]); + } + + NvBlastChunk* chunks = poco->getChunks(); + + uint32_t chunkCount = reader.getChunkCount(); + auto readerChunks = reader.getChunks(); + for (uint32_t i = 0; i < chunkCount; i++) + { + auto chunkReader = readerChunks[i]; + + NvBlastChunkDTO::deserializeInto(chunkReader, &chunks[i]); + } + + poco->m_graph.m_nodeCount = reader.getGraph().getNodeCount(); + + NVBLAST_ASSERT(reader.getSubtreeLeafChunkCounts().size() == poco->m_chunkCount); + auto readerSubtreeLeafChunkCounts = reader.getSubtreeLeafChunkCounts(); + for (uint32_t i = 0; i < poco->m_chunkCount; i++) { - bool AssetDTO::serialize(Nv::Blast::Serialization::Asset::Builder builder, const Nv::Blast::Asset * poco) - { - NvBlastIDDTO::serialize(builder.initID(), &poco->m_ID); - - builder.setLeafChunkCount(poco->m_leafChunkCount); - - builder.setFirstSubsupportChunkIndex(poco->m_firstSubsupportChunkIndex); - - capnp::List<Nv::Blast::Serialization::NvBlastChunk>::Builder chunks = builder.initChunks(poco->m_chunkCount); - - builder.setChunkCount(poco->m_chunkCount); - - NVBLAST_ASSERT_WITH_MESSAGE(builder.getChunkCount() == poco->m_chunkCount, "WTF"); - - for (uint32_t i = 0; i < poco->m_chunkCount; i++) - { - NvBlastChunk& chunk = poco->getChunks()[i]; - - NvBlastChunkDTO::serialize(chunks[i], &chunk); - } - - NVBLAST_ASSERT_WITH_MESSAGE(builder.getChunkCount() == poco->m_chunkCount, "WTF"); - - capnp::List<Nv::Blast::Serialization::NvBlastBond>::Builder bonds = builder.initBonds(poco->m_bondCount); - - builder.setBondCount(poco->m_bondCount); - - for (uint32_t i = 0; i < poco->m_bondCount; i++) - { - NvBlastBond& bond = poco->getBonds()[i]; - - NvBlastBondDTO::serialize(bonds[i], &bond); - } - - kj::ArrayPtr<uint32_t> stlcArray(poco->getSubtreeLeafChunkCounts(), poco->m_chunkCount); - builder.initSubtreeLeafChunkCounts(poco->m_chunkCount); - builder.setSubtreeLeafChunkCounts(stlcArray); - - kj::ArrayPtr<uint32_t> ctgnArray(poco->getChunkToGraphNodeMap(), poco->m_chunkCount); - builder.setChunkToGraphNodeMap(ctgnArray); - - Nv::Blast::Serialization::NvBlastSupportGraph::Builder graphBulder = builder.initGraph(); - - graphBulder.setNodeCount(poco->m_graph.m_nodeCount); - - uint32_t* ciPtr = poco->m_graph.getChunkIndices(); - - kj::ArrayPtr<const uint32_t> ciArray(ciPtr, poco->m_graph.m_nodeCount); - graphBulder.setChunkIndices(ciArray); - - kj::ArrayPtr<const uint32_t> adjPart(poco->m_graph.getAdjacencyPartition(), poco->m_graph.m_nodeCount + 1); - graphBulder.setAdjacencyPartition(adjPart); - - NVBLAST_ASSERT(graphBulder.getAdjacencyPartition().size() == poco->m_graph.m_nodeCount + 1); - - kj::ArrayPtr<const uint32_t> nodeIndices(poco->m_graph.getAdjacentNodeIndices(), poco->m_bondCount * 2); - graphBulder.setAdjacentNodeIndices(nodeIndices); - - NVBLAST_ASSERT(graphBulder.getAdjacentNodeIndices().size() == poco->m_bondCount * 2); - - kj::ArrayPtr<const uint32_t> bondIndices(poco->m_graph.getAdjacentBondIndices(), poco->m_bondCount * 2); - graphBulder.setAdjacentBondIndices(bondIndices); - - return true; - } - - Nv::Blast::Asset* AssetDTO::deserialize(Nv::Blast::Serialization::Asset::Reader reader) - { - NvBlastID EmptyId = {}; - - NvBlastExtAlloc allocFn = gAlloc; - NvBlastLog logFn = gLog; - -#if !defined(BLAST_LL_ALLOC) - allocFn = ExtAllocator::alignedAlloc16; - logFn = NvBlastTkFrameworkGet()->getLogFn(); -#endif - - void* mem = allocFn(reader.totalSize().wordCount * sizeof(uint64_t)); - - auto asset = Nv::Blast::initializeAsset(mem, EmptyId, reader.getChunkCount(), reader.getGraph().getNodeCount(), reader.getLeafChunkCount(), reader.getFirstSubsupportChunkIndex(), reader.getBondCount(), - logFn); - - bool result = deserializeInto(reader, asset); - - return result ? asset : nullptr; - } - - bool AssetDTO::deserializeInto(Nv::Blast::Serialization::Asset::Reader reader, Nv::Blast::Asset * poco) - { - NvBlastIDDTO::deserializeInto(reader.getID(), &poco->m_ID); - - NvBlastBond* bonds = poco->getBonds(); - - uint32_t bondCount = reader.getBondCount(); - for (uint32_t i = 0; i < bondCount; i++) - { - auto bondReader = reader.getBonds()[i]; - - NvBlastBondDTO::deserializeInto(bondReader, &bonds[i]); - } - - NvBlastChunk* chunks = poco->getChunks(); - - uint32_t chunkCount = reader.getChunkCount(); - for (uint32_t i = 0; i < chunkCount; i++) - { - auto chunkReader = reader.getChunks()[i]; - - NvBlastChunkDTO::deserializeInto(chunkReader, &chunks[i]); - } - - poco->m_graph.m_nodeCount = reader.getGraph().getNodeCount(); - - NVBLAST_ASSERT(reader.getSubtreeLeafChunkCounts().size() == poco->m_chunkCount); - for (uint32_t i = 0; i < poco->m_chunkCount; i++) - { - poco->getSubtreeLeafChunkCounts()[i] = reader.getSubtreeLeafChunkCounts()[i]; - } - - for (uint32_t i = 0; i < chunkCount; i++) - { - poco->getChunkToGraphNodeMap()[i] = reader.getChunkToGraphNodeMap()[i]; - } - - uint32_t* ciPtr = poco->m_graph.getChunkIndices(); - - NVBLAST_ASSERT(reader.getGraph().getChunkIndices().size() == poco->m_graph.m_nodeCount); - for (uint32_t i = 0; i < poco->m_graph.m_nodeCount; i++) - { - ciPtr[i] = reader.getGraph().getChunkIndices()[i]; - } - - uint32_t* adjPartition = poco->m_graph.getAdjacencyPartition(); - uint32_t idx = 0; - - for (uint32_t adjPartIndex : reader.getGraph().getAdjacencyPartition()) - { - adjPartition[idx++] = adjPartIndex; - } - - uint32_t* adjNodes = poco->m_graph.getAdjacentNodeIndices(); - idx = 0; - - for (uint32_t adjNodeIndex : reader.getGraph().getAdjacentNodeIndices()) - { - adjNodes[idx++] = adjNodeIndex; - } - - uint32_t* adjBonds = poco->m_graph.getAdjacentBondIndices(); - idx = 0; - - for (uint32_t adjBondIndex : reader.getGraph().getAdjacentBondIndices()) - { - adjBonds[idx++] = adjBondIndex; - } - - return true; - } + poco->getSubtreeLeafChunkCounts()[i] = readerSubtreeLeafChunkCounts[i]; } + + auto readerChunkToGraphNodeMap = reader.getChunkToGraphNodeMap(); + for (uint32_t i = 0; i < chunkCount; i++) + { + poco->getChunkToGraphNodeMap()[i] = readerChunkToGraphNodeMap[i]; + } + + uint32_t* ciPtr = poco->m_graph.getChunkIndices(); + + NVBLAST_ASSERT(reader.getGraph().getChunkIndices().size() == poco->m_graph.m_nodeCount); + auto readerGraphChunkIndices = reader.getGraph().getChunkIndices(); + for (uint32_t i = 0; i < poco->m_graph.m_nodeCount; i++) + { + ciPtr[i] = readerGraphChunkIndices[i]; + } + + uint32_t* adjPartition = poco->m_graph.getAdjacencyPartition(); + const uint32_t graphAdjacencyPartitionSize = reader.getGraph().getAdjacencyPartition().size(); + auto readerGraphAdjacencyPartition = reader.getGraph().getAdjacencyPartition(); + for (uint32_t i = 0; i < graphAdjacencyPartitionSize; ++i) + { + adjPartition[i] = readerGraphAdjacencyPartition[i]; + } + + uint32_t* adjNodes = poco->m_graph.getAdjacentNodeIndices(); + const uint32_t graphAdjacentNodeIndicesSize = reader.getGraph().getAdjacentNodeIndices().size(); + auto readerGraphAdjacentNodeIndices = reader.getGraph().getAdjacentNodeIndices(); + for (uint32_t i = 0; i < graphAdjacentNodeIndicesSize; ++i) + { + adjNodes[i] = readerGraphAdjacentNodeIndices[i]; + } + + uint32_t* adjBonds = poco->m_graph.getAdjacentBondIndices(); + const uint32_t graphAdjacentBondIndicesSize = reader.getGraph().getAdjacentBondIndices().size(); + auto readerGraphAdjacentBondIndices = reader.getGraph().getAdjacentBondIndices(); + for (uint32_t i = 0; i < graphAdjacentBondIndicesSize; ++i) + { + adjBonds[i] = readerGraphAdjacentBondIndices[i]; + } + + return true; } + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/AssetDTO.h b/sdk/extensions/serialization/source/DTO/AssetDTO.h index c090b5f..492e847 100644 --- a/sdk/extensions/serialization/source/DTO/AssetDTO.h +++ b/sdk/extensions/serialization/source/DTO/AssetDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastAsset.h" -#include "generated/NvBlastExtSerializationLL.capn.h" +#include "generated/NvBlastExtLlSerialization.capn.h" -DTO_CLASS_LL(Asset, Nv::Blast::Asset, Nv::Blast::Serialization::Asset) +DTO_CLASS(Asset, Nv::Blast::Asset, Nv::Blast::Serialization::Asset) diff --git a/sdk/extensions/serialization/source/DTO/DTOMacros.h b/sdk/extensions/serialization/source/DTO/DTOMacros.h index a234aec..b3b71ef 100644 --- a/sdk/extensions/serialization/source/DTO/DTOMacros.h +++ b/sdk/extensions/serialization/source/DTO/DTOMacros.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once @@ -16,29 +34,10 @@ namespace Blast { \ class _NAME ## DTO \ { \ public: \ - static class physx::PxCooking* Cooking; \ - static class physx::PxPhysics* Physics; \ - \ - static bool serialize(_SERIALIZER::Builder builder, const _POCO * poco); \ - static _POCO* deserialize(_SERIALIZER::Reader reader); \ - static bool deserializeInto(_SERIALIZER::Reader reader, _POCO * poco); \ -}; \ -} \ -} \ - \ - -#define DTO_CLASS_LL(_NAME, _POCO, _SERIALIZER) \ -namespace Nv { \ -namespace Blast { \ -class _NAME ## DTO \ -{ \ -public: \ \ static bool serialize(_SERIALIZER::Builder builder, const _POCO * poco); \ static _POCO* deserialize(_SERIALIZER::Reader reader); \ static bool deserializeInto(_SERIALIZER::Reader reader, _POCO * poco); \ }; \ } \ -} \ - \ - +} diff --git a/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.cpp b/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.cpp index cf4cadc..865f141 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "ExtPxAssetDTO.h" #include "TkAssetDTO.h" @@ -14,65 +32,127 @@ #include "ExtPxSubchunkDTO.h" #include "physics/NvBlastExtPxAssetImpl.h" #include "NvBlastAssert.h" +#include "NvBlast.h" + namespace Nv { - namespace Blast +namespace Blast +{ + +bool ExtPxAssetDTO::serialize(Nv::Blast::Serialization::ExtPxAsset::Builder builder, const Nv::Blast::ExtPxAsset * poco) +{ + TkAssetDTO::serialize(builder.getAsset(), &poco->getTkAsset()); + + auto chunks = builder.initChunks(poco->getChunkCount()); + + for (uint32_t i = 0; i <poco->getChunkCount(); i++) { - bool ExtPxAssetDTO::serialize(Nv::Blast::Serialization::ExtPxAsset::Builder builder, const Nv::Blast::ExtPxAsset * poco) - { - TkAssetDTO::serialize(builder.getAsset(), &poco->getTkAsset()); - - auto chunks = builder.initChunks(poco->getChunkCount()); - - for (uint32_t i = 0; i <poco->getChunkCount(); i++) - { - ExtPxChunkDTO::serialize(chunks[i], &poco->getChunks()[i]); - } - - auto subchunks = builder.initSubchunks(poco->getSubchunkCount()); - - for (uint32_t i = 0; i < poco->getSubchunkCount(); i++) - { - ExtPxSubchunkDTO::serialize(subchunks[i], &poco->getSubchunks()[i]); - } - - return true; - } - - Nv::Blast::ExtPxAsset* ExtPxAssetDTO::deserialize(Nv::Blast::Serialization::ExtPxAsset::Reader reader) + ExtPxChunkDTO::serialize(chunks[i], &poco->getChunks()[i]); + } + + auto subchunks = builder.initSubchunks(poco->getSubchunkCount()); + + for (uint32_t i = 0; i < poco->getSubchunkCount(); i++) + { + ExtPxSubchunkDTO::serialize(subchunks[i], &poco->getSubchunks()[i]); + } + + const NvBlastActorDesc& actorDesc = poco->getDefaultActorDesc(); + + builder.setUniformInitialBondHealth(actorDesc.uniformInitialBondHealth); + + if (actorDesc.initialBondHealths != nullptr) + { + const uint32_t bondCount = poco->getTkAsset().getBondCount(); + kj::ArrayPtr<const float> bondHealthArray(actorDesc.initialBondHealths, bondCount); + builder.initBondHealths(bondCount); + builder.setBondHealths(bondHealthArray); + } + + builder.setUniformInitialLowerSupportChunkHealth(actorDesc.uniformInitialLowerSupportChunkHealth); + + if (actorDesc.initialSupportChunkHealths != nullptr) + { + const uint32_t supportChunkCount = NvBlastAssetGetSupportChunkCount(poco->getTkAsset().getAssetLL(), logLL); + kj::ArrayPtr<const float> supportChunkHealthArray(actorDesc.initialSupportChunkHealths, supportChunkCount); + builder.initSupportChunkHealths(supportChunkCount); + builder.setSupportChunkHealths(supportChunkHealthArray); + } + + return true; +} + + +Nv::Blast::ExtPxAsset* ExtPxAssetDTO::deserialize(Nv::Blast::Serialization::ExtPxAsset::Reader reader) +{ + auto tkAsset = TkAssetDTO::deserialize(reader.getAsset()); + + Nv::Blast::ExtPxAssetImpl* asset = reinterpret_cast<Nv::Blast::ExtPxAssetImpl*>(Nv::Blast::ExtPxAsset::create(tkAsset)); + + NVBLAST_ASSERT(asset != nullptr); + + auto& chunks = asset->getChunksArray(); + const uint32_t chunkCount = reader.getChunks().size(); + chunks.resize(chunkCount); + auto readerChunks = reader.getChunks(); + for (uint32_t i = 0; i < chunkCount; i++) + { + ExtPxChunkDTO::deserializeInto(readerChunks[i], &chunks[i]); + } + + auto& subchunks = asset->getSubchunksArray(); + const uint32_t subChunkCount = reader.getSubchunks().size(); + subchunks.resize(subChunkCount); + auto readerSubchunks = reader.getSubchunks(); + for (uint32_t i = 0; i < subChunkCount; i++) + { + ExtPxSubchunkDTO::deserializeInto(readerSubchunks[i], &subchunks[i]); + } + + NvBlastActorDesc& actorDesc = asset->getDefaultActorDesc(); + + actorDesc.uniformInitialBondHealth = reader.getUniformInitialBondHealth(); + + actorDesc.initialBondHealths = nullptr; + if (reader.hasBondHealths()) + { + const uint32_t bondCount = asset->getTkAsset().getBondCount(); + Nv::Blast::Array<float>::type& bondHealths = asset->getBondHealthsArray(); + bondHealths.resize(bondCount); + auto readerBondHealths = reader.getBondHealths(); + for (uint32_t i = 0; i < bondCount; ++i) { - auto tkAsset = TkAssetDTO::deserialize(reader.getAsset()); - - Nv::Blast::ExtPxAssetImpl* asset = reinterpret_cast<Nv::Blast::ExtPxAssetImpl*>(Nv::Blast::ExtPxAsset::create(tkAsset)); - - NVBLAST_ASSERT(asset != nullptr); - - auto chunks = asset->getChunksArray(); - - chunks.resize(reader.getChunks().size()); - for (uint32_t i = 0; i < reader.getChunks().size(); i++) - { - ExtPxChunkDTO::deserializeInto(reader.getChunks()[i], &chunks[i]); - } - - auto subchunks = asset->getSubchunksArray(); - - subchunks.resize(reader.getSubchunks().size()); - for (uint32_t i = 0; i < reader.getSubchunks().size(); i++) - { - ExtPxSubchunkDTO::deserializeInto(reader.getSubchunks()[i], &subchunks[i]); - } - - return asset; + bondHealths[i] = readerBondHealths[i]; } - - bool ExtPxAssetDTO::deserializeInto(Nv::Blast::Serialization::ExtPxAsset::Reader reader, Nv::Blast::ExtPxAsset * poco) + } + + actorDesc.uniformInitialLowerSupportChunkHealth = reader.getUniformInitialLowerSupportChunkHealth(); + + actorDesc.initialSupportChunkHealths = nullptr; + if (reader.hasSupportChunkHealths()) + { + const uint32_t supportChunkCount = NvBlastAssetGetSupportChunkCount(asset->getTkAsset().getAssetLL(), logLL); + Nv::Blast::Array<float>::type& supportChunkHealths = asset->getSupportChunkHealthsArray(); + supportChunkHealths.resize(supportChunkCount); + auto readerSupportChunkHealths = reader.getSupportChunkHealths(); + for (uint32_t i = 0; i < supportChunkCount; ++i) { - reader = reader; - poco = nullptr; - //NOTE: Because of the way this is structured, can't do this. - return false; + supportChunkHealths[i] = readerSupportChunkHealths[i]; } } + + return asset; +} + + +bool ExtPxAssetDTO::deserializeInto(Nv::Blast::Serialization::ExtPxAsset::Reader reader, Nv::Blast::ExtPxAsset * poco) +{ + reader = reader; + poco = nullptr; + //NOTE: Because of the way this is structured, can't do this. + return false; } + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.h b/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.h index a35d38a..9729ec9 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.h +++ b/sdk/extensions/serialization/source/DTO/ExtPxAssetDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "NvBlastBondDTO.h" #include "NvBlastExtPxAsset.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" DTO_CLASS(ExtPxAsset, Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset) diff --git a/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.cpp b/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.cpp index e096bc1..74333b6 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.cpp @@ -1,43 +1,65 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "ExtPxChunkDTO.h" namespace Nv { - namespace Blast - { - bool ExtPxChunkDTO::serialize(Nv::Blast::Serialization::ExtPxChunk::Builder builder, const Nv::Blast::ExtPxChunk * poco) - { - builder.setFirstSubchunkIndex(poco->firstSubchunkIndex); - builder.setSubchunkCount(poco->subchunkCount); - builder.setIsStatic(poco->isStatic); - - return true; - } - - Nv::Blast::ExtPxChunk* ExtPxChunkDTO::deserialize(Nv::Blast::Serialization::ExtPxChunk::Reader reader) - { - reader = reader; - //TODO: Allocate with ExtContext and return - - return nullptr; - } - - bool ExtPxChunkDTO::deserializeInto(Nv::Blast::Serialization::ExtPxChunk::Reader reader, Nv::Blast::ExtPxChunk * poco) - { - poco->firstSubchunkIndex = reader.getFirstSubchunkIndex(); - poco->subchunkCount = reader.getSubchunkCount(); - poco->isStatic = reader.getIsStatic(); - - return true; - } - } -}
\ No newline at end of file +namespace Blast +{ + +bool ExtPxChunkDTO::serialize(Nv::Blast::Serialization::ExtPxChunk::Builder builder, const Nv::Blast::ExtPxChunk * poco) +{ + builder.setFirstSubchunkIndex(poco->firstSubchunkIndex); + builder.setSubchunkCount(poco->subchunkCount); + builder.setIsStatic(poco->isStatic); + + return true; +} + + +Nv::Blast::ExtPxChunk* ExtPxChunkDTO::deserialize(Nv::Blast::Serialization::ExtPxChunk::Reader reader) +{ + reader = reader; + //TODO: Allocate with ExtContext and return + + return nullptr; +} + + +bool ExtPxChunkDTO::deserializeInto(Nv::Blast::Serialization::ExtPxChunk::Reader reader, Nv::Blast::ExtPxChunk * poco) +{ + poco->firstSubchunkIndex = reader.getFirstSubchunkIndex(); + poco->subchunkCount = reader.getSubchunkCount(); + poco->isStatic = reader.getIsStatic(); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.h b/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.h index 1ff36df..e9935c3 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.h +++ b/sdk/extensions/serialization/source/DTO/ExtPxChunkDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastExtPxAsset.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" DTO_CLASS(ExtPxChunk, Nv::Blast::ExtPxChunk, Nv::Blast::Serialization::ExtPxChunk) diff --git a/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.cpp b/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.cpp index cc2be96..c3e290b 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.cpp @@ -1,43 +1,66 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "ExtPxSubchunkDTO.h" #include "PxTransformDTO.h" #include "PxConvexMeshGeometryDTO.h" + namespace Nv { - namespace Blast - { - bool ExtPxSubchunkDTO::serialize(Nv::Blast::Serialization::ExtPxSubchunk::Builder builder, const Nv::Blast::ExtPxSubchunk * poco) - { - PxTransformDTO::serialize(builder.getTransform(), &poco->transform); - PxConvexMeshGeometryDTO::serialize(builder.getGeometry(), &poco->geometry); - - return true; - } - - Nv::Blast::ExtPxSubchunk* ExtPxSubchunkDTO::deserialize(Nv::Blast::Serialization::ExtPxSubchunk::Reader reader) - { - reader = reader; - //TODO: Allocate with ExtContext and return - - return nullptr; - } - - bool ExtPxSubchunkDTO::deserializeInto(Nv::Blast::Serialization::ExtPxSubchunk::Reader reader, Nv::Blast::ExtPxSubchunk * poco) - { - PxTransformDTO::deserializeInto(reader.getTransform(), &poco->transform); - - return true; - } - - } +namespace Blast +{ + +bool ExtPxSubchunkDTO::serialize(Nv::Blast::Serialization::ExtPxSubchunk::Builder builder, const Nv::Blast::ExtPxSubchunk * poco) +{ + PxTransformDTO::serialize(builder.getTransform(), &poco->transform); + PxConvexMeshGeometryDTO::serialize(builder.getGeometry(), &poco->geometry); + + return true; } + + +Nv::Blast::ExtPxSubchunk* ExtPxSubchunkDTO::deserialize(Nv::Blast::Serialization::ExtPxSubchunk::Reader reader) +{ + reader = reader; + //TODO: Allocate with ExtContext and return + + return nullptr; +} + + +bool ExtPxSubchunkDTO::deserializeInto(Nv::Blast::Serialization::ExtPxSubchunk::Reader reader, Nv::Blast::ExtPxSubchunk * poco) +{ + PxTransformDTO::deserializeInto(reader.getTransform(), &poco->transform); + PxConvexMeshGeometryDTO::deserializeInto(reader.getGeometry(), &poco->geometry); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.h b/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.h index 91f78e0..72b6c24 100644 --- a/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.h +++ b/sdk/extensions/serialization/source/DTO/ExtPxSubchunkDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "NvBlastExtPxAsset.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" #include "DTOMacros.h" DTO_CLASS(ExtPxSubchunk, Nv::Blast::ExtPxSubchunk, Nv::Blast::Serialization::ExtPxSubchunk) diff --git a/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.cpp b/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.cpp index 27cbb11..7865eb3 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.cpp @@ -1,63 +1,86 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastBondDTO.h" #include "NvBlastAssert.h" namespace Nv { - namespace Blast - { - - bool NvBlastBondDTO::serialize(Nv::Blast::Serialization::NvBlastBond::Builder builder, const NvBlastBond * poco) - { - NVBLAST_ASSERT(poco != nullptr); - - kj::ArrayPtr<const float> normArray(poco->normal, 3); - - builder.setNormal(normArray); - - builder.setArea(poco->area); - - kj::ArrayPtr<const float> centArray(poco->centroid, 3); - - builder.setCentroid(centArray); - - builder.setUserData(poco->userData); - - return true; - } - - NvBlastBond* NvBlastBondDTO::deserialize(Nv::Blast::Serialization::NvBlastBond::Reader reader) - { - //FIXME - reader = reader; - //TODO: Allocate with ExtContext and return - return nullptr; - } - - bool NvBlastBondDTO::deserializeInto(Nv::Blast::Serialization::NvBlastBond::Reader reader, NvBlastBond * poco) - { - poco->area = reader.getArea(); - - poco->centroid[0] = reader.getCentroid()[0]; - poco->centroid[1] = reader.getCentroid()[1]; - poco->centroid[2] = reader.getCentroid()[2]; - - poco->normal[0] = reader.getNormal()[0]; - poco->normal[1] = reader.getNormal()[1]; - poco->normal[2] = reader.getNormal()[2]; - - poco->userData = reader.getUserData(); - - return true; - } - } +namespace Blast +{ + +bool NvBlastBondDTO::serialize(Nv::Blast::Serialization::NvBlastBond::Builder builder, const NvBlastBond * poco) +{ + NVBLAST_ASSERT(poco != nullptr); + + kj::ArrayPtr<const float> normArray(poco->normal, 3); + + builder.setNormal(normArray); + + builder.setArea(poco->area); + + kj::ArrayPtr<const float> centArray(poco->centroid, 3); + + builder.setCentroid(centArray); + + builder.setUserData(poco->userData); + + return true; +} + + +NvBlastBond* NvBlastBondDTO::deserialize(Nv::Blast::Serialization::NvBlastBond::Reader reader) +{ + //FIXME + reader = reader; + //TODO: Allocate with ExtContext and return + return nullptr; +} + + +bool NvBlastBondDTO::deserializeInto(Nv::Blast::Serialization::NvBlastBond::Reader reader, NvBlastBond * poco) +{ + poco->area = reader.getArea(); + + auto readerCentroid = reader.getCentroid(); + poco->centroid[0] = readerCentroid[0]; + poco->centroid[1] = readerCentroid[1]; + poco->centroid[2] = readerCentroid[2]; + + auto readerNormal = reader.getNormal(); + poco->normal[0] = readerNormal[0]; + poco->normal[1] = readerNormal[1]; + poco->normal[2] = readerNormal[2]; + + poco->userData = reader.getUserData(); + + return true; } + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.h b/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.h index 8b67bd7..3a8e0d1 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.h +++ b/sdk/extensions/serialization/source/DTO/NvBlastBondDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastTypes.h" -#include "generated/NvBlastExtSerializationLL.capn.h" +#include "generated/NvBlastExtLlSerialization.capn.h" -DTO_CLASS_LL(NvBlastBond, NvBlastBond, Nv::Blast::Serialization::NvBlastBond) +DTO_CLASS(NvBlastBond, NvBlastBond, Nv::Blast::Serialization::NvBlastBond) diff --git a/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.cpp b/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.cpp index 38814ed..71924f3 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.cpp @@ -1,60 +1,83 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastChunkDTO.h" #include "NvBlastAssert.h" namespace Nv { - namespace Blast - { - bool NvBlastChunkDTO::serialize(Nv::Blast::Serialization::NvBlastChunk::Builder builder, const NvBlastChunk* poco) - { - NVBLAST_ASSERT(poco != nullptr); - - kj::ArrayPtr<const float> centArray(poco->centroid, 3); - builder.setCentroid(centArray); - - builder.setVolume(poco->volume); - - builder.setParentChunkIndex(poco->parentChunkIndex); - builder.setFirstChildIndex(poco->firstChildIndex); - builder.setChildIndexStop(poco->childIndexStop); - builder.setUserData(poco->userData); - - return true; - } - - NvBlastChunk* NvBlastChunkDTO::deserialize(Nv::Blast::Serialization::NvBlastChunk::Reader reader) - { - //FIXME - reader = reader; - - return nullptr; - } - - bool NvBlastChunkDTO::deserializeInto(Nv::Blast::Serialization::NvBlastChunk::Reader reader, NvBlastChunk* target) - { - NVBLAST_ASSERT(target != nullptr); - - target->centroid[0] = reader.getCentroid()[0]; - target->centroid[1] = reader.getCentroid()[1]; - target->centroid[2] = reader.getCentroid()[2]; - - target->childIndexStop = reader.getChildIndexStop(); - target->firstChildIndex = reader.getFirstChildIndex(); - target->parentChunkIndex = reader.getParentChunkIndex(); - target->userData = reader.getUserData(); - target->volume = reader.getVolume(); - - return true; - } - } +namespace Blast +{ + +bool NvBlastChunkDTO::serialize(Nv::Blast::Serialization::NvBlastChunk::Builder builder, const NvBlastChunk* poco) +{ + NVBLAST_ASSERT(poco != nullptr); + + kj::ArrayPtr<const float> centArray(poco->centroid, 3); + builder.setCentroid(centArray); + + builder.setVolume(poco->volume); + + builder.setParentChunkIndex(poco->parentChunkIndex); + builder.setFirstChildIndex(poco->firstChildIndex); + builder.setChildIndexStop(poco->childIndexStop); + builder.setUserData(poco->userData); + + return true; } + + +NvBlastChunk* NvBlastChunkDTO::deserialize(Nv::Blast::Serialization::NvBlastChunk::Reader reader) +{ + //FIXME + reader = reader; + + return nullptr; +} + + +bool NvBlastChunkDTO::deserializeInto(Nv::Blast::Serialization::NvBlastChunk::Reader reader, NvBlastChunk* target) +{ + NVBLAST_ASSERT(target != nullptr); + + auto readerCentroid = reader.getCentroid(); + target->centroid[0] = readerCentroid[0]; + target->centroid[1] = readerCentroid[1]; + target->centroid[2] = readerCentroid[2]; + + target->childIndexStop = reader.getChildIndexStop(); + target->firstChildIndex = reader.getFirstChildIndex(); + target->parentChunkIndex = reader.getParentChunkIndex(); + target->userData = reader.getUserData(); + target->volume = reader.getVolume(); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.h b/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.h index 5fec498..e4c3f1f 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.h +++ b/sdk/extensions/serialization/source/DTO/NvBlastChunkDTO.h @@ -1,18 +1,36 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastTypes.h" -#include "generated/NvBlastExtSerializationLL.capn.h" +#include "generated/NvBlastExtLlSerialization.capn.h" -DTO_CLASS_LL(NvBlastChunk, NvBlastChunk, Nv::Blast::Serialization::NvBlastChunk) +DTO_CLASS(NvBlastChunk, NvBlastChunk, Nv::Blast::Serialization::NvBlastChunk) diff --git a/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.cpp b/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.cpp index e540cd8..0be5863 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.cpp @@ -1,48 +1,70 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastIDDTO.h" #include "NvBlastTypes.h" #include "NvBlastAssert.h" -#include "generated/NvBlastExtSerializationLL.capn.h" +#include "generated/NvBlastExtLlSerialization.capn.h" namespace Nv { - namespace Blast - { - - bool NvBlastIDDTO::serialize(Nv::Blast::Serialization::UUID::Builder builder, const NvBlastID * poco) - { - capnp::Data::Reader idArrayReader((unsigned char *)poco->data, 16); - builder.setValue(idArrayReader); - - return true; - } - - NvBlastID* NvBlastIDDTO::deserialize(Nv::Blast::Serialization::UUID::Reader reader) - { - //FIXME - reader = reader; - //TODO: Allocate with ExtContext and return - - return nullptr; - } - - bool NvBlastIDDTO::deserializeInto(Nv::Blast::Serialization::UUID::Reader reader, NvBlastID * poco) - { - NVBLAST_ASSERT_WITH_MESSAGE(reader.getValue().size() == 16, "BlastID must be 16 bytes"); - - memcpy(poco, reader.getValue().begin(), 16); - - return true; - } - } -}
\ No newline at end of file +namespace Blast +{ + + +bool NvBlastIDDTO::serialize(Nv::Blast::Serialization::UUID::Builder builder, const NvBlastID * poco) +{ + capnp::Data::Reader idArrayReader((unsigned char *)poco->data, 16); + builder.setValue(idArrayReader); + + return true; +} + + +NvBlastID* NvBlastIDDTO::deserialize(Nv::Blast::Serialization::UUID::Reader reader) +{ + //FIXME + reader = reader; + //TODO: Allocate with ExtContext and return + + return nullptr; +} + + +bool NvBlastIDDTO::deserializeInto(Nv::Blast::Serialization::UUID::Reader reader, NvBlastID * poco) +{ + NVBLAST_ASSERT_WITH_MESSAGE(reader.getValue().size() == 16, "BlastID must be 16 bytes"); + + memcpy(poco, reader.getValue().begin(), 16); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.h b/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.h index afe6cf0..ac4b1c0 100644 --- a/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.h +++ b/sdk/extensions/serialization/source/DTO/NvBlastIDDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "NvBlastTypes.h" -#include "generated/NvBlastExtSerializationLL.capn.h" +#include "generated/NvBlastExtLlSerialization.capn.h" #include "DTOMacros.h" -DTO_CLASS_LL(NvBlastID, NvBlastID, ::Nv::Blast::Serialization::UUID) +DTO_CLASS(NvBlastID, NvBlastID, ::Nv::Blast::Serialization::UUID) diff --git a/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.cpp b/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.cpp index 1c46f9e..099e458 100644 --- a/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "PxConvexMeshGeometryDTO.h" #include "PxMeshScaleDTO.h" @@ -17,111 +35,108 @@ #include "NvBlastExtSerialization.h" #include "PxVec3.h" #include <algorithm> +#include <vector> #include "PxPhysics.h" +#include "NvBlastPxCallbacks.h" +#include "PxDefaultStreams.h" namespace Nv { - namespace Blast - { - physx::PxCooking* PxConvexMeshGeometryDTO::Cooking = nullptr; - physx::PxPhysics* PxConvexMeshGeometryDTO::Physics = nullptr; +namespace Blast +{ + +extern physx::PxPhysics* sExtPxSerializerPhysics; +extern physx::PxCooking* sExtPxSerializerCooking; + + +bool PxConvexMeshGeometryDTO::serialize(Nv::Blast::Serialization::PxConvexMeshGeometry::Builder builder, const physx::PxConvexMeshGeometry * poco) +{ + NVBLAST_ASSERT(sExtPxSerializerCooking != nullptr); + + PxMeshScaleDTO::serialize(builder.getScale(), &poco->scale); + + //TODO: Use cooking.cookConvexMesh to cook the mesh to a stream - then get that backing buffer and put it into the Data field - bool PxConvexMeshGeometryDTO::serialize(Nv::Blast::Serialization::PxConvexMeshGeometry::Builder builder, const physx::PxConvexMeshGeometry * poco) + physx::PxConvexMeshDesc desc; + desc.points.data = poco->convexMesh->getVertices(); + desc.points.count = poco->convexMesh->getNbVertices(); + desc.points.stride = sizeof(physx::PxVec3); + + std::vector<uint32_t> indicesScratch; + std::vector<physx::PxHullPolygon> hullPolygonsScratch; + + hullPolygonsScratch.resize(poco->convexMesh->getNbPolygons()); + + uint32_t indexCount = 0; + for (uint32_t i = 0; i < hullPolygonsScratch.size(); i++) + { + physx::PxHullPolygon polygon; + poco->convexMesh->getPolygonData(i, polygon); + if (polygon.mNbVerts) { - PxMeshScaleDTO::serialize(builder.getScale(), &poco->scale); - - //TODO: Use cooking.cookConvexMesh to cook the mesh to a stream - then get that backing buffer and put it into the Data field - - physx::PxConvexMeshDesc desc; - desc.points.data = poco->convexMesh->getVertices(); - desc.points.count = poco->convexMesh->getNbVertices(); - desc.points.stride = sizeof(physx::PxVec3); - - std::vector<uint32_t> indicesScratch; - std::vector<physx::PxHullPolygon> hullPolygonsScratch; - - hullPolygonsScratch.resize(poco->convexMesh->getNbPolygons()); - - uint32_t indexCount = 0; - for (uint32_t i = 0; i < hullPolygonsScratch.size(); i++) - { - physx::PxHullPolygon polygon; - poco->convexMesh->getPolygonData(i, polygon); - if (polygon.mNbVerts) - { - indexCount = std::max<uint32_t>(indexCount, polygon.mIndexBase + polygon.mNbVerts); - } - } - indicesScratch.resize(indexCount); - - for (uint32_t i = 0; i < hullPolygonsScratch.size(); i++) - { - physx::PxHullPolygon polygon; - poco->convexMesh->getPolygonData(i, polygon); - for (uint32_t j = 0; j < polygon.mNbVerts; j++) - { - indicesScratch[polygon.mIndexBase + j] = poco->convexMesh->getIndexBuffer()[polygon.mIndexBase + j]; - } - - hullPolygonsScratch[i] = polygon; - } - - desc.indices.count = indexCount; - desc.indices.data = indicesScratch.data(); - desc.indices.stride = sizeof(uint32_t); - - desc.polygons.count = poco->convexMesh->getNbPolygons(); - desc.polygons.data = hullPolygonsScratch.data(); - desc.polygons.stride = sizeof(physx::PxHullPolygon); - - - std::vector<unsigned char> buffer; - buffer.resize(16 * 1024 * 1024); // No idea how much memory is needed! Allocate 16MB - kj::ArrayPtr<unsigned char> bufferArray(buffer.data(), buffer.size()); - - Nv::Blast::ExtKJPxOutputStream outputStream(bufferArray); - - bool cookResult = Cooking->cookConvexMesh(desc, outputStream); - - if (!cookResult) - { - return false; - } - - kj::ArrayPtr<unsigned char> cookedBuffer(outputStream.getBuffer().begin(), outputStream.getWrittenBytes()); - - builder.setConvexMesh(cookedBuffer); - - // builder.getConvexMesh(). - - return true; + indexCount = std::max<uint32_t>(indexCount, polygon.mIndexBase + polygon.mNbVerts); } - - physx::PxConvexMeshGeometry* PxConvexMeshGeometryDTO::deserialize(Nv::Blast::Serialization::PxConvexMeshGeometry::Reader reader) - { - NVBLAST_ASSERT(PxConvexMeshGeometryDTO::Cooking != nullptr); - - reader = reader; - - return nullptr; - } - - bool PxConvexMeshGeometryDTO::deserializeInto(Nv::Blast::Serialization::PxConvexMeshGeometry::Reader reader, physx::PxConvexMeshGeometry * poco) + } + indicesScratch.resize(indexCount); + + for (uint32_t i = 0; i < hullPolygonsScratch.size(); i++) + { + physx::PxHullPolygon polygon; + poco->convexMesh->getPolygonData(i, polygon); + for (uint32_t j = 0; j < polygon.mNbVerts; j++) { - NVBLAST_ASSERT(PxConvexMeshGeometryDTO::Cooking != nullptr); - - PxMeshScaleDTO::deserializeInto(reader.getScale(), &poco->scale); - - Nv::Blast::ExtKJPxInputStream inputStream(reader.getConvexMesh()); - - //NOTE: Naive approach, no shared convex hulls - poco->convexMesh = Physics->createConvexMesh(inputStream); - - return false; + indicesScratch[polygon.mIndexBase + j] = poco->convexMesh->getIndexBuffer()[polygon.mIndexBase + j]; } + + hullPolygonsScratch[i] = polygon; + } + + desc.indices.count = indexCount; + desc.indices.data = indicesScratch.data(); + desc.indices.stride = sizeof(uint32_t); + + desc.polygons.count = poco->convexMesh->getNbPolygons(); + desc.polygons.data = hullPolygonsScratch.data(); + desc.polygons.stride = sizeof(physx::PxHullPolygon); - - + physx::PxDefaultMemoryOutputStream outStream(NvBlastGetPxAllocatorCallback()); + if (!sExtPxSerializerCooking->cookConvexMesh(desc, outStream)) + { + return false; } + + kj::ArrayPtr<unsigned char> cookedBuffer(outStream.getData(), outStream.getSize()); + + builder.setConvexMesh(cookedBuffer); + + return true; } + + +physx::PxConvexMeshGeometry* PxConvexMeshGeometryDTO::deserialize(Nv::Blast::Serialization::PxConvexMeshGeometry::Reader reader) +{ + NVBLAST_ASSERT(sExtPxSerializerCooking != nullptr); + + reader = reader; + + return nullptr; +} + + +bool PxConvexMeshGeometryDTO::deserializeInto(Nv::Blast::Serialization::PxConvexMeshGeometry::Reader reader, physx::PxConvexMeshGeometry * poco) +{ + NVBLAST_ASSERT(sExtPxSerializerPhysics != nullptr); + + PxMeshScaleDTO::deserializeInto(reader.getScale(), &poco->scale); + + Nv::Blast::ExtKJPxInputStream inputStream(reader.getConvexMesh()); + + //NOTE: Naive approach, no shared convex hulls + poco->convexMesh = sExtPxSerializerPhysics->createConvexMesh(inputStream); + + return poco->convexMesh != nullptr; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.h b/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.h index 27b3754..0628518 100644 --- a/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.h +++ b/sdk/extensions/serialization/source/DTO/PxConvexMeshGeometryDTO.h @@ -1,16 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" #include "PxConvexMeshGeometry.h" #include "PxCooking.h" diff --git a/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.cpp b/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.cpp index 8fee6ad..76f0d90 100644 --- a/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.cpp @@ -1,42 +1,64 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "PxMeshScaleDTO.h" #include "PxVec3DTO.h" #include "PxQuatDTO.h" + namespace Nv { - namespace Blast - { - bool PxMeshScaleDTO::serialize(Nv::Blast::Serialization::PxMeshScale::Builder builder, const physx::PxMeshScale * poco) - { - PxVec3DTO::serialize(builder.getScale(), &poco->scale); - PxQuatDTO::serialize(builder.getRotation(), &poco->rotation); - - return true; - } - - physx::PxMeshScale* PxMeshScaleDTO::deserialize(Nv::Blast::Serialization::PxMeshScale::Reader reader) - { - reader = reader; - return nullptr; - } - - bool PxMeshScaleDTO::deserializeInto(Nv::Blast::Serialization::PxMeshScale::Reader reader, physx::PxMeshScale * poco) - { - PxVec3DTO::deserializeInto(reader.getScale(), &poco->scale); - PxQuatDTO::deserializeInto(reader.getRotation(), &poco->rotation); - - return true; - } - } +namespace Blast +{ + +bool PxMeshScaleDTO::serialize(Nv::Blast::Serialization::PxMeshScale::Builder builder, const physx::PxMeshScale * poco) +{ + PxVec3DTO::serialize(builder.getScale(), &poco->scale); + PxQuatDTO::serialize(builder.getRotation(), &poco->rotation); + + return true; +} + + +physx::PxMeshScale* PxMeshScaleDTO::deserialize(Nv::Blast::Serialization::PxMeshScale::Reader reader) +{ + reader = reader; + return nullptr; +} + + +bool PxMeshScaleDTO::deserializeInto(Nv::Blast::Serialization::PxMeshScale::Reader reader, physx::PxMeshScale * poco) +{ + PxVec3DTO::deserializeInto(reader.getScale(), &poco->scale); + PxQuatDTO::deserializeInto(reader.getRotation(), &poco->rotation); + + return true; } +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.h b/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.h index 7b758c8..bf3c521 100644 --- a/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.h +++ b/sdk/extensions/serialization/source/DTO/PxMeshScaleDTO.h @@ -1,17 +1,35 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "PxMeshScale.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" #include "PxCooking.h" DTO_CLASS(PxMeshScale, physx::PxMeshScale, Nv::Blast::Serialization::PxMeshScale) diff --git a/sdk/extensions/serialization/source/DTO/PxQuatDTO.cpp b/sdk/extensions/serialization/source/DTO/PxQuatDTO.cpp index 8faeaa6..05490af 100644 --- a/sdk/extensions/serialization/source/DTO/PxQuatDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/PxQuatDTO.cpp @@ -1,45 +1,65 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "PxQuatDTO.h" namespace Nv { - namespace Blast - { - - bool PxQuatDTO::serialize(Nv::Blast::Serialization::PxQuat::Builder builder, const physx::PxQuat * poco) - { - builder.setX(poco->x); - builder.setY(poco->y); - builder.setZ(poco->z); - builder.setW(poco->w); - - return true; - } - - physx::PxQuat* PxQuatDTO::deserialize(Nv::Blast::Serialization::PxQuat::Reader reader) - { - reader = reader; - return nullptr; - } - - bool PxQuatDTO::deserializeInto(Nv::Blast::Serialization::PxQuat::Reader reader, physx::PxQuat * poco) - { - poco->x = reader.getX(); - poco->y = reader.getY(); - poco->z = reader.getZ(); - poco->w = reader.getW(); - - return true; - } - - } +namespace Blast +{ + +bool PxQuatDTO::serialize(Nv::Blast::Serialization::PxQuat::Builder builder, const physx::PxQuat * poco) +{ + builder.setX(poco->x); + builder.setY(poco->y); + builder.setZ(poco->z); + builder.setW(poco->w); + + return true; } + + +physx::PxQuat* PxQuatDTO::deserialize(Nv::Blast::Serialization::PxQuat::Reader reader) +{ + reader = reader; + return nullptr; +} + + +bool PxQuatDTO::deserializeInto(Nv::Blast::Serialization::PxQuat::Reader reader, physx::PxQuat * poco) +{ + poco->x = reader.getX(); + poco->y = reader.getY(); + poco->z = reader.getZ(); + poco->w = reader.getW(); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/PxQuatDTO.h b/sdk/extensions/serialization/source/DTO/PxQuatDTO.h index 460d6c5..b7d15b9 100644 --- a/sdk/extensions/serialization/source/DTO/PxQuatDTO.h +++ b/sdk/extensions/serialization/source/DTO/PxQuatDTO.h @@ -1,17 +1,35 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "PxQuat.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" #include "PxCooking.h" DTO_CLASS(PxQuat, physx::PxQuat, Nv::Blast::Serialization::PxQuat) diff --git a/sdk/extensions/serialization/source/DTO/PxTransformDTO.cpp b/sdk/extensions/serialization/source/DTO/PxTransformDTO.cpp index 20a7cbb..0b1a240 100644 --- a/sdk/extensions/serialization/source/DTO/PxTransformDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/PxTransformDTO.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "PxTransformDTO.h" #include "PxQuatDTO.h" @@ -14,29 +32,32 @@ namespace Nv { - namespace Blast - { - - bool PxTransformDTO::serialize(Nv::Blast::Serialization::PxTransform::Builder builder, const physx::PxTransform * poco) - { - PxQuatDTO::serialize(builder.getQ(), &poco->q); - PxVec3DTO::serialize(builder.getP(), &poco->p); - - return true; - } - - physx::PxTransform* PxTransformDTO::deserialize(Nv::Blast::Serialization::PxTransform::Reader reader) - { - reader = reader; - return nullptr; - } - - bool PxTransformDTO::deserializeInto(Nv::Blast::Serialization::PxTransform::Reader reader, physx::PxTransform * poco) - { - PxQuatDTO::deserializeInto(reader.getQ(), &poco->q); - PxVec3DTO::deserializeInto(reader.getP(), &poco->p); +namespace Blast +{ - return true; - } - } +bool PxTransformDTO::serialize(Nv::Blast::Serialization::PxTransform::Builder builder, const physx::PxTransform * poco) +{ + PxQuatDTO::serialize(builder.getQ(), &poco->q); + PxVec3DTO::serialize(builder.getP(), &poco->p); + + return true; +} + + +physx::PxTransform* PxTransformDTO::deserialize(Nv::Blast::Serialization::PxTransform::Reader reader) +{ + reader = reader; + return nullptr; } + + +bool PxTransformDTO::deserializeInto(Nv::Blast::Serialization::PxTransform::Reader reader, physx::PxTransform * poco) +{ + PxQuatDTO::deserializeInto(reader.getQ(), &poco->q); + PxVec3DTO::deserializeInto(reader.getP(), &poco->p); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/PxTransformDTO.h b/sdk/extensions/serialization/source/DTO/PxTransformDTO.h index 49a6b73..3523375 100644 --- a/sdk/extensions/serialization/source/DTO/PxTransformDTO.h +++ b/sdk/extensions/serialization/source/DTO/PxTransformDTO.h @@ -1,17 +1,35 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "PxTransform.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" #include "PxCooking.h" DTO_CLASS(PxTransform, physx::PxTransform, Nv::Blast::Serialization::PxTransform) diff --git a/sdk/extensions/serialization/source/DTO/PxVec3DTO.cpp b/sdk/extensions/serialization/source/DTO/PxVec3DTO.cpp index 9827cd0..995bb44 100644 --- a/sdk/extensions/serialization/source/DTO/PxVec3DTO.cpp +++ b/sdk/extensions/serialization/source/DTO/PxVec3DTO.cpp @@ -1,45 +1,65 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "PxVec3DTO.h" #include "NvBlastAssert.h" namespace Nv { - namespace Blast - { - bool PxVec3DTO::serialize(Nv::Blast::Serialization::PxVec3::Builder builder, const physx::PxVec3 * poco) - { - NVBLAST_ASSERT(poco != nullptr); - - builder.setX(poco->x); - builder.setY(poco->y); - builder.setZ(poco->z); - - return true; - } - - physx::PxVec3* PxVec3DTO::deserialize(Nv::Blast::Serialization::PxVec3::Reader reader) - { - //TODO: Allocate using ExtContext and return - reader = reader; - return nullptr; - } - - bool PxVec3DTO::deserializeInto(Nv::Blast::Serialization::PxVec3::Reader reader, physx::PxVec3* target) - { - target->x = reader.getX(); - target->y = reader.getY(); - target->z = reader.getZ(); - - return true; - } - } +namespace Blast +{ + +bool PxVec3DTO::serialize(Nv::Blast::Serialization::PxVec3::Builder builder, const physx::PxVec3 * poco) +{ + NVBLAST_ASSERT(poco != nullptr); + + builder.setX(poco->x); + builder.setY(poco->y); + builder.setZ(poco->z); + + return true; +} + +physx::PxVec3* PxVec3DTO::deserialize(Nv::Blast::Serialization::PxVec3::Reader reader) +{ + //TODO: Allocate using ExtContext and return + reader = reader; + return nullptr; } + +bool PxVec3DTO::deserializeInto(Nv::Blast::Serialization::PxVec3::Reader reader, physx::PxVec3* target) +{ + target->x = reader.getX(); + target->y = reader.getY(); + target->z = reader.getZ(); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/PxVec3DTO.h b/sdk/extensions/serialization/source/DTO/PxVec3DTO.h index 8a04c8b..84fce39 100644 --- a/sdk/extensions/serialization/source/DTO/PxVec3DTO.h +++ b/sdk/extensions/serialization/source/DTO/PxVec3DTO.h @@ -1,17 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtTkSerialization.capn.h" #include "PxVec3.h" -#include "PxCooking.h" DTO_CLASS(PxVec3, physx::PxVec3, Nv::Blast::Serialization::PxVec3) diff --git a/sdk/extensions/serialization/source/DTO/TkAssetDTO.cpp b/sdk/extensions/serialization/source/DTO/TkAssetDTO.cpp index acc55ba..7ba6d4f 100644 --- a/sdk/extensions/serialization/source/DTO/TkAssetDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/TkAssetDTO.cpp @@ -1,67 +1,94 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "TkAssetDTO.h" #include "AssetDTO.h" #include "TkAssetJointDescDTO.h" #include <vector> #include "NvBlastTkFramework.h" - +#include "NvBlastGlobals.h" namespace Nv { - namespace Blast +namespace Blast +{ + +extern TkFramework* sExtTkSerializerFramework; + + +bool TkAssetDTO::serialize(Nv::Blast::Serialization::TkAsset::Builder builder, const Nv::Blast::TkAsset * poco) +{ + const Asset* assetLL = reinterpret_cast<const Nv::Blast::Asset*>(poco->getAssetLL()); + + Nv::Blast::AssetDTO::serialize(builder.getAssetLL(), assetLL); + + uint32_t jointDescCount = poco->getJointDescCount(); + + capnp::List<Nv::Blast::Serialization::TkAssetJointDesc>::Builder jointDescs = builder.initJointDescs(jointDescCount); + + for (uint32_t i = 0; i < jointDescCount; i++) { - bool TkAssetDTO::serialize(Nv::Blast::Serialization::TkAsset::Builder builder, const Nv::Blast::TkAsset * poco) - { - const Asset* assetLL = reinterpret_cast<const Nv::Blast::Asset*>(poco->getAssetLL()); - - Nv::Blast::AssetDTO::serialize(builder.getAssetLL(), assetLL); - - uint32_t jointDescCount = poco->getJointDescCount(); - - capnp::List<Nv::Blast::Serialization::TkAssetJointDesc>::Builder jointDescs = builder.initJointDescs(jointDescCount); - - for (uint32_t i = 0; i < jointDescCount; i++) - { - TkAssetJointDescDTO::serialize(jointDescs[i], &poco->getJointDescs()[i]); - } - - return true; - } - - Nv::Blast::TkAsset* TkAssetDTO::deserialize(Nv::Blast::Serialization::TkAsset::Reader reader) - { - const NvBlastAsset* assetLL = reinterpret_cast<const NvBlastAsset*>(AssetDTO::deserialize(reader.getAssetLL())); - - std::vector<Nv::Blast::TkAssetJointDesc> jointDescs; - jointDescs.resize(reader.getJointDescs().size()); - - for (uint32_t i = 0; i < jointDescs.size(); i++) - { - TkAssetJointDescDTO::deserializeInto(reader.getJointDescs()[i], &jointDescs[i]); - } - - // Make sure to set ownsAsset to true - this is serialization and no one else owns it. - Nv::Blast::TkAsset* asset = NvBlastTkFrameworkGet()->createAsset(assetLL, jointDescs.data(), jointDescs.size(), true); - - return asset; - } - - bool TkAssetDTO::deserializeInto(Nv::Blast::Serialization::TkAsset::Reader reader, Nv::Blast::TkAsset * poco) - { - reader = reader; - poco = nullptr; - // NOTE: Because of the way TkAsset is currently structured, this won't work. - return false; - } + TkAssetJointDescDTO::serialize(jointDescs[i], &poco->getJointDescs()[i]); } + + return true; } + + +Nv::Blast::TkAsset* TkAssetDTO::deserialize(Nv::Blast::Serialization::TkAsset::Reader reader) +{ + const NvBlastAsset* assetLL = reinterpret_cast<const NvBlastAsset*>(AssetDTO::deserialize(reader.getAssetLL())); + + std::vector<Nv::Blast::TkAssetJointDesc> jointDescs; + + const uint32_t jointDescCount = reader.getJointDescs().size(); + jointDescs.resize(jointDescCount); + auto readerJointDescs = reader.getJointDescs(); + for (uint32_t i = 0; i < jointDescCount; i++) + { + TkAssetJointDescDTO::deserializeInto(readerJointDescs[i], &jointDescs[i]); + } + + // Make sure to set ownsAsset to true - this is serialization and no one else owns it. + Nv::Blast::TkAsset* asset = NvBlastTkFrameworkGet()->createAsset(assetLL, jointDescs.data(), jointDescCount, true); + + return asset; +} + + +bool TkAssetDTO::deserializeInto(Nv::Blast::Serialization::TkAsset::Reader reader, Nv::Blast::TkAsset * poco) +{ + reader = reader; + poco = nullptr; + // NOTE: Because of the way TkAsset is currently structured, this won't work. + return false; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/TkAssetDTO.h b/sdk/extensions/serialization/source/DTO/TkAssetDTO.h index 1b21eba..d0eceea 100644 --- a/sdk/extensions/serialization/source/DTO/TkAssetDTO.h +++ b/sdk/extensions/serialization/source/DTO/TkAssetDTO.h @@ -1,17 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastTkAsset.h" -#include "generated/NvBlastExtSerialization.capn.h" -#include "PxCooking.h" +#include "generated/NvBlastExtTkSerialization.capn.h" DTO_CLASS(TkAsset, Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset) diff --git a/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.cpp b/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.cpp index 9118d19..cbc1ef8 100644 --- a/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.cpp +++ b/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "TkAssetJointDescDTO.h" #include "PxVec3DTO.h" @@ -14,40 +32,45 @@ namespace Nv { - namespace Blast +namespace Blast +{ + +bool TkAssetJointDescDTO::serialize(Nv::Blast::Serialization::TkAssetJointDesc::Builder builder, const Nv::Blast::TkAssetJointDesc * poco) +{ + kj::ArrayPtr<const uint32_t> nodeIndices(poco->nodeIndices, 2); + builder.setNodeIndices(nodeIndices); + + for (int i = 0; i < 2; i++) { - - bool TkAssetJointDescDTO::serialize(Nv::Blast::Serialization::TkAssetJointDesc::Builder builder, const Nv::Blast::TkAssetJointDesc * poco) - { - kj::ArrayPtr<const uint32_t> nodeIndices(poco->nodeIndices, 2); - builder.setNodeIndices(nodeIndices); - - for (int i = 0; i < 2; i++) - { - PxVec3DTO::serialize(builder.getAttachPositions()[i], &poco->attachPositions[i]); - } - - return true; - } - - Nv::Blast::TkAssetJointDesc* TkAssetJointDescDTO::deserialize(Nv::Blast::Serialization::TkAssetJointDesc::Reader reader) - { - //TODO: Allocate with ExtContent and return - - reader = reader; - - return nullptr; - } - - bool TkAssetJointDescDTO::deserializeInto(Nv::Blast::Serialization::TkAssetJointDesc::Reader reader, Nv::Blast::TkAssetJointDesc * poco) - { - PxVec3DTO::deserializeInto(reader.getAttachPositions()[0], &poco->attachPositions[0]); - PxVec3DTO::deserializeInto(reader.getAttachPositions()[1], &poco->attachPositions[1]); - - poco->nodeIndices[0] = reader.getNodeIndices()[0]; - poco->nodeIndices[1] = reader.getNodeIndices()[1]; - - return true; - } + PxVec3DTO::serialize(builder.getAttachPositions()[i], &poco->attachPositions[i]); } -}
\ No newline at end of file + + return true; +} + + +Nv::Blast::TkAssetJointDesc* TkAssetJointDescDTO::deserialize(Nv::Blast::Serialization::TkAssetJointDesc::Reader reader) +{ + //TODO: Allocate with ExtContent and return + + reader = reader; + + return nullptr; +} + + +bool TkAssetJointDescDTO::deserializeInto(Nv::Blast::Serialization::TkAssetJointDesc::Reader reader, Nv::Blast::TkAssetJointDesc * poco) +{ + auto readerAttachPositions = reader.getAttachPositions(); + PxVec3DTO::deserializeInto(readerAttachPositions[0], &poco->attachPositions[0]); + PxVec3DTO::deserializeInto(readerAttachPositions[1], &poco->attachPositions[1]); + + auto readerNodeIndices = reader.getNodeIndices(); + poco->nodeIndices[0] = readerNodeIndices[0]; + poco->nodeIndices[1] = readerNodeIndices[1]; + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.h b/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.h index 88364bd..1dca2f9 100644 --- a/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.h +++ b/sdk/extensions/serialization/source/DTO/TkAssetJointDescDTO.h @@ -1,17 +1,34 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "DTOMacros.h" #include "NvBlastTkAsset.h" -#include "generated/NvBlastExtSerialization.capn.h" -#include "PxCooking.h" +#include "generated/NvBlastExtTkSerialization.capn.h" DTO_CLASS(TkAssetJointDesc, Nv::Blast::TkAssetJointDesc, Nv::Blast::Serialization::TkAssetJointDesc) diff --git a/sdk/extensions/serialization/source/NvBlastExtGlobals.h b/sdk/extensions/serialization/source/NvBlastExtGlobals.h deleted file mode 100644 index dd50afd..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtGlobals.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -/** -Function pointer type for allocation - has same signature as stdlib malloc. -*/ -typedef void* (*NvBlastExtAlloc)(size_t size); - -extern NvBlastExtAlloc gAlloc; -extern NvBlastLog gLog; - diff --git a/sdk/extensions/serialization/source/NvBlastExtInputStream.cpp b/sdk/extensions/serialization/source/NvBlastExtInputStream.cpp index 7ef9b62..805990d 100644 --- a/sdk/extensions/serialization/source/NvBlastExtInputStream.cpp +++ b/sdk/extensions/serialization/source/NvBlastExtInputStream.cpp @@ -1,17 +1,35 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastExtInputStream.h" -Nv::Blast::ExtInputStream::ExtInputStream(std::istream &inputStream): +Nv::Blast::ExtInputStream::ExtInputStream(std::istream &inputStream) : m_inputStream(inputStream) { @@ -25,13 +43,13 @@ size_t Nv::Blast::ExtInputStream::tryRead(void* buffer, size_t /*minBytes*/, siz if (m_inputStream.fail()) { // Throw exception, log error -// NVBLASTEXT_LOG_ERROR("Failure when reading from stream"); +// NVBLAST_LOG_ERROR("Failure when reading from stream"); } // Since we're using a blocking read above, if we don't have maxBytes we're probably done if ((size_t) m_inputStream.gcount() < maxBytes) { -// NVBLASTEXT_LOG_ERROR("Failed to read requested number of bytes during blocking read."); +// NVBLAST_LOG_ERROR("Failed to read requested number of bytes during blocking read."); } return m_inputStream.gcount(); diff --git a/sdk/extensions/serialization/source/NvBlastExtInputStream.h b/sdk/extensions/serialization/source/NvBlastExtInputStream.h index 9b19d9c..cd36e9e 100644 --- a/sdk/extensions/serialization/source/NvBlastExtInputStream.h +++ b/sdk/extensions/serialization/source/NvBlastExtInputStream.h @@ -1,32 +1,53 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "kj/io.h" #include <istream> + namespace Nv { - namespace Blast - { - class ExtInputStream : public kj::InputStream - { - public: - ExtInputStream() = delete; - ExtInputStream(std::istream &inputStream); - - // Returns a read of maxBytes. This is supposed to be happy doing partial reads, but currently isn't. - virtual size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; - - private: - std::istream &m_inputStream; - }; - } -}
\ No newline at end of file +namespace Blast +{ + +class ExtInputStream : public kj::InputStream +{ +public: + ExtInputStream() = delete; + ExtInputStream(std::istream &inputStream); + + // Returns a read of maxBytes. This is supposed to be happy doing partial reads, but currently isn't. + virtual size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; + +private: + std::istream &m_inputStream; +}; + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.cpp b/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.cpp index 9af13a9..cc73e6b 100644 --- a/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.cpp +++ b/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.cpp @@ -1,32 +1,53 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastExtKJPxInputStream.h" namespace Nv { - namespace Blast - { - ExtKJPxInputStream::ExtKJPxInputStream(capnp::Data::Reader inReader) : - dataReader(inReader), - inputStream(nullptr) - { - kj::ArrayPtr<const unsigned char> buffer(inReader.begin(), inReader.size()); - - inputStream = std::make_shared<kj::ArrayInputStream>(buffer); - } - - uint32_t ExtKJPxInputStream::read(void* dest, uint32_t count) - { - return inputStream->tryRead(dest, count, count); - } - } +namespace Blast +{ + +ExtKJPxInputStream::ExtKJPxInputStream(capnp::Data::Reader inReader) : +dataReader(inReader), +inputStream(nullptr) +{ + kj::ArrayPtr<const unsigned char> buffer(inReader.begin(), inReader.size()); + + inputStream = std::make_shared<kj::ArrayInputStream>(buffer); +} + + +uint32_t ExtKJPxInputStream::read(void* dest, uint32_t count) +{ + return inputStream->tryRead(dest, count, count); } +} // namespace Blast +} // namespace Nv + diff --git a/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.h b/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.h index 452892d..bc0074a 100644 --- a/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.h +++ b/sdk/extensions/serialization/source/NvBlastExtKJPxInputStream.h @@ -1,41 +1,62 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "PxIO.h" #include "capnp/common.h" #include "kj/io.h" #include <memory> -#include "generated/NvBlastExtSerialization.capn.h" +#include "generated/NvBlastExtPxSerialization.capn.h" + namespace Nv { - namespace Blast - { - /* - A wrapper around a Capn Proto Data reader. - - Since it needs to behave like a stream, it's internally wrapped in a stream. - - */ - class ExtKJPxInputStream : public physx::PxInputStream - { - public: - ExtKJPxInputStream(capnp::Data::Reader inReader); - ~ExtKJPxInputStream() = default; - - virtual uint32_t read(void* dest, uint32_t count) override; - - private: - capnp::Data::Reader dataReader; - std::shared_ptr<kj::ArrayInputStream> inputStream; - }; - } -} +namespace Blast +{ + +/* +A wrapper around a Capn Proto Data reader. + +Since it needs to behave like a stream, it's internally wrapped in a stream. + +*/ +class ExtKJPxInputStream : public physx::PxInputStream +{ +public: + ExtKJPxInputStream(capnp::Data::Reader inReader); + ~ExtKJPxInputStream() = default; + + virtual uint32_t read(void* dest, uint32_t count) override; + +private: + capnp::Data::Reader dataReader; + std::shared_ptr<kj::ArrayInputStream> inputStream; +}; + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.cpp b/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.cpp index 0f17a01..d1ea822 100644 --- a/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.cpp +++ b/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.cpp @@ -1,35 +1,55 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastExtKJPxOutputStream.h" namespace Nv { - namespace Blast - { - ExtKJPxOutputStream::ExtKJPxOutputStream(kj::ArrayPtr<unsigned char> inBuffer) : - writtenBytes(0), - Buffer(inBuffer), - outputStream(nullptr) - { - outputStream = std::make_shared<kj::ArrayOutputStream>(inBuffer); - } - - uint32_t ExtKJPxOutputStream::write(const void* src, uint32_t count) - { - outputStream->write(src, count); - - writtenBytes += count; - - return count; - } - } +namespace Blast +{ + +ExtKJPxOutputStream::ExtKJPxOutputStream(kj::ArrayPtr<unsigned char> inBuffer) : +writtenBytes(0), +Buffer(inBuffer), +outputStream(nullptr) +{ + outputStream = std::make_shared<kj::ArrayOutputStream>(inBuffer); +} + + +uint32_t ExtKJPxOutputStream::write(const void* src, uint32_t count) +{ + outputStream->write(src, count); + + writtenBytes += count; + + return count; } +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.h b/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.h index 0ed563f..325a65a 100644 --- a/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.h +++ b/sdk/extensions/serialization/source/NvBlastExtKJPxOutputStream.h @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "PxIO.h" @@ -14,27 +32,30 @@ #include <memory> #include "kj/io.h" + namespace Nv { - namespace Blast - { - class ExtKJPxOutputStream : public physx::PxOutputStream - { - public: - ExtKJPxOutputStream(kj::ArrayPtr<unsigned char> inBuffer); - ~ExtKJPxOutputStream() = default; +namespace Blast +{ + +class ExtKJPxOutputStream : public physx::PxOutputStream +{ +public: + ExtKJPxOutputStream(kj::ArrayPtr<unsigned char> inBuffer); + ~ExtKJPxOutputStream() = default; + + virtual uint32_t write(const void* src, uint32_t count) override; - virtual uint32_t write(const void* src, uint32_t count) override; + uint32_t getWrittenBytes() { return writtenBytes; } - uint32_t getWrittenBytes() { return writtenBytes; } + kj::ArrayPtr<unsigned char> getBuffer() { return Buffer; } - kj::ArrayPtr<unsigned char> getBuffer() { return Buffer; } +private: + uint32_t writtenBytes; - private: - uint32_t writtenBytes; + kj::ArrayPtr<unsigned char> Buffer; + std::shared_ptr<kj::ArrayOutputStream> outputStream; +}; - kj::ArrayPtr<unsigned char> Buffer; - std::shared_ptr<kj::ArrayOutputStream> outputStream; - }; - } -} +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtLlSerialization.capn b/sdk/extensions/serialization/source/NvBlastExtLlSerialization.capn new file mode 100644 index 0000000..31c1db4 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtLlSerialization.capn @@ -0,0 +1,108 @@ +# 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. + + +@0x9a4a58fac38375e0; + +using Cxx = import "/capnp/c++.capnp"; + +$Cxx.namespace("Nv::Blast::Serialization"); + +struct Asset +{ + header @0 :NvBlastDataBlock; + + iD @1 :UUID; + + chunkCount @2 :UInt32; + + graph @3 :NvBlastSupportGraph; + + leafChunkCount @4 :UInt32; + + firstSubsupportChunkIndex @5 :UInt32; + + bondCount @6 :UInt32; + + chunks @7: List(NvBlastChunk); + + bonds @8: List(NvBlastBond); + + subtreeLeafChunkCounts @9: List(UInt32); + + chunkToGraphNodeMap @10: List(UInt32); +} + +struct NvBlastDataBlock +{ + enum Type + { + assetDataBlock @0; + instanceDataBlock @1; + } + + dataType @0 :Type; + + formatVersion @1 :UInt32; + + size @2 :UInt32; +} + +struct NvBlastChunk +{ + centroid @0 :List(Float32); + + volume @1 :Float32; + + parentChunkIndex @2 :UInt32; + firstChildIndex @3 :UInt32; + childIndexStop @4 :UInt32; + userData @5 :UInt32; +} + +struct NvBlastBond +{ + normal @0 :List(Float32); + area @1 :Float32; + centroid @2 :List(Float32); + userData @3 :UInt32; +} + +struct NvBlastSupportGraph +{ + nodeCount @0 : UInt32; + + chunkIndices @1 : List(UInt32); + adjacencyPartition @2 : List(UInt32); + adjacentNodeIndices @3 : List(UInt32); + adjacentBondIndices @4 : List(UInt32); +} + +struct UUID +{ + value @0 : Data; +} diff --git a/sdk/extensions/serialization/source/NvBlastExtLlSerialization.cpp b/sdk/extensions/serialization/source/NvBlastExtLlSerialization.cpp new file mode 100644 index 0000000..b9c261b --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtLlSerialization.cpp @@ -0,0 +1,136 @@ +// 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 "NvBlastExtSerializationInternal.h" +#include "NvBlastExtLlSerialization.h" +#include "NvBlastExtLlSerializerCAPN.h" + + +namespace Nv +{ +namespace Blast +{ + +class ExtLlSerializerAsset_CPNB : public ExtSerializer +{ +public: + ExtSerializerBoilerplate("LLAsset_CPNB", "Blast low-level asset (NvBlastAsset) serialization using Cap'n Proto binary format.", LlObjectTypeID::Asset, ExtSerialization::EncodingID::CapnProtoBinary); + ExtSerializerDefaultFactoryAndRelease(ExtLlSerializerAsset_CPNB); + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + return ExtSerializationCAPN<Asset, Serialization::Asset::Reader, Serialization::Asset::Builder>::deserializeFromBuffer(reinterpret_cast<const unsigned char*>(buffer), size); + } + + virtual uint64_t serializeIntoBuffer(void*& buffer, ExtSerialization::BufferProvider& bufferProvider, const void* object, uint64_t offset = 0) override + { + uint64_t usedSize; + if (!ExtSerializationCAPN<Asset, Serialization::Asset::Reader, Serialization::Asset::Builder>::serializeIntoBuffer(reinterpret_cast<const Asset*>(object), + reinterpret_cast<unsigned char*&>(buffer), usedSize, &bufferProvider, offset)) + { + return 0; + } + return usedSize; + } +}; + + +class ExtLlSerializerObject_RAW : public ExtSerializer +{ +public: + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + const NvBlastDataBlock* block = reinterpret_cast<const NvBlastDataBlock*>(buffer); + if (static_cast<uint64_t>(block->size) > size) + { + return nullptr; + } + void* llobject = NVBLAST_ALLOC(block->size); + return memcpy(llobject, block, block->size); + } + + virtual uint64_t serializeIntoBuffer(void*& buffer, ExtSerialization::BufferProvider& bufferProvider, const void* object, uint64_t offset = 0) override + { + const NvBlastDataBlock* block = reinterpret_cast<const NvBlastDataBlock*>(object); + const uint64_t size = block->size + offset; + buffer = bufferProvider.requestBuffer(size); + if (buffer == nullptr) + { + return 0; + } + memcpy(static_cast<char*>(buffer) + offset, object, block->size); + return size; + } +}; + + +class ExtLlSerializerAsset_RAW : public ExtLlSerializerObject_RAW +{ +public: + ExtSerializerBoilerplate("LLAsset_RAW", "Blast low-level asset (NvBlastAsset) serialization using raw memory format.", LlObjectTypeID::Asset, ExtSerialization::EncodingID::RawBinary); + ExtSerializerDefaultFactoryAndRelease(ExtLlSerializerAsset_RAW); +}; + + +class ExtLlSerializerFamily_RAW : public ExtLlSerializerObject_RAW +{ +public: + ExtSerializerBoilerplate("LLFamily_RAW", "Blast low-level family (NvBlastFamily) serialization using raw memory format.", LlObjectTypeID::Family, ExtSerialization::EncodingID::RawBinary); + ExtSerializerDefaultFactoryAndRelease(ExtLlSerializerFamily_RAW); +}; + +} // namespace Blast +} // namespace Nv + + +/////////////////////////////////////// + + +size_t NvBlastExtLlSerializerLoadSet(Nv::Blast::ExtSerialization& serialization) +{ + Nv::Blast::ExtSerializer* (*factories[])() = + { + Nv::Blast::ExtLlSerializerAsset_CPNB::create, + Nv::Blast::ExtLlSerializerAsset_RAW::create, + Nv::Blast::ExtLlSerializerFamily_RAW::create + }; + + return Nv::Blast::ExtSerializationLoadSet(static_cast<Nv::Blast::ExtSerializationInternal&>(serialization), factories); +} + + +uint64_t NvBlastExtSerializationSerializeAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const NvBlastAsset* asset) +{ + return serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::LlObjectTypeID::Asset); +} + + +uint64_t NvBlastExtSerializationSerializeFamilyIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const NvBlastFamily* family) +{ + return serialization.serializeIntoBuffer(buffer, family, Nv::Blast::LlObjectTypeID::Family); +} diff --git a/sdk/extensions/serialization/source/NvBlastExtLlSerializerCAPN.h b/sdk/extensions/serialization/source/NvBlastExtLlSerializerCAPN.h new file mode 100644 index 0000000..1e4bbc2 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtLlSerializerCAPN.h @@ -0,0 +1,72 @@ +// 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. + + +#pragma once + +#include "NvBlastExtSerializationCAPN.h" +#include "NvBlastAsset.h" +#include "AssetDTO.h" + + +/** +Specializations of ExtSerializationCAPN for Blast LL +*/ + +namespace Nv +{ +namespace Blast +{ + +//// Nv::Blast::Asset //// + +template<> +NV_INLINE bool ExtSerializationCAPN<Asset, Serialization::Asset::Reader, Serialization::Asset::Builder>::serializeIntoBuilder(Serialization::Asset::Builder& assetBuilder, const Asset* asset) +{ + return AssetDTO::serialize(assetBuilder, asset); +} + + +template<> +NV_INLINE bool ExtSerializationCAPN<Asset, Serialization::Asset::Reader, Serialization::Asset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const Asset* asset) +{ + Serialization::Asset::Builder assetBuilder = message.initRoot<Serialization::Asset>(); + + return serializeIntoBuilder(assetBuilder, asset); +} + + +template<> +NV_INLINE Asset* ExtSerializationCAPN<Asset, Serialization::Asset::Reader, Serialization::Asset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) +{ + Serialization::Asset::Reader reader = message.getRoot<Serialization::Asset>(); + + return AssetDTO::deserialize(reader); +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtOutputStream.cpp b/sdk/extensions/serialization/source/NvBlastExtOutputStream.cpp index cf6e31f..c270fa8 100644 --- a/sdk/extensions/serialization/source/NvBlastExtOutputStream.cpp +++ b/sdk/extensions/serialization/source/NvBlastExtOutputStream.cpp @@ -1,15 +1,32 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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 "NvBlastExtOutputStream.h" +#include "NvBlastExtOutputStream.h" Nv::Blast::ExtOutputStream::ExtOutputStream(std::ostream &outputStream): diff --git a/sdk/extensions/serialization/source/NvBlastExtOutputStream.h b/sdk/extensions/serialization/source/NvBlastExtOutputStream.h index ba0044e..89b19a9 100644 --- a/sdk/extensions/serialization/source/NvBlastExtOutputStream.h +++ b/sdk/extensions/serialization/source/NvBlastExtOutputStream.h @@ -1,31 +1,52 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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. + #pragma once #include "kj/io.h" #include <ostream> + namespace Nv { - namespace Blast - { - class ExtOutputStream : public kj::OutputStream - { - - public: - ExtOutputStream() = delete; - ExtOutputStream(std::ostream &outputStream); - - virtual void write(const void* buffer, size_t size) override; - private: - std::ostream &m_outputStream; - }; - } -} +namespace Blast +{ + +class ExtOutputStream : public kj::OutputStream +{ +public: + ExtOutputStream() = delete; + ExtOutputStream(std::ostream &outputStream); + + virtual void write(const void* buffer, size_t size) override; + +private: + std::ostream &m_outputStream; +}; + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerialization.capn b/sdk/extensions/serialization/source/NvBlastExtPxSerialization.capn new file mode 100644 index 0000000..802898f --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtPxSerialization.capn @@ -0,0 +1,99 @@ +# 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. + + +@0xf4df9a42d5842b01; + +using Cxx = import "/capnp/c++.capnp"; + +using TK = import "NvBlastExtTkSerialization.capn"; + +$Cxx.namespace("Nv::Blast::Serialization"); + +struct ExtPxAsset +{ + asset @0 :TK.TkAsset; + chunks @1 :List(ExtPxChunk); + subchunks @2 :List(ExtPxSubchunk); + uniformInitialBondHealth @3 :Float32; + bondHealths @4 :List(Float32); + uniformInitialLowerSupportChunkHealth @5 :Float32; + supportChunkHealths @6 :List(Float32); +} + +struct ExtPxChunk +{ + firstSubchunkIndex @0 :UInt32; + subchunkCount @1 :UInt32; + isStatic @2 :Bool; +} + +struct ExtPxSubchunk +{ + transform @0 :PxTransform; + geometry @1 :PxConvexMeshGeometry; +} + +struct PxConvexMeshGeometry +{ + scale @0 :PxMeshScale; + convexMesh @1 :Data; + meshFlags @2 :UInt8; + + enum Type + { + eSPHERE @0; + ePLANE @1; + eCAPSULE @2; + eBOX @3; + eCONVEXMESH @4; + eTRIANGLEMESH @5; + eHEIGHTFIELD @6; + } + + type @3 :Type; +} + +struct PxQuat +{ + x @0 :Float32; + y @1 :Float32; + z @2 :Float32; + w @3 :Float32; +} + +struct PxMeshScale +{ + scale @0 :TK.PxVec3; + rotation @1 :PxQuat; +} + +struct PxTransform +{ + q @0 :PxQuat; + p @1 :TK.PxVec3; +} diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerialization.cpp b/sdk/extensions/serialization/source/NvBlastExtPxSerialization.cpp new file mode 100644 index 0000000..d48213d --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtPxSerialization.cpp @@ -0,0 +1,109 @@ +// 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 "NvBlastExtSerializationInternal.h" +#include "NvBlastExtPxSerialization.h" +#include "NvBlastExtPxSerializerCAPN.h" +#include "NvBlastExtPxSerializerRAW.h" + + +namespace Nv +{ +namespace Blast +{ + +TkFramework* sExtPxSerializerFramework = nullptr; +physx::PxPhysics* sExtPxSerializerPhysics = nullptr; +physx::PxCooking* sExtPxSerializerCooking = nullptr; + + +class ExtPxSerializerAsset_CPNB : public ExtSerializer +{ +public: + ExtSerializerBoilerplate("ExtPxAsset_CPNB", "Blast PhysX extension asset (Nv::Blast::ExtPxAsset) serialization using Cap'n Proto binary format.", ExtPxObjectTypeID::Asset, ExtSerialization::EncodingID::CapnProtoBinary); + ExtSerializerDefaultFactoryAndRelease(ExtPxSerializerAsset_CPNB); + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + return ExtSerializationCAPN<ExtPxAsset, Serialization::ExtPxAsset::Reader, Serialization::ExtPxAsset::Builder>::deserializeFromBuffer(reinterpret_cast<const unsigned char*>(buffer), size); + } + + virtual uint64_t serializeIntoBuffer(void*& buffer, ExtSerialization::BufferProvider& bufferProvider, const void* object, uint64_t offset = 0) override + { + uint64_t usedSize; + if (!ExtSerializationCAPN<ExtPxAsset, Serialization::ExtPxAsset::Reader, Serialization::ExtPxAsset::Builder>::serializeIntoBuffer(reinterpret_cast<const ExtPxAsset*>(object), + reinterpret_cast<unsigned char*&>(buffer), usedSize, &bufferProvider, offset)) + { + return 0; + } + return usedSize; + } +}; + + +class ExtPxSerializerAsset_RAW : public ExtSerializer +{ +public: + ExtSerializerBoilerplate("ExtPxAsset_RAW", "Blast PhysX extension asset (Nv::Blast::TkAsset) serialization using raw memory format.", ExtPxObjectTypeID::Asset, ExtSerialization::EncodingID::RawBinary); + ExtSerializerDefaultFactoryAndRelease(ExtPxSerializerAsset_RAW); + ExtSerializerReadOnly(ExtPxSerializerAsset_RAW); + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + ExtIStream stream(buffer, size); + return deserializeExtPxAsset(stream, *sExtPxSerializerFramework, *sExtPxSerializerPhysics); + } +}; + +} // namespace Blast +} // namespace Nv + + +/////////////////////////////////////// + + +size_t NvBlastExtPxSerializerLoadSet(Nv::Blast::TkFramework& framework, physx::PxPhysics& physics, physx::PxCooking& cooking, Nv::Blast::ExtSerialization& serialization) +{ + Nv::Blast::sExtPxSerializerFramework = &framework; + Nv::Blast::sExtPxSerializerPhysics = &physics; + Nv::Blast::sExtPxSerializerCooking = &cooking; + + Nv::Blast::ExtSerializer* (*factories[])() = + { + Nv::Blast::ExtPxSerializerAsset_CPNB::create, + Nv::Blast::ExtPxSerializerAsset_RAW::create + }; + + return Nv::Blast::ExtSerializationLoadSet(static_cast<Nv::Blast::ExtSerializationInternal&>(serialization), factories); +} + + +uint64_t NvBlastExtSerializationSerializeExtPxAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const Nv::Blast::ExtPxAsset* asset) +{ + return serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::ExtPxObjectTypeID::Asset); +} diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerializerCAPN.h b/sdk/extensions/serialization/source/NvBlastExtPxSerializerCAPN.h new file mode 100644 index 0000000..cd0e45f --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtPxSerializerCAPN.h @@ -0,0 +1,70 @@ +// 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. + + +#pragma once + +#include "NvBlastExtSerializationCAPN.h" +#include "NvBlastExtPxAsset.h" +#include "ExtPxAssetDTO.h" + + +/** +Specializations of ExtSerializationCAPN for BlastExtPx +*/ + +namespace Nv +{ +namespace Blast +{ + +//// Nv::Blast::ExtPxAsset //// + +template<> +NV_INLINE bool ExtSerializationCAPN<ExtPxAsset, Serialization::ExtPxAsset::Reader, Serialization::ExtPxAsset::Builder>::serializeIntoBuilder(Serialization::ExtPxAsset::Builder& assetBuilder, const ExtPxAsset* asset) +{ + return ExtPxAssetDTO::serialize(assetBuilder, asset); +} + +template<> +NV_INLINE ExtPxAsset* ExtSerializationCAPN<ExtPxAsset, Serialization::ExtPxAsset::Reader, Serialization::ExtPxAsset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) +{ + Serialization::ExtPxAsset::Reader reader = message.getRoot<Serialization::ExtPxAsset>(); + + return ExtPxAssetDTO::deserialize(reader); +} + +template<> +NV_INLINE bool ExtSerializationCAPN<ExtPxAsset, Serialization::ExtPxAsset::Reader, Serialization::ExtPxAsset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const ExtPxAsset* asset) +{ + Serialization::ExtPxAsset::Builder assetBuilder = message.initRoot<Serialization::ExtPxAsset>(); + + return serializeIntoBuilder(assetBuilder, asset); +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp new file mode 100644 index 0000000..526b148 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp @@ -0,0 +1,220 @@ +// 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 "NvBlastExtSerialization.h" +#include "NvBlastExtTkSerializerRAW.h" +#include "NvBlastExtPxAsset.h" +#include "NvBlastTkAsset.h" +#include "physics/NvBlastExtPxAssetImpl.h" +#include "NvBlastIndexFns.h" +#include "NvBlastAssert.h" +#include "NvBlastExtSerializationInternal.h" + +#include "PxPhysics.h" +#include "PsMemoryBuffer.h" +#include "PxIO.h" + + +namespace Nv +{ +namespace Blast +{ + +// Legacy IDs +struct ExtPxSerializationLegacyID +{ + enum Enum + { + Asset = NVBLAST_FOURCC('B', 'P', 'X', 'A'), //!< ExtPxAsset identifier token, used in serialization + }; +}; + + +// Legacy object format versions +struct ExtPxSerializationLegacyAssetVersion +{ + enum Enum + { + /** Initial version */ + Initial, + + // New formats must come before Count. They should be given descriptive names with more information in comments. + + /** The number of serialized formats. */ + Count, + + /** The current version. This should always be Count-1 */ + Current = Count - 1 + }; +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Helpers/Wrappers +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class FileBufToPxInputStream final : public PxInputStream +{ +public: + FileBufToPxInputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {} + + virtual uint32_t read(void* dest, uint32_t count) + { + return m_filebuf.read(dest, count); + } + +private: + FileBufToPxInputStream& operator=(const FileBufToPxInputStream&); + + PxFileBuf& m_filebuf; +}; + + +class FileBufToPxOutputStream final : public PxOutputStream +{ +public: + FileBufToPxOutputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {} + + virtual uint32_t write(const void* src, uint32_t count) override + { + return m_filebuf.write(src, count); + } + +private: + FileBufToPxOutputStream& operator=(const FileBufToPxOutputStream&); + + PxFileBuf& m_filebuf; +}; + + +ExtPxAsset* deserializeExtPxAsset(ExtIStream& stream, TkFramework& framework, physx::PxPhysics& physics) +{ + // Read header + struct LegacyAssetDataHeader + { + uint32_t dataType; + uint32_t version; + }; + LegacyAssetDataHeader header; + stream >> header.dataType; + stream >> header.version; + NVBLAST_CHECK_ERROR(header.dataType == ExtPxSerializationLegacyID::Asset, "deserializeExtPxAsset: wrong data type in filebuf stream.", return nullptr); + NVBLAST_CHECK_ERROR(header.version == ExtPxSerializationLegacyAssetVersion::Current, "deserializeExtPxAsset: wrong data version in filebuf stream.", return nullptr); + + // Read initial TkAsset + TkAsset* tkAsset = deserializeTkAsset(stream, framework); + NVBLAST_CHECK_ERROR(tkAsset != nullptr, "ExtPxAsset::deserialize: failed to deserialize TkAsset.", return nullptr); + + // Create ExtPxAsset + ExtPxAssetImpl* asset = reinterpret_cast<ExtPxAssetImpl*>(ExtPxAsset::create(tkAsset)); + + // Fill arrays + auto& chunks = asset->getChunksArray(); + chunks.resize(tkAsset->getChunkCount()); + const uint32_t chunkCount = chunks.size(); + for (uint32_t i = 0; i < chunkCount; ++i) + { + ExtPxChunk& chunk = chunks[i]; + stream >> chunk.firstSubchunkIndex; + stream >> chunk.subchunkCount; + uint32_t val; + stream >> val; + chunk.isStatic = 0 != val; + } + + auto& subchunks = asset->getSubchunksArray(); + uint32_t subchunkCount; + stream >> subchunkCount; + subchunks.resize(subchunkCount); + for (uint32_t i = 0; i < subchunkCount; ++i) + { + ExtPxSubchunk& subchunk = subchunks[i]; + + // Subchunk transform + stream >> subchunk.transform.q.x >> subchunk.transform.q.y >> subchunk.transform.q.z >> subchunk.transform.q.w; + stream >> subchunk.transform.p.x >> subchunk.transform.p.y >> subchunk.transform.p.z; + + // Subchunk scale + stream >> subchunk.geometry.scale.scale.x >> subchunk.geometry.scale.scale.y >> subchunk.geometry.scale.scale.z; + stream >> subchunk.geometry.scale.rotation.x >> subchunk.geometry.scale.rotation.y >> subchunk.geometry.scale.rotation.z >> subchunk.geometry.scale.rotation.w; + + uint32_t convexReuseIndex; + stream >> convexReuseIndex; + if (isInvalidIndex(convexReuseIndex)) + { + physx::PsMemoryBuffer memBuf(stream.view(), stream.left()); + FileBufToPxInputStream inputStream(memBuf); + subchunk.geometry.convexMesh = physics.createConvexMesh(inputStream); + stream.advance(memBuf.tellRead()); + } + else + { + NVBLAST_ASSERT_WITH_MESSAGE(convexReuseIndex < i, "ExtPxAsset::deserialize: wrong convexReuseIndex."); + subchunk.geometry.convexMesh = subchunks[convexReuseIndex].geometry.convexMesh; + } + if (!subchunk.geometry.convexMesh) + { + NVBLAST_LOG_ERROR("ExtPxAsset::deserialize: failed to deserialize convex mesh."); + return nullptr; + } + } + + // checking if it's the end, so it will be binary compatible with asset before m_defaultActorDesc was added + if (!stream.eof()) + { + auto& defaultActorDesc = asset->getDefaultActorDesc(); + + stream >> defaultActorDesc.uniformInitialBondHealth; + stream >> defaultActorDesc.uniformInitialLowerSupportChunkHealth; + + auto& bondHealths = asset->getBondHealthsArray(); + uint32_t bondHealthCount; + stream >> bondHealthCount; + bondHealths.resize(bondHealthCount); + for (uint32_t i = 0; i < bondHealths.size(); ++i) + { + stream >> bondHealths[i]; + } + defaultActorDesc.initialBondHealths = bondHealthCount ? bondHealths.begin() : nullptr; + + auto& supportChunkHealths = asset->getBondHealthsArray(); + uint32_t supportChunkHealthCount; + stream >> supportChunkHealthCount; + supportChunkHealths.resize(supportChunkHealthCount); + for (uint32_t i = 0; i < supportChunkHealths.size(); ++i) + { + stream >> supportChunkHealths[i]; + } + defaultActorDesc.initialSupportChunkHealths = supportChunkHealthCount ? supportChunkHealths.begin() : nullptr; + } + + return asset; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.h b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.h new file mode 100644 index 0000000..1e287c5 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.h @@ -0,0 +1,61 @@ +// 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. + + +#pragma once + + +/** +Raw serialization function declarations for BlastExtPx +*/ + +#include <stdint.h> + + +// Forward declarations +namespace physx +{ +class PxPhysics; +} + +namespace Nv +{ +namespace Blast +{ + +// Forward declarations +class ExtPxAsset; +class TkFramework; +class ExtIStream; + + +//// Nv::Blast::TkAsset //// + +ExtPxAsset* deserializeExtPxAsset(ExtIStream& stream, TkFramework& framework, physx::PxPhysics& physics); + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtSerialization.capn b/sdk/extensions/serialization/source/NvBlastExtSerialization.capn deleted file mode 100644 index ddc439a..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerialization.capn +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -# -# NVIDIA CORPORATION and its licensors retain all intellectual property -# and proprietary rights in and to this software, 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. - -@0xaffe4498f275ee58; - -using Cxx = import "/capnp/c++.capnp"; - -using LL = import "NvBlastExtSerializationLL.capn"; - -$Cxx.namespace("Nv::Blast::Serialization"); - -struct TkAsset -{ - assetLL @0 :LL.Asset; - - jointDescs @1 :List(TkAssetJointDesc); -} - -struct ExtPxAsset -{ - asset @0 :TkAsset; - chunks @1 :List(ExtPxChunk); - subchunks @2 :List(ExtPxSubchunk); -} - -struct ExtPxChunk -{ - firstSubchunkIndex @0 :UInt32; - subchunkCount @1 :UInt32; - isStatic @2 :Bool; -} - -struct ExtPxSubchunk -{ - transform @0 :PxTransform; - geometry @1 :PxConvexMeshGeometry; -} - -struct PxConvexMeshGeometry -{ - scale @0 :PxMeshScale; - convexMesh @1 :Data; - meshFlags @2 :UInt8; - - enum Type - { - eSPHERE @0; - ePLANE @1; - eCAPSULE @2; - eBOX @3; - eCONVEXMESH @4; - eTRIANGLEMESH @5; - eHEIGHTFIELD @6; - } - - type @3 :Type; -} - -struct TkAssetJointDesc -{ - nodeIndices @0 :List(UInt32); - attachPositions @1 :List(PxVec3); -} - -struct PxVec3 -{ - x @0 :Float32; - y @1 :Float32; - z @2 :Float32; -} - -struct PxQuat -{ - x @0 :Float32; - y @1 :Float32; - z @2 :Float32; - w @3 :Float32; -} - -struct PxMeshScale -{ - scale @0 :PxVec3; - rotation @1 :PxQuat; -} - -struct PxTransform -{ - q @0 :PxQuat; - p @1 :PxVec3; -} diff --git a/sdk/extensions/serialization/source/NvBlastExtSerialization.cpp b/sdk/extensions/serialization/source/NvBlastExtSerialization.cpp index 28a1553..77ecdf6 100644 --- a/sdk/extensions/serialization/source/NvBlastExtSerialization.cpp +++ b/sdk/extensions/serialization/source/NvBlastExtSerialization.cpp @@ -1,146 +1,401 @@ +// 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 "NvBlastExtSerialization.h" -#include "BlastSerialization.h" -#include <memory> -#include "PxPhysicsVersion.h" -#include "PxConvexMeshGeometryDTO.h" -#include "NvBlastExtDefs.h" +#include "NvBlastExtLlSerialization.h" +#include "NvBlastHashMap.h" +#include "NvBlastExtSerializationInternal.h" + + +namespace Nv +{ +namespace Blast +{ + +class ExtSerializationImpl : public ExtSerializationInternal +{ +public: + // Default buffer provider + class AllocBufferProvider : public ExtSerialization::BufferProvider + { + public: + virtual void* requestBuffer(size_t size) override; + }; + + + ExtSerializationImpl(); + ~ExtSerializationImpl(); + + // ExtSerialization interface begin + virtual bool setSerializationEncoding(uint32_t encodingID) override; + virtual uint32_t getSerializationEncoding() const override; + + virtual void setBufferProvider(BufferProvider* bufferProvider) override; + + virtual bool peekHeader(uint32_t* objectTypeID, uint32_t* encodingID, uint64_t* dataSize, const void* buffer, uint64_t bufferSize) override; + virtual const void* skipObject(uint64_t& bufferSize, const void* buffer) override; + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size, uint32_t* objectTypeIDPtr = nullptr) override; + virtual uint64_t serializeIntoBuffer(void*& buffer, const void* object, uint32_t objectTypeID) override; + virtual void release() override; + // ExtSerialization interface end -// This is terrible. -physx::PxPhysics* g_Physics = nullptr; + // ExtSerializationInternal interface begin + virtual bool registerSerializer(ExtSerializer& serializer) override; + virtual bool unregisterSerializer(ExtSerializer& serializer) override; + + virtual ExtSerializer* findSerializer(uint32_t objectTypeID, uint32_t encodingID) override; + // ExtSerializationInternal interface end + +private: + char* writeHeaderIntoBuffer(char* buffer, uint64_t bufferSize, uint32_t objectTypeID, uint32_t encodingID, uint64_t dataSize) const; + const char* readHeaderFromBuffer(uint32_t* objectTypeID, uint32_t* encodingID, uint64_t* dataSize, const char* buffer, uint64_t bufferSize) const; + + //// Static data //// + static const char* s_identifier; + static const char* s_version; + static AllocBufferProvider s_defaultBufferProvider; + + //// Member data //// + HashMap<uint64_t, ExtSerializer*>::type m_serializers; + uint32_t m_serializationEncoding; + BufferProvider* m_bufferProvider; +}; + + +//////// ExtSerializationImpl static member variables //////// + +/** Module identifying header. This should never change. */ +const char* ExtSerializationImpl::s_identifier = "NVidia(r) GameWorks Blast(tm) v."; + +const char* ExtSerializationImpl::s_version = "1"; + +ExtSerializationImpl::AllocBufferProvider ExtSerializationImpl::s_defaultBufferProvider; + + +//////// Local utility functions //////// + +static NV_INLINE uint64_t generateKey(uint32_t objectTypeID, uint32_t encodingID) +{ + return static_cast<uint64_t>(encodingID) << 32 | static_cast<uint64_t>(objectTypeID); +} -std::shared_ptr<physx::PxCooking> getCooking() +static NV_INLINE uint64_t generateKey(const ExtSerializer& serializer) { - physx::PxCookingParams cookingParams(g_Physics->getTolerancesScale()); - cookingParams.buildGPUData = true; + return generateKey(serializer.getObjectTypeID(), serializer.getEncodingID()); +} + - std::shared_ptr<physx::PxCooking> m_Cooking = std::shared_ptr<physx::PxCooking>(PxCreateCooking(PX_PHYSICS_VERSION, g_Physics->getFoundation(), cookingParams), [=](physx::PxCooking* cooking) +static NV_INLINE void writeIDToBuffer(char* buffer, uint32_t id) +{ + for (int i = 0; i < 4; ++i, id >>= 8) { - cooking->release(); - }); + *buffer++ = static_cast<char>(id & 0xFF); + } +} - NVBLASTEXT_CHECK_ERROR(m_Cooking, "Error: failed to create PhysX Cooking\n", return nullptr); - return m_Cooking; +static NV_INLINE uint32_t readIDFromBuffer(const char* buffer) +{ + return NVBLAST_FOURCC(buffer[0], buffer[1], buffer[2], buffer[3]); } -extern "C" +static NV_INLINE void writeU64InHexToBuffer(char* buffer, uint64_t val) { - NVBLAST_API void setPhysXSDK(physx::PxPhysics* physXSDK) + for (char* curr = buffer + 16; curr-- > buffer; val >>= 4) { - g_Physics = physXSDK; + *curr = "0123456789ABCDEF"[val & 0xF]; } +} + - NVBLAST_API NvBlastAsset* deserializeAsset(const unsigned char* input, uint32_t size) +static NV_INLINE uint64_t readU64InHexFromBuffer(const char* buffer) +{ + uint64_t val = 0; + for (const char* curr = buffer; curr < buffer + 16; ++curr) { - return Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::deserialize(input, size); + const char c = *curr; + const char msn = c >> 4; + const char mask = ((88 >> msn) & 1) - 1; + const unsigned char digit = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xA\xB\xC\xD\xE\xF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"[((msn - 3) & 1) << 4 | (c & 0xF)] | mask; + if (digit == 0xFF) + { + return 0; // Not a hexidecimal digit + } + val = val << 4 | digit; } + return val; +} + + +//////// ExtSerialization member functions //////// + +ExtSerializationImpl::ExtSerializationImpl() : m_serializationEncoding(EncodingID::CapnProtoBinary), m_bufferProvider(&s_defaultBufferProvider) +{ +} - NVBLAST_API NvBlastAsset* deserializeAssetFromStream(std::istream &inputStream) + +ExtSerializationImpl::~ExtSerializationImpl() +{ + // Release and remove all registered serializers + auto it = m_serializers.getEraseIterator(); + while (auto entry = it.eraseCurrentGetNext(true)) { - return Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::deserializeFromStream(inputStream); + entry->second->release(); } - - NVBLAST_API bool serializeAssetIntoStream(const NvBlastAsset *asset, std::ostream &outputStream) +} + + +char* ExtSerializationImpl::writeHeaderIntoBuffer(char* buffer, uint64_t bufferSize, uint32_t objectTypeID, uint32_t encodingID, uint64_t dataSize) const +{ + if (bufferSize < HeaderSize) { - return Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::Asset *>(asset), outputStream); + return nullptr; } - NVBLAST_API bool serializeAssetIntoNewBuffer(const NvBlastAsset *asset, unsigned char **outBuffer, uint32_t &outSize) + char* stop = buffer + HeaderSize; + + size_t versionLen = strlen(s_version); + if (versionLen > 63) { - return Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::Asset *>(asset), outBuffer, outSize); + versionLen = 63; } - NVBLAST_API bool serializeAssetIntoExistingBuffer(const NvBlastAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) + memset(buffer, ' ', HeaderSize); + memcpy(buffer, s_identifier, 32); buffer += 32; + memcpy(buffer, s_version, versionLen); buffer += 64; + writeIDToBuffer(buffer, objectTypeID); buffer += 5; + writeIDToBuffer(buffer, encodingID); buffer += 5; + writeU64InHexToBuffer(buffer, dataSize); buffer += 16; + *(stop - 1) = '\n'; + + return stop; +} + + +const char* ExtSerializationImpl::readHeaderFromBuffer(uint32_t* objectTypeID, uint32_t* encodingID, uint64_t* dataSize, const char* buffer, uint64_t bufferSize) const +{ + if (bufferSize < HeaderSize) { - return Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::Asset *>(asset), buffer, maxSize, usedSize); + NVBLAST_LOG_ERROR("ExtSerializationImpl::readHeaderFromBuffer: header terminator not found."); + return nullptr; } - ////////////////////////////////////////////////////////////////////////// - // TkAsset - ////////////////////////////////////////////////////////////////////////// + const char* stop = buffer + HeaderSize; - NVBLAST_API Nv::Blast::TkAsset* deserializeTkAsset(const unsigned char* input, uint32_t size) + if (memcmp(buffer, s_identifier, 32)) { - return Nv::Blast::BlastSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::deserialize(input, size); + NVBLAST_LOG_ERROR("ExtSerializationImpl::readHeaderFromBuffer: file identifier does not match expected value."); + return nullptr; } + buffer += 32; - NVBLAST_API Nv::Blast::TkAsset* deserializeTkAssetFromStream(std::istream &inputStream) + const char* s = strchr(buffer, ' '); + if (s == nullptr) + { + NVBLAST_LOG_ERROR("ExtSerializationImpl::readHeaderFromBuffer: file format error reading serializer library version."); + } + if (memcmp(buffer, s_version, s - buffer)) { - return Nv::Blast::BlastSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::deserializeFromStream(inputStream); + NVBLAST_LOG_ERROR("ExtSerializationImpl::readHeaderFromBuffer: file version does not match serializer library version."); + return nullptr; } + buffer += 64; - NVBLAST_API bool serializeTkAssetIntoStream(const Nv::Blast::TkAsset *asset, std::ostream &outputStream) + if (objectTypeID != nullptr) { - return Nv::Blast::BlastSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), outputStream); + *objectTypeID = readIDFromBuffer(buffer); } + buffer += 5; - NVBLAST_API bool serializeTkAssetIntoNewBuffer(const Nv::Blast::TkAsset *asset, unsigned char **outBuffer, uint32_t &outSize) + if (encodingID != nullptr) { - return Nv::Blast::BlastSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), outBuffer, outSize); + *encodingID = readIDFromBuffer(buffer); } + buffer += 5; - NVBLAST_API bool serializeTkAssetIntoExistingBuffer(const Nv::Blast::TkAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) + if (dataSize != nullptr) { - return Nv::Blast::BlastSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), buffer, maxSize, usedSize); + *dataSize = readU64InHexFromBuffer(buffer); } + buffer += 16; - ////////////////////////////////////////////////////////////////////////// - // ExtPxAsset - ////////////////////////////////////////////////////////////////////////// + return stop; +} - NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAsset(const unsigned char* input, uint32_t size) - { - NVBLAST_ASSERT(g_Physics != nullptr); - return Nv::Blast::BlastSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::deserialize(input, size); - } +bool ExtSerializationImpl::registerSerializer(ExtSerializer& serializer) +{ + return m_serializers.insert(generateKey(serializer), &serializer); +} - NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAssetFromStream(std::istream &inputStream) - { - NVBLAST_ASSERT(g_Physics != nullptr); - return Nv::Blast::BlastSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::deserializeFromStream(inputStream); +bool ExtSerializationImpl::unregisterSerializer(ExtSerializer& serializer) +{ + const uint64_t key = generateKey(serializer); + const auto entry = m_serializers.find(key); + if (entry == nullptr) + { + return false; } + entry->second->release(); + return m_serializers.erase(key); +} + - NVBLAST_API bool serializeExtPxAssetIntoStream(const Nv::Blast::ExtPxAsset *asset, std::ostream &outputStream) +ExtSerializer* ExtSerializationImpl::findSerializer(uint32_t objectTypeID, uint32_t encodingID) +{ + auto entry = m_serializers.find(generateKey(objectTypeID, encodingID)); + return entry != nullptr ? entry->second : nullptr; +} + + +bool ExtSerializationImpl::setSerializationEncoding(uint32_t encodingID) +{ + m_serializationEncoding = encodingID; + + return true; +} + + +uint32_t ExtSerializationImpl::getSerializationEncoding() const +{ + return m_serializationEncoding; +} + + +void ExtSerializationImpl::setBufferProvider(BufferProvider* bufferProvider) +{ + m_bufferProvider = bufferProvider != nullptr ? bufferProvider : &s_defaultBufferProvider; +} + + +bool ExtSerializationImpl::peekHeader(uint32_t* objectTypeID, uint32_t* encodingID, uint64_t* dataSize, const void* buffer, uint64_t bufferSize) +{ + return nullptr != readHeaderFromBuffer(objectTypeID, encodingID, dataSize, reinterpret_cast<const char*>(buffer), bufferSize); +} + + +const void* ExtSerializationImpl::skipObject(uint64_t& bufferSize, const void* buffer) +{ + uint64_t dataSize; + const char* next = readHeaderFromBuffer(nullptr, nullptr, &dataSize, static_cast<const char*>(buffer), bufferSize); + if (next == nullptr) { - NVBLAST_ASSERT(g_Physics != nullptr); + return nullptr; + } + next += dataSize; + const uint64_t skipSize = next - static_cast<const char*>(buffer); + NVBLAST_CHECK_ERROR(skipSize <= bufferSize, "Object size in buffer is too large for given buffer size.", return nullptr); + bufferSize -= skipSize; + return next; +} - auto cooking = getCooking(); - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; +void* ExtSerializationImpl::deserializeFromBuffer(const void* buffer, uint64_t bufferSize, uint32_t* objectTypeIDPtr) +{ + uint32_t objectTypeID; + uint32_t encodingID; + uint64_t dataSize; + void* result = nullptr; - return Nv::Blast::BlastSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), outputStream); + buffer = readHeaderFromBuffer(&objectTypeID, &encodingID, &dataSize, reinterpret_cast<const char*>(buffer), bufferSize); + if (buffer != nullptr) + { + auto entry = m_serializers.find(generateKey(objectTypeID, encodingID)); + if (entry != nullptr && entry->second != nullptr) + { + result = entry->second->deserializeFromBuffer(buffer, dataSize); + } } - NVBLAST_API bool serializeExtPxAssetIntoNewBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char **outBuffer, uint32_t &outSize) + if (objectTypeIDPtr != nullptr) { - NVBLAST_ASSERT(g_Physics != nullptr); + *objectTypeIDPtr = result != nullptr ? objectTypeID : 0; + } - auto cooking = getCooking(); + return result; +} - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; - return Nv::Blast::BlastSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), outBuffer, outSize); +uint64_t ExtSerializationImpl::serializeIntoBuffer(void*& buffer, const void* object, uint32_t objectTypeID) +{ + if (!m_serializationEncoding) + { + NVBLAST_LOG_ERROR("ExtSerializationImpl::serializeIntoBuffer: no serialization encoding has been set."); + return false; // No encoding available + } + + auto entry = m_serializers.find(generateKey(objectTypeID, m_serializationEncoding)); + if (entry == nullptr || entry->second == nullptr) + { + return false; } - NVBLAST_API bool serializeExtPxAssetIntoExistingBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) + const uint64_t size = entry->second->serializeIntoBuffer(buffer, *m_bufferProvider, object, HeaderSize); + if (size < HeaderSize) { - NVBLAST_ASSERT(g_Physics != nullptr); + NVBLAST_LOG_ERROR("ExtSerializationImpl::serializeIntoBuffer: failed to write data to buffer."); + return 0; + } + + writeHeaderIntoBuffer(reinterpret_cast<char*>(buffer), HeaderSize, objectTypeID, m_serializationEncoding, size - HeaderSize); - auto cooking = getCooking(); + return size; +} - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; - return Nv::Blast::BlastSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), buffer, maxSize, usedSize); - } +void ExtSerializationImpl::release() +{ + NVBLAST_DELETE(this, ExtSerializationImpl); +} + +//////// ExtSerializationImpl::AllocBufferProvider member functions //////// +void* ExtSerializationImpl::AllocBufferProvider::requestBuffer(size_t size) +{ + return NVBLAST_ALLOC(size); } +} // namespace Blast +} // namespace Nv + + +Nv::Blast::ExtSerialization* NvBlastExtSerializationCreate() +{ + Nv::Blast::ExtSerializationImpl* serialization = NVBLAST_NEW(Nv::Blast::ExtSerializationImpl) (); + + // Automatically load LL serializers + NvBlastExtLlSerializerLoadSet(*serialization); + + return serialization; +} diff --git a/sdk/extensions/serialization/source/NvBlastExtSerialization.h b/sdk/extensions/serialization/source/NvBlastExtSerialization.h deleted file mode 100644 index 5d44554..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerialization.h +++ /dev/null @@ -1,172 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#pragma once -#include "kj/io.h" -#include "capnp/serialize.h" -#include "generated/NvBlastExtSerializationLL.capn.h" -#include <vector> -#include "NvBlastExtInputStream.h" -#include "NvBlastExtOutputStream.h" - -#if !defined(BLAST_LL_ALLOC) -#include "NvBlastExtAllocator.h" -#endif -#include "NvBlastExtGlobals.h" - -namespace Nv -{ - namespace Blast - { - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - class ExtSerialization - { - public: - static TAsset* deserialize(const unsigned char* input, uint32_t size); - static TAsset* deserializeFromStream(std::istream &inputStream); - - static bool serializeIntoExistingBuffer(const TAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize); - static bool serializeIntoNewBuffer(const TAsset *asset, unsigned char **outBuffer, uint32_t &outSize); - static bool serializeIntoStream(const TAsset *asset, std::ostream &outputStream); - - private: - - static void serializeMessageIntoNewBuffer(capnp::MallocMessageBuilder& message, unsigned char ** outBuffer, uint32_t &outSize); - - // Specialized - static bool serializeIntoBuilder(TSerializationBuilder& assetBuilder, const TAsset* asset); - static bool serializeIntoMessage(capnp::MallocMessageBuilder& message, const TAsset* asset); - static TAsset* deserializeFromStreamReader(capnp::InputStreamMessageReader &message); - }; - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - TAsset* ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::deserialize(const unsigned char* input, uint32_t size) - { - kj::ArrayPtr<const unsigned char> source(input, size); - - kj::ArrayInputStream inputStream(source); - - std::vector<uint64_t> scratch; - scratch.resize(size); - kj::ArrayPtr<capnp::word> scratchArray((capnp::word*) scratch.data(), size); - - capnp::InputStreamMessageReader message(inputStream, capnp::ReaderOptions(), scratchArray); - - return deserializeFromStreamReader(message); - } - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - TAsset* ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::deserializeFromStream(std::istream &inputStream) - { - Nv::Blast::ExtInputStream readStream(inputStream); - - capnp::InputStreamMessageReader message(readStream); - - return deserializeFromStreamReader(message); - } - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - bool ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::serializeIntoExistingBuffer(const TAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) - { - capnp::MallocMessageBuilder message; - - bool result = serializeIntoMessage(message, asset); - - if (result == false) - { - usedSize = 0; - return false; - } - - uint32_t messageSize = computeSerializedSizeInWords(message) * sizeof(uint64_t); - - if (maxSize < messageSize) - { - NvBlastLog logFn = gLog; - -#if !defined(BLAST_LL_ALLOC) - logFn = NvBlastTkFrameworkGet()->getLogFn(); -#endif - - NVBLAST_LOG_ERROR(logFn, "When attempting to serialize into an existing buffer, the provided buffer was too small."); - usedSize = 0; - return false; - } - - kj::ArrayPtr<unsigned char> outputBuffer(buffer, maxSize); - kj::ArrayOutputStream outputStream(outputBuffer); - - capnp::writeMessage(outputStream, message); - - usedSize = messageSize;; - return true; - } - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - bool ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::serializeIntoNewBuffer(const TAsset *asset, unsigned char **outBuffer, uint32_t &outSize) - { - capnp::MallocMessageBuilder message; - - bool result = serializeIntoMessage(message, asset); - - if (result == false) - { - *outBuffer = nullptr; - outSize = 0; - return false; - } - - serializeMessageIntoNewBuffer(message, outBuffer, outSize); - - return true; - } - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - bool ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::serializeIntoStream(const TAsset *asset, std::ostream &outputStream) - { - capnp::MallocMessageBuilder message; - - bool result = serializeIntoMessage(message, asset); - - if (result == false) - { - return false; - } - - Nv::Blast::ExtOutputStream blastOutputStream(outputStream); - - writeMessage(blastOutputStream, message); - - return true; - } - - template<typename TAsset, typename TSerializationReader, typename TSerializationBuilder> - void ExtSerialization<TAsset, TSerializationReader, TSerializationBuilder>::serializeMessageIntoNewBuffer(capnp::MallocMessageBuilder& message, unsigned char ** outBuffer, uint32_t &outSize) - { - uint32_t messageSize = computeSerializedSizeInWords(message) * sizeof(uint64_t); - - NvBlastExtAlloc allocFn = gAlloc; - -#if !defined(BLAST_LL_ALLOC) - allocFn = ExtAllocator::alignedAlloc16; -#endif - - unsigned char* buffer = static_cast<unsigned char *>(allocFn(messageSize)); - - kj::ArrayPtr<unsigned char> outputBuffer(buffer, messageSize); - kj::ArrayOutputStream outputStream(outputBuffer); - - capnp::writeMessage(outputStream, message); - - *outBuffer = buffer; - outSize = messageSize; - } - } -} diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationCAPN.h b/sdk/extensions/serialization/source/NvBlastExtSerializationCAPN.h new file mode 100644 index 0000000..fe261e6 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtSerializationCAPN.h @@ -0,0 +1,188 @@ +// 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. + + +#pragma once + +#include "capnp/serialize.h" +#include "NvBlastExtInputStream.h" +#include "NvBlastExtOutputStream.h" +#include "NvBlastArray.h" +#include "NvBlastExtSerialization.h" + + +namespace Nv +{ +namespace Blast +{ + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +class ExtSerializationCAPN +{ +public: + static TObject* deserializeFromBuffer(const unsigned char* input, uint64_t size); + static TObject* deserializeFromStream(std::istream& inputStream); + + static uint64_t serializationBufferSize(const TObject* object); + + static bool serializeIntoBuffer(const TObject* object, unsigned char* buffer, uint64_t maxSize, uint64_t& usedSize); + static bool serializeIntoBuffer(const TObject *object, unsigned char*& buffer, uint64_t& size, ExtSerialization::BufferProvider* bufferProvider = nullptr, uint64_t offset = 0); + static bool serializeIntoStream(const TObject* object, std::ostream& outputStream); + +private: + // Specialized + static bool serializeIntoBuilder(TSerializationBuilder& objectBuilder, const TObject* object); + static bool serializeIntoMessage(capnp::MallocMessageBuilder& message, const TObject* object); + static TObject* deserializeFromStreamReader(capnp::InputStreamMessageReader& message); +}; + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +TObject* ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::deserializeFromBuffer(const unsigned char* input, uint64_t size) +{ + kj::ArrayPtr<const unsigned char> source(input, size); + + kj::ArrayInputStream inputStream(source); + + Nv::Blast::Array<uint64_t>::type scratch(static_cast<uint32_t>(size)); + kj::ArrayPtr<capnp::word> scratchArray((capnp::word*) scratch.begin(), size); + + capnp::InputStreamMessageReader message(inputStream, capnp::ReaderOptions(), scratchArray); + + return deserializeFromStreamReader(message); +} + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +TObject* ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::deserializeFromStream(std::istream& inputStream) +{ + ExtInputStream readStream(inputStream); + + capnp::InputStreamMessageReader message(readStream); + + return deserializeFromStreamReader(message); +} + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +uint64_t ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::serializationBufferSize(const TObject* object) +{ + capnp::MallocMessageBuilder message; + + bool result = serializeIntoMessage(message, object); + + if (result == false) + { + return 0; + } + + return computeSerializedSizeInWords(message) * sizeof(uint64_t); +} + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +bool ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::serializeIntoBuffer(const TObject* object, unsigned char* buffer, uint64_t maxSize, uint64_t& usedSize) +{ + capnp::MallocMessageBuilder message; + + bool result = serializeIntoMessage(message, object); + + if (result == false) + { + usedSize = 0; + return false; + } + + uint64_t messageSize = computeSerializedSizeInWords(message) * sizeof(uint64_t); + + if (maxSize < messageSize) + { + NVBLAST_LOG_ERROR("When attempting to serialize into an existing buffer, the provided buffer was too small."); + usedSize = 0; + return false; + } + + kj::ArrayPtr<unsigned char> outputBuffer(buffer, maxSize); + kj::ArrayOutputStream outputStream(outputBuffer); + + capnp::writeMessage(outputStream, message); + + usedSize = messageSize; + return true; +} + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +bool ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::serializeIntoBuffer(const TObject *object, unsigned char*& buffer, uint64_t& size, ExtSerialization::BufferProvider* bufferProvider, uint64_t offset) +{ + capnp::MallocMessageBuilder message; + + bool result = serializeIntoMessage(message, object); + + if (result == false) + { + buffer = nullptr; + size = 0; + return false; + } + + const uint64_t blockSize = computeSerializedSizeInWords(message) * sizeof(uint64_t); + + size = blockSize + offset; + + buffer = static_cast<unsigned char *>(bufferProvider != nullptr ? bufferProvider->requestBuffer(size) : NVBLAST_ALLOC(size)); + + kj::ArrayPtr<unsigned char> outputBuffer(buffer + offset, blockSize); + kj::ArrayOutputStream outputStream(outputBuffer); + + capnp::writeMessage(outputStream, message); + + return true; +} + + +template<typename TObject, typename TSerializationReader, typename TSerializationBuilder> +bool ExtSerializationCAPN<TObject, TSerializationReader, TSerializationBuilder>::serializeIntoStream(const TObject* object, std::ostream& outputStream) +{ + capnp::MallocMessageBuilder message; + + bool result = serializeIntoMessage(message, object); + + if (result == false) + { + return false; + } + + ExtOutputStream blastOutputStream(outputStream); + + writeMessage(blastOutputStream, message); + + return true; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationImpl.h b/sdk/extensions/serialization/source/NvBlastExtSerializationImpl.h deleted file mode 100644 index 7f9fbc9..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerializationImpl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#pragma once - -#include "NvBlastExtSerialization.h" -#include "NvBlastTkAsset.h" -#include "NvBlastExtPxAsset.h" -#include "TkAssetDTO.h" -#include "ExtPxAssetDTO.h" - -namespace Nv -{ - namespace Blast - { - /* - Specializations here - one set for each top level asset. (TkAsset, ExtPxAsset) - */ - - - // TkAsset - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoBuilder(Nv::Blast::Serialization::TkAsset::Builder& assetBuilder, const Nv::Blast::TkAsset* asset) - { - return TkAssetDTO::serialize(assetBuilder, asset); - } - - template<> - NV_INLINE Nv::Blast::TkAsset* ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) - { - Nv::Blast::Serialization::TkAsset::Reader reader = message.getRoot<Nv::Blast::Serialization::TkAsset>(); - - return TkAssetDTO::deserialize(reader); - } - - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const Nv::Blast::TkAsset* asset) - { - Nv::Blast::Serialization::TkAsset::Builder assetBuilder = message.initRoot<Nv::Blast::Serialization::TkAsset>(); - - return serializeIntoBuilder(assetBuilder, asset); - } - - - //ExtPxAsset - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoBuilder(Nv::Blast::Serialization::ExtPxAsset::Builder& assetBuilder, const Nv::Blast::ExtPxAsset* asset) - { - return ExtPxAssetDTO::serialize(assetBuilder, asset); - } - - template<> - NV_INLINE Nv::Blast::ExtPxAsset* ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) - { - Nv::Blast::Serialization::ExtPxAsset::Reader reader = message.getRoot<Nv::Blast::Serialization::ExtPxAsset>(); - - return ExtPxAssetDTO::deserialize(reader); - } - - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const Nv::Blast::ExtPxAsset* asset) - { - Nv::Blast::Serialization::ExtPxAsset::Builder assetBuilder = message.initRoot<Nv::Blast::Serialization::ExtPxAsset>(); - - return serializeIntoBuilder(assetBuilder, asset); - } - } -} diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationInterface.cpp b/sdk/extensions/serialization/source/NvBlastExtSerializationInterface.cpp deleted file mode 100644 index bebee5b..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerializationInterface.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtSerializationImpl.h" -#include <memory> -#include "PxPhysicsVersion.h" -#include "PxConvexMeshGeometryDTO.h" -#include "NvBlastExtDefs.h" -#include "PxPhysics.h" -#include "NvBlastAssert.h" - - -// This is terrible. -physx::PxPhysics* g_Physics = nullptr; - -using namespace Nv::Blast; - -std::shared_ptr<physx::PxCooking> getCooking() -{ - physx::PxCookingParams cookingParams(g_Physics->getTolerancesScale()); - cookingParams.buildGPUData = true; - - std::shared_ptr<physx::PxCooking> m_Cooking = std::shared_ptr<physx::PxCooking>(PxCreateCooking(PX_PHYSICS_VERSION, g_Physics->getFoundation(), cookingParams), [=](physx::PxCooking* cooking) - { - cooking->release(); - }); - - NVBLASTEXT_CHECK_ERROR(m_Cooking, "Error: failed to create PhysX Cooking\n", return nullptr); - - return m_Cooking; -} - - -extern "C" -{ - NVBLAST_API void setPhysXSDK(physx::PxPhysics* physXSDK) - { - g_Physics = physXSDK; - } - - ////////////////////////////////////////////////////////////////////////// - // TkAsset - ////////////////////////////////////////////////////////////////////////// - - NVBLAST_API Nv::Blast::TkAsset* deserializeTkAsset(const unsigned char* input, uint32_t size) - { - return Nv::Blast::ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::deserialize(input, size); - } - - NVBLAST_API Nv::Blast::TkAsset* deserializeTkAssetFromStream(std::istream &inputStream) - { - return Nv::Blast::ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::deserializeFromStream(inputStream); - } - - NVBLAST_API bool serializeTkAssetIntoStream(const Nv::Blast::TkAsset *asset, std::ostream &outputStream) - { - return Nv::Blast::ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), outputStream); - } - - NVBLAST_API bool serializeTkAssetIntoNewBuffer(const Nv::Blast::TkAsset *asset, unsigned char **outBuffer, uint32_t &outSize) - { - return Nv::Blast::ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), outBuffer, outSize); - } - - NVBLAST_API bool serializeTkAssetIntoExistingBuffer(const Nv::Blast::TkAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) - { - return Nv::Blast::ExtSerialization<Nv::Blast::TkAsset, Nv::Blast::Serialization::TkAsset::Reader, Nv::Blast::Serialization::TkAsset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::TkAsset *>(asset), buffer, maxSize, usedSize); - } - - ////////////////////////////////////////////////////////////////////////// - // ExtPxAsset - ////////////////////////////////////////////////////////////////////////// - - NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAsset(const unsigned char* input, uint32_t size) - { - NVBLAST_ASSERT(g_Physics != nullptr); - - return Nv::Blast::ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::deserialize(input, size); - } - - NVBLAST_API Nv::Blast::ExtPxAsset* deserializeExtPxAssetFromStream(std::istream &inputStream) - { - NVBLAST_ASSERT(g_Physics != nullptr); - - return Nv::Blast::ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::deserializeFromStream(inputStream); - } - - NVBLAST_API bool serializeExtPxAssetIntoStream(const Nv::Blast::ExtPxAsset *asset, std::ostream &outputStream) - { - NVBLAST_ASSERT(g_Physics != nullptr); - - auto cooking = getCooking(); - - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; - - return Nv::Blast::ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), outputStream); - } - - NVBLAST_API bool serializeExtPxAssetIntoNewBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char **outBuffer, uint32_t &outSize) - { - NVBLAST_ASSERT(g_Physics != nullptr); - - auto cooking = getCooking(); - - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; - - return Nv::Blast::ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), outBuffer, outSize); - } - - NVBLAST_API bool serializeExtPxAssetIntoExistingBuffer(const Nv::Blast::ExtPxAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) - { - NVBLAST_ASSERT(g_Physics != nullptr); - - auto cooking = getCooking(); - - PxConvexMeshGeometryDTO::Cooking = cooking.get(); - PxConvexMeshGeometryDTO::Physics = g_Physics; - - return Nv::Blast::ExtSerialization<Nv::Blast::ExtPxAsset, Nv::Blast::Serialization::ExtPxAsset::Reader, Nv::Blast::Serialization::ExtPxAsset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::ExtPxAsset *>(asset), buffer, maxSize, usedSize); - } - - -} - diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationInternal.h b/sdk/extensions/serialization/source/NvBlastExtSerializationInternal.h new file mode 100644 index 0000000..117280a --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtSerializationInternal.h @@ -0,0 +1,291 @@ +// 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. + + +#pragma once + +#include "NvBlastExtSerialization.h" + +#include <cstring> + +#define ExtSerializerBoilerplate(_name, _description, _objectTypeID, _encodingID) \ +virtual const char* getName() const override { return _name; } \ +virtual const char* getDescription() const override { return _description; } \ +virtual uint32_t getObjectTypeID() const override { return _objectTypeID; } \ +virtual uint32_t getEncodingID() const override { return _encodingID; } + + +#define ExtSerializerReadOnly(_name) \ +virtual bool isReadOnly() const override { return true; } \ +virtual uint64_t serializeIntoBuffer \ +( \ + void*& buffer, \ + ExtSerialization::BufferProvider& bufferProvider, \ + const void* object, \ + uint64_t offset = 0 \ +) override \ +{ \ + NVBLAST_LOG_WARNING(#_name "::serializeIntoBuffer: ExtPxAsset_RAW serializer is read-only."); \ + NV_UNUSED(buffer); \ + NV_UNUSED(bufferProvider); \ + NV_UNUSED(object); \ + NV_UNUSED(offset); \ + return 0; \ +} + + +#define ExtSerializerDefaultFactoryAndRelease(_classname) \ +static ExtSerializer* create() \ +{ \ + return NVBLAST_NEW(_classname) (); \ +} \ +virtual void release() override \ +{ \ + NVBLAST_DELETE(this, _classname); \ +} + + +namespace Nv +{ +namespace Blast +{ + +/** +Serializer internal interface +*/ +class ExtSerializer +{ +public: + virtual ~ExtSerializer() {} + + /** + return the name of this serializer. + */ + virtual const char* getName() const = 0; + + /** + return a description of this serializer. + */ + virtual const char* getDescription() const = 0; + + /** + return an identifier for the type of object handled. + */ + virtual uint32_t getObjectTypeID() const = 0; + + /** + return an identifier for serialization format. + */ + virtual uint32_t getEncodingID() const = 0; + + /** + Whether or not this serializer supports writing. Legacy formats, for example, may not. + + \return true iff this serialization does not support writing. + */ + virtual bool isReadOnly() const { return false; } + + /** + Deserialize from a buffer into a newly allocated object. + + \param[in] buffer Pointer to the buffer to read. + \param[in] size Size of the buffer to read. + \return object pointer; returns null if failed to deserialize. + */ + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) = 0; + + /** + Serialize into a buffer. Allocates the buffer internally using the ExtSerialization::BufferProvider callack interface. + + \param[out] buffer Pointer to the buffer created. + \param[in] bufferProvider The buffer provider callback interface to use. + \param[in] object Object pointer. + + \return the number of bytes serialized into the buffer (zero if unsuccessful). + */ + virtual uint64_t serializeIntoBuffer(void*& buffer, ExtSerialization::BufferProvider& bufferProvider, const void* object, uint64_t offset = 0) = 0; + + /** + Release the serializer and free associated memory. + */ + virtual void release() = 0; +}; + + +/** +Internal serialization manager interface +*/ +class ExtSerializationInternal : public ExtSerialization +{ +public: + /** + Internal interfaces to register and unregister a serializer, used by modules to automatically + register all of their serializers with a serialization manager. + */ + virtual bool registerSerializer(ExtSerializer& serializer) = 0; + virtual bool unregisterSerializer(ExtSerializer& serializer) = 0; + + /** + Find a registered serializer for the given object type and encoding. + + \param[in] objectTypeID ID for the requested object type. + \param[in] encodingID ID for the requested encoding (see EncodingID). + + \return a registered serializer if found, NULL otherwise. + */ + virtual ExtSerializer* findSerializer(uint32_t objectTypeID, uint32_t encodingID) = 0; + + //// Enums //// + enum { HeaderSize = 128 }; +}; + + +template<typename Factory, size_t N> +size_t ExtSerializationLoadSet(Nv::Blast::ExtSerializationInternal& serialization, Factory(&factories)[N]) +{ + size_t count = 0; + + for (auto f : factories) + { + Nv::Blast::ExtSerializer* serializer = f(); + if (serializer != nullptr) + { + if (serialization.registerSerializer(*serializer)) + { + ++count; + } + else + { + NVBLAST_LOG_ERROR("Nv::Blast::ExtSerializationLoadSet: failed to register serailizer:"); + NVBLAST_LOG_ERROR(serializer->getName()); + serializer->release(); + } + } + else + { + NVBLAST_LOG_ERROR("Nv::Blast::ExtSerializationLoadSet: failed to create serailizer."); + } + } + + return count; +} + + +class ExtIStream +{ +public: + enum Flags + { + LittleEndian = (1 << 0), + Fail = (1 << 1) + }; + + ExtIStream(const void* buffer, size_t size) : m_buf(reinterpret_cast<const char*>(buffer)), m_flags(0) + { + m_cur = m_buf; + m_end = m_buf + size; + const uint16_t x = LittleEndian; + m_flags = *reinterpret_cast<const char*>(&x); + } + + bool advance(ptrdiff_t diff) + { + m_cur += diff; + if (m_cur < m_buf) + { + m_cur = m_buf; + m_flags |= Fail; + return false; + } + else + if (m_cur > m_end) + { + m_cur = m_end; + m_flags |= Fail; + return false; + } + return true; + } + + const void* view() + { + return m_cur; + } + + bool read(void* buffer, size_t size) + { + if (!canRead(size)) return false; + std::memcpy(buffer, m_cur, size); + m_cur += size; + return true; + } + + size_t tellg() const { return m_cur - m_buf; } + size_t left() const { return m_end - m_cur; } + + bool eof() const { return m_cur >= m_end; } + bool fail() const { return (m_flags & Fail) != 0; } + +private: + const char* m_buf; + const char* m_cur; + const char* m_end; + uint32_t m_flags; + + bool isLittleEndian() const { return (m_flags & LittleEndian) != 0; } + + bool canRead(size_t size) const { return m_cur + size <= m_end; } + + template<typename T> + friend ExtIStream& operator >> (ExtIStream& s, T& x); +}; + +template<typename T> +NV_INLINE ExtIStream& operator >> (ExtIStream& s, T& x) +{ + if (s.canRead(sizeof(T))) + { + if (s.isLittleEndian()) + { + x = *reinterpret_cast<const T*>(s.m_cur); + s.m_cur += sizeof(T); + } + else + { + char* b = reinterpret_cast<char*>(&x) + sizeof(T); + for (size_t n = sizeof(T); n--;) *--b = *s.m_cur++; + } + } + else + { + s.m_flags |= ExtIStream::Fail; + } + return s; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationLL.capn b/sdk/extensions/serialization/source/NvBlastExtSerializationLL.capn deleted file mode 100644 index 026056f..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerializationLL.capn +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -# -# NVIDIA CORPORATION and its licensors retain all intellectual property -# and proprietary rights in and to this software, 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. - -@0x9a4a58fac38375e0; - -using Cxx = import "/capnp/c++.capnp"; - -$Cxx.namespace("Nv::Blast::Serialization"); - -struct Asset -{ - header @0 :NvBlastDataBlock; - - iD @1 :UUID; - - chunkCount @2 :UInt32; - - graph @3 :NvBlastSupportGraph; - - leafChunkCount @4 :UInt32; - - firstSubsupportChunkIndex @5 :UInt32; - - bondCount @6 :UInt32; - - chunks @7: List(NvBlastChunk); - - bonds @8: List(NvBlastBond); - - subtreeLeafChunkCounts @9: List(UInt32); - - chunkToGraphNodeMap @10: List(UInt32); -} - -struct NvBlastDataBlock -{ - enum Type - { - assetDataBlock @0; - instanceDataBlock @1; - } - - dataType @0 :Type; - - formatVersion @1 :UInt32; - - size @2 :UInt32; -} - -struct NvBlastChunk -{ - centroid @0 :List(Float32); - - volume @1 :Float32; - - parentChunkIndex @2 :UInt32; - firstChildIndex @3 :UInt32; - childIndexStop @4 :UInt32; - userData @5 :UInt32; -} - -struct NvBlastBond -{ - normal @0 :List(Float32); - area @1 :Float32; - centroid @2 :List(Float32); - userData @3 :UInt32; -} - -struct NvBlastSupportGraph -{ - nodeCount @0 : UInt32; - - chunkIndices @1 : List(UInt32); - adjacencyPartition @2 : List(UInt32); - adjacentNodeIndices @3 : List(UInt32); - adjacentBondIndices @4 : List(UInt32); -} - -struct UUID -{ - value @0 : Data; -} - diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationLLImpl.h b/sdk/extensions/serialization/source/NvBlastExtSerializationLLImpl.h deleted file mode 100644 index d7595ba..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerializationLLImpl.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#pragma once - -#include "NvBlastExtSerialization.h" -#include "NvBlastAsset.h" -#include "AssetDTO.h" - -namespace Nv -{ - namespace Blast - { - /* - Specializations here - LL asset only - */ - - // Asset - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoBuilder(Nv::Blast::Serialization::Asset::Builder& assetBuilder, const Nv::Blast::Asset* asset) - { - return AssetDTO::serialize(assetBuilder, asset); - } - - template<> - NV_INLINE Nv::Blast::Asset* ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) - { - Nv::Blast::Serialization::Asset::Reader reader = message.getRoot<Nv::Blast::Serialization::Asset>(); - - return AssetDTO::deserialize(reader); - } - - template<> - NV_INLINE bool ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const Nv::Blast::Asset* asset) - { - Nv::Blast::Serialization::Asset::Builder assetBuilder = message.initRoot<Nv::Blast::Serialization::Asset>(); - - return serializeIntoBuilder(assetBuilder, asset); - } - } -} diff --git a/sdk/extensions/serialization/source/NvBlastExtSerializationLLInterface.cpp b/sdk/extensions/serialization/source/NvBlastExtSerializationLLInterface.cpp deleted file mode 100644 index 26d8667..0000000 --- a/sdk/extensions/serialization/source/NvBlastExtSerializationLLInterface.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* -* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtSerializationLLInterface.h" -#include "NvBlastExtSerializationLLImpl.h" -#include <memory> -#include "NvBlastExtSerialization.h" -#include "NvBlastAsset.h" -#include <iostream> -#include "NvBlastExtGlobals.h" - - -NvBlastExtAlloc gAlloc = nullptr; -NvBlastLog gLog = nullptr; - -extern "C" -{ - NVBLAST_API void setAllocator(NvBlastExtAlloc alloc) - { - gAlloc = alloc; - } - - NVBLAST_API void setLog(NvBlastLog log) - { - gLog = log; - } - - NVBLAST_API NvBlastAsset* deserializeAsset(const unsigned char* input, uint32_t size) - { -#if defined(BLAST_LL_ALLOC) - if (gAlloc == nullptr || gLog == nullptr) - { - std::cerr << "Must set allocator and log when using low level serialization library. See setAllocator() and setLog() functions." << std::endl; - return nullptr; - } -#endif - - return Nv::Blast::ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::deserialize(input, size); - } - - NVBLAST_API NvBlastAsset* deserializeAssetFromStream(std::istream &inputStream) - { -#if defined(BLAST_LL_ALLOC) - if (gAlloc == nullptr || gLog == nullptr) - { - std::cerr << "Must set allocator and log when using low level serialization library. See setAllocator() and setLog() functions." << std::endl; - return nullptr; - } -#endif - - return Nv::Blast::ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::deserializeFromStream(inputStream); - } - - NVBLAST_API bool serializeAssetIntoStream(const NvBlastAsset *asset, std::ostream &outputStream) - { -#if defined(BLAST_LL_ALLOC) - if (gAlloc == nullptr || gLog == nullptr) - { - std::cerr << "Must set allocator and log when using low level serialization library. See setAllocator() and setLog() functions." << std::endl; - return false; - } -#endif - - return Nv::Blast::ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoStream(reinterpret_cast<const Nv::Blast::Asset *>(asset), outputStream); - } - - NVBLAST_API bool serializeAssetIntoNewBuffer(const NvBlastAsset *asset, unsigned char **outBuffer, uint32_t &outSize) - { -#if defined(BLAST_LL_ALLOC) - if (gAlloc == nullptr || gLog == nullptr) - { - std::cerr << "Must set allocator and log when using low level serialization library. See setAllocator() and setLog() functions." << std::endl; - return false; - } -#endif - - return Nv::Blast::ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoNewBuffer(reinterpret_cast<const Nv::Blast::Asset *>(asset), outBuffer, outSize); - } - - NVBLAST_API bool serializeAssetIntoExistingBuffer(const NvBlastAsset *asset, unsigned char *buffer, uint32_t maxSize, uint32_t &usedSize) - { -#if defined(BLAST_LL_ALLOC) - if (gAlloc == nullptr || gLog == nullptr) - { - std::cerr << "Must set allocator and log when using low level serialization library. See setAllocator() and setLog() functions." << std::endl; - return false; - } -#endif - - return Nv::Blast::ExtSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoExistingBuffer(reinterpret_cast<const Nv::Blast::Asset *>(asset), buffer, maxSize, usedSize); - } - -} - diff --git a/sdk/extensions/serialization/source/NvBlastExtTkSerialization.capn b/sdk/extensions/serialization/source/NvBlastExtTkSerialization.capn new file mode 100644 index 0000000..5605863 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtTkSerialization.capn @@ -0,0 +1,55 @@ +# 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. + + +@0xaffe4498f275ee58; + +using Cxx = import "/capnp/c++.capnp"; + +using LL = import "NvBlastExtLlSerialization.capn"; + +$Cxx.namespace("Nv::Blast::Serialization"); + +struct TkAsset +{ + assetLL @0 :LL.Asset; + + jointDescs @1 :List(TkAssetJointDesc); +} + +struct TkAssetJointDesc +{ + nodeIndices @0 :List(UInt32); + attachPositions @1 :List(PxVec3); +} + +struct PxVec3 +{ + x @0 :Float32; + y @1 :Float32; + z @2 :Float32; +} diff --git a/sdk/extensions/serialization/source/NvBlastExtTkSerialization.cpp b/sdk/extensions/serialization/source/NvBlastExtTkSerialization.cpp new file mode 100644 index 0000000..4ecc920 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtTkSerialization.cpp @@ -0,0 +1,105 @@ +// 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 "NvBlastExtSerializationInternal.h" +#include "NvBlastExtTkSerialization.h" +#include "NvBlastExtTkSerializerCAPN.h" +#include "NvBlastExtTkSerializerRAW.h" + + +namespace Nv +{ +namespace Blast +{ + +TkFramework* sExtTkSerializerFramework = nullptr; + + +class ExtTkSerializerAsset_CPNB : public ExtSerializer +{ +public: + ExtSerializerBoilerplate("TkAsset_CPNB", "Blast high-level asset (Nv::Blast::TkAsset) serialization using Cap'n Proto binary format.", TkObjectTypeID::Asset, ExtSerialization::EncodingID::CapnProtoBinary); + ExtSerializerDefaultFactoryAndRelease(ExtTkSerializerAsset_CPNB); + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + return ExtSerializationCAPN<TkAsset, Serialization::TkAsset::Reader, Serialization::TkAsset::Builder>::deserializeFromBuffer(reinterpret_cast<const unsigned char*>(buffer), size); + } + + virtual uint64_t serializeIntoBuffer(void*& buffer, ExtSerialization::BufferProvider& bufferProvider, const void* object, uint64_t offset = 0) override + { + uint64_t usedSize; + if (!ExtSerializationCAPN<TkAsset, Serialization::TkAsset::Reader, Serialization::TkAsset::Builder>::serializeIntoBuffer(reinterpret_cast<const TkAsset*>(object), + reinterpret_cast<unsigned char*&>(buffer), usedSize, &bufferProvider, offset)) + { + return 0; + } + return usedSize; + } +}; + + +class ExTkSerializerAsset_RAW : public ExtSerializer +{ +public: + ExtSerializerBoilerplate("TkAsset_RAW", "Blast high-level asset (Nv::Blast::TkAsset) serialization using raw memory format.", TkObjectTypeID::Asset, ExtSerialization::EncodingID::RawBinary); + ExtSerializerDefaultFactoryAndRelease(ExTkSerializerAsset_RAW); + ExtSerializerReadOnly(ExTkSerializerAsset_RAW); + + virtual void* deserializeFromBuffer(const void* buffer, uint64_t size) override + { + ExtIStream stream(buffer, size); + return deserializeTkAsset(stream, *sExtTkSerializerFramework); + } +}; + +} // namespace Blast +} // namespace Nv + + +/////////////////////////////////////// + + +size_t NvBlastExtTkSerializerLoadSet(Nv::Blast::TkFramework& framework, Nv::Blast::ExtSerialization& serialization) +{ + Nv::Blast::sExtTkSerializerFramework = &framework; + + Nv::Blast::ExtSerializer* (*factories[])() = + { + Nv::Blast::ExtTkSerializerAsset_CPNB::create, + Nv::Blast::ExTkSerializerAsset_RAW::create + }; + + return Nv::Blast::ExtSerializationLoadSet(static_cast<Nv::Blast::ExtSerializationInternal&>(serialization), factories); +} + + +uint64_t NvBlastExtSerializationSerializeTkAssetIntoBuffer(void*& buffer, Nv::Blast::ExtSerialization& serialization, const Nv::Blast::TkAsset* asset) +{ + return serialization.serializeIntoBuffer(buffer, asset, Nv::Blast::TkObjectTypeID::Asset); +} diff --git a/sdk/extensions/serialization/source/NvBlastExtTkSerializerCAPN.h b/sdk/extensions/serialization/source/NvBlastExtTkSerializerCAPN.h new file mode 100644 index 0000000..7922338 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtTkSerializerCAPN.h @@ -0,0 +1,70 @@ +// 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. + + +#pragma once + +#include "NvBlastExtSerializationCAPN.h" +#include "NvBlastTkAsset.h" +#include "TkAssetDTO.h" + + +/** +Specializations of ExtSerializationCAPN for BlastTk +*/ + +namespace Nv +{ +namespace Blast +{ + +//// Nv::Blast::TkAsset //// + +template<> +NV_INLINE bool ExtSerializationCAPN<TkAsset, Serialization::TkAsset::Reader, Serialization::TkAsset::Builder>::serializeIntoBuilder(Serialization::TkAsset::Builder& assetBuilder, const TkAsset* asset) +{ + return TkAssetDTO::serialize(assetBuilder, asset); +} + +template<> +NV_INLINE TkAsset* ExtSerializationCAPN<TkAsset, Serialization::TkAsset::Reader, Serialization::TkAsset::Builder>::deserializeFromStreamReader(capnp::InputStreamMessageReader &message) +{ + Serialization::TkAsset::Reader reader = message.getRoot<Serialization::TkAsset>(); + + return TkAssetDTO::deserialize(reader); +} + +template<> +NV_INLINE bool ExtSerializationCAPN<TkAsset, Serialization::TkAsset::Reader, Serialization::TkAsset::Builder>::serializeIntoMessage(capnp::MallocMessageBuilder& message, const TkAsset* asset) +{ + Serialization::TkAsset::Builder assetBuilder = message.initRoot<Serialization::TkAsset>(); + + return serializeIntoBuilder(assetBuilder, asset); +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.cpp b/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.cpp new file mode 100644 index 0000000..ed5ce00 --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.cpp @@ -0,0 +1,184 @@ +// 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 "NvBlastExtSerializationInternal.h" +#include "NvBlastTkFramework.h" +#include "NvBlastTkAsset.h" +#include "NvBlast.h" + + +namespace Nv +{ +namespace Blast +{ + +// Legacy IDs +struct ExtTkSerializationLegacyID +{ + enum Enum + { + Framework = NVBLAST_FOURCC('T', 'K', 'F', 'W'), //!< TkFramework identifier token, used in serialization + Asset = NVBLAST_FOURCC('A', 'S', 'S', 'T'), //!< TkAsset identifier token, used in serialization + Family = NVBLAST_FOURCC('A', 'C', 'T', 'F'), //!< TkFamily identifier token, used in serialization + }; +}; + + +// Legacy object format versions +struct ExtTkSerializationLegacyAssetVersion +{ + enum Enum + { + /** Initial version */ + Initial, + + // New formats must come before Count. They should be given descriptive names with more information in comments. + + /** The number of serialized formats. */ + Count, + + /** The current version. This should always be Count-1 */ + Current = Count - 1 + }; +}; + +struct ExtTkSerializationLegacyFamilyVersion +{ + enum Enum + { + /** Initial version */ + Initial, + + // New formats must come before Count. They should be given descriptive names with more information in comments. + + /** The number of serialized formats. */ + Count, + + /** The current version. This should always be Count-1 */ + Current = Count - 1 + }; +}; + + +static bool deserializeTkObjectHeader(uint32_t& legacyTypeID, uint32_t& legacyVersion, NvBlastID& objID, uint64_t& userIntData, ExtIStream& stream) +{ + // Read framework ID + uint32_t fwkID; + stream >> fwkID; + if (fwkID != ExtTkSerializationLegacyID::Framework) + { + NVBLAST_LOG_ERROR("deserializeTkObjectHeader: stream does not contain a BlastTk legacy object."); + return false; + } + + // Read object class ID + stream >> legacyTypeID; + + // Read object class version and ensure it's current + stream >> legacyVersion; + + // Object ID + stream.read(objID.data, sizeof(NvBlastID)); + + // Serializable user data + uint32_t lsd, msd; + stream >> lsd >> msd; + userIntData = static_cast<uint64_t>(msd) << 32 | static_cast<uint64_t>(lsd); + + return !stream.fail(); +} + + +TkAsset* deserializeTkAsset(ExtIStream& stream, TkFramework& framework) +{ + // Deserializer header + uint32_t legacyTypeID; + uint32_t legacyVersion; + NvBlastID objID; + uint64_t userIntData; + if (!deserializeTkObjectHeader(legacyTypeID, legacyVersion, objID, userIntData, stream)) + { + return nullptr; + } + + if (legacyTypeID != ExtTkSerializationLegacyID::Asset) + { + NVBLAST_LOG_ERROR("deserializeTkAsset: stream does not contain a BlastTk legacy asset."); + return nullptr; + } + + if (legacyVersion > ExtTkSerializationLegacyAssetVersion::Current) + { + NVBLAST_LOG_ERROR("deserializeTkAsset: stream contains a BlastTk legacy asset which is in an unknown version."); + return nullptr; + } + + // LL asset + uint32_t assetSize; + stream >> assetSize; + NvBlastAsset* llAsset = static_cast<NvBlastAsset*>(NVBLAST_ALLOC_NAMED(assetSize, "deserializeTkAsset")); + stream.read(reinterpret_cast<char*>(llAsset), assetSize); + + // Joint descs + uint32_t jointDescCount; + stream >> jointDescCount; + std::vector<TkAssetJointDesc> jointDescs(jointDescCount); + for (uint32_t i = 0; i < jointDescs.size(); ++i) + { + TkAssetJointDesc& jointDesc = jointDescs[i]; + stream >> jointDesc.nodeIndices[0]; + stream >> jointDesc.nodeIndices[1]; + stream >> jointDesc.attachPositions[0].x; + stream >> jointDesc.attachPositions[0].y; + stream >> jointDesc.attachPositions[0].z; + stream >> jointDesc.attachPositions[1].x; + stream >> jointDesc.attachPositions[1].y; + stream >> jointDesc.attachPositions[1].z; + } + + if (stream.fail()) + { + NVBLAST_FREE(llAsset); + return nullptr; + } + + TkAsset* asset = framework.createAsset(llAsset, jointDescs.data(), (uint32_t)jointDescs.size(), true); + + NvBlastID zeroID; + memset(zeroID.data, 0, sizeof(zeroID)); + if (!memcmp(zeroID.data, objID.data, sizeof(NvBlastID))) + { + asset->setID(objID); + } + asset->userIntData = userIntData; + + return asset; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.h b/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.h new file mode 100644 index 0000000..74006ee --- /dev/null +++ b/sdk/extensions/serialization/source/NvBlastExtTkSerializerRAW.h @@ -0,0 +1,54 @@ +// 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. + + +#pragma once + + +/** +Raw serialization function declarations for BlastTk +*/ + +#include <stdint.h> + + +namespace Nv +{ +namespace Blast +{ + +// Forward declarations +class TkAsset; +class TkFramework; +class ExtIStream; + +//// Nv::Blast::TkAsset //// + +TkAsset* deserializeTkAsset(ExtIStream& stream, TkFramework& framework); + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h b/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h index 385bf52..8daf9cf 100644 --- a/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h +++ b/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h @@ -1,18 +1,36 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ +// 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-2017 NVIDIA Corporation. All rights reserved. + #ifndef NVBLASTEXTDAMAGESHADERS_H #define NVBLASTEXTDAMAGESHADERS_H #include "NvBlastTypes.h" -#include "NvBlastPreprocessor.h" + /** A few example damage shader implementations. @@ -24,22 +42,39 @@ A few example damage shader implementations. /////////////////////////////////////////////////////////////////////////////// /** -Specific parameters for the material functions here present. +Example of simple material. It is passed into damage shader, thus it is not used +currently in any of them. The user can use it to filter and normalize before applying. Material function implementers may choose their own set. */ struct NvBlastExtMaterial { - float singleChunkThreshold; //!< subsupport chunks only take damage surpassing this value - float graphChunkThreshold; //!< support chunks only take damage surpassing this value - float bondTangentialThreshold; //!< bond only take damage surpassing this value - float bondNormalThreshold; //!< currently unused - forward damage propagation - float damageAttenuation; //!< factor of damage attenuation while forwarding + NvBlastExtMaterial() : health(100.f), minDamageThreshold(0.0f), maxDamageThreshold(1.0f) {} + + float health; //!< health + float minDamageThreshold; //!< min damage fraction threshold to be applied. Range [0, 1]. For example 0.1 filters all damage below 10% of health. + float maxDamageThreshold; //!< max damage fraction threshold to be applied. Range [0, 1]. For example 0.8 won't allow more then 80% of health damage to be applied. + + /** + Helper to normalize damage. + + Pass damage defined in health, damage in range [0, 1] is returned, where 0 basically + indicates that the threshold wasn't reached and there is no point in applying it. + + \param[in] damageInHealth Damage defined in terms of health amount to be reduced. + + \return normalized damage + */ + float getNormalizedDamage(float damageInHealth) const + { + const float damage = health > 0.f ? damageInHealth / health : 1.0f; + return damage > minDamageThreshold ? (damage < maxDamageThreshold ? damage : maxDamageThreshold) : 0.f; + } }; /////////////////////////////////////////////////////////////////////////////// -// Radial Damage +// Point Radial Damage /////////////////////////////////////////////////////////////////////////////// /** @@ -47,7 +82,7 @@ Radial Damage Desc */ struct NvBlastExtRadialDamageDesc { - float compressive; //!< compressive (radial) damage component + float damage; //!< normalized damage amount, range: [0, 1] (maximum health value to be reduced) float position[3]; //!< origin of damage action float minRadius; //!< inner radius of damage action float maxRadius; //!< outer radius of damage action @@ -85,6 +120,36 @@ NVBLAST_API bool NvBlastExtDamageActorRadialFalloff(NvBlastActor* actor, NvBlast /////////////////////////////////////////////////////////////////////////////// +// Segment Radial Damage +/////////////////////////////////////////////////////////////////////////////// + +/** +Segment Radial Damage Desc +*/ +struct NvBlastExtSegmentRadialDamageDesc +{ + float damage; //!< normalized damage amount, range: [0, 1] (maximum health value to be reduced) + float position0[3]; //!< damage segment point A position + float position1[3]; //!< damage segment point B position + float minRadius; //!< inner radius of damage action + float maxRadius; //!< outer radius of damage action +}; + +/** +Segment Radial Falloff damage for both graph and subgraph shaders. + +For every bond/chunk damage is calculated from the distance to line segment AB described in NvBlastExtSegmentRadialDamageDesc. +If distance is smaller then minRadius, full compressive amount of damage is applied. From minRadius to maxRaidus it linearly falls off to zero. + +NOTE: The signature of shader functions are equal to NvBlastGraphShaderFunction and NvBlastSubgraphShaderFunction respectively. +They are not expected to be called directly. +@see NvBlastGraphShaderFunction, NvBlastSubgraphShaderFunction +*/ +NVBLAST_API void NvBlastExtSegmentFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params); +NVBLAST_API void NvBlastExtSegmentFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params); + + +/////////////////////////////////////////////////////////////////////////////// // Shear Damage /////////////////////////////////////////////////////////////////////////////// @@ -93,8 +158,13 @@ Shear Damage Desc */ struct NvBlastExtShearDamageDesc { - float shear[3]; //!< directional damage component + float damage; //!< normalized damage amount, range: [0, 1] (maximum health value to be reduced) + + float normal[3]; //!< directional damage component float position[3]; //!< origin of damage action + + float minRadius; //!< inner radius of damage action + float maxRadius; //!< outer radius of damage action }; /** diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp new file mode 100644 index 0000000..8027447 --- /dev/null +++ b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp @@ -0,0 +1,368 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastExtDamageShaders.h" +#include "NvBlastIndexFns.h" +#include "NvBlastMath.h" +#include "NvBlastGeometry.h" +#include "NvBlastAssert.h" +#include "NvBlast.h" +#include <cmath> // for abs() on linux + +using namespace Nv::Blast; +using namespace Nv::Blast::VecMath; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Profiles +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef float(*ProfileFunction)(float, float, float, float); + +float falloffProfile(float min, float max, float x, float f = 1.0f) +{ + if (x > max) return 0.0f; + if (x < min) return f; + + float y = 1.0f - (x - min) / (max - min); + return y * f; +} + +float cutterProfile(float min, float max, float x, float f = 1.0f) +{ + if (x > max || x < min) return 0.0f; + + return f; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Damage Functions +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef float(*DamageFunction)(const float pos[3], const void* damageDescBuffer, uint32_t damageIndex); + +template <ProfileFunction profileFn, typename DescT = NvBlastExtRadialDamageDesc> +float pointDistanceDamage(const float pos[3], const void* damageDescBuffer, uint32_t damageIndex) +{ + const DescT* damageData = reinterpret_cast<const DescT*>(damageDescBuffer); + const DescT& desc = damageData[damageIndex]; + + float relativePosition[3]; + sub(desc.position, pos, relativePosition); + const float distance = sqrtf(dot(relativePosition, relativePosition)); + const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage); + return damage; +} + + +// Distance from point 'p' to line segment '(a, b)' +float distanceToSegment(const float p[3], const float a[3], const float b[3]) +{ + float v[3]; + sub(b, a, v); + + float w[3]; + sub(p, a, w); + + const float c1 = dot(v, w); + if (c1 <= 0) + return length(w); + + const float c2 = dot(v, v); + if (c2 < c1) + return dist(p, b); + + const float t = c1 / c2; + mul(v, t); + return dist(v, w); +} + +template <ProfileFunction profileFn> +float segmentDistanceDamage(const float pos[3], const void* damageDescBuffer, uint32_t damageIndex) +{ + const NvBlastExtSegmentRadialDamageDesc* damageData = reinterpret_cast<const NvBlastExtSegmentRadialDamageDesc*>(damageDescBuffer); + const NvBlastExtSegmentRadialDamageDesc& desc = damageData[damageIndex]; + + const float distance = distanceToSegment(pos, desc.position0, desc.position1); + const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage); + return damage; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Radial Graph Shader Template +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template <DamageFunction damageFn> +void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks; + const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex; + const uint32_t* adjacencyPartition = actor->adjacencyPartition; + const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices; + const uint32_t* adjacentBondIndices = actor->adjacentBondIndices; + const NvBlastBond* assetBonds = actor->assetBonds; + const float* familyBondHealths = actor->familyBondHealths; + + const uint32_t damageCount = params->damageDescCount; + + uint32_t outCount = 0; + + uint32_t currentNodeIndex = firstGraphNodeIndex; + while (!Nv::Blast::isInvalidIndex(currentNodeIndex)) + { + for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++) + { + uint32_t adjacentNodeIndex = adjacentNodeIndices[adj]; + if (currentNodeIndex < adjacentNodeIndex) + { + uint32_t bondIndex = adjacentBondIndices[adj]; + + // skip bonds that are already broken or were visited already + // TODO: investigate why testing against health > -1.0f seems slower + // could reuse the island edge bitmap instead + if ((familyBondHealths[bondIndex] > 0.0f)) + { + + const NvBlastBond& bond = assetBonds[bondIndex]; + + float totalBondDamage = 0.0f; + + for (uint32_t damageIndex = 0; damageIndex < damageCount; damageIndex++) + { + totalBondDamage += damageFn(bond.centroid, params->damageDescBuffer, damageIndex); + } + + if (totalBondDamage > 0.0f) + { + NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++]; + outCommand.nodeIndex0 = currentNodeIndex; + outCommand.nodeIndex1 = adjacentNodeIndex; + outCommand.health = totalBondDamage; + } + } + } + } + currentNodeIndex = graphNodeIndexLinks[currentNodeIndex]; + } + + commandBuffers->bondFractureCount = outCount; + commandBuffers->chunkFractureCount = 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Radial Single Shader Template +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template <DamageFunction damageFn> +void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + uint32_t chunkFractureCount = 0; + uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount; + const uint32_t chunkIndex = actor->chunkIndex; + const NvBlastChunk* assetChunks = actor->assetChunks; + const NvBlastChunk& chunk = assetChunks[chunkIndex]; + + float totalDamage = 0.0f; + for (uint32_t damageIndex = 0; damageIndex < params->damageDescCount; ++damageIndex) + { + totalDamage += damageFn(chunk.centroid, params->damageDescBuffer, damageIndex); + } + + if (totalDamage > 0.0f && chunkFractureCount < chunkFractureCountMax) + { + NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; + frac.chunkIndex = chunkIndex; + frac.health = totalDamage; + } + + commandBuffers->bondFractureCount = 0; + commandBuffers->chunkFractureCount = chunkFractureCount; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Radial Shaders Instantiation +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileGraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params); +} + +void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params); +} + +void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileGraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params); +} + +void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params); +} + +void NvBlastExtSegmentFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileGraphShader<segmentDistanceDamage<falloffProfile>>(commandBuffers, actor, params); +} + +void NvBlastExtSegmentFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<segmentDistanceDamage<falloffProfile>>(commandBuffers, actor, params); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Shear Shader +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + uint32_t chunkFractureCount = 0; + uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount; + uint32_t bondFractureCount = 0; + uint32_t bondFractureCountMax = commandBuffers->bondFractureCount; + + for (uint32_t i = 0; i < params->damageDescCount; ++i) + { + const NvBlastExtShearDamageDesc& desc = reinterpret_cast<const NvBlastExtShearDamageDesc*>(params->damageDescBuffer)[i]; + const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks; + const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex; + const uint32_t* chunkIndices = actor->chunkIndices; + const uint32_t* adjacencyPartition = actor->adjacencyPartition; + const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices; + const uint32_t* adjacentBondIndices = actor->adjacentBondIndices; + const NvBlastBond* assetBonds = actor->assetBonds; + const NvBlastChunk* assetChunks = actor->assetChunks; + const float* familyBondHealths = actor->familyBondHealths; + const float* supportChunkHealths = actor->supportChunkHealths; + + uint32_t closestNode = findClosestNode(desc.position + , firstGraphNodeIndex, graphNodeIndexLinks + , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices + , assetBonds, familyBondHealths + , assetChunks, supportChunkHealths, chunkIndices); + + uint32_t nodeIndex = closestNode; + float maxDist = 0.0f; + uint32_t nextNode = invalidIndex<uint32_t>(); + + if (chunkFractureCount < chunkFractureCountMax) + { + const uint32_t chunkIndex = chunkIndices[nodeIndex]; + const NvBlastChunk& chunk = assetChunks[chunkIndex]; + NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; + frac.chunkIndex = chunkIndex; + frac.health = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(chunk.centroid, params->damageDescBuffer, i); + } + + do { + const uint32_t startIndex = adjacencyPartition[nodeIndex]; + const uint32_t stopIndex = adjacencyPartition[nodeIndex + 1]; + + + for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++) + { + const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex]; + const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex]; + const NvBlastBond& bond = assetBonds[bondIndex]; + + if (!(familyBondHealths[bondIndex] > 0.0f)) + continue; + + float shear = 1 * std::abs(1 - std::abs(VecMath::dot(desc.normal, bond.normal))); + + float d[3]; VecMath::sub(bond.centroid, desc.position, d); + float ahead = VecMath::dot(d, desc.normal); + if (ahead > maxDist) + { + maxDist = ahead; + nextNode = neighbourIndex; + } + + const float damage = pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>(bond.centroid, params->damageDescBuffer, i); + if (damage > 0.0f && bondFractureCount < bondFractureCountMax) + { + NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++]; + frac.userdata = bond.userData; + frac.nodeIndex0 = nodeIndex; + frac.nodeIndex1 = neighbourIndex; + frac.health = shear * damage; + } + } + + if (nodeIndex == nextNode) + break; + + nodeIndex = nextNode; + } while (!isInvalidIndex(nextNode)); + } + + commandBuffers->bondFractureCount = bondFractureCount; + commandBuffers->chunkFractureCount = chunkFractureCount; +} + +void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>>(commandBuffers, actor, params); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Helper Functions +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool NvBlastExtDamageActorRadialFalloff(NvBlastActor* actor, NvBlastFractureBuffers* buffers, const NvBlastExtRadialDamageDesc* damageDescBuffer, uint32_t damageDescCount, const NvBlastExtMaterial* material, NvBlastLog logFn, NvBlastTimers* timers) +{ + NvBlastDamageProgram program = + { + NvBlastExtFalloffGraphShader, + NvBlastExtFalloffSubgraphShader + }; + + NvBlastProgramParams params = + { + damageDescBuffer, + damageDescCount, + material + }; + + NvBlastActorGenerateFracture(buffers, actor, program, ¶ms, logFn, timers); + if (buffers->bondFractureCount > 0 || buffers->chunkFractureCount > 0) + { + NvBlastActorApplyFracture(nullptr, actor, buffers, logFn, timers); + return true; + } + + return false; +}
\ No newline at end of file diff --git a/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp b/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp deleted file mode 100644 index 00d1010..0000000 --- a/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtDamageShaders.h" -#include "NvBlastIndexFns.h" -#include "NvBlastMath.h" -#include "NvBlastGeometry.h" -#include "NvBlastAssert.h" -#include "NvBlast.h" -#include "stdlib.h" // for abs() on linux - -using namespace Nv::Blast; -using namespace Nv::Blast::VecMath; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Profiles -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef float(*ProfileFunction)(float, float, float, float); - -float falloffProfile(float min, float max, float x, float f = 1.0f) -{ - if (x > max) return 0.0f; - if (x < min) return f; - - float y = 1.0f - (x - min) / (max - min); - return y * f; -} - -float cutterProfile(float min, float max, float x, float f = 1.0f) -{ - if (x > max || x < min) return 0.0f; - - return f; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Radial Graph Shader Template -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -template <ProfileFunction profile> -void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) -{ - const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks; - const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex; - const uint32_t* adjacencyPartition = actor->adjacencyPartition; - const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices; - const uint32_t* adjacentBondIndices = actor->adjacentBondIndices; - const NvBlastBond* assetBonds = actor->assetBonds; - const float* familyBondHealths = actor->familyBondHealths; - - const NvBlastExtRadialDamageDesc* damageData = reinterpret_cast<const NvBlastExtRadialDamageDesc*>(params->damageDescBuffer); - const uint32_t damageCount = params->damageDescCount; - - uint32_t outCount = 0; - - uint32_t currentNodeIndex = firstGraphNodeIndex; - while (!Nv::Blast::isInvalidIndex(currentNodeIndex)) - { - for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++) - { - uint32_t adjacentNodeIndex = adjacentNodeIndices[adj]; - if (currentNodeIndex < adjacentNodeIndex) - { - uint32_t bondIndex = adjacentBondIndices[adj]; - - // skip bonds that are already broken or were visited already - // TODO: investigate why testing against health > -1.0f seems slower - // could reuse the island edge bitmap instead - if ((familyBondHealths[bondIndex] > 0.0f)) - { - - const NvBlastBond& bond = assetBonds[bondIndex]; - - float totalBondDamage = 0.0f; - - for (uint32_t damageIndex = 0; damageIndex < damageCount; damageIndex++) - { - const NvBlastExtRadialDamageDesc& damage = damageData[damageIndex]; - - float relativePosition[3]; - sub(damage.position, bond.centroid, relativePosition); - float distance = sqrtf(dot(relativePosition, relativePosition)); - - float dir[3]; - normal(relativePosition, dir); - - totalBondDamage += profile(damage.minRadius, damage.maxRadius, distance, damage.compressive); - } - - if (totalBondDamage > 0.0f) - { - NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++]; - outCommand.nodeIndex0 = currentNodeIndex; - outCommand.nodeIndex1 = adjacentNodeIndex; - outCommand.health = totalBondDamage; - } - } - } - } - currentNodeIndex = graphNodeIndexLinks[currentNodeIndex]; - } - - commandBuffers->bondFractureCount = outCount; - commandBuffers->chunkFractureCount = 0; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Radial Single Shader Template -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -template <ProfileFunction profile> -void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) -{ - uint32_t chunkFractureCount = 0; - const uint32_t chunkIndex = actor->chunkIndex; - const NvBlastChunk* assetChunks = actor->assetChunks; - const NvBlastChunk& chunk = assetChunks[chunkIndex]; - - float totalDamage = 0.0f; - for (uint32_t i = 0; i < params->damageDescCount; ++i) - { - const NvBlastExtRadialDamageDesc& damage = reinterpret_cast<const NvBlastExtRadialDamageDesc*>(params->damageDescBuffer)[i]; - - float relativePosition[3]; - sub(damage.position, chunk.centroid, relativePosition); - float distance = sqrtf(dot(relativePosition, relativePosition)); - - totalDamage += profile(damage.minRadius, damage.maxRadius, distance, damage.compressive); - } - - if (totalDamage > 0.0f) - { - NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; - frac.chunkIndex = chunkIndex; - frac.health = totalDamage; - } - - commandBuffers->bondFractureCount = 0; - commandBuffers->chunkFractureCount = chunkFractureCount; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Shader Instantiation -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) -{ - RadialProfileGraphShader<falloffProfile>(commandBuffers, actor, params); -} - -void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) -{ - RadialProfileSubgraphShader<falloffProfile>(commandBuffers, actor, params); -} - -void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) -{ - RadialProfileGraphShader<cutterProfile>(commandBuffers, actor, params); -} - -void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) -{ - RadialProfileSubgraphShader<cutterProfile>(commandBuffers, actor, params); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Helper Functions -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -bool NvBlastExtDamageActorRadialFalloff(NvBlastActor* actor, NvBlastFractureBuffers* buffers, const NvBlastExtRadialDamageDesc* damageDescBuffer, uint32_t damageDescCount, const NvBlastExtMaterial* material, NvBlastLog logFn, NvBlastTimers* timers) -{ - NvBlastDamageProgram program = - { - NvBlastExtFalloffGraphShader, - NvBlastExtFalloffSubgraphShader - }; - - NvBlastProgramParams params = - { - damageDescBuffer, - damageDescCount, - material - }; - - NvBlastActorGenerateFracture(buffers, actor, program, ¶ms, logFn, timers); - if (buffers->bondFractureCount > 0 || buffers->chunkFractureCount > 0) - { - NvBlastActorApplyFracture(nullptr, actor, buffers, logFn, timers); - return true; - } - - return false; -}
\ No newline at end of file diff --git a/sdk/extensions/shaders/source/NvBlastExtShearShaders.cpp b/sdk/extensions/shaders/source/NvBlastExtShearShaders.cpp deleted file mode 100644 index 26707e1..0000000 --- a/sdk/extensions/shaders/source/NvBlastExtShearShaders.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtDamageShaders.h" -#include "NvBlastIndexFns.h" -#include "NvBlastMath.h" -#include "NvBlastGeometry.h" -#include "NvBlastAssert.h" -#include "stdlib.h" // for abs() on linux - -using namespace Nv::Blast; -using namespace Nv::Blast::VecMath; - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Graph Shader -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) -{ - const NvBlastExtMaterial* materialProperties = reinterpret_cast<const NvBlastExtMaterial*>(params->material); - const float graphChunkThreshold = materialProperties->graphChunkThreshold; - const float bondTangentialThreshold = materialProperties->bondTangentialThreshold; - const float damageAttenuation = 1.0f - materialProperties->damageAttenuation; - - uint32_t chunkFractureCount = 0; - uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount; - uint32_t bondFractureCount = 0; - uint32_t bondFractureCountMax = commandBuffers->bondFractureCount; - - for (uint32_t i = 0; i < params->damageDescCount; ++i) - { - const NvBlastExtShearDamageDesc& damage = reinterpret_cast<const NvBlastExtShearDamageDesc*>(params->damageDescBuffer)[i]; - - const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks; - const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex; - const uint32_t* chunkIndices = actor->chunkIndices; - const uint32_t* adjacencyPartition = actor->adjacencyPartition; - const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices; - const uint32_t* adjacentBondIndices = actor->adjacentBondIndices; - const NvBlastBond* assetBonds = actor->assetBonds; - const float* familyBondHealths = actor->familyBondHealths; - - uint32_t closestNode = findNodeByPositionLinked(damage.position, firstGraphNodeIndex, graphNodeIndexLinks, adjacencyPartition, adjacentNodeIndices, adjacentBondIndices, assetBonds, familyBondHealths); - NVBLAST_ASSERT(!isInvalidIndex(closestNode)); - - float damageDir[3]; - float damageMag = VecMath::normal(damage.shear, damageDir); - - uint32_t nodeIndex = closestNode; - float maxDist = 0.0f; - uint32_t nextNode = invalidIndex<uint32_t>(); - - if (damageMag > graphChunkThreshold && chunkFractureCount < chunkFractureCountMax) - { - NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; - frac.chunkIndex = chunkIndices[nodeIndex]; - frac.health = damageMag * 2; - } - - do { - const uint32_t startIndex = adjacencyPartition[nodeIndex]; - const uint32_t stopIndex = adjacencyPartition[nodeIndex + 1]; - - - for (uint32_t adjacentNodeIndex = startIndex; adjacentNodeIndex < stopIndex; adjacentNodeIndex++) - { - const uint32_t neighbourIndex = adjacentNodeIndices[adjacentNodeIndex]; - const uint32_t bondIndex = adjacentBondIndices[adjacentNodeIndex]; - const NvBlastBond& bond = assetBonds[bondIndex]; - - if (!(familyBondHealths[bondIndex] > 0.0f)) - continue; - - float shear = 1 * abs(1 - abs(VecMath::dot(damage.shear, bond.normal))); - - float d[3]; VecMath::sub(bond.centroid, damage.position, d); - float ahead = VecMath::dot(d, damage.shear); - if (ahead > maxDist) - { - maxDist = ahead; - nextNode = neighbourIndex; - } - - if (shear > bondTangentialThreshold && bondFractureCount < bondFractureCountMax) - { - NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++]; - frac.userdata = bond.userData; - frac.nodeIndex0 = nodeIndex; - frac.nodeIndex1 = neighbourIndex; - frac.health = shear; - } - } - - if (nodeIndex == nextNode) - break; - - nodeIndex = nextNode; - - damageMag *= damageAttenuation; - } while (!isInvalidIndex(nextNode)); - } - - commandBuffers->bondFractureCount = bondFractureCount; - commandBuffers->chunkFractureCount = chunkFractureCount; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Single Shader -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) -{ - const NvBlastExtMaterial* materialProperties = reinterpret_cast<const NvBlastExtMaterial*>(params->material); - - uint32_t chunkFractureCount = 0; - - float totalDamage = 0.0f; - for (uint32_t i = 0; i < params->damageDescCount; ++i) - { - const NvBlastExtShearDamageDesc& damage = reinterpret_cast<const NvBlastExtShearDamageDesc*>(params->damageDescBuffer)[i]; - - float damageDir[3]; - float damageMag = VecMath::normal(damage.shear, damageDir); - - if (damageMag > materialProperties->singleChunkThreshold) - { - totalDamage += damageMag * 2; - } - } - - if (totalDamage > 0.0f) - { - NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; - frac.chunkIndex = actor->chunkIndex; - frac.health = totalDamage; - } - - commandBuffers->bondFractureCount = 0; - commandBuffers->chunkFractureCount = chunkFractureCount; -} diff --git a/sdk/extensions/stress/include/NvBlastExtStressSolver.h b/sdk/extensions/stress/include/NvBlastExtStressSolver.h new file mode 100644 index 0000000..471c35e --- /dev/null +++ b/sdk/extensions/stress/include/NvBlastExtStressSolver.h @@ -0,0 +1,410 @@ +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTEXTSTRESSSOLVER_H +#define NVBLASTEXTSTRESSSOLVER_H + +#include "NvBlastTypes.h" +#include "PxVec3.h" +#include <vector> + + +namespace Nv +{ +namespace Blast +{ + + +/** +Stress Solver Settings + +Stress on every bond is calculated as +stress = (bond.linearStress * stressLinearFactor + bond.angularStress * stressAngularFactor) / hardness; +where: +bond.linearStress = the linear stress force on particular bond +bond.angularStress = the angular stress force on particular bond +stressLinearFactor, stressAngularFactor, hardness = multiplier parameters set by this struct + +Support graph reduction: +graphReductionLevel is the number of node merge passes. The resulting graph will be +roughly 2^graphReductionLevel times smaller than the original. +*/ +struct ExtStressSolverSettings +{ + float hardness; //!< hardness of bond's material + float stressLinearFactor; //!< linear stress on bond multiplier + float stressAngularFactor; //!< angular stress on bond multiplier + uint32_t bondIterationsPerFrame; //!< number of bond iterations to perform per frame, @see getIterationsPerFrame() below + uint32_t graphReductionLevel; //!< graph reduction level + + ExtStressSolverSettings() : + hardness(1000.0f), + stressLinearFactor(0.25f), + stressAngularFactor(0.75f), + bondIterationsPerFrame(18000), + graphReductionLevel(3) + {} +}; + + +/** +Parameter to addForce() calls, determines the exact operation that is carried out. + +@see ExtStressSolver.addForce() +*/ +struct ExtForceMode +{ + enum Enum + { + IMPULSE, //!< parameter has unit of mass * distance /time + VELOCITY, //!< parameter has unit of distance / time, i.e. the effect is mass independent: a velocity change. + }; +}; + + +/** +Stress Solver. + +Uses NvBlastFamily, allocates and prepares its graph once when it's created. Then it's being quickly updated on every +actor split. +It uses NvBlastAsset support graph, you can apply forces on nodes and stress on bonds will be calculated as the result. +When stress on bond exceeds it's health bond is considered broken (overstressed). +Basic usage: +1. Create it with create function once for family +2. Fill node info for every node in support graph or use setAllNodesInfoFromLL() function. +3. Use notifyActorCreated / notifyActorDestroyed whenever actors are created and destroyed in family. +4. Every frame: Apply forces (there are different functions for it see @addForce) +5. Every frame: Call update() for actual solver to process. +6. If getOverstressedBondCount() > 0 use generateFractureCommands() functions to get FractureCommands with bonds fractured +*/ +class NV_DLL_EXPORT ExtStressSolver +{ +public: + //////// creation //////// + + /** + Create a new ExtStressSolver. + + \param[in] family The ExtPxFamily instance to calculate stress on. + \param[in] settings The settings to be set on ExtStressSolver. + + \return the new ExtStressSolver if successful, NULL otherwise. + */ + static ExtStressSolver* create(NvBlastFamily& family, ExtStressSolverSettings settings = ExtStressSolverSettings()); + + + //////// interface //////// + + /** + Release this stress solver. + */ + virtual void release() = 0; + + /** + Set node info. + + All the required info per node for stress solver is set with this function. Call it for every node in graph or use setAllNodesInfoFromLL(). + + \param[in] graphNodeIndex Index of the node in support graph. see NvBlastSupportGraph. + \param[in] mass Node mass. For static node it is irrelevant. + \param[in] volume Node volume. For static node it is irrelevant. + \param[in] localPosition Node local position. + \param[in] isStatic Is node static. + */ + virtual void setNodeInfo(uint32_t graphNodeIndex, float mass, float volume, physx::PxVec3 localPosition, bool isStatic) = 0; + + /** + Set all nodes info using low level NvBlastAsset data. + Uses NvBlastChunk's centroid and volume. + Uses 'world' node to mark nodes as static. + + \param[in] density Density. Used to convert volume to mass. + */ + virtual void setAllNodesInfoFromLL(float density = 1.0f) = 0; + + /** + Set stress solver settings. + Changing graph reduction level will lead to graph being rebuilt (which is fast, but still not recommended). + All other settings are applied instantly and can be changed every frame. + + \param[in] settings The settings to be set on ExtStressSolver. + */ + virtual void setSettings(const ExtStressSolverSettings& settings) = 0; + + /** + Get stress solver settings. + + \return the pointer to stress solver settings currently set. + */ + virtual const ExtStressSolverSettings& getSettings() const = 0; + + /** + Notify stress solver on newly created actor. + + Call this function for all initial actors present in family and later upon every actor split. + + \param[in] actor The actor created. + + \return true if actor will take part in stress solver process. false if actor doesn't contain any bonds. + */ + virtual bool notifyActorCreated(const NvBlastActor& actor) = 0; + + /** + Notify stress solver on destroyed actor. + + Call this function when actor is destroyed (split futher) or deactivated. + + \param[in] actor The actor destroyed. + */ + virtual void notifyActorDestroyed(const NvBlastActor& actor) = 0; + + /** + Apply external impulse on particular actor of family. This function will find nearest actor's graph node to apply impulse on. + + \param[in] actor The actor to apply impulse on. + \param[in] localPosition Local position in actor's coordinates to apply impulse on. + \param[in] localForce Force to apply in local actor's coordinates. + \param[in] mode The mode to use when applying the force/impulse(see #ExtForceMode) + + \return true iff node was found and force applied. + */ + virtual bool addForce(const NvBlastActor& actor, physx::PxVec3 localPosition, physx::PxVec3 localForce, ExtForceMode::Enum mode = ExtForceMode::IMPULSE) = 0; + + /** + Apply external impulse on particular node. + + \param[in] graphNodeIndex The graph node index to apply impulse on. See #NvBlastSupportGraph. + \param[in] localForce Force to apply in local actor's coordinates. + \param[in] mode The mode to use when applying the force/impulse(see #ExtForceMode) + */ + virtual void addForce(uint32_t graphNodeIndex, physx::PxVec3 localForce, ExtForceMode::Enum mode = ExtForceMode::IMPULSE) = 0; + + /** + Apply external gravity on particular actor of family. This function applies gravity on every node withing actor, so it makes sense only for static actors. + + \param[in] actor The actor to apply impulse on. + \param[in] localGravity Gravity to apply in local actor's coordinates. ExtForceMode::VELOCITY is used. + + \return true iff force was applied on at least one node. + */ + virtual bool addGravityForce(const NvBlastActor& actor, physx::PxVec3 localGravity) = 0; + + /** + Apply centrifugal force produced by actor's angular movement. + + \param[in] actor The actor to apply impulse on. + \param[in] localCenterMass Actor's local center of mass. + \param[in] localAngularVelocity Local angular velocity of an actor. + + \return true iff force was applied on at least one node. + */ + virtual bool addAngularVelocity(const NvBlastActor& actor, physx::PxVec3 localCenterMass, physx::PxVec3 localAngularVelocity) = 0; + + /** + Update stress solver. + + Actual performance heavy stress calculation happens there. Call it after all relevant forces were applied, usually every frame. + */ + virtual void update() = 0; + + /** + Get overstressed/broken bonds count. + + This count is updated after every update() call. Number of overstressed bond directly hints if any bond fracture is recommended by stress solver. + + \return the overstressed bonds count. + */ + virtual uint32_t getOverstressedBondCount() const = 0; + + /** + Generate fracture commands for particular actor. + + Calling this function if getOverstressedBondCount() == 0 or actor has no bond doesn't make sense, bondFractureCount will be '0'. + Filled fracture commands buffer can be passed directly to NvBlastActorApplyFracture. + + IMPORTANT: NvBlastFractureBuffers::bondFractures will point to internal stress solver memory which will be valid till next call + of any of generateFractureCommands() functions or stress solver release() call. + + \param[in] actor The actor to fill fracture commands for. + \param[in] commands Pointer to command buffer to fill. + */ + virtual void generateFractureCommands(const NvBlastActor& actor, NvBlastFractureBuffers& commands) = 0; + + /** + Generate fracture commands for whole family. A bit faster way to get all fractured bonds then calling generateFractureCommands() for every actor. + + Calling this function if getOverstressedBondCount() == 0 or actor has no bond doesn't make sense, bondFractureCount will be '0'. + + IMPORTANT: NvBlastFractureBuffers::bondFractures will point to internal stress solver memory which will be valid till next call + of any of generateFractureCommands() functions or stress solver release() call. + + \param[in] commands Pointer to command buffer to fill. + */ + virtual void generateFractureCommands(NvBlastFractureBuffers& commands) = 0; + + /** + Generate fracture commands for every actor in family. + + Actors and commands buffer must be passed in order to be filled. It's recommended for bufferSize to be the count of actor with more then one bond in family. + + Calling this function if getOverstressedBondCount() == 0 or actor has no bond doesn't make sense, '0' will be returned. + + IMPORTANT: NvBlastFractureBuffers::bondFractures will point to internal stress solver memory which will be valid till next call + of any of generateFractureCommands() functions or stress solver release() call. + + \param[out] buffer A user-supplied array of NvBlastActor pointers to fill. + \param[out] commandsBuffer A user-supplied array of NvBlastFractureBuffers to fill. + \param[in] bufferSize The number of elements available to write into buffer. + + \return the number of actors and command buffers written to the buffer. + */ + virtual uint32_t generateFractureCommandsPerActor(const NvBlastActor** actorBuffer, NvBlastFractureBuffers* commandsBuffer, uint32_t bufferSize) = 0; + + /** + Reset stress solver. + + Stress solver uses warm start internally, calling this function will flush all previous data calculated and also zeros frame count. + This function is to be used for debug purposes. + */ + virtual void reset() = 0; + + /** + Get stress solver linear error. + + \return the total linear error of stress calculation. + */ + virtual float getStressErrorLinear() const = 0; + + /** + Get stress solver angular error. + + \return the total angular error of stress calculation. + */ + virtual float getStressErrorAngular() const = 0; + + /** + Get stress solver total frames count (update() calls) since it was created (or reset). + + \return the frames count. + */ + virtual uint32_t getFrameCount() const = 0; + + /** + Get stress solver bonds count, after graph reduction was applied. + + \return the bonds count. + */ + virtual uint32_t getBondCount() const = 0; + + + /** + Debug Render Mode + */ + enum DebugRenderMode + { + STRESS_GRAPH = 0, //!< render only stress graph + STRESS_GRAPH_NODES_IMPULSES = 1, //!< render stress graph + nodes impulses after solving stress + STRESS_GRAPH_BONDS_IMPULSES = 2 //!< render stress graph + bonds impulses after solving stress + }; + + /** + Used to store a single line and colour for debug rendering. + */ + struct DebugLine + { + DebugLine(const physx::PxVec3& p0, const physx::PxVec3& p1, const uint32_t& c) + : pos0(p0), color0(c), pos1(p1), color1(c) {} + + physx::PxVec3 pos0; + uint32_t color0; + physx::PxVec3 pos1; + uint32_t color1; + }; + + /** + Debug Buffer + */ + struct DebugBuffer + { + const DebugLine* lines; + uint32_t lineCount; + }; + + /** + Fill debug render for passed array of support graph nodes. + + NOTE: Returned DebugBuffer points into internal memory which is valid till next fillDebugRender() call. + + \param[in] nodes Node indices of support graph to debug render for. + \param[in] nodeCount Node indices count. + \param[in] mode Debug render mode. + \param[in] scale Scale to be applied on impulses. + + \return debug buffer with array of lines + */ + virtual const DebugBuffer fillDebugRender(const uint32_t* nodes, uint32_t nodeCount, DebugRenderMode mode, float scale = 1.0f) = 0; + + + //////// helpers //////// + + /** + Get solver iteration per frame (update() call) for particular settings and bondCount. + + Helper method to know how many solver iterations are made per frame. + This function made so transparent to make it clear how ExtStressSolverSettings::bondIterationsPerFrame is used. + + \param[in] settings Debug render mode. + \param[in] bondCount Scale to be applied on impulses. + + \return the iterations per frame count. + */ + static uint32_t getIterationsPerFrame(const ExtStressSolverSettings& settings, uint32_t bondCount) + { + uint32_t perFrame = settings.bondIterationsPerFrame / (bondCount + 1); + return perFrame > 0 ? perFrame : 1; + } + + /** + Get iteration per frame (update() call). + + Helper method to know how many solver iterations are made per frame. + + \return the iterations per frame count. + */ + uint32_t getIterationsPerFrame() const + { + return getIterationsPerFrame(getSettings(), getBondCount()); + } + +}; + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTEXTSTRESSSOLVER_H diff --git a/sdk/extensions/physx/source/physics/NvBlastExtImpulseStressSolver.cpp b/sdk/extensions/stress/source/NvBlastExtStressSolver.cpp index 8329de5..335aacb 100644 --- a/sdk/extensions/physx/source/physics/NvBlastExtImpulseStressSolver.cpp +++ b/sdk/extensions/stress/source/NvBlastExtStressSolver.cpp @@ -1,39 +1,53 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, 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. -*/ - -#include "NvBlastExtImpulseStressSolver.h" -#include "NvBlastExtPxAsset.h" -#include "NvBlastExtPxFamily.h" -#include "NvBlastExtPxActor.h" +// 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-2017 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastExtStressSolver.h" +#include "NvBlast.h" +#include "NvBlastGlobals.h" +#include "NvBlastArray.h" +#include "NvBlastHashMap.h" +#include "NvBlastHashSet.h" #include "NvBlastAssert.h" #include "NvBlastIndexFns.h" -#include "NvBlastExtDefs.h" - -#include "NvBlastTkAsset.h" -#include "NvBlastTkActor.h" -#include "NvBlastTkFamily.h" - -#include "PxScene.h" -#include "PxRigidDynamic.h" #include <PsVecMath.h> #include "PsFPU.h" #include <algorithm> -#include <set> #define USE_SCALAR_IMPL 0 #define WARM_START 1 -#define USE_PHYSX_CONVEX_DATA 1 #define GRAPH_INTERGRIRY_CHECK 0 +#if GRAPH_INTERGRIRY_CHECK +#include <set> +#endif + namespace Nv { @@ -59,11 +73,6 @@ public: uint32_t node1; physx::PxVec3 offset0; float invOffsetSqrLength; - - float getStressHealth(const ExtStressSolverSettings& settings) const - { - return (impulseLinear.magnitude() * settings.stressLinearFactor + impulseAngular.magnitude() * settings.stressAngularFactor); - } } PX_ALIGN_SUFFIX(16); @@ -83,33 +92,33 @@ public: m_bondsData.reserve(maxBondCount); } - NV_INLINE const NodeData& getNodeData(uint32_t node) const + const NodeData& getNodeData(uint32_t node) const { return m_nodesData[node]; } - NV_INLINE const BondData& getBondData(uint32_t bond) const + const BondData& getBondData(uint32_t bond) const { return m_bondsData[bond]; } - NV_INLINE uint32_t getBondCount() const + uint32_t getBondCount() const { return m_bondsData.size(); } - NV_INLINE uint32_t getNodeCount() const + uint32_t getNodeCount() const { return m_nodesData.size();; } - NV_INLINE void setNodeMassInfo(uint32_t node, float invMass, float invI) + void setNodeMassInfo(uint32_t node, float invMass, float invI) { m_nodesData[node].invMass = invMass; m_nodesData[node].invI = invI; } - NV_INLINE void initialize() + void initialize() { for (auto& node : m_nodesData) { @@ -118,13 +127,13 @@ public: } } - NV_INLINE void setNodeVelocities(uint32_t node, const PxVec3& velocityLinear, const PxVec3& velocityAngular) + void setNodeVelocities(uint32_t node, const PxVec3& velocityLinear, const PxVec3& velocityAngular) { m_nodesData[node].velocityLinear = velocityLinear; m_nodesData[node].velocityAngular = velocityAngular; } - NV_INLINE uint32_t addBond(uint32_t node0, uint32_t node1, const PxVec3& offset) + uint32_t addBond(uint32_t node0, uint32_t node1, const PxVec3& offset) { const BondData data = { PxVec3(PxZero), @@ -138,23 +147,23 @@ public: return m_bondsData.size() - 1; } - NV_INLINE void replaceWithLast(uint32_t bondIndex) + void replaceWithLast(uint32_t bondIndex) { m_bondsData.replaceWithLast(bondIndex); } - NV_INLINE void reset(uint32_t nodeCount) + void reset(uint32_t nodeCount) { m_bondsData.clear(); m_nodesData.resize(nodeCount); } - NV_INLINE void clearBonds() + void clearBonds() { m_bondsData.clear(); } - void solve(uint32_t iterationCount, bool warmStart = false) + void solve(uint32_t iterationCount, bool warmStart = true) { solveInit(warmStart); @@ -218,7 +227,7 @@ private: } - NV_INLINE void iterate() + void iterate() { using namespace physx::shdfnd::aos; @@ -297,8 +306,8 @@ private: } } - shdfnd::Array<BondData, ExtAlignedAllocator<16>> m_bondsData; - shdfnd::Array<NodeData, ExtAlignedAllocator<16>> m_nodesData; + Array<BondData>::type m_bondsData; + Array<NodeData>::type m_nodesData; }; @@ -321,6 +330,7 @@ public: uint32_t node0; uint32_t node1; uint32_t blastBondIndex; + float stress; }; struct NodeData @@ -349,7 +359,7 @@ public: struct SolverBondData { - ExtInlineArray<uint32_t, 8>::type blastBondIndices; + InlineArray<uint32_t, 8>::type blastBondIndices; }; SupportGraphProcessor(uint32_t nodeCount, uint32_t maxBondCount) : m_solver(nodeCount, maxBondCount), m_nodesDirty(true) @@ -364,67 +374,85 @@ public: m_blastBondIndexMap.resize(maxBondCount); memset(m_blastBondIndexMap.begin(), 0xFF, m_blastBondIndexMap.size() * sizeof(uint32_t)); + + resetImpulses(); } - NV_INLINE const NodeData& getNodeData(uint32_t node) const + const NodeData& getNodeData(uint32_t node) const { return m_nodesData[node]; } - NV_INLINE const BondData& getBondData(uint32_t bond) const + const BondData& getBondData(uint32_t bond) const { return m_bondsData[bond]; } - NV_INLINE const SolverNodeData& getSolverNodeData(uint32_t node) const + const SolverNodeData& getSolverNodeData(uint32_t node) const { return m_solverNodesData[node]; } - NV_INLINE const SolverBondData& getSolverBondData(uint32_t bond) const + const SolverBondData& getSolverBondData(uint32_t bond) const { return m_solverBondsData[bond]; } - NV_INLINE const SequentialImpulseSolver::BondData& getSolverInternalBondData(uint32_t bond) const + const SequentialImpulseSolver::BondData& getSolverInternalBondData(uint32_t bond) const { return m_solver.getBondData(bond); } - NV_INLINE const SequentialImpulseSolver::NodeData& getSolverInternalNodeData(uint32_t node) const + const SequentialImpulseSolver::NodeData& getSolverInternalNodeData(uint32_t node) const { return m_solver.getNodeData(node); } - NV_INLINE uint32_t getBondCount() const + uint32_t getBondCount() const { return m_bondsData.size(); } - NV_INLINE uint32_t getNodeCount() const + uint32_t getNodeCount() const { return m_nodesData.size();; } - NV_INLINE uint32_t getSolverBondCount() const + uint32_t getSolverBondCount() const { return m_solverBondsData.size(); } - NV_INLINE uint32_t getSolverNodeCount() const + uint32_t getSolverNodeCount() const { return m_solverNodesData.size();; } - NV_INLINE void setNodeInfo(uint32_t node, float mass, float volume, PxVec3 localPos, bool isStatic) + uint32_t getOverstressedBondCount() const + { + return m_overstressedBondCount; + } + + float getSolverBondStressHealth(uint32_t bond, const ExtStressSolverSettings& settings) const + { + const auto& solverBond = getSolverInternalBondData(bond); + const float impulse = solverBond.impulseLinear.magnitude() * settings.stressLinearFactor + solverBond.impulseAngular.magnitude() * settings.stressAngularFactor; + // We then divide uniformly across bonds, which is obviously rough estimate. + // Potentially we can add bond area there and norm across area sum + const auto& blastBondIndices = m_solverBondsData[bond].blastBondIndices; + return blastBondIndices.empty() ? 0.0f : impulse / (blastBondIndices.size() * settings.hardness); + } + + void setNodeInfo(uint32_t node, float mass, float volume, PxVec3 localPos, bool isStatic) { m_nodesData[node].mass = mass; m_nodesData[node].volume = volume; m_nodesData[node].localPos = localPos; m_nodesData[node].isStatic = isStatic; + m_nodesDirty = true; } - NV_INLINE void setNodeNeighborsCount(uint32_t node, uint32_t neighborsCount) + void setNodeNeighborsCount(uint32_t node, uint32_t neighborsCount) { // neighbors count is expected to be the number of nodes on 1 island/actor. m_nodesData[node].neighborsCount = neighborsCount; @@ -436,44 +464,38 @@ public: } } - NV_INLINE void initialize() + void addNodeForce(uint32_t node, const PxVec3& force, ExtForceMode::Enum mode) { - sync(); - - m_solver.initialize(); - - for (auto& node : m_nodesData) - { - node.impulse = PxVec3(PxZero); - } + const PxVec3 impuse = (mode == ExtForceMode::IMPULSE) ? force : force * m_nodesData[node].mass; + m_nodesData[node].impulse += impuse; } - NV_INLINE void addNodeImpulse(uint32_t node, const PxVec3& impulse) + void addNodeVelocity(uint32_t node, const PxVec3& velocity) { - m_nodesData[node].impulse += impulse; + addNodeForce(node, velocity, ExtForceMode::VELOCITY); } - NV_INLINE void addNodeVelocity(uint32_t node, const PxVec3& velocity) + void addNodeImpulse(uint32_t node, const PxVec3& impulse) { - PxVec3 impulse = velocity * m_nodesData[node].mass; - addNodeImpulse(node, impulse); + addNodeForce(node, impulse, ExtForceMode::IMPULSE); } - NV_INLINE void addBond(uint32_t node0, uint32_t node1, uint32_t blastBondIndex) + void addBond(uint32_t node0, uint32_t node1, uint32_t blastBondIndex) { if (isInvalidIndex(m_blastBondIndexMap[blastBondIndex])) { const BondData data = { node0, node1, - blastBondIndex + blastBondIndex, + 0.0f }; m_bondsData.pushBack(data); m_blastBondIndexMap[blastBondIndex] = m_bondsData.size() - 1; } } - NV_INLINE void removeBondIfExists(uint32_t blastBondIndex) + void removeBondIfExists(uint32_t blastBondIndex) { const uint32_t bondIndex = m_blastBondIndexMap[blastBondIndex]; @@ -528,7 +550,7 @@ public: } } - NV_INLINE void setGraphReductionLevel(uint32_t level) + void setGraphReductionLevel(uint32_t level) { m_graphReductionLevel = level; m_nodesDirty = true; @@ -539,9 +561,11 @@ public: return m_graphReductionLevel; } - void solve(uint32_t iterationCount, bool warmStart = false) + void solve(const ExtStressSolverSettings& settings, const float* bondHealth, bool warmStart = true) { - CHECK_GRAPH_INTEGRITY; + sync(); + + m_solver.initialize(); for (const NodeData& node : m_nodesData) { @@ -549,7 +573,12 @@ public: m_solver.setNodeVelocities(node.solverNode, solverNode.velocityLinear + node.impulse * solverNode.invMass, PxVec3(PxZero)); } + uint32_t iterationCount = ExtStressSolver::getIterationsPerFrame(settings, getSolverBondCount()); m_solver.solve(iterationCount, warmStart); + + resetImpulses(); + + updateBondStress(settings, bondHealth); } void calcError(float& linear, float& angular) @@ -557,40 +586,53 @@ public: m_solver.calcError(linear, angular); } - void generateFracture(ExtArray<NvBlastBondFractureData>::type& bondFractureBuffer, const ExtStressSolverSettings& settings, const float* blastBondHealths) + float getBondStress(uint32_t blastBondIndex) { - CHECK_GRAPH_INTEGRITY; + const uint32_t bondIndex = m_blastBondIndexMap[blastBondIndex]; + return isInvalidIndex(bondIndex) ? 0.0f : m_bondsData[bondIndex].stress; + } + +private: + + void resetImpulses() + { + for (auto& node : m_nodesData) + { + node.impulse = PxVec3(PxZero); + } + } + + void updateBondStress(const ExtStressSolverSettings& settings, const float* bondHealth) + { + m_overstressedBondCount = 0; for (uint32_t i = 0; i < m_solverBondsData.size(); ++i) { - const SequentialImpulseSolver::BondData& solverInternalBond = m_solver.getBondData(i); - if (solverInternalBond.getStressHealth(settings) > 1.0f) + const float stress = getSolverBondStressHealth(i, settings); + const auto& blastBondIndices = m_solverBondsData[i].blastBondIndices; + const float stressPerBond = blastBondIndices.size() > 0 ? stress / blastBondIndices.size() : 0.0f; + for (auto blastBondIndex : blastBondIndices) { - const auto& blastBondIndices = m_solverBondsData[i].blastBondIndices; - for (auto blastBondIndex : blastBondIndices) + const uint32_t bondIndex = m_blastBondIndexMap[blastBondIndex]; + if (!isInvalidIndex(bondIndex)) { - const uint32_t bondIndex = m_blastBondIndexMap[blastBondIndex]; - if (!isInvalidIndex(bondIndex)) - { - const BondData& bond = m_bondsData[bondIndex]; + BondData& bond = m_bondsData[bondIndex]; - NVBLAST_ASSERT(getNodeData(bond.node0).solverNode != getNodeData(bond.node1).solverNode); - NVBLAST_ASSERT(bond.blastBondIndex == blastBondIndex); + NVBLAST_ASSERT(getNodeData(bond.node0).solverNode != getNodeData(bond.node1).solverNode); + NVBLAST_ASSERT(bond.blastBondIndex == blastBondIndex); + + bond.stress = stressPerBond; - NvBlastBondFractureData data; - data.health = blastBondHealths[blastBondIndex]; - data.nodeIndex0 = bond.node0; - data.nodeIndex1 = bond.node1; - bondFractureBuffer.pushBack(data); + if (stress > bondHealth[blastBondIndex]) + { + m_overstressedBondCount++; } } } } } -private: - - NV_INLINE void sync() + void sync() { if (m_nodesDirty) { @@ -620,6 +662,10 @@ private: const uint32_t STATIC_NODES_COUNT_PENALTY = 2 << 2; // reducing graph by aggregating nodes level by level + // NOTE (@anovoselov): Recently, I found a flow in the algorithm below. In very rare situations aggregate (solver node) + // can contain more then one connected component. I didn't notice it to produce any visual artifacts and it's + // unlikely to influence stress solvement a lot. Possible solution is to merge *whole* solver nodes, that + // will raise complexity a bit (at least will add another loop on nodes for every reduction level. for (uint32_t k = 0; k < m_graphReductionLevel; k++) { const uint32_t maxAggregateSize = 1 << (k + 1); @@ -748,11 +794,14 @@ private: m_solver.clearBonds(); m_solverBondsMap.clear(); m_solverBondsData.clear(); - for (const BondData& bond : m_bondsData) + for (BondData& bond : m_bondsData) { const NodeData& node0 = m_nodesData[bond.node0]; const NodeData& node1 = m_nodesData[bond.node1]; + // reset stress, bond structure changed and internal bonds stress won't be updated during updateBondStress() + bond.stress = 0.0f; + if (node0.solverNode == node1.solverNode) continue; // skip (internal) @@ -852,106 +901,199 @@ private: }; SequentialImpulseSolver m_solver; - ExtArray<SolverNodeData>::type m_solverNodesData; - ExtArray<SolverBondData>::type m_solverBondsData; + Array<SolverNodeData>::type m_solverNodesData; + Array<SolverBondData>::type m_solverBondsData; - uint32_t m_graphReductionLevel; + uint32_t m_graphReductionLevel; bool m_nodesDirty; bool m_bondsDirty; - ExtHashMap<BondKey, uint32_t>::type m_solverBondsMap; - ExtArray<uint32_t>::type m_blastBondIndexMap; + uint32_t m_overstressedBondCount; + + HashMap<BondKey, uint32_t>::type m_solverBondsMap; + Array<uint32_t>::type m_blastBondIndexMap; - ExtArray<BondData>::type m_bondsData; - ExtArray<NodeData>::type m_nodesData; + Array<BondData>::type m_bondsData; + Array<NodeData>::type m_nodesData; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ExtImpulseStressSolver +// ExtStressSolver /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Creation -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +struct ExtStressNodeCachedData +{ + physx::PxVec3 localPos; + bool isStatic; +}; -ExtImpulseStressSolver::ExtImpulseStressSolver(ExtPxFamily& family, ExtStressSolverSettings settings) - : m_family(family), m_settings(settings), m_isDirty(false), m_reset(false), - m_errorAngular(std::numeric_limits<float>::max()), m_errorLinear(std::numeric_limits<float>::max()), m_framesCount(0) + +struct ExtStressBondCachedData +{ + uint32_t bondIndex; +}; + +/** +*/ +class ExtStressSolverImpl final : public ExtStressSolver { + NV_NOCOPY(ExtStressSolverImpl) - const TkAsset* tkAsset = m_family.getTkFamily().getAsset(); - const ExtPxAsset& asset = m_family.getPxAsset(); - const ExtPxChunk* chunks = asset.getChunks(); - const ExtPxSubchunk* subChunks = asset.getSubchunks(); - m_graph = tkAsset->getGraph(); - const uint32_t bondCount = tkAsset->getBondCount(); - - TkActor* tkActor; - m_family.getTkFamily().getActors(&tkActor, 1); - m_bondHealths = tkActor->getBondHealths(); +public: + ExtStressSolverImpl(NvBlastFamily& family, ExtStressSolverSettings settings); + virtual void release() override; - m_graphProcessor = NVBLASTEXT_NEW(SupportGraphProcessor)(m_graph.nodeCount, bondCount); - // traverse graph and fill node info - for (uint32_t i = 0; i < m_graph.nodeCount; ++i) + //////// ExtStressSolverImpl interface //////// + + virtual void setAllNodesInfoFromLL(float density = 1.0f) override; + + virtual void setNodeInfo(uint32_t graphNode, float mass, float volume, PxVec3 localPos, bool isStatic) override; + + virtual void setSettings(const ExtStressSolverSettings& settings) override { - uint32_t node0 = i; - uint32_t chunkIndex0 = m_graph.chunkIndices[node0]; - const ExtPxChunk& chunk0 = chunks[chunkIndex0]; + m_settings = settings; + } - bool isChunkStatic = chunk0.isStatic; + virtual const ExtStressSolverSettings& getSettings() const override + { + return m_settings; + } - for (uint32_t adjacencyIndex = m_graph.adjacencyPartition[node0]; adjacencyIndex < m_graph.adjacencyPartition[node0 + 1]; adjacencyIndex++) - { - uint32_t bondIndex = m_graph.adjacentBondIndices[adjacencyIndex]; - if (m_bondHealths[bondIndex] <= 0.0f) - continue; - uint32_t node1 = m_graph.adjacentNodeIndices[adjacencyIndex]; - uint32_t chunkIndex1 = m_graph.chunkIndices[node1]; - const ExtPxChunk& chunk1 = chunks[chunkIndex1]; + virtual bool addForce(const NvBlastActor& actor, physx::PxVec3 localPosition, physx::PxVec3 localForce, ExtForceMode::Enum mode) override; - if (chunk1.subchunkCount == 0 || chunk1.isStatic) - { - isChunkStatic |= chunk1.isStatic; - continue; - } - } + virtual void addForce(uint32_t graphNode, physx::PxVec3 localForce, ExtForceMode::Enum mode) override; - // fill node info + virtual bool addGravityForce(const NvBlastActor& actor, physx::PxVec3 localGravity) override; + virtual bool addAngularVelocity(const NvBlastActor& actor, PxVec3 localCenterMass, physx::PxVec3 localAngularVelocity) override; - float mass; - float volume; - PxVec3 localPos; - if (chunk0.subchunkCount > 0) - { -#if USE_PHYSX_CONVEX_DATA - const ExtPxSubchunk& subChunk = subChunks[chunk0.firstSubchunkIndex]; - PxVec3 localCenterOfMass; - PxMat33 intertia; - PxVec3 scale = subChunk.geometry.scale.scale; - subChunk.geometry.convexMesh->getMassInformation(mass, intertia, localCenterOfMass); - mass *= scale.x * scale.y * scale.z; - const PxTransform& chunk0LocalTransform = subChunk.transform; - localPos = chunk0LocalTransform.transform(localCenterOfMass); - volume = mass / 1.0f; // unit density -#else - volume = solverChunk0.volume; - mass = volume * 1.0f; // density - localPos = *reinterpret_cast<const PxVec3*>(solverChunk0.centroid); -#endif - } - else - { - mass = 0.0f; - volume = 0.0f; - localPos = PxVec3(PxZero); - isChunkStatic = true; - } - m_graphProcessor->setNodeInfo(node0, mass, volume, localPos, isChunkStatic); + virtual void update() override; + + virtual uint32_t getOverstressedBondCount() const override + { + return m_graphProcessor->getOverstressedBondCount(); + } + + virtual void generateFractureCommands(const NvBlastActor& actor, NvBlastFractureBuffers& commands) override; + virtual void generateFractureCommands(NvBlastFractureBuffers& commands) override; + virtual uint32_t generateFractureCommandsPerActor(const NvBlastActor** actorBuffer, NvBlastFractureBuffers* commandsBuffer, uint32_t bufferSize) override; + + + void reset() override + { + m_reset = true; + } + + virtual float getStressErrorLinear() const override + { + return m_errorLinear; } + virtual float getStressErrorAngular() const override + { + return m_errorAngular; + } + + virtual uint32_t getFrameCount() const override + { + return m_framesCount; + } + + virtual uint32_t getBondCount() const override + { + return m_graphProcessor->getSolverBondCount(); + } + + virtual bool notifyActorCreated(const NvBlastActor& actor) override; + + virtual void notifyActorDestroyed(const NvBlastActor& actor) override; + + virtual const DebugBuffer fillDebugRender(const uint32_t* nodes, uint32_t nodeCount, DebugRenderMode mode, float scale) override; + + +private: + ~ExtStressSolverImpl(); + + + //////// private methods //////// + + void solve(); + + void fillFractureCommands(const NvBlastActor& actor, NvBlastFractureBuffers& commands); + + void initialize(); + + void iterate(); + + void syncSolver(); + + template<class T> + T* getScratchArray(uint32_t size); + + + //////// data //////// + + struct ImpulseData + { + physx::PxVec3 position; + physx::PxVec3 impulse; + }; + + NvBlastFamily& m_family; + HashSet<const NvBlastActor*>::type m_activeActors; + ExtStressSolverSettings m_settings; + NvBlastSupportGraph m_graph; + bool m_isDirty; + bool m_reset; + const float* m_bondHealths; + SupportGraphProcessor* m_graphProcessor; + float m_errorAngular; + float m_errorLinear; + uint32_t m_framesCount; + Array<NvBlastBondFractureData>::type m_bondFractureBuffer; + Array<uint8_t>::type m_scratch; + Array<DebugLine>::type m_debugLineBuffer; +}; + + +template<class T> +NV_INLINE T* ExtStressSolverImpl::getScratchArray(uint32_t size) +{ + const uint32_t scratchSize = sizeof(T) * size; + if (m_scratch.size() < scratchSize) + { + m_scratch.resize(scratchSize); + } + return reinterpret_cast<T*>(m_scratch.begin()); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Creation +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ExtStressSolverImpl::ExtStressSolverImpl(NvBlastFamily& family, ExtStressSolverSettings settings) + : m_family(family), m_settings(settings), m_isDirty(false), m_reset(false), + m_errorAngular(std::numeric_limits<float>::max()), m_errorLinear(std::numeric_limits<float>::max()), m_framesCount(0) +{ + const NvBlastAsset* asset = NvBlastFamilyGetAsset(&m_family, logLL); + NVBLAST_ASSERT(asset); + + m_graph = NvBlastAssetGetSupportGraph(asset, logLL); + const uint32_t bondCount = NvBlastAssetGetBondCount(asset, logLL); + + m_bondFractureBuffer.reserve(bondCount); + + { + NvBlastActor* actor; + NvBlastFamilyGetActors(&actor, 1, &family, logLL); + m_bondHealths = NvBlastActorGetBondHealths(actor, logLL); + } + + m_graphProcessor = NVBLAST_NEW(SupportGraphProcessor)(m_graph.nodeCount, bondCount); + // traverse graph and fill bond info for (uint32_t node0 = 0; node0 < m_graph.nodeCount; ++node0) { @@ -968,69 +1110,110 @@ ExtImpulseStressSolver::ExtImpulseStressSolver(ExtPxFamily& family, ExtStressSol } } } - - // fire initial actor's created - ExtInlineArray<ExtPxActor*, 4>::type actors;; - actors.resize((uint32_t)m_family.getActorCount()); - m_family.getActors(actors.begin(), actors.size()); - for (const auto actor : actors) - { - onActorCreated(m_family, *actor); - } - - m_family.subscribe(*this); } -ExtImpulseStressSolver::~ExtImpulseStressSolver() +ExtStressSolverImpl::~ExtStressSolverImpl() { - NVBLASTEXT_DELETE(m_graphProcessor, SupportGraphProcessor); - m_family.unsubscribe(*this); + NVBLAST_DELETE(m_graphProcessor, SupportGraphProcessor); } -ExtStressSolver* ExtStressSolver::create(ExtPxFamily& family, ExtStressSolverSettings settings) +ExtStressSolver* ExtStressSolver::create(NvBlastFamily& family, ExtStressSolverSettings settings) { - return NVBLASTEXT_NEW(ExtImpulseStressSolver) (family, settings); + return NVBLAST_NEW(ExtStressSolverImpl) (family, settings); } -void ExtImpulseStressSolver::release() +void ExtStressSolverImpl::release() { - NVBLASTEXT_DELETE(this, ExtImpulseStressSolver); + NVBLAST_DELETE(this, ExtStressSolverImpl); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Actors +// Actors & Graph Data /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ExtImpulseStressSolver::onActorCreated(ExtPxFamily& /*family*/, ExtPxActor& actor) +void ExtStressSolverImpl::setAllNodesInfoFromLL(float density) +{ + const NvBlastAsset* asset = NvBlastFamilyGetAsset(&m_family, logLL); + NVBLAST_ASSERT(asset); + + const uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, logLL); + const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, logLL); + + // traverse graph and fill node info + for (uint32_t node0 = 0; node0 < m_graph.nodeCount; ++node0) + { + const uint32_t chunkIndex0 = m_graph.chunkIndices[node0]; + if (chunkIndex0 >= chunkCount) + { + // chunkIndex is invalid means it is static node (represents world) + m_graphProcessor->setNodeInfo(node0, 0.0f, 0.0f, PxVec3(), true); + } + else + { + // Check if node is static. There is at maximum only one static node in LL that represents world, but we consider all nodes + // connected to it directly to be static too. It's better for general stress solver quality to have more then 1 static node. + bool isNodeConnectedToStatic = false; + for (uint32_t adjacencyIndex = m_graph.adjacencyPartition[node0]; adjacencyIndex < m_graph.adjacencyPartition[node0 + 1]; adjacencyIndex++) + { + uint32_t bondIndex = m_graph.adjacentBondIndices[adjacencyIndex]; + if (m_bondHealths[bondIndex] <= 0.0f) + continue; + uint32_t node1 = m_graph.adjacentNodeIndices[adjacencyIndex]; + uint32_t chunkIndex1 = m_graph.chunkIndices[node1]; + if (chunkIndex1 >= chunkCount) + { + isNodeConnectedToStatic = true; + break; + } + } + + // fill node info + const NvBlastChunk& chunk = chunks[chunkIndex0]; + const float volume = chunk.volume; + const float mass = volume * density; + const PxVec3 localPos = *reinterpret_cast<const PxVec3*>(chunk.centroid); + m_graphProcessor->setNodeInfo(node0, mass, volume, localPos, isNodeConnectedToStatic); + } + } +} + +void ExtStressSolverImpl::setNodeInfo(uint32_t graphNode, float mass, float volume, PxVec3 localPos, bool isStatic) { - if (actor.getTkActor().getGraphNodeCount() > 1) + m_graphProcessor->setNodeInfo(graphNode, mass, volume, localPos, isStatic); +} + +bool ExtStressSolverImpl::notifyActorCreated(const NvBlastActor& actor) +{ + const uint32_t graphNodeCount = NvBlastActorGetGraphNodeCount(&actor, logLL); + if (graphNodeCount > 1) { // update neighbors { - const uint32_t graphNodeCount = actor.getTkActor().getGraphNodeCount(); uint32_t* graphNodeIndices = getScratchArray<uint32_t>(graphNodeCount); - actor.getTkActor().getGraphNodeIndices(graphNodeIndices, graphNodeCount); + NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeCount, &actor, logLL); for (uint32_t i = 0; i < graphNodeCount; ++i) { m_graphProcessor->setNodeNeighborsCount(graphNodeIndices[i], graphNodeCount); } } - m_actors.insert(&actor); + m_activeActors.insert(&actor); m_isDirty = true; + return true; } + return false; } -void ExtImpulseStressSolver::onActorDestroyed(ExtPxFamily& /*family*/, ExtPxActor& actor) +void ExtStressSolverImpl::notifyActorDestroyed(const NvBlastActor& actor) { - if (m_actors.erase(&actor)) + if (m_activeActors.erase(&actor)) { m_isDirty = true; } } -void ExtImpulseStressSolver::syncSolver() +void ExtStressSolverImpl::syncSolver() { // traverse graph and remove dead bonds for (uint32_t node0 = 0; node0 < m_graph.nodeCount; ++node0) @@ -1053,8 +1236,7 @@ void ExtImpulseStressSolver::syncSolver() m_isDirty = false; } - -void ExtImpulseStressSolver::initialize() +void ExtStressSolverImpl::initialize() { if (m_reset) { @@ -1070,86 +1252,82 @@ void ExtImpulseStressSolver::initialize() { m_graphProcessor->setGraphReductionLevel(m_settings.graphReductionLevel); } +} - m_graphProcessor->initialize(); +bool ExtStressSolverImpl::addForce(const NvBlastActor& actor, physx::PxVec3 localPosition, physx::PxVec3 localForce, ExtForceMode::Enum mode) +{ + float bestDist = FLT_MAX; + uint32_t bestNode = invalidIndex<uint32_t>(); - for (auto it = m_actors.getIterator(); !it.done(); ++it) + const uint32_t graphNodeCount = NvBlastActorGetGraphNodeCount(&actor, logLL); + if (graphNodeCount > 1) { - const ExtPxActor* actor = *it; - const uint32_t graphNodeCount = actor->getTkActor().getGraphNodeCount(); uint32_t* graphNodeIndices = getScratchArray<uint32_t>(graphNodeCount); - actor->getTkActor().getGraphNodeIndices(graphNodeIndices, graphNodeCount); - - PxRigidDynamic& rigidDynamic = actor->getPhysXActor(); - const bool isStatic = rigidDynamic.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC; - if (isStatic) - { - PxVec3 gravity = rigidDynamic.getScene()->getGravity(); - gravity = rigidDynamic.getGlobalPose().rotateInv(gravity); + NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeCount, &actor, logLL); - for (uint32_t i = 0; i < graphNodeCount; ++i) - { - const uint32_t node = graphNodeIndices[i]; - m_graphProcessor->addNodeVelocity(node, gravity); - } - } - else + for (uint32_t i = 0; i < graphNodeCount; ++i) { - PxVec3 cMassPose = rigidDynamic.getCMassLocalPose().p; - - PxVec3 angularVelocity = rigidDynamic.getGlobalPose().rotateInv(rigidDynamic.getAngularVelocity()); - //PxVec3 linearVelocity = rigidDynamic.getGlobalPose().rotateInv(rigidDynamic.getLinearVelocity()); - - // Apply centrifugal force - for (uint32_t i = 0; i < graphNodeCount; ++i) + const uint32_t node = graphNodeIndices[i]; + const float sqrDist = (localPosition - m_graphProcessor->getNodeData(node).localPos).magnitudeSquared(); + if (sqrDist < bestDist) { - const uint32_t node = graphNodeIndices[i]; - const auto& localPos = m_graphProcessor->getNodeData(node).localPos; - // a = w x (w x r) - const PxVec3 centrifugalAcceleration = angularVelocity.cross(angularVelocity.cross(localPos - cMassPose)); - m_graphProcessor->addNodeVelocity(node, centrifugalAcceleration); + bestDist = sqrDist; + bestNode = node; } } - const auto entry = m_impulseBuffer.find(actor); - if (entry) + if (!isInvalidIndex(bestNode)) { - for (const ImpulseData& data : entry->second) - { - float bestDist = FLT_MAX; - uint32_t bestNode = invalidIndex<uint32_t>(); - - for (uint32_t i = 0; i < graphNodeCount; ++i) - { - const uint32_t node = graphNodeIndices[i]; - const float sqrDist = (data.position - m_graphProcessor->getNodeData(node).localPos).magnitudeSquared(); - if (sqrDist < bestDist) - { - bestDist = sqrDist; - bestNode = node; - } - } - - if (!isInvalidIndex(bestNode)) - { - m_graphProcessor->addNodeImpulse(bestNode, data.impulse); - } - } - m_impulseBuffer[actor].clear(); + m_graphProcessor->addNodeForce(bestNode, localForce, mode); + return true; } } + return false; +} + +void ExtStressSolverImpl::addForce(uint32_t graphNode, physx::PxVec3 localForce, ExtForceMode::Enum mode) +{ + m_graphProcessor->addNodeForce(graphNode, localForce, mode); } -void ExtImpulseStressSolver::applyImpulse(ExtPxActor& actor, physx::PxVec3 position, physx::PxVec3 force) +bool ExtStressSolverImpl::addGravityForce(const NvBlastActor& actor, physx::PxVec3 localGravity) { - ImpulseData data = { position, force }; + const uint32_t graphNodeCount = NvBlastActorGetGraphNodeCount(&actor, logLL); + if (graphNodeCount > 1) + { + uint32_t* graphNodeIndices = getScratchArray<uint32_t>(graphNodeCount); + NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeCount, &actor, logLL); - m_impulseBuffer[&actor].pushBack(data); + for (uint32_t i = 0; i < graphNodeCount; ++i) + { + const uint32_t node = graphNodeIndices[i]; + m_graphProcessor->addNodeVelocity(node, localGravity); + } + return true; + } + return false; } -uint32_t ExtImpulseStressSolver::getBondCount() const +bool ExtStressSolverImpl::addAngularVelocity(const NvBlastActor& actor, PxVec3 localCenterMass, physx::PxVec3 localAngularVelocity) { - return m_graphProcessor->getSolverBondCount(); + const uint32_t graphNodeCount = NvBlastActorGetGraphNodeCount(&actor, logLL); + if (graphNodeCount > 1) + { + uint32_t* graphNodeIndices = getScratchArray<uint32_t>(graphNodeCount); + NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeCount, &actor, logLL); + + // Apply centrifugal force + for (uint32_t i = 0; i < graphNodeCount; ++i) + { + const uint32_t node = graphNodeIndices[i]; + const auto& localPos = m_graphProcessor->getNodeData(node).localPos; + // a = w x (w x r) + const PxVec3 centrifugalAcceleration = localAngularVelocity.cross(localAngularVelocity.cross(localPos - localCenterMass)); + m_graphProcessor->addNodeVelocity(node, centrifugalAcceleration); + } + return true; + } + return false; } @@ -1157,26 +1335,20 @@ uint32_t ExtImpulseStressSolver::getBondCount() const // Update /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ExtImpulseStressSolver::update(bool doDamage) +void ExtStressSolverImpl::update() { initialize(); solve(); - if (doDamage) - { - applyDamage(); - } - m_framesCount++; } -void ExtImpulseStressSolver::solve() +void ExtStressSolverImpl::solve() { PX_SIMD_GUARD; - const uint32_t iterations = getIterationsPerFrame(); - m_graphProcessor->solve(iterations, WARM_START && !m_reset); + m_graphProcessor->solve(m_settings, m_bondHealths, WARM_START && !m_reset); m_reset = false; m_graphProcessor->calcError(m_errorLinear, m_errorAngular); @@ -1187,25 +1359,103 @@ void ExtImpulseStressSolver::solve() // Damage /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ExtImpulseStressSolver::applyDamage() +void ExtStressSolverImpl::fillFractureCommands(const NvBlastActor& actor, NvBlastFractureBuffers& commands) { - m_bondFractureBuffer.clear(); - m_graphProcessor->generateFracture(m_bondFractureBuffer, m_settings, m_bondHealths); + const uint32_t graphNodeCount = NvBlastActorGetGraphNodeCount(&actor, logLL); + uint32_t commandCount = 0; - if (m_bondFractureBuffer.size() > 0) + if (graphNodeCount > 1 && m_graphProcessor->getOverstressedBondCount() > 0) { - NvBlastFractureBuffers fractureCommands; - fractureCommands.chunkFractureCount = 0; - fractureCommands.bondFractureCount = m_bondFractureBuffer.size(); - fractureCommands.bondFractures = m_bondFractureBuffer.begin(); + uint32_t* graphNodeIndices = getScratchArray<uint32_t>(graphNodeCount); + NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeCount, &actor, logLL); + + for (uint32_t i = 0; i < graphNodeCount; ++i) + { + const uint32_t node0 = graphNodeIndices[i]; + for (uint32_t adjacencyIndex = m_graph.adjacencyPartition[node0]; adjacencyIndex < m_graph.adjacencyPartition[node0 + 1]; adjacencyIndex++) + { + uint32_t node1 = m_graph.adjacentNodeIndices[adjacencyIndex]; + if (node0 < node1) + { + uint32_t bondIndex = m_graph.adjacentBondIndices[adjacencyIndex]; + const float bondHealth = m_bondHealths[bondIndex]; + const float bondStress = m_graphProcessor->getBondStress(bondIndex); - m_family.getTkFamily().applyFracture(&fractureCommands); + if (bondHealth > 0.0f && bondStress > bondHealth) + { + const NvBlastBondFractureData data = { + 0, + node0, + node1, + bondHealth + }; + m_bondFractureBuffer.pushBack(data); + commandCount++; + } + } + } + } + } + + commands.chunkFractureCount = 0; + commands.chunkFractures = nullptr; + commands.bondFractureCount = commandCount; + commands.bondFractures = commandCount > 0 ? m_bondFractureBuffer.end() - commandCount : nullptr; +} + +void ExtStressSolverImpl::generateFractureCommands(const NvBlastActor& actor, NvBlastFractureBuffers& commands) +{ + m_bondFractureBuffer.clear(); + fillFractureCommands(actor, commands); +} + +void ExtStressSolverImpl::generateFractureCommands(NvBlastFractureBuffers& commands) +{ + m_bondFractureBuffer.clear(); + + const uint32_t bondCount = m_graphProcessor->getBondCount(); + const uint32_t overstressedBondCount = m_graphProcessor->getOverstressedBondCount(); + for (uint32_t i = 0; i < bondCount && m_bondFractureBuffer.size() < overstressedBondCount; i++) + { + const auto& bondData = m_graphProcessor->getBondData(i); + const float bondHealth = m_bondHealths[bondData.blastBondIndex]; + if (bondHealth > 0.0f && bondData.stress > bondHealth) + { + const NvBlastBondFractureData data = { + 0, + bondData.node0, + bondData.node1, + bondHealth + }; + m_bondFractureBuffer.pushBack(data); + } } + + commands.chunkFractureCount = 0; + commands.chunkFractures = nullptr; + commands.bondFractureCount = m_bondFractureBuffer.size(); + commands.bondFractures = m_bondFractureBuffer.size() > 0 ? m_bondFractureBuffer.begin() : nullptr; } -uint32_t ExtImpulseStressSolver::getIterationCount() const +uint32_t ExtStressSolverImpl::generateFractureCommandsPerActor(const NvBlastActor** actorBuffer, NvBlastFractureBuffers* commandsBuffer, uint32_t bufferSize) { - return getFrameCount() * getIterationsPerFrame(); + if (m_graphProcessor->getOverstressedBondCount() == 0) + return 0; + + m_bondFractureBuffer.clear(); + uint32_t index = 0; + for (auto it = m_activeActors.getIterator(); !it.done() && index < bufferSize; ++it) + { + const NvBlastActor* actor = *it; + NvBlastFractureBuffers& nextCommand = commandsBuffer[index]; + fillFractureCommands(*actor, nextCommand); + if (nextCommand.bondFractureCount > 0) + { + actorBuffer[index] = actor; + index++; + } + } + return index; } @@ -1230,7 +1480,7 @@ static PxVec4 PxVec4Lerp(const PxVec4 v0, const PxVec4 v1, float val) v0.y * (1 - val) + v1.y * val, v0.z * (1 - val) + v1.z * val, v0.w * (1 - val) + v1.w * val - ); + ); return v; } @@ -1250,21 +1500,26 @@ inline PxVec4 bondHealthColor(float healthFraction) return healthFraction < 0.5 ? PxVec4Lerp(BOND_BROKEN_COLOR, BOND_MID_COLOR, 2.0f * healthFraction) : PxVec4Lerp(BOND_MID_COLOR, BOND_HEALTHY_COLOR, 2.0f * healthFraction - 1.0f); } -void ExtImpulseStressSolver::fillDebugRender(const std::vector<uint32_t>& nodes, std::vector<PxDebugLine>& lines, DebugRenderMode mode, float scale) +const ExtStressSolver::DebugBuffer ExtStressSolverImpl::fillDebugRender(const uint32_t* nodes, uint32_t nodeCount, DebugRenderMode mode, float scale) { const PxVec4 BOND_IMPULSE_LINEAR_COLOR(0.0f, 1.0f, 0.0f, 1.0f); const PxVec4 BOND_IMPULSE_ANGULAR_COLOR(1.0f, 0.0f, 0.0f, 1.0f); + ExtStressSolver::DebugBuffer debugBuffer = { nullptr, 0 }; + if (m_isDirty) - return; + return debugBuffer; - ExtArray<uint8_t>::type& nodesSet = m_scratch; + m_debugLineBuffer.clear(); + + Array<uint8_t>::type& nodesSet = m_scratch; nodesSet.resize(m_graphProcessor->getSolverNodeCount()); memset(nodesSet.begin(), 0, nodesSet.size() * sizeof(uint8_t)); - for (auto& nodeIndex : nodes) + for (uint32_t i = 0; i < nodeCount; ++i) { - nodesSet[m_graphProcessor->getNodeData(nodeIndex).solverNode] = 1; + NVBLAST_ASSERT(m_graphProcessor->getNodeData(nodes[i]).solverNode < nodesSet.size()); + nodesSet[m_graphProcessor->getNodeData(nodes[i]).solverNode] = 1; } const uint32_t bondCount = m_graphProcessor->getSolverBondCount(); @@ -1273,8 +1528,7 @@ void ExtImpulseStressSolver::fillDebugRender(const std::vector<uint32_t>& nodes, const auto& solverInternalBondData = m_graphProcessor->getSolverInternalBondData(i); if (nodesSet[solverInternalBondData.node0] != 0) { - NVBLAST_ASSERT(nodesSet[solverInternalBondData.node1] != 0); - + //NVBLAST_ASSERT(nodesSet[solverInternalBondData.node1] != 0); const auto& solverInternalNode0 = m_graphProcessor->getSolverInternalNodeData(solverInternalBondData.node0); const auto& solverInternalNode1 = m_graphProcessor->getSolverInternalNodeData(solverInternalBondData.node1); const auto& solverNode0 = m_graphProcessor->getSolverNodeData(solverInternalBondData.node0); @@ -1284,27 +1538,32 @@ void ExtImpulseStressSolver::fillDebugRender(const std::vector<uint32_t>& nodes, PxVec3 p1 = solverNode1.localPos; PxVec3 center = (p0 + p1) * 0.5f; - const float stress = std::min<float>(solverInternalBondData.getStressHealth(m_settings), 1.0f); + const float stress = std::min<float>(m_graphProcessor->getSolverBondStressHealth(i, m_settings), 1.0f); PxVec4 color = bondHealthColor(1.0f - stress); - lines.push_back(PxDebugLine(p0, p1, PxVec4ToU32Color(color))); + m_debugLineBuffer.pushBack(DebugLine(p0, p1, PxVec4ToU32Color(color))); float impulseScale = scale; if (mode == DebugRenderMode::STRESS_GRAPH_NODES_IMPULSES) { - lines.push_back(PxDebugLine(p0, p0 + solverInternalNode0.velocityLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); - lines.push_back(PxDebugLine(p0, p0 + solverInternalNode0.velocityAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); - lines.push_back(PxDebugLine(p1, p1 + solverInternalNode1.velocityLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); - lines.push_back(PxDebugLine(p1, p1 + solverInternalNode1.velocityAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(p0, p0 + solverInternalNode0.velocityLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(p0, p0 + solverInternalNode0.velocityAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(p1, p1 + solverInternalNode1.velocityLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(p1, p1 + solverInternalNode1.velocityAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); } else if (mode == DebugRenderMode::STRESS_GRAPH_BONDS_IMPULSES) { - lines.push_back(PxDebugLine(center, center + solverInternalBondData.impulseLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); - lines.push_back(PxDebugLine(center, center + solverInternalBondData.impulseAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(center, center + solverInternalBondData.impulseLinear * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_LINEAR_COLOR))); + m_debugLineBuffer.pushBack(DebugLine(center, center + solverInternalBondData.impulseAngular * impulseScale, PxVec4ToU32Color(BOND_IMPULSE_ANGULAR_COLOR))); } } } + + debugBuffer.lines = m_debugLineBuffer.begin(); + debugBuffer.lineCount = m_debugLineBuffer.size(); + + return debugBuffer; } |