aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions/shaders')
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/include/NvBlastExtDamageShaders.h554
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp760
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h296
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h192
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp86
-rwxr-xr-x[-rw-r--r--]sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp1526
6 files changed, 1707 insertions, 1707 deletions
diff --git a/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h b/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h
index ef66062..943a0ec 100644..100755
--- a/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h
+++ b/sdk/extensions/shaders/include/NvBlastExtDamageShaders.h
@@ -1,277 +1,277 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTEXTDAMAGESHADERS_H
-#define NVBLASTEXTDAMAGESHADERS_H
-
-#include "NvBlastTypes.h"
-#include "NvBlastDebugRender.h"
-
-
-/**
-A few example damage shader implementations.
-*/
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Damage Accelerator
-///////////////////////////////////////////////////////////////////////////////
-
-class NvBlastExtDamageAccelerator
-{
-public:
- virtual void release() = 0;
-
- virtual Nv::Blast::DebugBuffer fillDebugRender(int depth = -1, bool segments = false) = 0;
-};
-
-NVBLAST_API NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Damage Program
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Damage program params.
-
-Custom user params to be passed in shader functions. This structure hints recommended parameters layout, but it
-doesn't required to be this way.
-
-The idea of this 'hint' is that damage parameters are basically 2 entities: material + damage description.
-1. Material is something that describes an actor properties (e.g. mass, stiffness, fragility) which are not expected to be changed often.
-2. Damage description is something that describes particular damage event (e.g. position, radius and force of explosion).
-
-Also this damage program hints that there could be more than one damage event happening and processed per one shader call (for efficiency reasons).
-So different damage descriptions can be stacked and passed in one shader call (while material is kept the same obviously).
-*/
-struct NvBlastExtProgramParams
-{
- NvBlastExtProgramParams(const void* desc, const void* material_ = nullptr, NvBlastExtDamageAccelerator* accelerator_ = nullptr)
- : damageDesc(desc), material(material_), accelerator(accelerator_) {}
-
- const void* damageDesc; //!< array of damage descriptions
- const void* material; //!< pointer to material
- NvBlastExtDamageAccelerator* accelerator;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Common Material
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-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
-{
- 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;
- }
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Point Radial Damage
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Radial Damage Desc
-*/
-struct NvBlastExtRadialDamageDesc
-{
- 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
-};
-
-/**
-Radial Falloff and Radial Cutter damage for both graph and subgraph shaders.
-
-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 NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Capsule Radial Damage
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Capsule Radial Damage Desc
-*/
-struct NvBlastExtCapsuleRadialDamageDesc
-{
- 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
-};
-
-/**
-Capsule 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 NvBlastExtCapsuleRadialDamageDesc.
-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 NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Shear Damage
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Shear Damage Desc
-*/
-struct NvBlastExtShearDamageDesc
-{
- 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
-};
-
-/**
-Shear Damage Shaders
-
-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 NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Triangle Intersection Damage
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Triangle Intersection Damage Desc
-*/
-struct NvBlastExtTriangleIntersectionDamageDesc
-{
- float damage; //!< normalized damage amount, range: [0, 1] (maximum health value to be reduced)
- NvcVec3 position0; //!< triangle point A position
- NvcVec3 position1; //!< triangle point B position
- NvcVec3 position2; //!< triangle point C position
-};
-
-/**
-Triangle Intersection damage for both graph and subgraph shaders.
-
-Every bond is considered to be a segment connecting two chunk centroids. For every bond (segment) intersection with passed triangle is checked. If intersects
-full damage is applied on bond.
-For subgraph shader segments are formed as connections between it's subchunks centroids. Intersection is check in the same fashion.
-
-The idea is that if you want to cut an object say with the laser sword, you can form a triangle by taking the position of a sword on this timeframe and on previous one.
-So that nothing will be missed in terms of space and time. By sweeping sword through whole object it will be cut in halves inevitably, since all bonds segments form connected graph.
-
-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 NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Impact Spread
-///////////////////////////////////////////////////////////////////////////////
-
-/**
-Impact Spread Damage Desc
-*/
-struct NvBlastExtImpactSpreadDamageDesc
-{
- 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
-};
-
-/**
-Impact Spread Damage Shaders.
-
-It assumes that position is somewhere on the chunk and looks for nearest chunk to this position and damages it.
-Then it does breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph.
-That allows to avoid damaging parts which are near in space but disjointed topologically. For example if you hit one column of an arc
-it would take much bigger radius for damage to travel to the other column than in the simple radial damage.
-
-Shader is designed to be used with impact damage, where it is know in advance that actual hit happened.
-
-This shader requires NvBlastExtDamageAccelerator passed in, it request scratch memory from it, therefore it is also designed to work
-only in single threaded mode. It can easily be changed by passing scratch memory as a part of NvBlastExtProgramParams if required.
-
-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 NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
-NVBLAST_API void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
-
-
-#endif // NVBLASTEXTDAMAGESHADERS_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-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTEXTDAMAGESHADERS_H
+#define NVBLASTEXTDAMAGESHADERS_H
+
+#include "NvBlastTypes.h"
+#include "NvBlastDebugRender.h"
+
+
+/**
+A few example damage shader implementations.
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Damage Accelerator
+///////////////////////////////////////////////////////////////////////////////
+
+class NvBlastExtDamageAccelerator
+{
+public:
+ virtual void release() = 0;
+
+ virtual Nv::Blast::DebugBuffer fillDebugRender(int depth = -1, bool segments = false) = 0;
+};
+
+NVBLAST_API NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Damage Program
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Damage program params.
+
+Custom user params to be passed in shader functions. This structure hints recommended parameters layout, but it
+doesn't required to be this way.
+
+The idea of this 'hint' is that damage parameters are basically 2 entities: material + damage description.
+1. Material is something that describes an actor properties (e.g. mass, stiffness, fragility) which are not expected to be changed often.
+2. Damage description is something that describes particular damage event (e.g. position, radius and force of explosion).
+
+Also this damage program hints that there could be more than one damage event happening and processed per one shader call (for efficiency reasons).
+So different damage descriptions can be stacked and passed in one shader call (while material is kept the same obviously).
+*/
+struct NvBlastExtProgramParams
+{
+ NvBlastExtProgramParams(const void* desc, const void* material_ = nullptr, NvBlastExtDamageAccelerator* accelerator_ = nullptr)
+ : damageDesc(desc), material(material_), accelerator(accelerator_) {}
+
+ const void* damageDesc; //!< array of damage descriptions
+ const void* material; //!< pointer to material
+ NvBlastExtDamageAccelerator* accelerator;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Common Material
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+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
+{
+ 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;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Point Radial Damage
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Radial Damage Desc
+*/
+struct NvBlastExtRadialDamageDesc
+{
+ 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
+};
+
+/**
+Radial Falloff and Radial Cutter damage for both graph and subgraph shaders.
+
+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 NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Capsule Radial Damage
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Capsule Radial Damage Desc
+*/
+struct NvBlastExtCapsuleRadialDamageDesc
+{
+ 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
+};
+
+/**
+Capsule 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 NvBlastExtCapsuleRadialDamageDesc.
+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 NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Shear Damage
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Shear Damage Desc
+*/
+struct NvBlastExtShearDamageDesc
+{
+ 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
+};
+
+/**
+Shear Damage Shaders
+
+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 NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtShearSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Triangle Intersection Damage
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Triangle Intersection Damage Desc
+*/
+struct NvBlastExtTriangleIntersectionDamageDesc
+{
+ float damage; //!< normalized damage amount, range: [0, 1] (maximum health value to be reduced)
+ NvcVec3 position0; //!< triangle point A position
+ NvcVec3 position1; //!< triangle point B position
+ NvcVec3 position2; //!< triangle point C position
+};
+
+/**
+Triangle Intersection damage for both graph and subgraph shaders.
+
+Every bond is considered to be a segment connecting two chunk centroids. For every bond (segment) intersection with passed triangle is checked. If intersects
+full damage is applied on bond.
+For subgraph shader segments are formed as connections between it's subchunks centroids. Intersection is check in the same fashion.
+
+The idea is that if you want to cut an object say with the laser sword, you can form a triangle by taking the position of a sword on this timeframe and on previous one.
+So that nothing will be missed in terms of space and time. By sweeping sword through whole object it will be cut in halves inevitably, since all bonds segments form connected graph.
+
+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 NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Impact Spread
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+Impact Spread Damage Desc
+*/
+struct NvBlastExtImpactSpreadDamageDesc
+{
+ 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
+};
+
+/**
+Impact Spread Damage Shaders.
+
+It assumes that position is somewhere on the chunk and looks for nearest chunk to this position and damages it.
+Then it does breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph.
+That allows to avoid damaging parts which are near in space but disjointed topologically. For example if you hit one column of an arc
+it would take much bigger radius for damage to travel to the other column than in the simple radial damage.
+
+Shader is designed to be used with impact damage, where it is know in advance that actual hit happened.
+
+This shader requires NvBlastExtDamageAccelerator passed in, it request scratch memory from it, therefore it is also designed to work
+only in single threaded mode. It can easily be changed by passing scratch memory as a part of NvBlastExtProgramParams if required.
+
+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 NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params);
+NVBLAST_API void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params);
+
+
+#endif // NVBLASTEXTDAMAGESHADERS_H
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
index 89df930..0f153b7 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.cpp
@@ -1,380 +1,380 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-#include "NvBlastExtDamageAcceleratorAABBTree.h"
-#include "NvBlastIndexFns.h"
-#include "NvBlastAssert.h"
-#include "PxVec4.h"
-#include <algorithm>
-
-using namespace physx;
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Creation
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-ExtDamageAcceleratorAABBTree* ExtDamageAcceleratorAABBTree::create(const NvBlastAsset* asset)
-{
- ExtDamageAcceleratorAABBTree* tree = NVBLAST_NEW(Nv::Blast::ExtDamageAcceleratorAABBTree) ();
- tree->build(asset);
- return tree;
-}
-
-
-void ExtDamageAcceleratorAABBTree::release()
-{
- NVBLAST_DELETE(this, ExtDamageAcceleratorAABBTree);
-}
-
-
-void ExtDamageAcceleratorAABBTree::build(const NvBlastAsset* asset)
-{
- NVBLAST_ASSERT(m_root == nullptr);
-
- const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL);
- const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, logLL);
- const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, logLL);
- const uint32_t N = NvBlastAssetGetBondCount(asset, logLL);
-
- m_indices.resizeUninitialized(N);
- m_points.resizeUninitialized(N);
- m_segments.resizeUninitialized(N);
- m_bonds.resizeUninitialized(N);
- m_nodes.reserve(2 * N);
-
- for (uint32_t node0 = 0; node0 < graph.nodeCount; ++node0)
- {
- for (uint32_t j = graph.adjacencyPartition[node0]; j < graph.adjacencyPartition[node0 + 1]; ++j)
- {
- uint32_t bondIndex = graph.adjacentBondIndices[j];
- uint32_t node1 = graph.adjacentNodeIndices[j];
- if (node0 < node1)
- {
- const NvBlastBond& bond = bonds[bondIndex];
- const PxVec3& p = (reinterpret_cast<const PxVec3&>(bond.centroid));
- m_points[bondIndex] = p;
- m_indices[bondIndex] = bondIndex;
- m_bonds[bondIndex].node0 = node0;
- m_bonds[bondIndex].node1 = node1;
-
- // filling bond segments as a connection of 2 chunk centroids
- const uint32_t chunk0 = graph.chunkIndices[node0];
- const uint32_t chunk1 = graph.chunkIndices[node1];
- if (isInvalidIndex(chunk1))
- {
- // for world node we don't have it's centroid, so approximate with projection on bond normal
- m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
- const PxVec3 normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- m_segments[bondIndex].p1 = m_segments[bondIndex].p0 + normal * (p - m_segments[bondIndex].p0).dot(normal) * 2;
-
- }
- else
- {
- m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
- m_segments[bondIndex].p1 = (reinterpret_cast<const PxVec3&>(chunks[chunk1].centroid));
- }
- }
- }
-
- }
-
- int rootIndex = N > 0 ? createNode(0, N - 1, 0) : -1;
- m_root = rootIndex >= 0 ? &m_nodes[rootIndex] : nullptr;
-}
-
-int ExtDamageAcceleratorAABBTree::createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth)
-{
- if (startIdx > endIdx)
- return -1;
-
- Node node;
- node.first = startIdx;
- node.last = endIdx;
-
- // calc node bounds
- node.pointsBound = PxBounds3::empty();
- node.segmentsBound = PxBounds3::empty();
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- node.pointsBound.include(m_points[idx]);
- node.segmentsBound.include(m_segments[idx].p0);
- node.segmentsBound.include(m_segments[idx].p1);
- }
-
- // select axis of biggest extent
- const PxVec3 ext = node.pointsBound.getExtents();
- uint32_t axis = 0;
- for (uint32_t k = 1; k < 3; k++)
- {
- if (ext[k] > ext[axis])
- {
- axis = k;
- }
- }
-
- // split on selected axis and partially sort around the middle
- const uint32_t mid = startIdx + (endIdx - startIdx) / 2;
- std::nth_element(m_indices.begin() + startIdx, m_indices.begin() + mid, m_indices.begin() + endIdx + 1, [&](uint32_t lhs, uint32_t rhs)
- {
- return m_points[lhs][axis] < m_points[rhs][axis];
- });
-
- const uint32_t BUCKET = 32;
- if (endIdx - startIdx > BUCKET && mid > startIdx && mid < endIdx)
- {
- node.child[0] = createNode(startIdx, mid, depth + 1);
- node.child[1] = createNode(mid + 1, endIdx, depth + 1);
- }
- else
- {
- node.child[0] = -1;
- node.child[1] = -1;
- }
-
- m_nodes.pushBack(node);
-
- return m_nodes.size() - 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Queries
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void ExtDamageAcceleratorAABBTree::findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const
-{
- if (m_root)
- {
- if (segments)
- findSegmentsInBounds(*m_root, callback, bounds);
- else
- findPointsInBounds(*m_root, callback, bounds);
- callback.dispatch();
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
-{
- if (!bounds.intersects(node.pointsBound))
- {
- return;
- }
-
- // if search bound contains node bound, simply add all point indexes.
- if (node.pointsBound.isInside(bounds))
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- pushResult(callback, m_indices[i]);
- return; // early pruning.
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (bounds.contains(m_points[idx]))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findPointsInBounds(m_nodes[node.child[c]], callback, bounds);
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
-{
- if (!bounds.intersects(node.segmentsBound))
- {
- return;
- }
-
- // if search bound contains node bound, simply add all point indexes.
- if (node.segmentsBound.isInside(bounds))
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- pushResult(callback, m_indices[i]);
- return; // early pruning.
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (bounds.contains(m_segments[idx].p0) || bounds.contains(m_segments[idx].p1))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findSegmentsInBounds(m_nodes[node.child[c]], callback, bounds);
- }
-}
-
-bool intersectSegmentPlane(const PxVec3& v1, const PxVec3& v2, const PxPlane& p)
-{
- const bool s1 = p.distance(v1) > 0.f;
- const bool s2 = p.distance(v2) > 0.f;
- return (s1 && !s2) || (s2 && !s1);
-}
-
-bool intersectBoundsPlane(const PxBounds3& b, const PxPlane& p)
-{
- const PxVec3 extents = b.getExtents();
- const PxVec3 center = b.getCenter();
-
- float r = extents.x * PxAbs(p.n.x) + extents.y * PxAbs(p.n.y) + extents.z * PxAbs(p.n.z);
- float s = p.n.dot(center) + p.d;
-
- return PxAbs(s) <= r;
-}
-
-void ExtDamageAcceleratorAABBTree::findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const
-{
- if (m_root)
- {
- findSegmentsPlaneIntersected(*m_root, resultCallback, plane);
- resultCallback.dispatch();
- }
-}
-
-void ExtDamageAcceleratorAABBTree::findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const
-{
- if (!intersectBoundsPlane(node.segmentsBound, plane))
- {
- return;
- }
-
- if (node.child[0] < 0)
- {
- for (uint32_t i = node.first; i <= node.last; i++)
- {
- const uint32_t idx = m_indices[i];
- if (intersectSegmentPlane(m_segments[idx].p0, m_segments[idx].p1, plane))
- pushResult(callback, idx);
- }
-
- return;
- }
-
- // check whether child nodes are in range.
- for (uint32_t c = 0; c < 2; ++c)
- {
- findSegmentsPlaneIntersected(m_nodes[node.child[c]], callback, plane);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Debug Render
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static uint32_t PxVec4ToU32Color(const PxVec4& color)
-{
- uint32_t c = 0;
- c |= (int)(color.w * 255); c <<= 8;
- c |= (int)(color.z * 255); c <<= 8;
- c |= (int)(color.y * 255); c <<= 8;
- c |= (int)(color.x * 255);
- return c;
-}
-
-Nv::Blast::DebugBuffer ExtDamageAcceleratorAABBTree::fillDebugRender(int depth, bool segments)
-{
- Nv::Blast::DebugBuffer debugBuffer = { nullptr, 0 };
-
- m_debugLineBuffer.clear();
-
- if (m_root)
- {
- fillDebugBuffer(*m_root, 0, depth, segments);
- }
-
- debugBuffer.lines = m_debugLineBuffer.begin();
- debugBuffer.lineCount = m_debugLineBuffer.size();
-
- return debugBuffer;
-}
-
-void ExtDamageAcceleratorAABBTree::fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments)
-{
- if (depth < 0 || currentDepth == depth)
- {
- const PxVec4 LEAF_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
- const PxVec4 NON_LEAF_COLOR(0.3f, 0.3f, 0.3f, 1.0f);
-
- // draw box
- const PxBounds3 bounds = segments ? node.segmentsBound : node.pointsBound;
- const PxVec3 center = bounds.getCenter();
- const PxVec3 extents = bounds.getExtents();
-
- const int vs[] = { 0,3,5,6 };
- for (int i = 0; i < 4; i++)
- {
- int v = vs[i];
- for (int d = 1; d < 8; d <<= 1)
- {
- auto flip = [](int x, int k) { return ((x >> k) & 1) * 2.f - 1.f; };
- const float s = std::pow(0.99f, currentDepth);
- PxVec3 p0 = center + s * extents.multiply(PxVec3(flip(v, 0), flip(v, 1), flip(v, 2)));
- PxVec3 p1 = center + s * extents.multiply(PxVec3(flip(v^d, 0), flip(v^d, 1), flip(v^d, 2)));
- m_debugLineBuffer.pushBack(Nv::Blast::DebugLine(
- reinterpret_cast<NvcVec3&>(p0),
- reinterpret_cast<NvcVec3&>(p1),
- PxVec4ToU32Color(LEAF_COLOR * (1.f - (currentDepth + 1) * 0.1f)))
- );
- }
- }
- }
-
- for (uint32_t i = 0; i < 2; ++i)
- {
- if (node.child[i] >= 0)
- {
- fillDebugBuffer(m_nodes[node.child[i]], currentDepth + 1, depth, segments);
- }
- }
-}
-
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+#include "NvBlastExtDamageAcceleratorAABBTree.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastAssert.h"
+#include "PxVec4.h"
+#include <algorithm>
+
+using namespace physx;
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Creation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ExtDamageAcceleratorAABBTree* ExtDamageAcceleratorAABBTree::create(const NvBlastAsset* asset)
+{
+ ExtDamageAcceleratorAABBTree* tree = NVBLAST_NEW(Nv::Blast::ExtDamageAcceleratorAABBTree) ();
+ tree->build(asset);
+ return tree;
+}
+
+
+void ExtDamageAcceleratorAABBTree::release()
+{
+ NVBLAST_DELETE(this, ExtDamageAcceleratorAABBTree);
+}
+
+
+void ExtDamageAcceleratorAABBTree::build(const NvBlastAsset* asset)
+{
+ NVBLAST_ASSERT(m_root == nullptr);
+
+ const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, logLL);
+ const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, logLL);
+ const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, logLL);
+ const uint32_t N = NvBlastAssetGetBondCount(asset, logLL);
+
+ m_indices.resizeUninitialized(N);
+ m_points.resizeUninitialized(N);
+ m_segments.resizeUninitialized(N);
+ m_bonds.resizeUninitialized(N);
+ m_nodes.reserve(2 * N);
+
+ for (uint32_t node0 = 0; node0 < graph.nodeCount; ++node0)
+ {
+ for (uint32_t j = graph.adjacencyPartition[node0]; j < graph.adjacencyPartition[node0 + 1]; ++j)
+ {
+ uint32_t bondIndex = graph.adjacentBondIndices[j];
+ uint32_t node1 = graph.adjacentNodeIndices[j];
+ if (node0 < node1)
+ {
+ const NvBlastBond& bond = bonds[bondIndex];
+ const PxVec3& p = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ m_points[bondIndex] = p;
+ m_indices[bondIndex] = bondIndex;
+ m_bonds[bondIndex].node0 = node0;
+ m_bonds[bondIndex].node1 = node1;
+
+ // filling bond segments as a connection of 2 chunk centroids
+ const uint32_t chunk0 = graph.chunkIndices[node0];
+ const uint32_t chunk1 = graph.chunkIndices[node1];
+ if (isInvalidIndex(chunk1))
+ {
+ // for world node we don't have it's centroid, so approximate with projection on bond normal
+ m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
+ const PxVec3 normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ m_segments[bondIndex].p1 = m_segments[bondIndex].p0 + normal * (p - m_segments[bondIndex].p0).dot(normal) * 2;
+
+ }
+ else
+ {
+ m_segments[bondIndex].p0 = (reinterpret_cast<const PxVec3&>(chunks[chunk0].centroid));
+ m_segments[bondIndex].p1 = (reinterpret_cast<const PxVec3&>(chunks[chunk1].centroid));
+ }
+ }
+ }
+
+ }
+
+ int rootIndex = N > 0 ? createNode(0, N - 1, 0) : -1;
+ m_root = rootIndex >= 0 ? &m_nodes[rootIndex] : nullptr;
+}
+
+int ExtDamageAcceleratorAABBTree::createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth)
+{
+ if (startIdx > endIdx)
+ return -1;
+
+ Node node;
+ node.first = startIdx;
+ node.last = endIdx;
+
+ // calc node bounds
+ node.pointsBound = PxBounds3::empty();
+ node.segmentsBound = PxBounds3::empty();
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ node.pointsBound.include(m_points[idx]);
+ node.segmentsBound.include(m_segments[idx].p0);
+ node.segmentsBound.include(m_segments[idx].p1);
+ }
+
+ // select axis of biggest extent
+ const PxVec3 ext = node.pointsBound.getExtents();
+ uint32_t axis = 0;
+ for (uint32_t k = 1; k < 3; k++)
+ {
+ if (ext[k] > ext[axis])
+ {
+ axis = k;
+ }
+ }
+
+ // split on selected axis and partially sort around the middle
+ const uint32_t mid = startIdx + (endIdx - startIdx) / 2;
+ std::nth_element(m_indices.begin() + startIdx, m_indices.begin() + mid, m_indices.begin() + endIdx + 1, [&](uint32_t lhs, uint32_t rhs)
+ {
+ return m_points[lhs][axis] < m_points[rhs][axis];
+ });
+
+ const uint32_t BUCKET = 32;
+ if (endIdx - startIdx > BUCKET && mid > startIdx && mid < endIdx)
+ {
+ node.child[0] = createNode(startIdx, mid, depth + 1);
+ node.child[1] = createNode(mid + 1, endIdx, depth + 1);
+ }
+ else
+ {
+ node.child[0] = -1;
+ node.child[1] = -1;
+ }
+
+ m_nodes.pushBack(node);
+
+ return m_nodes.size() - 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Queries
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ExtDamageAcceleratorAABBTree::findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const
+{
+ if (m_root)
+ {
+ if (segments)
+ findSegmentsInBounds(*m_root, callback, bounds);
+ else
+ findPointsInBounds(*m_root, callback, bounds);
+ callback.dispatch();
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
+{
+ if (!bounds.intersects(node.pointsBound))
+ {
+ return;
+ }
+
+ // if search bound contains node bound, simply add all point indexes.
+ if (node.pointsBound.isInside(bounds))
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ pushResult(callback, m_indices[i]);
+ return; // early pruning.
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (bounds.contains(m_points[idx]))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findPointsInBounds(m_nodes[node.child[c]], callback, bounds);
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const
+{
+ if (!bounds.intersects(node.segmentsBound))
+ {
+ return;
+ }
+
+ // if search bound contains node bound, simply add all point indexes.
+ if (node.segmentsBound.isInside(bounds))
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ pushResult(callback, m_indices[i]);
+ return; // early pruning.
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (bounds.contains(m_segments[idx].p0) || bounds.contains(m_segments[idx].p1))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findSegmentsInBounds(m_nodes[node.child[c]], callback, bounds);
+ }
+}
+
+bool intersectSegmentPlane(const PxVec3& v1, const PxVec3& v2, const PxPlane& p)
+{
+ const bool s1 = p.distance(v1) > 0.f;
+ const bool s2 = p.distance(v2) > 0.f;
+ return (s1 && !s2) || (s2 && !s1);
+}
+
+bool intersectBoundsPlane(const PxBounds3& b, const PxPlane& p)
+{
+ const PxVec3 extents = b.getExtents();
+ const PxVec3 center = b.getCenter();
+
+ float r = extents.x * PxAbs(p.n.x) + extents.y * PxAbs(p.n.y) + extents.z * PxAbs(p.n.z);
+ float s = p.n.dot(center) + p.d;
+
+ return PxAbs(s) <= r;
+}
+
+void ExtDamageAcceleratorAABBTree::findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const
+{
+ if (m_root)
+ {
+ findSegmentsPlaneIntersected(*m_root, resultCallback, plane);
+ resultCallback.dispatch();
+ }
+}
+
+void ExtDamageAcceleratorAABBTree::findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const
+{
+ if (!intersectBoundsPlane(node.segmentsBound, plane))
+ {
+ return;
+ }
+
+ if (node.child[0] < 0)
+ {
+ for (uint32_t i = node.first; i <= node.last; i++)
+ {
+ const uint32_t idx = m_indices[i];
+ if (intersectSegmentPlane(m_segments[idx].p0, m_segments[idx].p1, plane))
+ pushResult(callback, idx);
+ }
+
+ return;
+ }
+
+ // check whether child nodes are in range.
+ for (uint32_t c = 0; c < 2; ++c)
+ {
+ findSegmentsPlaneIntersected(m_nodes[node.child[c]], callback, plane);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Debug Render
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static uint32_t PxVec4ToU32Color(const PxVec4& color)
+{
+ uint32_t c = 0;
+ c |= (int)(color.w * 255); c <<= 8;
+ c |= (int)(color.z * 255); c <<= 8;
+ c |= (int)(color.y * 255); c <<= 8;
+ c |= (int)(color.x * 255);
+ return c;
+}
+
+Nv::Blast::DebugBuffer ExtDamageAcceleratorAABBTree::fillDebugRender(int depth, bool segments)
+{
+ Nv::Blast::DebugBuffer debugBuffer = { nullptr, 0 };
+
+ m_debugLineBuffer.clear();
+
+ if (m_root)
+ {
+ fillDebugBuffer(*m_root, 0, depth, segments);
+ }
+
+ debugBuffer.lines = m_debugLineBuffer.begin();
+ debugBuffer.lineCount = m_debugLineBuffer.size();
+
+ return debugBuffer;
+}
+
+void ExtDamageAcceleratorAABBTree::fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments)
+{
+ if (depth < 0 || currentDepth == depth)
+ {
+ const PxVec4 LEAF_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
+ const PxVec4 NON_LEAF_COLOR(0.3f, 0.3f, 0.3f, 1.0f);
+
+ // draw box
+ const PxBounds3 bounds = segments ? node.segmentsBound : node.pointsBound;
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 extents = bounds.getExtents();
+
+ const int vs[] = { 0,3,5,6 };
+ for (int i = 0; i < 4; i++)
+ {
+ int v = vs[i];
+ for (int d = 1; d < 8; d <<= 1)
+ {
+ auto flip = [](int x, int k) { return ((x >> k) & 1) * 2.f - 1.f; };
+ const float s = std::pow(0.99f, currentDepth);
+ PxVec3 p0 = center + s * extents.multiply(PxVec3(flip(v, 0), flip(v, 1), flip(v, 2)));
+ PxVec3 p1 = center + s * extents.multiply(PxVec3(flip(v^d, 0), flip(v^d, 1), flip(v^d, 2)));
+ m_debugLineBuffer.pushBack(Nv::Blast::DebugLine(
+ reinterpret_cast<NvcVec3&>(p0),
+ reinterpret_cast<NvcVec3&>(p1),
+ PxVec4ToU32Color(LEAF_COLOR * (1.f - (currentDepth + 1) * 0.1f)))
+ );
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < 2; ++i)
+ {
+ if (node.child[i] >= 0)
+ {
+ fillDebugBuffer(m_nodes[node.child[i]], currentDepth + 1, depth, segments);
+ }
+ }
+}
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
index baded40..505db50 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorAABBTree.h
@@ -1,148 +1,148 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-#pragma once
-
-#include "NvBlastExtDamageAcceleratorInternal.h"
-#include "NvBlast.h"
-#include "NvBlastArray.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-class ExtDamageAcceleratorAABBTree final : public ExtDamageAcceleratorInternal
-{
-public:
- //////// ctor ////////
-
- ExtDamageAcceleratorAABBTree() :
- m_root(nullptr)
- {
- }
-
- virtual ~ExtDamageAcceleratorAABBTree()
- {
- }
-
- static ExtDamageAcceleratorAABBTree* create(const NvBlastAsset* asset);
-
-
- //////// interface ////////
-
- virtual void release() override;
-
- virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
- {
- const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, false);
- }
-
- virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
- {
- const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, true);
-
- }
-
- virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const override;
-
- virtual Nv::Blast::DebugBuffer fillDebugRender(int depth, bool segments) override;
-
- virtual void* getImmediateScratch(size_t size) override
- {
- m_scratch.resizeUninitialized(size);
- return m_scratch.begin();
- }
-
-
-private:
- // no copy/assignment
- ExtDamageAcceleratorAABBTree(ExtDamageAcceleratorAABBTree&);
- ExtDamageAcceleratorAABBTree& operator=(const ExtDamageAcceleratorAABBTree& tree);
-
- // Tree node
- struct Node
- {
- int child[2];
- uint32_t first;
- uint32_t last;
- physx::PxBounds3 pointsBound;
- physx::PxBounds3 segmentsBound;
- };
-
-
- void build(const NvBlastAsset* asset);
-
- int createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth);
-
- void pushResult(ResultCallback& callback, uint32_t pointIndex) const
- {
- callback.push(pointIndex, m_bonds[pointIndex].node0, m_bonds[pointIndex].node1);
- }
-
- void findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const;
-
- void findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
-
- void findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
-
- void findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const;
-
- void fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments);
-
-
- //////// data ////////
-
- Node* m_root;
- Array<Node>::type m_nodes;
- Array<uint32_t>::type m_indices;
-
- Array<physx::PxVec3>::type m_points;
-
- struct Segment
- {
- physx::PxVec3 p0;
- physx::PxVec3 p1;
- };
- Array<Segment>::type m_segments;
-
- struct BondData
- {
- uint32_t node0;
- uint32_t node1;
- };
- Array<BondData>::type m_bonds;
-
- Array<Nv::Blast::DebugLine>::type m_debugLineBuffer;
-
- Array<char>::type m_scratch;
-};
-
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+#pragma once
+
+#include "NvBlastExtDamageAcceleratorInternal.h"
+#include "NvBlast.h"
+#include "NvBlastArray.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+class ExtDamageAcceleratorAABBTree final : public ExtDamageAcceleratorInternal
+{
+public:
+ //////// ctor ////////
+
+ ExtDamageAcceleratorAABBTree() :
+ m_root(nullptr)
+ {
+ }
+
+ virtual ~ExtDamageAcceleratorAABBTree()
+ {
+ }
+
+ static ExtDamageAcceleratorAABBTree* create(const NvBlastAsset* asset);
+
+
+ //////// interface ////////
+
+ virtual void release() override;
+
+ virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
+ {
+ const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, false);
+ }
+
+ virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const override
+ {
+ const_cast<ExtDamageAcceleratorAABBTree*>(this)->findInBounds(bounds, resultCallback, true);
+
+ }
+
+ virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const override;
+
+ virtual Nv::Blast::DebugBuffer fillDebugRender(int depth, bool segments) override;
+
+ virtual void* getImmediateScratch(size_t size) override
+ {
+ m_scratch.resizeUninitialized(size);
+ return m_scratch.begin();
+ }
+
+
+private:
+ // no copy/assignment
+ ExtDamageAcceleratorAABBTree(ExtDamageAcceleratorAABBTree&);
+ ExtDamageAcceleratorAABBTree& operator=(const ExtDamageAcceleratorAABBTree& tree);
+
+ // Tree node
+ struct Node
+ {
+ int child[2];
+ uint32_t first;
+ uint32_t last;
+ physx::PxBounds3 pointsBound;
+ physx::PxBounds3 segmentsBound;
+ };
+
+
+ void build(const NvBlastAsset* asset);
+
+ int createNode(uint32_t startIdx, uint32_t endIdx, uint32_t depth);
+
+ void pushResult(ResultCallback& callback, uint32_t pointIndex) const
+ {
+ callback.push(pointIndex, m_bonds[pointIndex].node0, m_bonds[pointIndex].node1);
+ }
+
+ void findInBounds(const physx::PxBounds3& bounds, ResultCallback& callback, bool segments) const;
+
+ void findPointsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
+
+ void findSegmentsInBounds(const Node& node, ResultCallback& callback, const physx::PxBounds3& bounds) const;
+
+ void findSegmentsPlaneIntersected(const Node& node, ResultCallback& callback, const physx::PxPlane& plane) const;
+
+ void fillDebugBuffer(const Node& node, int currentDepth, int depth, bool segments);
+
+
+ //////// data ////////
+
+ Node* m_root;
+ Array<Node>::type m_nodes;
+ Array<uint32_t>::type m_indices;
+
+ Array<physx::PxVec3>::type m_points;
+
+ struct Segment
+ {
+ physx::PxVec3 p0;
+ physx::PxVec3 p1;
+ };
+ Array<Segment>::type m_segments;
+
+ struct BondData
+ {
+ uint32_t node0;
+ uint32_t node1;
+ };
+ Array<BondData>::type m_bonds;
+
+ Array<Nv::Blast::DebugLine>::type m_debugLineBuffer;
+
+ Array<char>::type m_scratch;
+};
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
index 3879fbc..edd07f5 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAcceleratorInternal.h
@@ -1,96 +1,96 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-#pragma once
-
-#include "NvBlastExtDamageShaders.h"
-#include "PxBounds3.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-
-class ExtDamageAcceleratorInternal : public NvBlastExtDamageAccelerator
-{
-public:
- struct QueryBondData
- {
- uint32_t bond;
- uint32_t node0;
- uint32_t node1;
- };
-
- class ResultCallback
- {
- public:
- ResultCallback(QueryBondData* buffer, uint32_t count) :
- m_bondBuffer(buffer), m_bondMaxCount(count), m_bondCount(0) {}
-
- virtual void processResults(const QueryBondData* bondBuffer, uint32_t count) = 0;
-
- void push(uint32_t bond, uint32_t node0, uint32_t node1)
- {
- m_bondBuffer[m_bondCount].bond = bond;
- m_bondBuffer[m_bondCount].node0 = node0;
- m_bondBuffer[m_bondCount].node1 = node1;
- m_bondCount++;
- if (m_bondCount == m_bondMaxCount)
- {
- dispatch();
- }
- }
-
- void dispatch()
- {
- if (m_bondCount)
- {
- processResults(m_bondBuffer, m_bondCount);
- m_bondCount = 0;
- }
- }
-
- private:
- QueryBondData* m_bondBuffer;
- uint32_t m_bondMaxCount;
-
- uint32_t m_bondCount;
- };
-
- virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
- virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
- virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const = 0;
-
- // Non-thread safe! Multiple calls return the same memory.
- virtual void* getImmediateScratch(size_t size) = 0;
-};
-
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+#pragma once
+
+#include "NvBlastExtDamageShaders.h"
+#include "PxBounds3.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+
+class ExtDamageAcceleratorInternal : public NvBlastExtDamageAccelerator
+{
+public:
+ struct QueryBondData
+ {
+ uint32_t bond;
+ uint32_t node0;
+ uint32_t node1;
+ };
+
+ class ResultCallback
+ {
+ public:
+ ResultCallback(QueryBondData* buffer, uint32_t count) :
+ m_bondBuffer(buffer), m_bondMaxCount(count), m_bondCount(0) {}
+
+ virtual void processResults(const QueryBondData* bondBuffer, uint32_t count) = 0;
+
+ void push(uint32_t bond, uint32_t node0, uint32_t node1)
+ {
+ m_bondBuffer[m_bondCount].bond = bond;
+ m_bondBuffer[m_bondCount].node0 = node0;
+ m_bondBuffer[m_bondCount].node1 = node1;
+ m_bondCount++;
+ if (m_bondCount == m_bondMaxCount)
+ {
+ dispatch();
+ }
+ }
+
+ void dispatch()
+ {
+ if (m_bondCount)
+ {
+ processResults(m_bondBuffer, m_bondCount);
+ m_bondCount = 0;
+ }
+ }
+
+ private:
+ QueryBondData* m_bondBuffer;
+ uint32_t m_bondMaxCount;
+
+ uint32_t m_bondCount;
+ };
+
+ virtual void findBondCentroidsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
+ virtual void findBondSegmentsInBounds(const physx::PxBounds3& bounds, ResultCallback& resultCallback) const = 0;
+ virtual void findBondSegmentsPlaneIntersected(const physx::PxPlane& plane, ResultCallback& resultCallback) const = 0;
+
+ // Non-thread safe! Multiple calls return the same memory.
+ virtual void* getImmediateScratch(size_t size) = 0;
+};
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
index 381f5e3..d2e563f 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageAccelerators.cpp
@@ -1,43 +1,43 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-//#include "NvBlastExtDamageAcceleratorOctree.h"
-//#include "NvBlastExtDamageAcceleratorKdtree.h"
-#include "NvBlastExtDamageAcceleratorAABBTree.h"
-
-NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type)
-{
- switch (type)
- {
- case 0:
- return nullptr;
- default:
- return Nv::Blast::ExtDamageAcceleratorAABBTree::create(asset);
- break;
- }
-}
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+//#include "NvBlastExtDamageAcceleratorOctree.h"
+//#include "NvBlastExtDamageAcceleratorKdtree.h"
+#include "NvBlastExtDamageAcceleratorAABBTree.h"
+
+NvBlastExtDamageAccelerator* NvBlastExtDamageAcceleratorCreate(const NvBlastAsset* asset, int type)
+{
+ switch (type)
+ {
+ case 0:
+ return nullptr;
+ default:
+ return Nv::Blast::ExtDamageAcceleratorAABBTree::create(asset);
+ break;
+ }
+}
diff --git a/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
index cddf8e5..6d9edd2 100644..100755
--- a/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
+++ b/sdk/extensions/shaders/source/NvBlastExtDamageShaders.cpp
@@ -1,763 +1,763 @@
-// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastExtDamageShaders.h"
-#include "NvBlastExtDamageAcceleratorInternal.h"
-#include "NvBlastIndexFns.h"
-#include "NvBlastMath.h"
-#include "NvBlastGeometry.h"
-#include "NvBlastAssert.h"
-#include "NvBlastFixedQueue.h"
-#include "NvBlastFixedBitmap.h"
-#include "NvBlast.h"
-#include <cmath> // for abs() on linux
-#include <new>
-
-
-using namespace Nv::Blast;
-using namespace Nv::Blast::VecMath;
-using namespace physx;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// 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);
-
-template <ProfileFunction profileFn, typename DescT = NvBlastExtRadialDamageDesc>
-float pointDistanceDamage(const float pos[3], const void* damageDescBuffer)
-{
- const DescT& desc = *static_cast<const DescT*>(damageDescBuffer);
-
- 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 capsuleDistanceDamage(const float pos[3], const void* damageDesc)
-{
- const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
-
- const float distance = distanceToSegment(pos, desc.position0, desc.position1);
- const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
- return damage;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// AABB Functions
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef PxBounds3(*BoundFunction)(const void* damageDesc);
-
-PxBounds3 sphereBounds(const void* damageDesc)
-{
- const NvBlastExtRadialDamageDesc& desc = *static_cast<const NvBlastExtRadialDamageDesc*>(damageDesc);
- const physx::PxVec3& p = (reinterpret_cast<const physx::PxVec3&>(desc.position));
- return physx::PxBounds3::centerExtents(p, physx::PxVec3(desc.maxRadius, desc.maxRadius, desc.maxRadius));
-}
-
-PxBounds3 capsuleBounds(const void* damageDesc)
-{
- const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
- const physx::PxVec3& p0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& p1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- PxBounds3 b = PxBounds3::empty();
- b.include(p0);
- b.include(p1);
- b.fattenFast(desc.maxRadius);
- return b;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Radial Graph Shader Template
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <DamageFunction damageFn, BoundFunction boundsFn>
-void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* 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 NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
-
- uint32_t outCount = 0;
-
- auto processBondFn = [&](uint32_t bondIndex, uint32_t node0, uint32_t node1)
- {
- // 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];
-
- const float totalBondDamage = damageFn(bond.centroid, programParams->damageDesc);
- if (totalBondDamage > 0.0f)
- {
- NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
- outCommand.nodeIndex0 = node0;
- outCommand.nodeIndex1 = node1;
- outCommand.health = totalBondDamage;
- }
- }
- };
-
- const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
- if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
- {
- physx::PxBounds3 bounds = boundsFn(programParams->damageDesc);
-
- const uint32_t CALLBACK_BUFFER_SIZE = 1000;
-
- class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
- {
- public:
- AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtProgramParams* programParams) :
- ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
- m_actor(actor),
- m_commandBuffers(commandBuffers),
- m_outCount(outCount),
- m_programParams(programParams)
- {
- }
-
- virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
- {
- for (uint32_t i = 0; i < count; i++)
- {
- const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
- if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
- {
- if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
- {
- const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
-
- const float totalBondDamage = damageFn(bond.centroid, m_programParams->damageDesc);
- if (totalBondDamage > 0.0f)
- {
- NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
- outCommand.nodeIndex0 = bondData.node0;
- outCommand.nodeIndex1 = bondData.node1;
- outCommand.health = totalBondDamage;
- }
- }
- }
- }
- }
-
- private:
- const NvBlastGraphShaderActor* m_actor;
- NvBlastFractureBuffers* m_commandBuffers;
- uint32_t& m_outCount;
- const NvBlastExtProgramParams* m_programParams;
-
- ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
- };
-
- AcceleratorCallback cb(commandBuffers, outCount, actor, programParams);
-
- damageAccelerator->findBondCentroidsInBounds(bounds, cb);
- }
- else
- {
- 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];
- processBondFn(bondIndex, currentNodeIndex, adjacentNodeIndex);
- }
- }
- currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
- }
- }
-
- commandBuffers->bondFractureCount = outCount;
- commandBuffers->chunkFractureCount = 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Radial Single Shader Template
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <DamageFunction damageFn>
-void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* 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];
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
-
- const float totalDamage = damageFn(chunk.centroid, programParams->damageDesc);
- 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 void* params)
-{
- RadialProfileGraphShader<pointDistanceDamage<falloffProfile>, sphereBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- RadialProfileGraphShader<pointDistanceDamage<cutterProfile>, sphereBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- RadialProfileGraphShader<capsuleDistanceDamage<falloffProfile>, capsuleBounds>(commandBuffers, actor, params);
-}
-
-void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- RadialProfileSubgraphShader<capsuleDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Shear Shader
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- uint32_t bondFractureCount = 0;
- uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtShearDamageDesc& desc = *static_cast<const NvBlastExtShearDamageDesc*>(programParams->damageDesc);
- 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, programParams->damageDesc);
- }
-
- 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, programParams->damageDesc);
- 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 void* params)
-{
- RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>>(commandBuffers, actor, params);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Triangle Intersection Damage
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#define SMALL_NUMBER (1.e-4f)
-
-bool intersectSegmentTriangle(const PxVec3& p, const PxVec3& q, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxPlane& trianglePlane)
-{
- const PxVec3 N = trianglePlane.n;
- const float D = trianglePlane.d;
-
- PxVec3 intersectPoint;
- float t = (-D - (p.dot(N))) / ((q - p).dot(N));
- // If the parameter value is not between 0 and 1, there is no intersection
- if (t > -SMALL_NUMBER && t < 1.f + SMALL_NUMBER)
- {
- intersectPoint = p + t * (q - p);
- }
- else
- {
- return false;
- }
-
- // Compute the normal of the triangle
- const PxVec3 TriNorm = (b - a).cross(c - a);
-
- // Compute twice area of triangle ABC
- const float AreaABCInv = 1.0f / (N.dot(TriNorm));
-
- // Compute v contribution
- const float AreaPBC = N.dot((b - intersectPoint).cross(c - intersectPoint));
- const float v = AreaPBC * AreaABCInv;
- if (v <= 0.f)
- return false;
-
- // Compute w contribution
- const float AreaPCA = N.dot((c - intersectPoint).cross(a - intersectPoint));
- const float w = AreaPCA * AreaABCInv;
- if (w <= 0.f)
- return false;
-
- const float u = 1.0f - v - w;
- return u > 0.f;
-}
-
-void NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* 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 NvBlastChunk* assetChunks = actor->assetChunks;
- const uint32_t* chunkIndices = actor->chunkIndices;
- const float* familyBondHealths = actor->familyBondHealths;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- uint32_t outCount = 0;
-
- const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
- if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
- {
- const uint32_t CALLBACK_BUFFER_SIZE = 1000;
-
- class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
- {
- public:
- AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtTriangleIntersectionDamageDesc& desc) :
- ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
- m_actor(actor),
- m_commandBuffers(commandBuffers),
- m_outCount(outCount),
- m_desc(desc)
- {
- }
-
- virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
- {
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- for (uint32_t i = 0; i < count; i++)
- {
- const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
- if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
- {
- if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
- {
- const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
- const uint32_t chunkIndex0 = m_actor->chunkIndices[bondData.node0];
- const uint32_t chunkIndex1 = m_actor->chunkIndices[bondData.node1];
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex0].centroid));
- const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
- const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
- (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex1].centroid));
-
- if(intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
- outCommand.nodeIndex0 = bondData.node0;
- outCommand.nodeIndex1 = bondData.node1;
- outCommand.health = m_desc.damage;
- }
- }
- }
- }
- }
-
- private:
- const NvBlastGraphShaderActor* m_actor;
- NvBlastFractureBuffers* m_commandBuffers;
- uint32_t& m_outCount;
- const NvBlastExtTriangleIntersectionDamageDesc& m_desc;
-
- ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
- };
-
- AcceleratorCallback cb(commandBuffers, outCount, actor, desc);
-
- damageAccelerator->findBondSegmentsPlaneIntersected(trianglePlane, cb);
- }
- else
- {
- 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];
- const uint32_t chunkIndex0 = chunkIndices[currentNodeIndex];
- const uint32_t chunkIndex1 = chunkIndices[adjacentNodeIndex];
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid));
- const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
- const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
- (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
-
- if (intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
- outCommand.nodeIndex0 = currentNodeIndex;
- outCommand.nodeIndex1 = adjacentNodeIndex;
- outCommand.health = desc.damage;
- }
- }
- }
- }
- currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
- }
- }
-
- commandBuffers->bondFractureCount = outCount;
- commandBuffers->chunkFractureCount = 0;
-}
-
-void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* 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];
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
- const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
- const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
- const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
- const PxPlane trianglePlane(t0, t1, t2);
-
- for (uint32_t subChunkIndex = chunk.firstChildIndex; subChunkIndex < chunk.childIndexStop; subChunkIndex++)
- {
- const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex].centroid));
- const physx::PxVec3& c1 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex + 1].centroid));
- if (chunkFractureCount < chunkFractureCountMax && intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
- {
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- break;
- }
- }
-
- commandBuffers->bondFractureCount = 0;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Impact Spread Shader
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- uint32_t bondFractureCount = 0;
- uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
- 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;
-
- // Find nearest chunk.
- uint32_t closestNode = findClosestNode(desc.position
- , firstGraphNodeIndex, graphNodeIndexLinks
- , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
- , assetBonds, familyBondHealths
- , assetChunks, supportChunkHealths, chunkIndices);
-
- uint32_t nodeIndex = closestNode;
-
- // Damage this chunk
- if (chunkFractureCount < chunkFractureCountMax)
- {
- const uint32_t chunkIndex = chunkIndices[nodeIndex];
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- }
-
- // Breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph
- ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
- NVBLAST_ASSERT_WITH_MESSAGE(damageAccelerator, "This shader requires damage accelerator passed");
- if (damageAccelerator)
- {
- struct NodeData
- {
- uint32_t index;
- float distance;
- };
-
- // Calculating scratch size and requesting it from the accelerator
- const uint32_t bondCount = actor->adjacencyPartition[actor->assetNodeCount];
- const size_t nodeQueueSize = align16(FixedQueue<NodeData>::requiredMemorySize(actor->graphNodeCount));
- const size_t visitedBitmapSize = align16(FixedBitmap::requiredMemorySize(bondCount));
- const size_t scratchSize = 16 + nodeQueueSize + visitedBitmapSize;
-
- void* scratch = damageAccelerator->getImmediateScratch(scratchSize);
-
- // prepare intermediate data on scratch
- scratch = (void*)align16((size_t)scratch); // Bump to 16-byte alignment
- FixedQueue<NodeData>* nodeQueue = new (scratch)FixedQueue<NodeData>(actor->graphNodeCount);
- scratch = pointerOffset(scratch, align16(nodeQueueSize));
- FixedBitmap* visitedBitmap = new (scratch)FixedBitmap(bondCount);
- scratch = pointerOffset(scratch, align16(FixedBitmap::requiredMemorySize(bondCount)));
-
- // initalize traversal
- nodeQueue->pushBack({ nodeIndex, 0.f });
- visitedBitmap->clear();
-
- while (!nodeQueue->empty())
- {
- NodeData currentNode = nodeQueue->popFront();
- const uint32_t startIndex = adjacencyPartition[currentNode.index];
- const uint32_t stopIndex = adjacencyPartition[currentNode.index + 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];
-
- const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
-
- if (!(familyBondHealths[bondIndex] > 0.0f))
- continue;
-
- if (visitedBitmap->test(bondIndex))
- continue;
- visitedBitmap->set(bondIndex);
-
- const uint32_t chunkIndex0 = chunkIndices[currentNode.index];
- const uint32_t chunkIndex1 = chunkIndices[neighbourIndex];
- const physx::PxVec3& c0 = reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid);
- bool isNeighbourWorldChunk = isInvalidIndex(chunkIndex1);
- const physx::PxVec3& c1 = isNeighbourWorldChunk ? bondCentroid : (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
-
- const float distance = (c1 - c0).magnitude() * (isNeighbourWorldChunk ? 2.f : 1.f);
- float totalDistance = currentNode.distance + distance;
- float totalDamage = falloffProfile(desc.minRadius, desc.maxRadius, totalDistance);
- if (totalDamage > 0.0f && bondFractureCount < bondFractureCountMax)
- {
- NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
- frac.userdata = bond.userData;
- frac.nodeIndex0 = currentNode.index;
- frac.nodeIndex1 = neighbourIndex;
- frac.health = totalDamage;
- if (!isNeighbourWorldChunk)
- {
- nodeQueue->pushBack({ neighbourIndex, totalDistance });
- }
- }
- }
- }
- }
-
- commandBuffers->bondFractureCount = bondFractureCount;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
-
-void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
-{
- uint32_t chunkFractureCount = 0;
- uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
- const uint32_t chunkIndex = actor->chunkIndex;
- const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
- const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
-
- if (chunkFractureCount < chunkFractureCountMax)
- {
- NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
- frac.chunkIndex = chunkIndex;
- frac.health = desc.damage;
- }
-
- commandBuffers->bondFractureCount = 0;
- commandBuffers->chunkFractureCount = chunkFractureCount;
-}
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastExtDamageShaders.h"
+#include "NvBlastExtDamageAcceleratorInternal.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlastMath.h"
+#include "NvBlastGeometry.h"
+#include "NvBlastAssert.h"
+#include "NvBlastFixedQueue.h"
+#include "NvBlastFixedBitmap.h"
+#include "NvBlast.h"
+#include <cmath> // for abs() on linux
+#include <new>
+
+
+using namespace Nv::Blast;
+using namespace Nv::Blast::VecMath;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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);
+
+template <ProfileFunction profileFn, typename DescT = NvBlastExtRadialDamageDesc>
+float pointDistanceDamage(const float pos[3], const void* damageDescBuffer)
+{
+ const DescT& desc = *static_cast<const DescT*>(damageDescBuffer);
+
+ 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 capsuleDistanceDamage(const float pos[3], const void* damageDesc)
+{
+ const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
+
+ const float distance = distanceToSegment(pos, desc.position0, desc.position1);
+ const float damage = profileFn(desc.minRadius, desc.maxRadius, distance, desc.damage);
+ return damage;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// AABB Functions
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef PxBounds3(*BoundFunction)(const void* damageDesc);
+
+PxBounds3 sphereBounds(const void* damageDesc)
+{
+ const NvBlastExtRadialDamageDesc& desc = *static_cast<const NvBlastExtRadialDamageDesc*>(damageDesc);
+ const physx::PxVec3& p = (reinterpret_cast<const physx::PxVec3&>(desc.position));
+ return physx::PxBounds3::centerExtents(p, physx::PxVec3(desc.maxRadius, desc.maxRadius, desc.maxRadius));
+}
+
+PxBounds3 capsuleBounds(const void* damageDesc)
+{
+ const NvBlastExtCapsuleRadialDamageDesc& desc = *static_cast<const NvBlastExtCapsuleRadialDamageDesc*>(damageDesc);
+ const physx::PxVec3& p0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& p1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ PxBounds3 b = PxBounds3::empty();
+ b.include(p0);
+ b.include(p1);
+ b.fattenFast(desc.maxRadius);
+ return b;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Radial Graph Shader Template
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DamageFunction damageFn, BoundFunction boundsFn>
+void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* 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 NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+
+ uint32_t outCount = 0;
+
+ auto processBondFn = [&](uint32_t bondIndex, uint32_t node0, uint32_t node1)
+ {
+ // 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];
+
+ const float totalBondDamage = damageFn(bond.centroid, programParams->damageDesc);
+ if (totalBondDamage > 0.0f)
+ {
+ NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
+ outCommand.nodeIndex0 = node0;
+ outCommand.nodeIndex1 = node1;
+ outCommand.health = totalBondDamage;
+ }
+ }
+ };
+
+ const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
+ if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
+ {
+ physx::PxBounds3 bounds = boundsFn(programParams->damageDesc);
+
+ const uint32_t CALLBACK_BUFFER_SIZE = 1000;
+
+ class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
+ {
+ public:
+ AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtProgramParams* programParams) :
+ ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
+ m_actor(actor),
+ m_commandBuffers(commandBuffers),
+ m_outCount(outCount),
+ m_programParams(programParams)
+ {
+ }
+
+ virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
+ {
+ for (uint32_t i = 0; i < count; i++)
+ {
+ const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
+ if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
+ {
+ if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
+ {
+ const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
+
+ const float totalBondDamage = damageFn(bond.centroid, m_programParams->damageDesc);
+ if (totalBondDamage > 0.0f)
+ {
+ NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
+ outCommand.nodeIndex0 = bondData.node0;
+ outCommand.nodeIndex1 = bondData.node1;
+ outCommand.health = totalBondDamage;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ const NvBlastGraphShaderActor* m_actor;
+ NvBlastFractureBuffers* m_commandBuffers;
+ uint32_t& m_outCount;
+ const NvBlastExtProgramParams* m_programParams;
+
+ ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
+ };
+
+ AcceleratorCallback cb(commandBuffers, outCount, actor, programParams);
+
+ damageAccelerator->findBondCentroidsInBounds(bounds, cb);
+ }
+ else
+ {
+ 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];
+ processBondFn(bondIndex, currentNodeIndex, adjacentNodeIndex);
+ }
+ }
+ currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
+ }
+ }
+
+ commandBuffers->bondFractureCount = outCount;
+ commandBuffers->chunkFractureCount = 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Radial Single Shader Template
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DamageFunction damageFn>
+void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* 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];
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+
+ const float totalDamage = damageFn(chunk.centroid, programParams->damageDesc);
+ 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 void* params)
+{
+ RadialProfileGraphShader<pointDistanceDamage<falloffProfile>, sphereBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ RadialProfileGraphShader<pointDistanceDamage<cutterProfile>, sphereBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<cutterProfile>>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCapsuleFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ RadialProfileGraphShader<capsuleDistanceDamage<falloffProfile>, capsuleBounds>(commandBuffers, actor, params);
+}
+
+void NvBlastExtCapsuleFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ RadialProfileSubgraphShader<capsuleDistanceDamage<falloffProfile>>(commandBuffers, actor, params);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Shear Shader
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void NvBlastExtShearGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ uint32_t bondFractureCount = 0;
+ uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtShearDamageDesc& desc = *static_cast<const NvBlastExtShearDamageDesc*>(programParams->damageDesc);
+ 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, programParams->damageDesc);
+ }
+
+ 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, programParams->damageDesc);
+ 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 void* params)
+{
+ RadialProfileSubgraphShader<pointDistanceDamage<falloffProfile, NvBlastExtShearDamageDesc>>(commandBuffers, actor, params);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Triangle Intersection Damage
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define SMALL_NUMBER (1.e-4f)
+
+bool intersectSegmentTriangle(const PxVec3& p, const PxVec3& q, const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxPlane& trianglePlane)
+{
+ const PxVec3 N = trianglePlane.n;
+ const float D = trianglePlane.d;
+
+ PxVec3 intersectPoint;
+ float t = (-D - (p.dot(N))) / ((q - p).dot(N));
+ // If the parameter value is not between 0 and 1, there is no intersection
+ if (t > -SMALL_NUMBER && t < 1.f + SMALL_NUMBER)
+ {
+ intersectPoint = p + t * (q - p);
+ }
+ else
+ {
+ return false;
+ }
+
+ // Compute the normal of the triangle
+ const PxVec3 TriNorm = (b - a).cross(c - a);
+
+ // Compute twice area of triangle ABC
+ const float AreaABCInv = 1.0f / (N.dot(TriNorm));
+
+ // Compute v contribution
+ const float AreaPBC = N.dot((b - intersectPoint).cross(c - intersectPoint));
+ const float v = AreaPBC * AreaABCInv;
+ if (v <= 0.f)
+ return false;
+
+ // Compute w contribution
+ const float AreaPCA = N.dot((c - intersectPoint).cross(a - intersectPoint));
+ const float w = AreaPCA * AreaABCInv;
+ if (w <= 0.f)
+ return false;
+
+ const float u = 1.0f - v - w;
+ return u > 0.f;
+}
+
+void NvBlastExtTriangleIntersectionGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* 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 NvBlastChunk* assetChunks = actor->assetChunks;
+ const uint32_t* chunkIndices = actor->chunkIndices;
+ const float* familyBondHealths = actor->familyBondHealths;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ uint32_t outCount = 0;
+
+ const ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<const ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ const uint32_t ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE = actor->assetNodeCount / 3;
+ if (damageAccelerator && actor->graphNodeCount > ACTOR_MINIMUM_NODE_COUNT_TO_ACCELERATE)
+ {
+ const uint32_t CALLBACK_BUFFER_SIZE = 1000;
+
+ class AcceleratorCallback : public ExtDamageAcceleratorInternal::ResultCallback
+ {
+ public:
+ AcceleratorCallback(NvBlastFractureBuffers* commandBuffers, uint32_t& outCount, const NvBlastGraphShaderActor* actor, const NvBlastExtTriangleIntersectionDamageDesc& desc) :
+ ExtDamageAcceleratorInternal::ResultCallback(m_buffer, CALLBACK_BUFFER_SIZE),
+ m_actor(actor),
+ m_commandBuffers(commandBuffers),
+ m_outCount(outCount),
+ m_desc(desc)
+ {
+ }
+
+ virtual void processResults(const ExtDamageAcceleratorInternal::QueryBondData* bondBuffer, uint32_t count) override
+ {
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(m_desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ for (uint32_t i = 0; i < count; i++)
+ {
+ const ExtDamageAcceleratorInternal::QueryBondData& bondData = bondBuffer[i];
+ if (m_actor->nodeActorIndices[bondData.node0] == m_actor->actorIndex)
+ {
+ if ((m_actor->familyBondHealths[bondData.bond] > 0.0f))
+ {
+ const NvBlastBond& bond = m_actor->assetBonds[bondData.bond];
+ const uint32_t chunkIndex0 = m_actor->chunkIndices[bondData.node0];
+ const uint32_t chunkIndex1 = m_actor->chunkIndices[bondData.node1];
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex0].centroid));
+ const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
+ (reinterpret_cast<const physx::PxVec3&>(m_actor->assetChunks[chunkIndex1].centroid));
+
+ if(intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastBondFractureData& outCommand = m_commandBuffers->bondFractures[m_outCount++];
+ outCommand.nodeIndex0 = bondData.node0;
+ outCommand.nodeIndex1 = bondData.node1;
+ outCommand.health = m_desc.damage;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ const NvBlastGraphShaderActor* m_actor;
+ NvBlastFractureBuffers* m_commandBuffers;
+ uint32_t& m_outCount;
+ const NvBlastExtTriangleIntersectionDamageDesc& m_desc;
+
+ ExtDamageAcceleratorInternal::QueryBondData m_buffer[CALLBACK_BUFFER_SIZE];
+ };
+
+ AcceleratorCallback cb(commandBuffers, outCount, actor, desc);
+
+ damageAccelerator->findBondSegmentsPlaneIntersected(trianglePlane, cb);
+ }
+ else
+ {
+ 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];
+ const uint32_t chunkIndex0 = chunkIndices[currentNodeIndex];
+ const uint32_t chunkIndex1 = chunkIndices[adjacentNodeIndex];
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid));
+ const PxVec3& normal = (reinterpret_cast<const PxVec3&>(bond.normal));
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+ const physx::PxVec3& c1 = isInvalidIndex(chunkIndex1) ? (c0 + normal * (bondCentroid - c0).dot(normal)) :
+ (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
+
+ if (intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++];
+ outCommand.nodeIndex0 = currentNodeIndex;
+ outCommand.nodeIndex1 = adjacentNodeIndex;
+ outCommand.health = desc.damage;
+ }
+ }
+ }
+ }
+ currentNodeIndex = graphNodeIndexLinks[currentNodeIndex];
+ }
+ }
+
+ commandBuffers->bondFractureCount = outCount;
+ commandBuffers->chunkFractureCount = 0;
+}
+
+void NvBlastExtTriangleIntersectionSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* 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];
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtTriangleIntersectionDamageDesc& desc = *static_cast<const NvBlastExtTriangleIntersectionDamageDesc*>(programParams->damageDesc);
+ const physx::PxVec3& t0 = (reinterpret_cast<const physx::PxVec3&>(desc.position0));
+ const physx::PxVec3& t1 = (reinterpret_cast<const physx::PxVec3&>(desc.position1));
+ const physx::PxVec3& t2 = (reinterpret_cast<const physx::PxVec3&>(desc.position2));
+ const PxPlane trianglePlane(t0, t1, t2);
+
+ for (uint32_t subChunkIndex = chunk.firstChildIndex; subChunkIndex < chunk.childIndexStop; subChunkIndex++)
+ {
+ const physx::PxVec3& c0 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex].centroid));
+ const physx::PxVec3& c1 = (reinterpret_cast<const physx::PxVec3&>(assetChunks[subChunkIndex + 1].centroid));
+ if (chunkFractureCount < chunkFractureCountMax && intersectSegmentTriangle(c0, c1, t0, t1, t2, trianglePlane))
+ {
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ break;
+ }
+ }
+
+ commandBuffers->bondFractureCount = 0;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Impact Spread Shader
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void NvBlastExtImpactSpreadGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ uint32_t bondFractureCount = 0;
+ uint32_t bondFractureCountMax = commandBuffers->bondFractureCount;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
+ 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;
+
+ // Find nearest chunk.
+ uint32_t closestNode = findClosestNode(desc.position
+ , firstGraphNodeIndex, graphNodeIndexLinks
+ , adjacencyPartition, adjacentNodeIndices, adjacentBondIndices
+ , assetBonds, familyBondHealths
+ , assetChunks, supportChunkHealths, chunkIndices);
+
+ uint32_t nodeIndex = closestNode;
+
+ // Damage this chunk
+ if (chunkFractureCount < chunkFractureCountMax)
+ {
+ const uint32_t chunkIndex = chunkIndices[nodeIndex];
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ }
+
+ // Breadth-first support graph traversal. For radial falloff metric distance is measured along the edges of the graph
+ ExtDamageAcceleratorInternal* damageAccelerator = programParams->accelerator ? static_cast<ExtDamageAcceleratorInternal*>(programParams->accelerator) : nullptr;
+ NVBLAST_ASSERT_WITH_MESSAGE(damageAccelerator, "This shader requires damage accelerator passed");
+ if (damageAccelerator)
+ {
+ struct NodeData
+ {
+ uint32_t index;
+ float distance;
+ };
+
+ // Calculating scratch size and requesting it from the accelerator
+ const uint32_t bondCount = actor->adjacencyPartition[actor->assetNodeCount];
+ const size_t nodeQueueSize = align16(FixedQueue<NodeData>::requiredMemorySize(actor->graphNodeCount));
+ const size_t visitedBitmapSize = align16(FixedBitmap::requiredMemorySize(bondCount));
+ const size_t scratchSize = 16 + nodeQueueSize + visitedBitmapSize;
+
+ void* scratch = damageAccelerator->getImmediateScratch(scratchSize);
+
+ // prepare intermediate data on scratch
+ scratch = (void*)align16((size_t)scratch); // Bump to 16-byte alignment
+ FixedQueue<NodeData>* nodeQueue = new (scratch)FixedQueue<NodeData>(actor->graphNodeCount);
+ scratch = pointerOffset(scratch, align16(nodeQueueSize));
+ FixedBitmap* visitedBitmap = new (scratch)FixedBitmap(bondCount);
+ scratch = pointerOffset(scratch, align16(FixedBitmap::requiredMemorySize(bondCount)));
+
+ // initalize traversal
+ nodeQueue->pushBack({ nodeIndex, 0.f });
+ visitedBitmap->clear();
+
+ while (!nodeQueue->empty())
+ {
+ NodeData currentNode = nodeQueue->popFront();
+ const uint32_t startIndex = adjacencyPartition[currentNode.index];
+ const uint32_t stopIndex = adjacencyPartition[currentNode.index + 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];
+
+ const PxVec3& bondCentroid = (reinterpret_cast<const PxVec3&>(bond.centroid));
+
+ if (!(familyBondHealths[bondIndex] > 0.0f))
+ continue;
+
+ if (visitedBitmap->test(bondIndex))
+ continue;
+ visitedBitmap->set(bondIndex);
+
+ const uint32_t chunkIndex0 = chunkIndices[currentNode.index];
+ const uint32_t chunkIndex1 = chunkIndices[neighbourIndex];
+ const physx::PxVec3& c0 = reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex0].centroid);
+ bool isNeighbourWorldChunk = isInvalidIndex(chunkIndex1);
+ const physx::PxVec3& c1 = isNeighbourWorldChunk ? bondCentroid : (reinterpret_cast<const physx::PxVec3&>(assetChunks[chunkIndex1].centroid));
+
+ const float distance = (c1 - c0).magnitude() * (isNeighbourWorldChunk ? 2.f : 1.f);
+ float totalDistance = currentNode.distance + distance;
+ float totalDamage = falloffProfile(desc.minRadius, desc.maxRadius, totalDistance);
+ if (totalDamage > 0.0f && bondFractureCount < bondFractureCountMax)
+ {
+ NvBlastBondFractureData& frac = commandBuffers->bondFractures[bondFractureCount++];
+ frac.userdata = bond.userData;
+ frac.nodeIndex0 = currentNode.index;
+ frac.nodeIndex1 = neighbourIndex;
+ frac.health = totalDamage;
+ if (!isNeighbourWorldChunk)
+ {
+ nodeQueue->pushBack({ neighbourIndex, totalDistance });
+ }
+ }
+ }
+ }
+ }
+
+ commandBuffers->bondFractureCount = bondFractureCount;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}
+
+void NvBlastExtImpactSpreadSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const void* params)
+{
+ uint32_t chunkFractureCount = 0;
+ uint32_t chunkFractureCountMax = commandBuffers->chunkFractureCount;
+ const uint32_t chunkIndex = actor->chunkIndex;
+ const NvBlastExtProgramParams* programParams = static_cast<const NvBlastExtProgramParams*>(params);
+ const NvBlastExtImpactSpreadDamageDesc& desc = *static_cast<const NvBlastExtImpactSpreadDamageDesc*>(programParams->damageDesc);
+
+ if (chunkFractureCount < chunkFractureCountMax)
+ {
+ NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++];
+ frac.chunkIndex = chunkIndex;
+ frac.health = desc.damage;
+ }
+
+ commandBuffers->bondFractureCount = 0;
+ commandBuffers->chunkFractureCount = chunkFractureCount;
+}