aboutsummaryrefslogtreecommitdiff
path: root/docs/_source
diff options
context:
space:
mode:
authorAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
committerAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
commit236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch)
treee486f2fa39dba203563895541e92c60ed3e25759 /docs/_source
parentAdded screens to welcome page (diff)
downloadblast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz
blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'docs/_source')
-rw-r--r--docs/_source/api_ext_users_guide.txt33
-rw-r--r--docs/_source/api_globals_users_guide.txt94
-rw-r--r--docs/_source/api_hl_users_guide.txt116
-rw-r--r--docs/_source/api_ll_users_guide.txt142
-rw-r--r--docs/_source/api_users_guide.txt2
-rw-r--r--docs/_source/copyrights.txt31
-rw-r--r--docs/_source/data_converter.txt42
-rw-r--r--docs/_source/ext_assetutils.txt94
-rw-r--r--docs/_source/ext_authoring.txt45
-rw-r--r--docs/_source/ext_converterll.txt38
-rw-r--r--docs/_source/ext_exporter.txt35
-rw-r--r--docs/_source/ext_import.txt6
-rw-r--r--docs/_source/ext_physx.txt95
-rw-r--r--docs/_source/ext_pxserialization.txt48
-rw-r--r--docs/_source/ext_serialization.txt189
-rw-r--r--docs/_source/ext_shaders.txt (renamed from docs/_source/ext_materials.txt)19
-rw-r--r--docs/_source/ext_stress.txt119
-rw-r--r--docs/_source/ext_tkserialization.txt45
-rw-r--r--docs/_source/introduction.txt36
-rw-r--r--docs/_source/legacy_converter.txt28
-rw-r--r--docs/_source/sample_asset_viewer.txt13
-rw-r--r--docs/_source/tools.txt21
22 files changed, 963 insertions, 328 deletions
diff --git a/docs/_source/api_ext_users_guide.txt b/docs/_source/api_ext_users_guide.txt
index 04fbb53..fd03c94 100644
--- a/docs/_source/api_ext_users_guide.txt
+++ b/docs/_source/api_ext_users_guide.txt
@@ -3,22 +3,41 @@
These are the current Blast extensions:
<br>
<br>
-\subpage pageextauthoring
+\subpage pageextshaders - Standard damage shaders (radial, shear, line segment) which can be used in NvBlast and NvBlastTk damage functions.
<br>
-\subpage pageextapeximport
<br>
-\subpage pageextserialization
+\subpage pageextstress - A toolkit for performing stress calculations on low-level Blast&tm; actors, using a minimal API to assign masses and apply forces. Does not use any external physics library.
<br>
-\subpage pageextconverterll
<br>
-\subpage pageextshaders
+\subpage pageextassetutils - NvBlastAsset utility functions. Add world bonds, merge assets, and transform geometric data.
<br>
-\subpage pageextphysx
+<br>
+\subpage pageextauthoring - Powerful tools for cleaning and fracturing meshes using voronoi, clustered voronoi, and slicing methods.
+<br>
+<br>
+\subpage pageextimport - Functions to import data from external formats and convert to a Blast&tm; asset. Currently handles APEX NvDestructibleAsset data.
+<br>
+<br>
+\subpage pageextexporter - Standard mesh and collision writer tools in fbx, obj, and json formats.
+<br>
+<br>
+\subpage pageextserialization - Blast&tm; object serialization manager. With the ExtTkSerialization and ExtPxSerialization extensions, can serialize assets for low-level, Tk, and ExtPhysX libraries
+using a variety of encodings. This extension comes with low-level serializers built-in.
+<br>
+<br>
+\subpage pageexttkserialization - This module contains serializers for NvBlastTk objects. Use in conjunction with ExtSerialization.
+<br>
+<br>
+\subpage pageextpxserialization - This module contains serializers for ExtPhysX objects. Use in conjunction with ExtSerialization.
+<br>
+<br>
+\subpage pageextphysx - A reference implementation of a physics manager, using the PhysX SDK. Creates and manages actors and joints, and handles impact damage and uses the stress solver (ExtStress) to
+handle stress calculations.
<br>
<br>
To use them, include the appropriate headers in include/extensions (each extension will describe which headers are necessary),
and link to the desired NvBlastExt*{config}{arch} library in the lib folder. Here, config is the usual DEBUG/CHECKED/PROFILE (or nothing for release),
and {arch} distinguishes achitecture, if needed (such as _x86 or _x64).
-
+<br>
<br>
*/
diff --git a/docs/_source/api_globals_users_guide.txt b/docs/_source/api_globals_users_guide.txt
new file mode 100644
index 0000000..2a5a9bf
--- /dev/null
+++ b/docs/_source/api_globals_users_guide.txt
@@ -0,0 +1,94 @@
+/*! \page pageglobalsapi Globals API (NvBlastGlobals)
+
+The NvBlastGlobals library is a utility library which is used by NvBlastTk (see \ref pagehlapi) and some extensions (see \ref pageextapi) and samples.
+
+It provides a global allocator, error callback, and profiler API.
+
+<br>
+\section globalsallocator Allocator
+
+<b>Include NvBlastGlobals.h</b>
+<br>
+
+A global allocator with interface
+
+\code
+Nv::Blast::AllocatorCallback
+\endcode
+
+may be set by the user with the function
+
+\code
+NvBlastGlobalSetAllocatorCallback
+\endcode
+
+and accessed using
+
+\code
+NvBlastGlobalGetAllocatorCallback
+\endcode
+
+An internal, default allocator is used if the user does not set their own, or if NULL is passed into NvBlastGlobalSetAllocatorCallback.
+
+This allocator is used by NvBlastTk, as well as any extension that allocates memory. In addition, utility macros are provided such as
+<b>NVBLAST_ALLOC</b>, <b>NVBLAST_FREE</b>, <b>NVBLAST_NEW</b>, and <b>NVBLAST_DELETE</b>.
+
+<br>
+\section globalserror Error Callback
+
+<b>Include NvBlastGlobals.h</b>
+
+A global error message callback with interface
+
+\code
+Nv::Blast::ErrorCallback
+\endcode
+
+may be set by the user with the function
+
+\code
+NvBlastGlobalSetErrorCallback
+\endcode
+
+and accessed using
+
+\code
+NvBlastGlobalGetErrorCallback
+\endcode
+
+An internal, default error callback is used if the user does not set their own, or if NULL is passed into NvBlastGlobalSetErrorCallback.
+
+This error callback is used by NvBlastTk, as well as many extensions. In addition, utility macros are provided such as
+<b>NVBLAST_LOG_ERROR</b> and <b>NVBLAST_LOG_WARNDING</b>.
+
+Finally, a function with signature given by NvBlastLog is provided which uses the global error callback,
+
+\code
+Nv::Blast::logLL
+\endcode
+
+This function may be passed into any NvBlast&tm; function's log parameter.
+
+<br>
+\section globalsprofiler Profiler API
+
+<b>Include NvBlastProfiler.h</b>
+<br>
+
+BlastTk contains many profiling zones which use the global profiler which can be accessed in this library. The user may implement
+the interface
+
+\code
+Nv::Blast::ProfilerCallback
+\endcode
+
+and pass it to the globals library using
+
+\code
+NvBlastProfilerSetCallback
+\endcode
+
+A NULL pointer may be passed in, disabling profiling. Profiler features are only active in checked, debug and profile builds.
+
+<br>
+*/
diff --git a/docs/_source/api_hl_users_guide.txt b/docs/_source/api_hl_users_guide.txt
index 99b2aa3..c5262ed 100644
--- a/docs/_source/api_hl_users_guide.txt
+++ b/docs/_source/api_hl_users_guide.txt
@@ -49,36 +49,38 @@ For the remainder of this page we will be in the Nv::Blast namespace, and will d
<br>
+BlastTk access the
+
BlastTk adds:
- An object class hierarchy (see \ref tk_class_hierarchy, below).
-- A global framework, <b>TkFramework</b> (a singleton). This holds an allocator and error message callback, keeps track of <b>TkIdentifiable</b> objects and allows
+- A global framework, <b>TkFramework</b> (a singleton). This keeps track of <b>TkIdentifiable</b> objects and allows
the user to query them based upon either GUID or <b>TkIdentifiable</b> subclass type, and also provides a number of functions to create the various objects in BlastTk.
-- Task management and processing groups (see <b>TkGroup</b>).
+- Processing groups with a task interface (see <b>TkGroup</b>).
- Event dispatching for actor families (see <b>TkFamily</b>).
-- Intra-actor and inter-actor joint management (see <b>TkJoint</b>). Note, only joint descriptions are managed, since physical objects are not handled by BlastTk.
-- Various damage and material options for actors (<b>TkActor</b>).
+- Intra-actor and inter-actor joint management (see <b>TkJoint</b>). Note, these "joints" only hold descriptor data, since physical objects are not handled by BlastTk.
<br>
\section tk_class_hierarchy NvBlastTk Class Hierarchy
-- There are three abstract interfaces, in an inheritance chain: <b>TkObject <- TkIdentifiable <- TkSerializable</b>.
+- There are two abstract interfaces, one of which deriving from the other: <b>TkObject <- TkIdentifiable.
- Lightweight objects are derived from <b>TkObject</b>.
- Objects which use a GUID and class identification are derieved from <b>TkIdentifiable</b>.
- - Objects which support serialization are derived from <b>TkSerializable</b>.
-- <b>TkAsset</b> derives from <b>TkSerializable</b>. This is mostly a wrapper for NvBlastAsset, however it also stores
-extra data associated with the asset such as a chunk map and internal joint descriptors.
-- <b>TkFamily</b> derives from <b>TkSerializable</b>. One and only one of these objects is made when a <b>TkActor</b> is instanced
+- <b>TkAsset</b> derives from <b>TkIdentifiable</b>. This is mostly a wrapper for NvBlastAsset, however it also stores
+extra data associated with the asset such as internal joint descriptors.
+- <b>TkFamily</b> derives from <b>TkIdentifiable</b>. One of these objects is made when a <b>TkActor</b> is instanced
from a <b>TkAsset</b>. All actors that are created by splitting the family's original actor remain within the same family. Actor and joint
events are dispatched from the <b>TkFamily</b>.
- <b>TkGroup</b> derives from <b>TkIdentifiable</b>. Groups are processing units. The user may create as many groups as they please, and add
-or remove actors as they please from groups. The group will process damage applied to its actors, and split the actors into new actors when
-the actors fracture. Groups use a user-defined task manager and can process actors in multiple threads simultaneously.
+or remove actors as they please from groups. The group provides a worker (TkGroupWorker) interface which allows the user to process multiple
+jobs in the group asynchoronously. These jobs, along with a call to TkGroup::endProcess(), perform the tasks of generating fracture commands,
+applying fracture commands, and actor splitting at the low-level. The user is informed of splitting through listeners given to TkFamily objects.
- <b>TkActor</b> derives from <b>TkObject</b>. It is mostly a wrapper for NvBlastActor, but it also provides a number of damage functions
to the user.
-- <b>TkJoint</b> derives from <b>TkObject</b>. Based upon <b>TkAsset</b> and <b>TkComposite</b> descriptors, a <b>TkJoint</b> may be internal
-to an actor (joining chunks within the same actor) or external (joining chunks between two actors). As actors split, internal joints may become
-external. The user gets notification whenever joints become external, or when actors joined by joints change or are deleted.
+- <b>TkJoint</b> derives from <b>TkObject</b>. <b>TkAsset</b> descriptors, cause internal <b>TkJoint</b> obejcts to be created within an actor
+(joining chunks within the same actor). Alternatively, the TkFramework provides a function which allows the user to create an external joint
+between any two different actors. As actors split, internal joints may become external. The user gets notification whenever joints become
+external, or when actors joined by joints change or are deleted, through listeners attached to the associated TkFamily objects.
<br>
\section tk_include_and_library Linking and Header Files
@@ -105,25 +107,14 @@ As a reminder, in this document we assume we are in the Nv::Blast namespace:
using Nv::Blast;
\endcode
-In order to use NvBlastTk, one first has to create a TkFramework singleton. This requires a descriptor which
-holds two callback classes defined by the user. These classes are derived from the physx::PxErrorCallback and
-physx::PxAllocatorCallback interfaces, and define message handling and allocation/deallocation functions,
-respectively. Assuming the user has already defined these objects with names gErrorCallback and gAllocatorCallback,
-the TkFramework descriptor is built as follows:
-
-\code
-TkFrameworkDesc desc;
-desc.errorCallback = &gErrorCallback; // physx::PxErrorCallback-derived callback object
-desc.allocatorCallback = &gAllocatorCallback; // physx::PxAllocatorCallback-derived callback object
-\endcode
-
-One then creates the framework:
+In order to use NvBlastTk, one first has to create a TkFramework singleton. This simply requires a call
+to the global function NvBlastTkFrameworkCreate:
\code
-TkFramework* framework = NvBlastTkFrameworkCreate( desc );
+TkFramework* framework = NvBlastTkFrameworkCreate();
\endcode
-The framework is a global singleton, and may be accessed via:
+The framework may be accessed via:
\code
TkFramework* framework = NvBlastTkFrameworkGet();
@@ -182,7 +173,8 @@ TkAsset using all of the default parameters of the createAsset function:
TkAsset* asset = framework->createAsset(llAsset, nullptr, 0, true);
\endcode
-The last parameter sets ownership.
+The last parameter sets ownership. N.B.: in order for the TkAsset to own the underlying llAsset, and therefore release it when the TkAsset is released,
+the memory for the llAsset must be allocated using the allocator accessed through NvBlastGlobals (see \ref pageglobalsapi).
If one wants to author internal joints in a TkAsset using this second createAsset method, one must pass in a valid array of joint descriptors of type
TkAssetJointDesc. Each joint descriptor takes two positions and two node indices. The positions are the joint's attachment positions in asset space, and
@@ -204,7 +196,7 @@ The code above assumes you know the support graph nodes to which you'd like to a
Fortunately it's easy to map chunk indices to graph node indices. In order to get the map, use the low-level function
\code
-const uint32_t map = NvBlastAssetGetChunkToGraphNodeMap(llAsset, nullptr);
+const uint32_t map = NvBlastAssetGetChunkToGraphNodeMap(llAsset, logFn);
\endcode
This map is an array with an entry for every chunk index. To get the graph node index for a chunk indexed <b>chunkIndex</b>, use
@@ -225,9 +217,9 @@ asset->release();
Whereas with the Blast&tm; low-level (\ref pagellapi), one must explicitly create a family (NvBlastFamily) from an asset (NvBlastAsset) before creating
the first actor (NvBlastActor) in the family, NvBlastTk creates a TkFamily automatically when an unfractured TkActor is instanced from a TkAsset using
-the framework's createActor function. This family is accessible through the actor and any actor that is created from splitting it. The family <em>not</em>
-released automatically when all actors within it have been released. The user must use the TkObject::release() method to do so. (Or wait until the
-framework is released.) If a family is released that contains actors, the actors within will be released as well.
+the framework's createActor function. This family is accessible through the actor and any actor that is created from splitting it. The family is
+<em>not</em> released automatically when all actors within it have been released. The user must use the TkFamily's release() method (see TkObject base
+API) to do so. (Or wait until the framework is released.) If a family is released that contains actors, the actors within will be released as well.
The TkFamily has a special roll in NvBlastTk, holding user-supplied event listeners (TkEventListener). All <em>internal</em> actor creation and destruction
events are broadcast to listeners through split events (TkSplitEvent). These signal when a fracturing operation has destroyed an actor and created
@@ -242,11 +234,8 @@ As with the TkAssetDesc, the TkActorDesc is derived from its low-level counterpa
the TkAsset being instanced. An example of TkActor creation is given below, given a TkAsset pointer <b>asset</b>.
\code
-TkActorDesc desc;
-
-myFunctionToFillInLowLevelActorFields(desc); // Fill in the low-level (NvBlastActorDesc) fields as usual
-
-desc.asset = asset;
+TkActorDesc desc; // The TkActorDesc constructor sets sane default values for the base (NvBlastActorDesc) fields, giving uniform chunk and bond healths of 1.0.
+desc.asset = asset; // This field of TkActorDesc must be set to a valid asset pointer.
TkActor* actor = framework->createActor(desc);
\endcode
@@ -266,15 +255,22 @@ in sync with the splitting of the TkActor. For more on this, see \ref tkevents.
<br>
\section tkgroups Groups
-One feature of NvBlastTk is multithreading of damage processing. The mechanism by which the toolkit does this is the group object, TkGroup. Groups are created
-at the request of the user; the user may create as many groups as they like. Actors may be added or removed from groups in any way the user wishes, with the only
-constraint being that a given actor may belong to no more than one group. A group is a processing object, much like a scene in a physics simulation. Indeed, a
-natural pattern would be to associate one group per physics scene, and synchronize the group processing with scene simulation. Another pattern would be to subdivide
-the world into neighborhoods, and associate each neighborhood with a group. A distributed game could take advantage of this structure to similarly distribute
-computation.
+One important feature of NvBlastTk is the ability to multitask damage processing. The mechanism by which the toolkit does this is the group object, TkGroup.
+Groups are created at the request of the user; the user may create as many groups as he or she likes. Actors may be added or removed from groups in any way the
+user wishes, with the only constraint being that a given actor may belong to no more than one group. A group is a processing object, much like a scene in a physics
+simulation. Indeed, a natural pattern would be to associate one group per physics scene, and synchronize the group processing with scene simulation. Another
+pattern would be to subdivide the world into neighborhoods, and associate each neighborhood with a group. A distributed game could take advantage of this structure
+to similarly distribute computation.
+
+Group processing is performed by <em>workers</em>, which have a TkGroupWorker API exposed to the user. The number of workers may be set by the user, with the idea being
+that this should correspond to the number of threads available for group processing. Processing starts with a call to TkGroup::startProcess(). This creates a number
+of jobs which the user may assign to workers as they like, each worker potentially on its own thread. The jobs calculate the effects of all damage taken
+by the group's actors. After all jobs have been run, the user must call TkGroup::endProcess(). This will result in all events being fired off to listeners associated
+with families with actors in the group.
-When processing, a group spawns tasks to calculate the effects of all damage taken by the group's actors. The group's sync function waits for all tasks to finish,
-and then has each family associated with its actors broadcast events to its listeners.
+A convenience function, TkGroup::process(), is provided which uses one worker to perform all jobs sequentially on the calling thread. This is useful shortcut to
+get BlastTk up and running quickly. A multithreaded group processing implementation is given by Nv::Blast::ExtGroupTaskManagerImpl (in NvBlastExtPxTaskImpl.h).
+This resides in \ref pageextphysx, because it uses physx::PxTask.
Actors resulting from the split of a "parent" actor will be placed automatically into the group that the parent belonged to. This is similar to the assigment of
families from a split, except that unlike families, the user then has the option to move the new actors to other groups, or no group at all.
@@ -282,8 +278,6 @@ families from a split, except that unlike families, the user then has the option
Also similar to families, groups are not automatically released when the last actor is removed from it. Unlike families, when a group is released, the actors which
belong to the group are <em>not</em> released. They will, however, be removed from the group before the release is complete.
-Because a group spawns tasks, for flexibility it requires a user-defined task manager. This manager needs to implement the type physx::PxTaskManager interface.
-
A typical usage is outlined below. See \ref damage_in_tk for methods of applying damage to actors.
\code
@@ -317,16 +311,10 @@ myDamageFunction(actor2);
myDamageFunction(actor3);
// etc...
-// Calling the groups' process functions will spawn tasks to process damage taken to the contained actors.
+// Calling the groups' process functions will (synchronously) run all jobs to process damage taken by the contained actors.
group1->process();
group2->process();
-// The user may insert code to be run asynchronously with group processing...
-
-// Call the groups' sync functions (with default block = true argument) to wait for processing to finish and fire off events.
-group1->sync();
-group2->sync();
-
// When the groups are no longer needed, they may be released with the usual release method.
group1->release();
group2->release();
@@ -380,11 +368,9 @@ damageDescs[1].maxRadius = 5.0f;
// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
Material material;
-material.singleChunkThreshold = 1.0f;
-material.graphChunkThreshold = 1.0f;
-material.bondTangentialThreshold = 0.5f;
-material.bondNormalThreshold = 0.25f;
-material.damageAttenuation = 0.75f
+material.health = 10.0f;
+material.minDamageThreshold = 0.1f;
+material.maxDamageThreshold = 0.8f;
// Set the damage params struct
NvBlastProgramParams params = { damageDescs, 2, &material };
@@ -405,11 +391,9 @@ To use this method, the user must first set a default material in the actor's fa
// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
Material material;
-material.singleChunkThreshold = 1.0f;
-material.graphChunkThreshold = 1.0f;
-material.bondTangentialThreshold = 0.5f;
-material.bondNormalThreshold = 0.25f;
-material.damageAttenuation = 0.75f
+material.health = 10.0f;
+material.minDamageThreshold = 0.1f;
+material.maxDamageThreshold = 0.8f;
// Set the default material used by the material-less TkActor::damage call
actor->getFamily().setMaterial(&material);
diff --git a/docs/_source/api_ll_users_guide.txt b/docs/_source/api_ll_users_guide.txt
index 33d12db..4dddfdc 100644
--- a/docs/_source/api_ll_users_guide.txt
+++ b/docs/_source/api_ll_users_guide.txt
@@ -16,35 +16,34 @@
\section llintroduction Introduction
The low-level API is the core of Blast&tm; destruction. It is designed to be a minimal API that allows an experienced user to incorporate destruction
-into their application. Summarizing what the low-level API has, or rather <em>doesn't</em> have:
+into their application. Summarizing what the low-level API has, and <em>doesn't</em> have:
- There is no physics representation. The low-level API is agnostic with respect to any physics engine, and furthermore does not have
any notion of collision geometry. The NvBlastActor is an abstraction which is intended to correspond to a rigid body. However
-it is up to the user to make that connection. The NvBlastActor references a list of visible chunk indices, which correspond to
+it is up to the user to implement that connection. The NvBlastActor references a list of visible chunk indices, which correspond to
NvBlastChunk data in the asset. The NvBlastChunk contains a userData field which can be used to associate collision
geometry with the actor based upon the visible chunks. The same is true for constraints created between actors. Bonds contain a
-userData field that can be used to inform the user that actors should have joints created at a particular location. After that it is up to the
-user to create the joint, and Blast&tm; does not manage them in any way.
-- There is no graphics representation. Just as there is no notion of collision geometry, there is no notion of graphics geometry either.
+userData field that can be used to inform the user that actors should have joints created at a particular location, but it is up to the
+user to create and manage physical joints between two actors.
+- There is no graphics representation. Just as there is no notion of collision geometry, there is also no notion of graphics geometry.
The NvBlastChunk userData field (see the item above) can be used to associate graphics geometry with the actor based upon the visible chunks.
-- There is no notion of threading. The API is a collection of free functions for which is is up to the user to call from appropriate threads.
+- There is no notion of threading. The API is a collection of free functions which the user may call from appropriate threads.
Blast&tm; guarantees that it is safe to operate on different actors from different threads.
-- There is no global memory manager, message handler, etc. Most functions take an optional message function pointer argument, in order to report
-warnings or errors. Memory is managed by the user, and functions that build objects require an appropriately-sized memory block to be passed in.
-A corresponding utility function that calculates the memory requirements is always present alongside such functions. Temporary storage needed by a
-function is always handled via user-supplied scratch space. For scratch, there is always a corresponding "RequiredScratch" function
-or documentation which lets the user know how much scratch space is needed based upon the function arguments.
-- One form of serialization is simply handled as a memory copy. Data associated with an asset or family (see \ref pagedefinitions) is
-available to the user, and may be copied and stored by the user. There are corresponding data association functions which may be used to recreate
-assets and families. Families contain a number of actors and so this form of deserialization recreates all actors in the family.
-These deserialization operations simply tie pointers in those objects to data within the given family. The families come with format
-version numbers, and association will only occur when the version number matches the current version used by the SDK.
-- Single-actor serialization and deserialization is supported. This is not as light-weight as family serialization, but may be a better serialization
-model for a particular application. To deserialize a single actor, one must have a family to hold the actor, created from the appropriate
+- There is no global memory manager, message handler, etc. All low-level API functions take an optional message function pointer argument
+in order to report warnings or errors. Memory is managed by the user, and functions that build objects require an appropriately-sized memory block
+to be passed in. A corresponding utility function that calculates the memory requirements is always present alongside such functions. Temporary
+storage needed by a function is always handled via user-supplied scratch space. For scratch, there is always a corresponding "RequiredScratch"
+function or documentation which lets the user know how much scratch space is needed based upon the function arguments.
+- Backwards-compatible, versioned, device-independent serialization is not handled by Blast&tm;. There <em>is<\em> however a Blast&tm; extension
+which does, see \ref pageextserialization. However, a simple form of serialization may be performed on assets and familes (see \ref pagedefinitions)
+via simple memory copy. The data associated with these objects is available to the user, and may be copied and stored by the user. There are
+Simply casting a pointer to such a block of memory to the correct object type will produce a usable object for Blast&tm;. (The only restriction is
+that the block must be 16-byte aligned.) Families contain a number of actors and so this form of deserialization recreates all actors in the family.
+This form of serialization may be used between two devices which have the same endianness, and contain Blast&tm; SDKs which use the same object format.
+- Single-actor serialization and deserialization is, however, supported. This is not as light-weight as family serialization, but may be a better
+serialization model for a particular application. To deserialize a single actor, one must have a family to hold the actor, created from the appropriate
asset. If none exists already, the user may create an empty family. After that, all actors that had been in that family may be deserialized
into it one-at-a-time, in any order.
-- No data format coversion is done. As mentioned above, data association will only occur with a current format version. It is up to extension
-functions to perform data conversion. (See \ref pageextserialization.)
<br>
\section include_and_library Linking and Header Files
@@ -76,9 +75,11 @@ within those descriptors so that they are valid for asset creation. The helper
chunk ordering to the new chunk ordering, so that corresponding adjustments or mappings may be made for graphics and other data
the user associates with chunks.</b>
-Example code is given below.
+Example code is given below. Throughout, we assume the user has defined a logging function called <B>logFn</B>, with the
+signature of NvBlastLog. In all cases, the log function is optional, and NULL may be passed in its place.
\code
+// Create chunk descriptors
std::vector<NvBlastChunkDesc> chunkDescs;
chunkDescs.resize( chunkCount ); // chunkCount > 0
@@ -99,8 +100,9 @@ chunkDescs[1].volume = 1.0; // Unit volume
chunkDescs[1].flags = NvBlastChunkDesc::SupportFlag; // This chunk should be represented in the support graph
chunkDescs[1].ID = 1;
-// ... etc.
+// ... etc. for all chunks
+// Create bond descriptors
std::vector<NvBlastBondDesc> bondDescs;
bondDescs.resize( bondCount ); // bondCount > 0
@@ -116,7 +118,11 @@ bondDescs[0].bond.m_centroid[2] = 3.f;
bondDescs[0].m_userData = 0; // this can be used to tell the user more information about this
// bond for example to create a joint when this bond breaks
-// ... etc.
+bondDescs[1].chunkIndices[0] = 1;
+bondDescs[1].chunkIndices[1] = ~0; // ~0 (UINT32_MAX) is the "invalid index." This creates a world bond
+// ... etc. for bondDescs[1], all other fields are filled in as usual
+
+// ... etc. for all bonds
// Set the fields of the descriptor
NvBlastAssetDesc assetDesc;
@@ -127,14 +133,14 @@ assetDesc.bondDescs = bondDescs.data();
// Now ensure the support coverage in the chunk descriptors is exact, and the chunks are correctly ordered
std::vector<char> scratch( chunkCount * sizeof(NvBlastChunkDesc) ); // This is enough scratch for both NvBlastEnsureAssetExactSupportCoverage and NvBlastReorderAssetDescChunks
-NvBlastEnsureAssetExactSupportCoverage( chunkDescs.data(), chunkCount, scratch.data(), nullptr );
+NvBlastEnsureAssetExactSupportCoverage( chunkDescs.data(), chunkCount, scratch.data(), logFn );
std::vector<uint32_t> map(chunkCount); // Will be filled with a map from the original chunk descriptor order to the new one
-NvBlastReorderAssetDescChunks( chunkDescs.data(), chunkDescs, bondDescs.data(), bondCount, map, scratch.data(), nullptr );
+NvBlastReorderAssetDescChunks( chunkDescs.data(), chunkCount, bondDescs.data(), bondCount, map, true, scratch.data(), logFn );
// Create the asset
scratch.resize( NvBlastGetRequiredScratchForCreateAsset( &assetDesc ) ); // Provide scratch memory for asset creation
void* mem = malloc( NvBlastGetAssetMemorySize( &assetDesc ) ); // Allocate memory for the asset object
-NvBlastAsset* asset = NvBlastCreateAsset( mem, &assetDesc, scratch.data(), nullptr ); // the log function (last argument) is optional
+NvBlastAsset* asset = NvBlastCreateAsset( mem, &assetDesc, scratch.data(), logFn );
\endcode
<br>
@@ -143,26 +149,25 @@ shader functions (see \ref pageextshaders). Depending on the shader, some, all,
The user may write damage shader functions that interpret this data in any way they wish.
<br>
-\subsection asset_copying Cloning an Asset (Serialization and Deserialization)
+\subsection asset_copying Cloning an Asset
-To clone an asset, or equivalently serialize and deserialize it (as long as the deserialized asset is being created on a host with the
-same data version and endianness), one only needs to copy the memory associated with the NvBlastAsset.
+To clone an asset, one only needs to copy the memory associated with the NvBlastAsset.
\code
-uint32_t assetSize = NvBlastAssetGetSize( data );
+uint32_t assetSize = NvBlastAssetGetSize( asset );
-NvBlastAsset* newAsset = (NvBlastAsset*)malloc(assetSize); // NOTE: the memory buffer <em> must <\em> be 16-byte aligned!
+NvBlastAsset* newAsset = (NvBlastAsset*)malloc(assetSize); // NOTE: the memory buffer MUST be 16-byte aligned!
memcpy( newAsset, asset, assetSize ); // this data may be copied into a buffer, stored to a file, etc.
\endcode
-N.B. the comment after the malloc call above. NvBlastAsset memory must be 16-byte aligned.
+N.B. the comment after the malloc call above. NvBlastAsset memory <B>must</B> be 16-byte aligned.
<br>
\subsection asset_releasing Releasing an Asset
Blast&tm low-level does no internal allocation; since the memory is allocated by the user, one simply has to free the memory they've
allocated. The asset pointer returned by NvBlastCreateAsset has the same numerical value as the mem block passed in (if the function
-is successful, or NULL otherwise). So releasing an asset done as follows:
+is successful, or NULL otherwise). So releasing an asset with memory allocate by <B>malloc</B> is simply done with a call to <B>free</B>:
\code
free( asset );
@@ -172,15 +177,15 @@ free( asset );
\section actors_and_families Creating Actors and Families
Actors live within a family created from asset data. To create an actor, one must first create a family. This family is used by the initial actor created from
-the asset, as well as all of the descendent actors created by recursively fracturing the initial actor. Like assets, family allocation is done by the user.
+the asset, as well as all of the descendent actors created by recursively fracturing the initial actor. As with assets, family allocation is done by the user.
To create a family, use:
\code
// Allocate memory for the family object - this depends on the asset being represented by the family.
-void* mem = malloc( NvBlastAssetGetFamilyMemorySize( &asset ) );
+void* mem = malloc( NvBlastAssetGetFamilyMemorySize( asset, logFn ) );
-NvBlastFamily* family = NvBlastAssetCreateFamily( mem, &asset, nullptr );
+NvBlastFamily* family = NvBlastAssetCreateFamily( mem, asset, logFn );
\endcode
When an actor is first created from an asset, it represents the root of the chunk hierarchy, that is the unfractured object. To create this actor, use:
@@ -196,29 +201,29 @@ actorDesc.initialChunkHealth = 1.0f; // this health value will be given to all l
std::vector<char> scratch( NvBlastFamilyGetRequiredScratchForCreateFirstActor( &actorDesc ) );
// Create the first actor
-NvBlastActor* actor = NvBlastFamilyCreateFirstActor( family, &actorDesc, scratch.data(), nullptr ); // ready to be associated with physics and graphics by the user
+NvBlastActor* actor = NvBlastFamilyCreateFirstActor( family, &actorDesc, scratch.data(), logFn ); // ready to be associated with physics and graphics by the user
\endcode
<br>
\subsection actor_copying Copying Actors (Serialization and Deserialization)
-There are two forms of serialization: family serialization and single actor serialization. Family serialization is extremely fast as it only requires a single
-memory copy. All actors in the family may be saved, loaded, or copied at once in this way.
+There are two ways to copy NvBlastActors: cloning an NvBlastFamily, and single-actor serialization. Cloning an NvBlastFamily is extremely fast as it only requires
+a single memory copy. All actors in the family may be saved, loaded, or copied at once in this way.
<br>
-\subsection family_serialization Family Serialization
+\subsection family_serialization Cloning a Family
-To serialize a family, use the family pointer which may be retrieved
+To clone a family, use the family pointer which may be retrieved
from any active actor in the family if needed, using the NvBlastActorGetFamily function:
\code
-const NvBlastFamily* family = NvBlastActorGetFamily( &actor, nullptr );
+const NvBlastFamily* family = NvBlastActorGetFamily( &actor, logFn );
\endcode
Then the size of the family may be obtained using:
\code
-size_t size = NvBlastFamilyGetSize( family, nullptr );
+size_t size = NvBlastFamilyGetSize( family, logFn );
\endcode
Now this memory may be copied, saved to disk, etc. To clone the family, for example, we can duplicate the memory:
@@ -230,21 +235,21 @@ memcpy( family2, family, size );
\endcode
<B>N.B.</B> If this data has been serialized from an external source, the family will not contain a valid reference to its associated asset.
-The user <em>must</em> set the family's asset. The family does however contain the asset's GUID, to help the user match the correct asset
+The user <em>must</em> set the family's asset. The family does however contain the asset's ID, to help the user match the correct asset
to the family. So one way of restoring the asset to the family follows:
\code
-const NvBlastGUID guid = NvBlastFamilyGetAssetGUID( family2, nullptr );
+const NvBlastGUID guid = NvBlastFamilyGetAssetID( family2, logFn );
// ... here the user must retrieve the asset using the GUID or by some other means
-NvBlastFamilySetAsset( family2, asset, nullptr );
+NvBlastFamilySetAsset( family2, asset, logFn );
\endcode
The data in family2 will contain the same actors as the original family. To access them, use:
\code
-uint32_t actorCount = NvBlastFamilyGetActorCount( family2, nullptr );
+uint32_t actorCount = NvBlastFamilyGetActorCount( family2, logFn );
std::vector<NvBlastActor*> actors( actorCount );
-uint32_t actorsWritten = NvBlastFamilyGetActors( actors.data(), actorCount, family2, nullptr );
+uint32_t actorsWritten = NvBlastFamilyGetActors( actors.data(), actorCount, family2, logFn );
\endcode
In the code above, actorsWritten should equal actorCount.
@@ -255,33 +260,34 @@ In the code above, actorsWritten should equal actorCount.
To perform single-actor serialization, first find the buffer size required to store the serialization data:
\code
-size_t bufferSize = NvBlastActorGetSerializationSize( actor, nullptr );
+size_t bufferSize = NvBlastActorGetSerializationSize( actor, logFn );
\endcode
If you want to use an upper bound which will be large enough for any actor in a family, you may use:
\code
-size_t bufferSize = NvBlastAssetGetActorSerializationSizeUpperBound( asset, nullptr );
+size_t bufferSize = NvBlastAssetGetActorSerializationSizeUpperBound( asset, logFn );
\endcode
Then create a buffer of that size and use NvBlastActorSerialize to write to the buffer:
\code
std::vector<char> buffer( bufferSize );
-size_t bytesWritten = NvBlastActorSerialize( buffer, bufferSize, actor, nullptr );
+size_t bytesWritten = NvBlastActorSerialize( buffer, bufferSize, actor, logFn );
\endcode
To deserialize the buffer, an appropriate family must be created. It must not already hold a copy of the actor. It must be formed
using the correct asset (the one that originally created the actor):
\code
-NvBlastFamily* family = NvBlastAssetCreateFamily( asset, malloc, nullptr );
+void* mem = malloc( NvBlastAssetGetFamilyMemorySize( asset, logFn ) );
+NvBlastFamily* family = NvBlastAssetCreateFamily( mem, asset, logFn );
\endcode
Then deserialize into the family:
\code
-NvBlastActor* newActor = NvBlastFamilyDeserializeActor( family, buffer.data(), nullptr );
+NvBlastActor* newActor = NvBlastFamilyDeserializeActor( family, buffer.data(), logFn );
\endcode
If newActor is not NULL, then the actor was successfully deserialized.
@@ -295,7 +301,7 @@ This clears the actor's chunk lists and marks it as invalid, effectively disasso
to be destroyed.
\code
-bool success = NvBlastActorDeactivate( actor ); // actor should always be a pointer, as it is an opaque type
+bool success = NvBlastActorDeactivate( actor, logFn );
\endcode
<br>
@@ -303,22 +309,20 @@ bool success = NvBlastActorDeactivate( actor ); // actor should always be a poin
As mentioned above, releasing an actor does not actually do any deallocation; it simply invalidates the actor within its family.
To actually deallocate memory, you must deallocate the family. Note, this will invalidate all actors in the family. This is
-a fast way to delete all actors that were created from repeated fracturing of a single instance. As with NvBlastAsse, memory is
-allocated by the user, so to release the family simply free that memory:
+a fast way to delete all actors that were created from repeated fracturing of a single instance. As with NvBlastAsset, memory is
+allocated by the user, so to release a family with memory allocated by <B>malloc</B>, simply free that memory with <B>free</B>:
\code
free( family );
\endcode
-The family will <em>not</em> be automatically released when all actors within it are invalidated using NvBlastActorDeactivate. However, the user may keep track
-of the number of active actors in a family using
+The family will <em>not</em> be automatically released when all actors within it are invalidated using NvBlastActorDeactivate. However, the user may query
+the number of active actors in a family using
\code
-uint32_t actorCount = NvBlastFamilyGetActorCount( family, nullptr );
+uint32_t actorCount = NvBlastFamilyGetActorCount( family, logFn );
\endcode
-The result of the call above, actually a reference count for the family, is accurate even if actors are created and deleted from different threads.
-
<br>
\section splitting Damage and Fracturing
@@ -328,9 +332,9 @@ In a first step, a \ref NvBlastDamageProgram creates lists of Bonds and Chunks t
The lists are created from input specific to the NvBlastDamageProgram.<br>
NvBlastDamagePrograms are composed of a \ref NvBlastGraphShaderFunction and a
\ref NvBlastSubgraphShaderFunction operating on support graphs (support chunks and bonds) and disconnected subsupport chunks respectively.
-An implementer can freely define the shader functions and paramters.
+An implementer can freely define the shader functions and parameters.
Different functions can have the effect of emulating different physical materials.<br>
-Blast&tm; provides example implementations of such functions in \ref pageextshaders, see also NvBlastExtDamageShaders.h.
+Blast&tm; provides reference implementations of such functions in \ref pageextshaders, see also NvBlastExtDamageShaders.h.
The NvBlastDamageProgram is used through \ref NvBlastActorGenerateFracture that will provide the necessary internal data for the NvBlastActor being processed.
The shader functions see the internal data as \ref NvBlastGraphShaderActor and \ref NvBlastSubgraphShaderActor respectively.
@@ -356,7 +360,7 @@ NvBlastDamageProgram damageProgram = { GraphShader, SubgraphShader };
NvBlastProgramParams programParams = { damageDescs, damageDescCount, materialProperties };
// Generating the set of Fracture Commands does not modify the NvBlastActor.
-NvBlastActorGenerateFracture(fractureCommands, actor, damageProgram, &programParams, logFn, &timers);
+NvBlastActorGenerateFracture( fractureCommands, actor, damageProgram, &programParams, logFn, &timers );
// Step two: Apply Fracture Commands
@@ -364,25 +368,25 @@ NvBlastActorGenerateFracture(fractureCommands, actor, damageProgram, &programPar
// Applying Fracture Commands does modify the state of the NvBlastActor.
// The Fracture Events report the resulting state of each Bond or Chunk involved.
// Chunks fractured hard enough will also fracture their children, creating Fracture Events for each.
-NvBlastActorApplyFracture(fractureEvents, actor, fractureCommands, logFn, &timers);
+NvBlastActorApplyFracture( fractureEvents, actor, fractureCommands, logFn, &timers );
// Step three: Splitting
// The Actor may be split into all its smallest pieces.
-uint32_t maxNewActorCount = NvBlastActorSplitMaxActorCount(actor);
-std::vector<NvBlastActor*> newActors(maxNewActorCount);
+uint32_t maxNewActorCount = NvBlastAssetGetChunkCount( asset, logFn ); // In the worst case, one NvBlastActor may be created for every chunk in the asset
+std::vector<NvBlastActor*> newActors( maxNewActorCount );
// Make this memory available to NvBlastSplitEvent.
NvBlastActorSplitEvent splitEvent;
splitEvent.newActors = newActors.data();
// Some temporary memory is necessary as well.
-std::vector<char> scratch(NvBlastActorGetRequiredScratchForSplit(actor));
+std::vector<char> scratch( NvBlastActorGetRequiredScratchForSplit( actor, logFn ) );
// New actors created are reported in splitEvent.newActors.
// If newActorCount != 0, then the old actor is deleted and is reported in splitEvent.deletedActor.
-size_t newActorCount = NvBlastActorSplit(&splitEvent, actor, maxNewActorCount, scratch.data(), logFn, &timers);
+size_t newActorCount = NvBlastActorSplit( &splitEvent, actor, maxNewActorCount, scratch.data(), logFn, &timers );
\endcode
<br>
diff --git a/docs/_source/api_users_guide.txt b/docs/_source/api_users_guide.txt
index f8ea9e9..c3d2f83 100644
--- a/docs/_source/api_users_guide.txt
+++ b/docs/_source/api_users_guide.txt
@@ -6,6 +6,8 @@ Blast&tm; User's Guide
\subpage pagellapi
+\subpage pageglobalsapi
+
\subpage pagehlapi
\subpage pageextapi
diff --git a/docs/_source/copyrights.txt b/docs/_source/copyrights.txt
index b3d38c3..8ccc9ef 100644
--- a/docs/_source/copyrights.txt
+++ b/docs/_source/copyrights.txt
@@ -30,4 +30,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endverbatim
<br>
+\section boost Boost
+
+Blast&tm; \ref pageextauthoring uses Boost (boost.org). This is licensed as follows.
+
+\verbatim
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+\endverbatim
+
+<br>
*/
diff --git a/docs/_source/data_converter.txt b/docs/_source/data_converter.txt
deleted file mode 100644
index a197483..0000000
--- a/docs/_source/data_converter.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*! \page pageconverter DataConverter
-
-\verbatim
-
-USAGE:
-
- DataConverter -i <infile> -o <outfile> [-v <outversion>] [--]
- [--version] [-h]
-
-Where:
-
- -i <infile>, --infile <infile>
- (required) Input binary file.
-
- -o <outfile>, --outfile <outfile>
- (required) Output binary file.
-
- -v <outversion>, --outversion <outversion>
- Output binary block version. Pass -1 or ignore this parameter to
- convert to latest version.
-
- --, --ignore_rest
- Ignores the rest of the labeled arguments following this flag.
-
- --version
- Displays version information and exits.
-
- -h, --help
- Displays usage information and exits.
-
-\endverbatim
-
-Blast&tm; low-level and Tk libraries will only load data in the most current format. If your data is in an older format, you may use the \ref pageextconverterll API to convert to the current format.
-
-DataConverter.exe is a utility to convert Blast&tm; data from an older format into the current format. The data must be stored in a binary-format file
-with filename given as the <infile> parameter. It uses the \ref pageextconverterll API to perform the conversion.
-
-Currently, DataConverter only works on the low-level data formats for an asset (NvBlastAsset) and family (NvBlastFamily). The .blast files used by
-SampleAssetViewer (see \ref pagesamples) may be converted using this tool.
-
-<br>
-*/
diff --git a/docs/_source/ext_assetutils.txt b/docs/_source/ext_assetutils.txt
new file mode 100644
index 0000000..383f791
--- /dev/null
+++ b/docs/_source/ext_assetutils.txt
@@ -0,0 +1,94 @@
+/*! \page pageextassetutils Asset Utilities (NvBlastExtAssetUtils)
+
+NvBlastExtAssetUtils provides simple utility functions for modifying NvBlastAsset objects. Three functions are provided, described in the following sections.
+
+<br>
+\section addworldbonds Add World Bonds
+
+The function NvBlastExtAssetUtilsAddWorldBonds allows the user to create an asset from an existing asset, with the addition of new bonds that connect
+support chunks to the world. (See the documentation for NvBlastBondDesc.)
+
+For example, given an asset called <em>oldAsset</em>,
+
+\code
+const uint32_t worldBoundChunks[3] = { 1, 2, 3 }; // Chunks to bind to the world. These must be support chunks.
+const NvcVec3 bondDirections[3] = { { -1, 0, 1 }, { 0, 0, -1}, { 1, 0, 0 } }; // Normal directions for the new bonds.
+
+// Create a new asset
+NvBlastAsset* newAsset = NvBlastExtAssetUtilsAddWorldBonds(oldAsset, worldBoundChunks, 3, bondDirections, NULL);
+\endcode
+
+Memory for the new asset is allocated using the allocator available through NvBlastGlobals (\ref pageglobalsapi). Therefore the new asset may be freed using
+
+\code
+NVBLAST_FREE(newAsset);
+\endcode
+
+<br>
+\section mergeassets Merge Assets
+
+The NvBlastExtAssetUtilsMergeAssets function will combine any number of assets, generating an asset descriptor which may be passed to NvBlastCreateAsset. This
+is done in order to allow the user to make adjustments to the descriptor before creating the merged asset.
+
+The geometric data in each asset to be merged may be transformed so that the assets will have desired relative poses. In addition, the user may describe new
+bonds, in order to join support chunks of two different assets and create a larger support graph which spans the entire combined asset. The reference frame for
+the new bonds' geometric data is that of the new asset.
+
+For example, if one wants to merge two wall assets together, with a relative translation between them of 10 units in the x-direction, the code might look something like this:
+
+\code
+const NvBlastAsset* components[2] = { asset0, asset1 }; // asset0 and asset1 are already created
+const NvcVec3 translations[2] = { { -5, 0, 0 }, { 5, 0, 0 } }; // Translate asset0 -5 in x, and asset1 +5 in x
+
+// New bonds:
+const uint32_t newBondCount = ... // Some number of new bonds
+const NvBlastExtAssetUtilsBondDesc newBondDescs[newBondCount];
+newBondDesc[0].bond.normal.x = 1; // Normal in the +x direction, pointing from asset0 to asset1
+newBondDesc[0].bond.normal.y = 0;
+newBondDesc[0].bond.normal.z = 0;
+newBondDesc[0].bond.area = 1;
+newBondDesc[0].bond.centroid.x = 0;
+newBondDesc[0].bond.centroid.y = 0;
+newBondDesc[0].bond.centroid.z = 2.5; // Position is in the middle, off the ground
+newBondDesc[0].bond.userData = 0;
+newBondDesc[0].chunkIndices[0] = 5; // Connect from chunk[5] in components[componentIndices[0]]
+newBondDesc[0].chunkIndices[1] = 13; // .. to chunk[13] in components[componentIndices[1]]
+newBondDesc[0].componentIndices[0] = 0; // Connect asset in components[0]
+newBondDesc[0].componentIndices[1] = 1; // .. to the asset in components[1]
+
+// Create merged asset descriptor
+NvBlastAssetDesc mergedDesc = NvBlastExtAssetUtilsMergeAssets(components, NULL, translations, 2, newBondDescs, newBondCount);
+\endcode
+
+Note, we passed in NULL for the list of relative rotations, meaning no asset will be rotated.
+
+Also note, the new bond descriptors can just as well apply to a single asset (by setting both component indices to the same index), allowing the user to create additional bonds within
+a single asset if desired.
+
+The chunk and bond arrays referenced by the returned NvBlastAssetDesc are allocated using the NvBlastGlobals allocator, and it is up to the user to free this memory when it is no
+longer needed:
+
+\code
+NVBLAST_FREE(mergedDesc.chunkDescs);
+NVBLAST_FREE(mergedDesc.bondDescs);
+\endcode
+
+<br>
+\section transforminplace Transform In-Place
+
+The NvBlastExtAssetTransformInPlace function will apply an affine transformation (given by scaling, rotation, translation components) to the geometric data within an asset.
+
+To use this function, simply pass in an NvcVec3 pointer to represent scale (which may be non-uniform), an NvcQuat pointer to represent rotation, and an NvcVec3 pointer to
+represent translation. Any of these pointers may be NULL, in which case that transform component is implicitly considered to be the identity. This transforms:
+
+- Chunk centroids
+- Chunk volumes
+- Bond normals
+- Bond areas
+- Bond centroids
+
+The transformation of position vectors is done in the following order: scale, followed by rotation, followed by translation.
+
+The transformation of normal vectors uses the cofactors of the scale matrix (diagonals given by {scale.y*scale.z, scale.z*scale.x, scale.x*scale.y}), followed by rotation.
+<br>
+*/
diff --git a/docs/_source/ext_authoring.txt b/docs/_source/ext_authoring.txt
index 9b9cbf9..aeae4e8 100644
--- a/docs/_source/ext_authoring.txt
+++ b/docs/_source/ext_authoring.txt
@@ -1,31 +1,39 @@
/*! \page pageextauthoring Asset Authoring (NvBlastExtAuthoring)
-Blast extensions provide tools for creation Blast asset from provided geometry mesh.
+The Authoring extension provides tools for creation of a Blast&tm; asset from a provided mesh.
There are three tools for creation Blast asset.
-First one is FractureTool which is used for fracturing input mesh. It supports Voronoi fracturing method and slicing.
-Internal surface of output chunks can be tesselated and noise can be applied to it.
-Slicing method supports slicing with noisy slicing surface, which makes possible creation of jagged slicing line. Noisy slicing is switched on by
-setting non-zero noise amplitude in slicing parameters.
+First one is FractureTool (see NvBlastExtAuthoringFractureTool.h) which is used to fracture an input mesh. It supports Voronoi fracturing and also
+simple slicing. Internal surfaces of output chunks can be tesselated and noise can be applied to them. The slicing method supports slicing with
+a noisy slicing surface, which allows the creation of a jagged slicing line. Noisy slicing is switched on by setting a non-zero noise amplitude
+in slicing parameters (Nv::Blast::SlicingConfiguration).
+
+<br>
+\section fracturetool FractureTool
Nv::Blast::FractureTool supports two types of output:
-1) Array of triangles - tool fills provided array with triangles of chunk, ID of chunk should be provided.
+1) Array of triangles - the tool fills provided array with triangles of chunk, ID of chunk should be provided.
2) Buffered output - tool fills provided array with vertices, and another array of arrays with indices. Indices form triplets of vertices of triangle.
+<br>
+\section convexmeshbuilder ConvexMeshBuilder
+
Nv::Blast::ConvexMeshBuilder is tool for creation collision geometry for physics engine. It recieves mesh vertices, and returns convex hull of that vertices. If creation of convex hull fails,
tool creates collision geometry as a bounding box of provided vertices.
Tool provides method to trim convex hulls against each other. It can be used along with noisy slicing to avoid "explosive" behavior due to penetration of neighboor collision hulls into each other.
As a drawback penetration of render meshes into each other is possible due to trimmed collision geometry.
+<br>
+\section bondgenerator BondGenerator
Nv::Blast::BlastBondGenerator tool for creation Blast Bond descriptors from provided geometry data.
It has separate method which is optimized for working FractureTool.
\code
- int32_t Nv::Blast::BlastBondGenerator::buildDescFromInternalFracture(FractureTool* tool, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& resultBondDescs, std::vector<NvBlastChunkDesc>& resultChunkDescriptors);
+int32_t Nv::Blast::BlastBondGenerator::buildDescFromInternalFracture(FractureTool* tool, const std::vector<bool>& chunkIsSupport, std::vector<NvBlastBondDesc>& resultBondDescs, std::vector<NvBlastChunkDesc>& resultChunkDescriptors);
\endcode
Other methods can work with prefractured mesh created in Third party tool, and can be used for converting prefractured models to Blast assets.
@@ -36,6 +44,29 @@ Nv::Blast::BlastBondGenerator supports two modes of NvBlastBond data generation:
2) Average - this mode uses approximations of interface, and can be used for gathering NvBlastBond data for assets, where chunks penetrate each other, e.g. chunks with noise.
+<br>
+\section meshcleaner MeshCleaner
+
+Nv::Blast::MeshCleaner can be used to remove self intersections and open edges in interior of mesh, making it more likely to fracture well.
+
+To use it, create a MeshCleaner using
+
+\code
+Nv::Blast::MeshCleaner* cleaner = NvBlastExtAuthoringCreateMeshCleaner();
+\endcode
+
+Given an Nv::Blast::Mesh called "mesh," simply call
+
+\code
+Nv::Blast::Mesh* newMesh = cleaner->cleanMesh(mesh);
+\endcode
+
+If successful, newMesh will be a valid pointer to the cleaned mesh. Otherwise, newMesh will be NULL.
+
+When done, release using
+\code
+cleaner->release();
+\endcode
<br>
*/
diff --git a/docs/_source/ext_converterll.txt b/docs/_source/ext_converterll.txt
deleted file mode 100644
index e00a97a..0000000
--- a/docs/_source/ext_converterll.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*! \page pageextconverterll Data Format Conversion Extension (NvBlastExtConverterLL)
-
-The low-level converter extension is a utility to convert NvBlastAsset and NvBlastFamily data from one format to another.
-
-The format version of an asset may be obtained using the function
-
-\code
-uint32_t assetVersion = NvBlastAssetGetFormatVersion(asset, logFn);
-\endcode
-
-and likewise the format version of a family may be obtained using the function
-
-\code
-uint32_t familyVersion = NvBlastAssetGetFormatVersion(family, logFn);
-\endcode
-
-If the format version does not match the SDK's current version for one of these objects, the data may not be used
-with the current SDK. The NvBlastExtConverterLL extension will apply a chain of conversion functions to transform
-an asset or family from its stored version to any other version, provided that such a chain exists.
-
-To apply it, simply use the function convertDataBlock. For example, given an asset pointer,
-
-\code
-vector<char> inBlock, outBlock;
-
-inBlock.resize( NvBlastAssetGetSize(asset), logFn );
-memcpy( inBlock.data(), asset, NvBlastAssetGetSize(asset) );
-
-if ( convertDataBlock(outBlock, inBlock) )
-{
- NvBlastAsset* convertedAsset = outBlock.data();
-
- // Use convertedAsset here
-}
-\endcode
-
-<br>
-*/
diff --git a/docs/_source/ext_exporter.txt b/docs/_source/ext_exporter.txt
new file mode 100644
index 0000000..d5dcfdf
--- /dev/null
+++ b/docs/_source/ext_exporter.txt
@@ -0,0 +1,35 @@
+/*! \page pageextexporter Exporter (NvBlastExtExporter)
+
+This extension provides both reader and writer tools for FBX and OBJ mesh formats. The file writers (IMeshFileWriter writer) use
+NvBlastMesh data to create a mesh hierarchy in the output file format that matches the Blast&tm; chunk hierarchy. The FBX writer
+is also capable of embedding collision data within the mesh. This data is stored in a second layer in the FBX scene, with node
+names that match the graphics mesh node names.
+
+From NvBlastExtExporter.h:
+
+\code
+/**
+ Creates an instance of IMeshFileReader for reading obj file.
+*/
+NVBLAST_API Nv::Blast::IMeshFileReader* NvBlastExtExporterCreateObjFileReader();
+
+/**
+ Creates an instance of IFbxFileReader for reading fbx file.
+*/
+NVBLAST_API Nv::Blast::IFbxFileReader* NvBlastExtExporterCreateFbxFileReader();
+
+/**
+ Creates an instance of IMeshFileWriter for writing obj file.
+*/
+NVBLAST_API Nv::Blast::IMeshFileWriter* NvBlastExtExporterCreateObjFileWriter();
+
+/**
+ Creates an instance of IMeshFileWriter for writing fbx file.
+
+ \param[in] outputFBXAscii If true writes fbx in ascii format otherwise write in binary.
+*/
+NVBLAST_API Nv::Blast::IMeshFileWriter* NvBlastExtExporterCreateFbxFileWriter(bool outputFBXAscii = false);
+\endcode
+
+<br>
+*/
diff --git a/docs/_source/ext_import.txt b/docs/_source/ext_import.txt
index 40eafcc..b7a17e2 100644
--- a/docs/_source/ext_import.txt
+++ b/docs/_source/ext_import.txt
@@ -1,6 +1,8 @@
-/*! \page pageextapeximport Apex Import (NvBlastExtApexImport)
+/*! \page pageextimport Importer (NvBlastExtImport)
-Blast extensions provide Nv::Blast::ApexImporter::ApexImportTool, which can be used for converting APEX Destructible assets into Blast assets.
+This extension provides tools to import data from external formats and convert to a Blast&tm; asset.
+
+Currently the only external data format handled is NvApexDestructibleAsset, handled by Nv::Blast::ApexImporter::ApexImportTool.
This tool supports two bond generation modes and can be configured by providing:
\code
diff --git a/docs/_source/ext_physx.txt b/docs/_source/ext_physx.txt
index 70a8e2e..afc24a6 100644
--- a/docs/_source/ext_physx.txt
+++ b/docs/_source/ext_physx.txt
@@ -1,10 +1,10 @@
-/*! \page pageextphysx PhysX Extensions
+/*! \page pageextphysx PhysX Extensions (NvBlastExtPhysX)
-NvBlastExtPhysX contains extensions for easier use of Blast Toolkit with the PhysX SDK.
+NvBlastExtPhysX contains classes for easier use of Blast Toolkit with the PhysX SDK.
There are 3 of them:
- <b>ExtPxManager</b>: Manager to keep Blast Actors in sync with PhysX actors.
- <b>ExtImpactDamageManager</b>: Manager to collect and apply impact damage caused by collision in PhysX Scene.
-- <b>ExtStressSolver</b>: Stress Solver to propagate stress through support graph and apply it as damage to Blast actors.
+- <b>ExtPxStressSolver</b>: Stress Solver to propagate stress through support graph and apply it as damage to Blast actors.
This library also contains an extension for synchronizing Blast state:
- <b>ExtSync</b> - Utility for writing Blast state to a buffer, to be read by a client. This may be used for networking, for example.
@@ -16,7 +16,7 @@ This library also contains an extension for synchronizing Blast state:
<b>Physics Manager</b> - is a reference implementation for keeping Blast Actors synced with PhysX actors. It's main job is to listen
for TkFamily events and update \a PxScene (by adding and removing PxActors) accordingly.
-In order to use it create ExtPxManager:
+In order to use it create an ExtPxManager. If we have a physx::PxPhysics object m_physics and a TkFramework m_tkFramework, use
\code
ExtPxManager* pxManager = ExtPxManager::create(m_physics, m_tkFramework);
@@ -47,7 +47,7 @@ You can subscribe to family events in order to sync graphics (or anything else)
family->subscribe(listener);
\endcode
-Listener will be notified with all physics actors added and removed.
+The listener will be notified with all physics actors added and removed.
And finally spawn the family in some world position (the first actor/actors will be created and event will be fired to the listener):
@@ -59,7 +59,7 @@ ExtPxSpawnSettings spawnSettings = {
RIGIDBODY_DENSITY
};
-family->spawn(PxTransform(0, 0, 0), spawnSettings);
+family->spawn(PxTransform(0, 0, 0), PxVec3(1, 1, 1), spawnSettings);
\endcode
You can get families actor's either from listening to events or by calling getActors().
@@ -70,21 +70,21 @@ ExtPxActor* actor = ....;
physx::PxRigidDynamic rigidDynamic = actor->getPxActor(); //
\endcode
-ExtPxActor remains internally unchanged through it's life time.
-Use \a ExtPxActor \a getChunkIndices() and \a getPxActor() to update graphics representation. Sample code:
+An ExtPxActor remains internally unchanged through its lifetime.
+Use \a ExtPxActor \a getChunkIndices() and \a getPxActor() to update your graphics representation. Sample code:
\code
- const uint32_t* chunkIndices;
- size_t chunkIndexCount;
- actor.getChunkIndices(chunkIndices, chunkIndexCount);
- for (uint32_t i = 0; i < chunkIndexCount; i++)
+const uint32_t* chunkIndices;
+size_t chunkIndexCount;
+actor.getChunkIndices(chunkIndices, chunkIndexCount);
+for (uint32_t i = 0; i < chunkIndexCount; i++)
+{
+ uint32_t chunkIndex = chunkIndices[i];
+ for (Renderable* r : m_chunks[chunkIndex].renderables)
{
- uint32_t chunkIndex = chunkIndices[i];
- for (Renderable* r : m_chunks[chunkIndex].renderables)
- {
- r->setTransform(actor.getPxActor()->getGlobalPose() * pxAsset.chunks[chunkIndex].convexes[0].transform);
- }
+ r->setTransform(actor.getPxActor()->getGlobalPose() * pxAsset.chunks[chunkIndex].convexes[0].transform);
}
+}
\endcode
In order to use joints set joint create function with \a ExtPxManager::setCreateJointFunction(...). It will be called when new TkJoint's are
@@ -101,22 +101,22 @@ In order to use it create it:
ExtImpactDamageManager* impactManager = ExtImpactDamageManager::create(pxManager);
\endcode
-Call it's onContact method on every \a PxSimulationEventCallback \a onContact()
+Call its onContact method on every \a PxSimulationEventCallback \a onContact()
\code
- class EventCallback : public PxSimulationEventCallback
- {
- public:
- EventCallback(ExtImpactDamageManager* manager) : m_manager(manager) {}
+class EventCallback : public PxSimulationEventCallback
+{
+public:
+ EventCallback(ExtImpactDamageManager* manager) : m_manager(manager) {}
- virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs)
- {
- m_manager->onContact(pairHeader, pairs, nbPairs);
- }
+ virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs)
+ {
+ m_manager->onContact(pairHeader, pairs, nbPairs);
+ }
- private:
- ExtImpactDamageManager* m_manager;
- };
+private:
+ ExtImpactDamageManager* m_manager;
+};
\endcode
Call \a applyDamage() when you want the buffered damage to be applied:
@@ -125,7 +125,7 @@ Call \a applyDamage() when you want the buffered damage to be applied:
impactManager->applyDamage();
\endcode
-Also important to enable contact notification with custom filter shader for PxScene. \a ImpactDamageManager has a reference filter shader
+<b>N.B.</b> for impact damage to work, you must enable contact notification with custom the filter shader for PxScene. \a ExtImpactDamageManager has a reference filter shader
implementation which can be used for that:
\code
@@ -134,23 +134,17 @@ sceneDesc.filterShader = ExtImpactDamageManager::FilterShader;
\endcode
<br>
-\section ExtStressSolver
-
-<b>Stress Solver</b> - is a reference implementation of stress propagation using Blast support graph.
+\section extpxstresssolver ExtPxStressSolver
-\subsection Features Features
-- Supports both static and dynamic actors
-- Propagates both linear and angular momentum
-- Graph complexity selection (reduces support graph to smaller size trade off speed and quality)
-- Apply stress damage on Blast Actor
-- Debug Render
+<b>Stress Solver</b> - this wrapper class uses \ref pageextstress to apply stress calculations to an ExtPxFamily. See \ref pageextstress for
+the details of the underlying stress solver.
-\subsection Usage Usage
+\subsection pxstresssolverusage Usage
-In order to use it instance stress solver by providing \a ExtPxFamily:
+In order to use it, instance an ExtPxStressSolver by providing \a ExtPxFamily:
\code
-ExtStressSolver* stressSolver = ExtStressSolver::create(family);
+ExtPxStressSolver* stressSolver = ExtPxStressSolver::create(family);
\endcode
And then call update() every frame:
@@ -161,20 +155,19 @@ stressSolver->update(doDamage);
\endcode
By default it will apply scene gravity on static actors and centrifugal force on dynamic actors.
-Also applyImpulse(...) can be called for additional stress to apply:
+
+The underlying ExtStressSolver can be accessed using ExtPxStressSolver::getSolver(). For example, to apply impulse to
+a particular actor, use applyImpulse(...) can be called for additional stress to apply:
\code
-stressSolver->applyImpulse(actor, position, force);
+stressSolver->getSolver().addForce(actor, position, impulse);
\endcode
-It fully utilizes the fact that it knows initial support graph structure and does maximum of processing
-in \a create(...) method calls. After that all actors split calls are synced internally quite fast and only the actual
-stress propagation takes most of computational time.
-Computational time is linearly proprtional to \a bondIterationsPerFrame setting. To fine tune look for balance
-between \a bondIterationsPerFrame and \a graphReductionLevel . The more bond iterations
-are set the more precise computation will be. The smaller graph allows to make higher fidelity computations witihing
-the same bond iterations per frame (same time spent), but actual cracks (damaged bonds) will be more sparsed as the result.
+Finally, the stress solver (and its underlying ExtStressSolver) may be released using
+\code
+stressSolver->release();
+\endcode
<br>
\section ExtSync
diff --git a/docs/_source/ext_pxserialization.txt b/docs/_source/ext_pxserialization.txt
new file mode 100644
index 0000000..21761fb
--- /dev/null
+++ b/docs/_source/ext_pxserialization.txt
@@ -0,0 +1,48 @@
+/*! \page pageextpxserialization ExtPhysX Serialization (NvBlastExtPxSerialization)
+
+This extension contains serializers which can be loaded into the ExtSerialization manager defined in \ref pageextserialization.
+
+To use this extension, you must also load the ExtSerialization extension and create a serialization manager as described in \ref pageextserialization.
+
+We repeat this here (again, assuming we're in the Nv::Blast namespace):
+
+\code
+ExtSerialization* ser = NvBlastExtSerializationCreate();
+\endcode
+
+Then, call the function NvBlastExtPxSerializerLoadSet, declared in <b>NvBlastExtPxSerialization.h</b>, passing in your TkFramework (required by ExtPhysX), along with
+your physx::PxPhysics and physx::PxCooking pointers:
+
+\code
+TkFramework* framework = ... // We must have created a TkFramework
+physx::PxPhysics* physics = ... // and PxPhysics
+physx::PxCooking* cooking = ... // and PxCooking
+
+NvBlastExtPxSerializerLoadSet(*framework, *physics, *cooking *ser);
+\endcode
+
+Now your serialization manager will have the serializers provided by this extension. Currently only ExtPxAsset serializers exist, with object type ID
+given by
+
+<br>
+<b>ExtPxObjectTypeID::Asset</b>
+<br>
+
+As with low-level assets, you can serialize using the serialization manager directly:
+
+\code
+const ExtPxAsset* asset = ... // Given pointer to an Nv::Blast::ExtPxAsset
+
+void* buffer;
+uint64_t size = ser->serializeIntoBuffer(buffer, asset, ExtPxObjectTypeID::Asset);
+\endcode
+
+or use the wrapper function defined in <b>NvBlastExtPxSerialization.h</b>:
+
+/code
+void* buffer;
+uint64_t size = NvBlastExtSerializationSerializeExtPxAssetIntoBuffer(buffer, *ser, asset);
+/endcode
+
+<br>
+*/
diff --git a/docs/_source/ext_serialization.txt b/docs/_source/ext_serialization.txt
index cae31a2..fe276f8 100644
--- a/docs/_source/ext_serialization.txt
+++ b/docs/_source/ext_serialization.txt
@@ -1,6 +1,193 @@
/*! \page pageextserialization Serialization (NvBlastExtSerialization)
-TBD
+\section serialization_intro Introduction
+
+This extension defines the Nv::Blast::ExtSerialization class, a modular serialization manager which can be extended to handle data types from different Blast&tm; modules
+(such as low-level, Tk, and ExtPhysX).
+
+An ExtSerialization manager is created using the global function NvBlastExtSerializationCreate:
+
+(From now on we'll assume we are using the Nv::Blast namespace.)
+
+\code
+ExtSerialization* ser = NvBlastExtSerializationCreate();
+\endcode
+
+ExtSerialization is capable of loading sets of serializers for different data types and encodings. The NvBlastExtSerialization extension comes with a set of low-level data serializers,
+with types enumerated in the header <b>NvBlastExtLlSerialization.h</b>.
+
+<b>The low-level serializers are automatically loaded into an ExtSerialization when it is created.</b>
+
+To load serializers for Tk and ExtPhysX assets, you must also load the extensions \ref pageexttkserialization and \ref pageextpxserialization, respectively. See the documentation for
+those modules.
+
+Each serializer is capable of reading (and writing, if it is not read-only) a single data type in a single encoding (format). Some serializers are read-only, in order to read legacy
+formats.
+
+The encodings available are enumerated in ExtSerialization::EncodingID. They are currently:
+
+- CapnProtoBinary - Uses Cap'n Proto's binary serialization format
+- Raw - For low-level NvBlastAsset and NvBlastFamily types, this is simply a memory copy. For Tk and ExtPx assets, this is the deprecated serialization format from Blast&tm; 1.0.
+
+<br>
+\section serialization_ser Serialization (writing)
+
+To serialize an object, the serialization manager's write encoding ID must be set to the desired value. By default it is set to EncodingID::CapnProtoBinary, as this is the only
+encoding which supports writing for all object types (at the present time). When other encodings become available, use ExtSerialization::setSerializationEncoding to set the write
+encoding to the desired type.
+
+Each serialization module defines the object types it can serialize. ExtSerialization defines the low-level types in <b>NvBlastExtLlSerialization.h</b>:
+
+- LlObjectTypeID::Asset - An NvBlastAsset
+- LlObjectTypeID::Family - An NvBlastFamily
+
+To serialize an object, for example an NvBlastAsset, use ExtSerialization::serializeIntoBuffer as follows:
+
+/code
+const NvBlastAsset* asset = ... // Given pointer to an NvBlastAsset
+
+void* buffer;
+uint64_t size = ser->serializeIntoBuffer(buffer, asset, LlObjectTypeID::Asset);
+/endcode
+
+If successful, the data is written into a buffer allocated using the NvBlastGlobals allocator, written to the "buffer" parameter, and the size of the buffer
+written is the return value of the function. If the function returns 0, then serialization was unsuccessful. Notice that the second function parameter is actually a void*,
+so it requires the last parameter to tell it what object it's serializing. A utility wrapper function is given in <b>NvBlastExtLlSerialization.h</b> which performs the
+same operation with an NvBlastAsset, so one could equivalently use
+
+/code
+void* buffer;
+uint64_t size = NvBlastExtSerializationSerializeAssetIntoBuffer(buffer, *ser, asset);
+/endcode
+
+A corresponding function also exists for NvBlastFamily, as well as other data types supported by other serialization extensions.
+
+This buffer may be written to disk, memory, networked, etc. Since the memory for the buffer is allocated using the allocator
+in NvBlastGlobals, it may be freed using the same allocator:
+
+\code
+NVBLAST_FREE(buffer)
+\endcode
+
+<br>
+\subsection bufferproviders Using a Buffer Provider
+
+If you wish to provide the serialization buffer by some means other than the NvBlastGlobals allocator, you may set a "buffer provider"
+in the serialization manager. A buffer provider is simply a callback that requests a buffer from the user of the necessary size.
+The user implements the interface ExtSerialization::BufferProvider, and passes a pointer to an instance of one to the serialization
+manager using ExtSerialization::setBufferProvider.
+
+For example:
+
+\code
+std::vector<char> growableBuffer;
+
+class MyBufferProvider : public Nv::Blast::ExtSerialization::BufferProvider
+{
+public:
+ MyBufferProvider(std::vector<char>& growableBuffer) : m_growableBuffer(growableBuffer) {}
+
+ virtual void* requestBuffer(size_t size) override
+ {
+ if (m_growableBuffer.size() < size)
+ {
+ m_growableBuffer.resize(size);
+ }
+ return m_growableBuffer.data();
+ }
+
+private:
+ std::vector<char>& m_growableBuffer;
+} myBufferProvider(growableBuffer);
+
+ser->setBufferProvider(&myBufferProvider);
+\endcode
+
+Passing NULL to setBufferProvider returns the serialization to its default behavior of using the NvBlastGlobals allocator.
+
+<br>
+\section serialization_deser Deserialization (reading)
+
+To deserialize an object, use the ExtSerialization::deserializeFromBuffer method. If you know the type of object in the buffer,
+you may directly cast the returned pointer to one of that type. For example, if the buffer contains an NvBlastAsset, use:
+
+\code
+const void* buffer = ... // A given buffer, may be read from disk, memory, etc.
+const uint64_t size = ... // The buffer's size in bytes
+
+NvBlastAsset* asset = static_cast<NvBlastAsset*>(ser->deserializeFromBuffer(buffer, size));
+\endcode
+
+This returns a valid pointer if deserialization was successful, or NULL otherwise. If no serializer is loaded which can handle
+the object type in the stream in its given encoding, it will fail and return NULL.
+
+Again, the memory for the asset is allocated using NvBlastGlobals, so that the asset may be released using
+
+\code
+NVBLAST_FREE(asset);
+\endcode
+
+<br>
+\section detecting_object_type Detecting the Object Type in a Buffer
+
+If you don't know the object type in the buffer, you may use the last (optional) argument in deserializeFromBuffer to return the type:
+
+\code
+uint32_t objTypeID;
+void* obj = ser->deserializeFromBuffer(buffer, size, &objTypeID);
+
+NVBLAST_CHECK_ERROR(obj != nullptr, "Object could not be read from buffer.", return);
+
+switch (objTypeID)
+{
+case LlObjectTypeID::Asset:
+ handleAssetLoad(static_cast<NvBlastAsset*>(obj));
+ break;
+case LlObjectTypeID::Family:
+ handleFamilyLoad(static_cast<NvBlastFamily*>(obj));
+ break;
+default:
+ NVBLAST_LOG_ERROR("Unknown object type ");
+}
+\endcode
+
+<br>
+\subsection peeking_and_skipping Peeking at and Skipping Buffer Data
+
+If a buffer contains multiple objects, you may peek at the buffer to get object information including object type, encoding, and data size, and skip to
+the next object in the buffer (whether or not you've chosen to read the current object). For example:
+
+\code
+const void* buffer = ... // The input buffer
+uint64_t size = ... // The input buffer size
+
+while (size)
+{
+ uint64_t objTypeID;
+ if (!ser->peekHeader(&objTypeID, NULL, NULL, buffer, size)) // Only reading the object type ID; may pass in NULL for the other header value pointers
+ {
+ break; // Read error, stop
+ }
+
+ if (objectShouldBeLoaded(objTypeID)) // Some function to determine whether or not we want this object
+ {
+ void* obj = ser->deserializeFromBuffer(buffer, size);
+ // Handle loaded object ...
+ }
+
+ // Jump to next object:
+ buffer = ser->skipObject(size, buffer); // Updates size as well
+}
+\endcode
+
+<br>
+\section serialization_term Cleaning Up
+
+When finished with the serialization manager, it may be released using its release() method:
+
+\code
+ser->release();
+\endcode
<br>
*/
diff --git a/docs/_source/ext_materials.txt b/docs/_source/ext_shaders.txt
index 8a31e52..3bfb37d 100644
--- a/docs/_source/ext_materials.txt
+++ b/docs/_source/ext_shaders.txt
@@ -1,37 +1,42 @@
/*! \page pageextshaders Damage Shaders (NvBlastExtShaders)
-Blast Extensions provide basic implementations of programs generating fracture commands, the first step in breaking a Blast&tm; Actor, see \ref splitting.
-These programs come as two shader functions (callbacks) for Actors with a support graph and Actors with just one chunk respectively.
+The Blast&tm; damage shader extension provides basic implementations of programs generating fracture commands, the first step in breaking a Blast&tm; Actor, see \ref splitting.
+These programs come as two shader functions (callbacks): one for Actors with a support graph, and one for Actors with just one chunk, respectively.
The NvBlastDamageProgram containing both shaders can be used for low-level directly (NvBlastActorGenerateFracture) or for TkActor's damage and fracture functions.
+For example, one may construct a damage program using the "shear" damage shaders declared in NvBlastExtDamageShaders.h:
+
\code
NvBlastDamageProgram damageProgram = { NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader };
\endcode
-The appropriate shader will be called for an Actor being processed, along with the necessary Actor's geometry and program parameters.
+The appropriate shader ("graph" or "subgraph") will be called for an Actor being processed, along with the Actor's necessary geometry and program parameters.
The parameters (NvBlastProgramParams) are set to contain
1. Material, something that describes an Actor properties (e.g. mass, stiffness, fragility) which are not expected to be changed often.
2. Damage description, something that describes a particular damage event (e.g. position, radius and force of explosion).
+For example:
+
\code
- NvBlastExtMaterial material = { singleChunkThreshold, graphChunkThreshold, bondTangentialThreshold, bondNormalThreshold, damageAttenuation };
+ NvBlastExtMaterial material = { health, minDamageThreshold, maxDamageThreshold };
NvBlastExtRadialDamageDesc damageDesc = { compressive, posX, posY, posZ, minR, maxR };
\endcode
When used with TkActor::damage() functions, TkActor will cache the necessary data for deferred processing through TkGroup. This includes accumulating damage requests for
-the same material and program parameter combination. A default material can be set for a TkFamily that all its Actors uses.
+the same material and program parameter combination. A default material can be set for a TkFamily that all its Actors uses.
+
+A Tk layer example follows.
\code
tkGroup->addActor(*tkActor);
tkActor->damage(damageProgram, damageDesc0, sizeof(NvBlastExtRadialDamageDesc), &material);
tkActor->damage(damageProgram, damageDesc1, sizeof(NvBlastExtRadialDamageDesc), &material);
tkGroup->process();
- tkGroup->sync();
\endcode
-In contrast, the user is responsible for providing all the damage descriptions persisting through the low-level NvBlastActorGenerateFracture call when not using the Tk layer.
+In contrast, the user is responsible for providing all the damage descriptions persisting through the low-level NvBlastActorGenerateFracture call when not using the Tk layer:
\code
NvBlastProgramParams programParams = { damageDescs, 2, &material };
diff --git a/docs/_source/ext_stress.txt b/docs/_source/ext_stress.txt
new file mode 100644
index 0000000..6ea909a
--- /dev/null
+++ b/docs/_source/ext_stress.txt
@@ -0,0 +1,119 @@
+/*! \page pageextstress Stress Solver Extension (NvBlastExtStress)
+
+
+The Blast&tm; stress solver extension provides implementation of quite fast and easy to use stress solver which works directly with bond graph. It simulates more
+complex damage model on support graph by allowing to apply forces on nodes of support graph (on chunks). The most common usage is just applying gravity force on a static construction
+so that it will fall apart at some point when carcass can't hold anymore. Dynamic actors are also supported, you could for example add centrifugal force so that rotating object fast enough will break bonds.
+
+It is also can be used as an another way to apply impact damage, which can give visually pleasant result of breaking actor in a weak place instead of the place of contact.
+
+<br>
+\section stresssolverfeatures Features
+
+- Requires only core \a NvBlast
+- Supports both static and dynamic actors
+- Propagates both linear and angular momentum
+- Graph complexity selection (reduces support graph to smaller size trade off speed and quality)
+- Apply stress damage on Blast Actor
+- Debug Render
+
+<br>
+\section stresssolvertunning Settings Tuning
+
+Computational time is linearly proprtional to \a bondIterationsPerFrame setting. To fine tune look for balance
+between \a bondIterationsPerFrame and \a graphReductionLevel . The more bond iterations
+are set the more precise computation will be. The smaller graph allows to make higher fidelity computations witihing
+the same bond iterations per frame (same time spent), but actual cracks (damaged bonds) will be more sparsed as the result.
+
+Debug render could help a lot with that, consider using \a stressSolver->fillDebugRender(...) for that.
+
+<br>
+\section stresssolverusage Usage
+
+In order to use it create an instance with \a ExtStressSolver::create(...).
+
+\code
+ExtStressSolver* stressSolver = ExtStressSolver::create(family, settings);
+\endcode
+
+\a ExtStressSolverSettings are passed in create function, but also can be changed at any time with \a stressSolver->setSettings(...).
+
+It fully utilizes the fact that it knows initial support graph structure and does maximum of processing
+in \a create(...) method calls. After that all actors split calls are synced internally quite fast and only the actual
+stress propagation takes most of computational time.
+
+Then you need to provide physics specific information (mass, volume, position, static) for every node in support graph since Blast itself is physics agnostic. There are two ways to do it, you can call \a stressSolver->setNodeInfo(...) for every graph node. Another was is to call stressSolver->setAllNodesInfoFromLL() once all the data will be populated using NvBlastAsset chunk's data, in particular
+\a volume and \a centroid are used. All nodes connected to 'world' chunk are marked as static.
+
+\code
+stressSolver->setAllNodesInfoFromLL();
+\endcode
+
+Stress solver needs to keep track for actor create/destroy events in order to update it's internal stress graph accordingly. So you need to call \a stressSolver->notifyActorCreated(actor) and \a stressSolver->notifyActorDestroyed(actor) every time actor is created or destroyed including the initial actor family had when stress solver were created. There is no need to track actors which contain only one or lesser graph nodes in that case \a notifyActorCreated(actor) returns 'false' as a hint, it means that stress solver will ignore them. For those actors applying forces is also doesn't make any sense.
+
+Typical update loop would can look like this:
+
+-# If split happend call relevant stressSolver->notifyActorCreated(actor) and stressSolver->notifyActorDestroyed(actor)
+-# Apply all forces, use \a stressSolver->addForce(...), stressSolver->addGravityForce(...), \a stressSolver->addAngularVelocity(...)
+-# Call \a stressSolver->update(). This is where all expensive computation happens.
+-# If \a stressSolver->getOverstressedBondCount() > 0 use one of \a stressSolver->generateFractureCommands() methods to get bond fracture commands and apply on them actors.
+
+Example code from ExtPxStressSolverImpl:
+
+\code
+void ExtPxStressSolverImpl::onActorCreated(ExtPxFamily& /*family*/, ExtPxActor& actor)
+{
+ if (m_solver->notifyActorCreated(*actor.getTkActor().getActorLL()))
+ {
+ m_actors.insert(&actor);
+ }
+}
+
+void ExtPxStressSolverImpl::onActorDestroyed(ExtPxFamily& /*family*/, ExtPxActor& actor)
+{
+ m_solver->notifyActorDestroyed(*actor.getTkActor().getActorLL());
+ m_actors.erase(&actor);
+}
+
+void ExtPxStressSolverImpl::update(bool doDamage)
+{
+ for (auto it = m_actors.getIterator(); !it.done(); ++it)
+ {
+ const ExtPxActor* actor = *it;
+
+ PxRigidDynamic& rigidDynamic = actor->getPhysXActor();
+ const bool isStatic = rigidDynamic.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC;
+ if (isStatic)
+ {
+ PxVec3 gravity = rigidDynamic.getScene()->getGravity();
+ PxVec3 localGravity = rigidDynamic.getGlobalPose().rotateInv(gravity);
+
+ m_solver->addGravityForce(*actor->getTkActor().getActorLL(), localGravity);
+ }
+ else
+ {
+ PxVec3 localCenterMass = rigidDynamic.getCMassLocalPose().p;
+ PxVec3 localAngularVelocity = rigidDynamic.getGlobalPose().rotateInv(rigidDynamic.getAngularVelocity());
+ m_solver->addAngularVelocity(*actor->getTkActor().getActorLL(), localCenterMass, localAngularVelocity);
+ }
+ }
+
+ m_solver->update();
+
+ if (doDamage && m_solver->getOverstressedBondCount() > 0)
+ {
+ NvBlastFractureBuffers commands;
+ m_solver->generateFractureCommands(commands);
+ if (commands.bondFractureCount > 0)
+ {
+ m_family.getTkFamily().applyFracture(&commands);
+ }
+ }
+}
+\endcode
+
+Have a look at \a ExtPxStressSolver implementation code, which is basically high level wrapper on \a NvBlastExtStress to couple it with PhysX&tm; and \a NvBlatExtPx extension (see \ref extpxstresssolver).
+
+<br>
+
+*/
diff --git a/docs/_source/ext_tkserialization.txt b/docs/_source/ext_tkserialization.txt
new file mode 100644
index 0000000..3addaae
--- /dev/null
+++ b/docs/_source/ext_tkserialization.txt
@@ -0,0 +1,45 @@
+/*! \page pageexttkserialization BlastTk Serialization (NvBlastExtTkSerialization)
+
+This extension contains serializers which can be loaded into the ExtSerialization manager defined in \ref pageextserialization.
+
+To use this extension, you must also load the ExtSerialization extension and create a serialization manager as described in \ref pageextserialization.
+
+We repeat this here (again, assuming we're in the Nv::Blast namespace):
+
+\code
+ExtSerialization* ser = NvBlastExtSerializationCreate();
+\endcode
+
+Then, call the function NvBlastExtTkSerializerLoadSet, declared in <b>NvBlastExtTkSerialization.h</b>, passing in your TkFramework:
+
+\code
+TkFramework* framework = ... // We must have created a TkFramework
+
+NvBlastExtTkSerializerLoadSet(*framework, *ser);
+\endcode
+
+Now your serialization manager will have the serializers provided by this extension. Currently only TkAsset serializers exist, with object type ID
+given by
+
+<br>
+<b>TkObjectTypeID::Asset</b>
+<br>
+
+As with low-level assets, you can serialize using the serialization manager directly:
+
+\code
+const TkAsset* asset = ... // Given pointer to an Nv::Blast::TkAsset
+
+void* buffer;
+uint64_t size = ser->serializeIntoBuffer(buffer, asset, TkObjectTypeID::Asset);
+\endcode
+
+or use the wrapper function defined in <b>NvBlastExtTkSerialization.h</b>:
+
+/code
+void* buffer;
+uint64_t size = NvBlastExtSerializationSerializeTkAssetIntoBuffer(buffer, *ser, asset);
+/endcode
+
+<br>
+*/
diff --git a/docs/_source/introduction.txt b/docs/_source/introduction.txt
index e9fca5f..3ff30b9 100644
--- a/docs/_source/introduction.txt
+++ b/docs/_source/introduction.txt
@@ -29,20 +29,26 @@ asset is initially instanced. Subsequent fracturing has the effect of breaking
\section support_model Support Model
Blast&tm; requires that support chunks form an <em>exact cover</em> (see the definition of exact coverage in \ref pagedefinitions).
-However, it is quite forgiving with respect to user input when creating an asset. The geometric interpretation of exact coverage is that
-the support chunks fill the space of the root (unfractured) chunk, without any volume being covered by more than one chunk. Upon
-asset creation, missing coverage will be filled in by Blast&tm;, by assigning support to chunks at the highest place possible (closest
-to root) in the hierarchy. If support is redundant, that is a chunk and one of its descendant chunks are both marked as support
-by the user, then Blast&tm; will remove support from the descendant chunk.
-
-Support chunks that are joined by bonds will be grouped together in the same actor when fracturing occurs. In order to take
-advantage of the chunk hieararchy to reduce the number of chunks which represent an actor physically and graphically, Blast&tm;
-calculates a list of <em>visible chunks</em> from the support chunks in an actor. These may be the support chunks, or they may
-be ancestors of support chunks if all descendant support chunks are in the actor.
+The geometric interpretation of exact coverage is that the support chunks fill the space of the root (unfractured) chunk, without
+any volume being covered by more than one chunk. A helper function are provided to modify a set of chunk descriptors so that they
+have exact coverage. This function fills in missing coverage by assigning support to chunks at the highest place possible (closest
+to root) in the hierarchy, and redundant support is removed: if a chunk and one of its descendant chunks are both marked as support,
+the function will remove support from the descendant chunk.
+
+Support chunks that are joined by bonds will be grouped together in the same actor when fracturing occurs. Bonds may be defined
+between any two support chunks, or between a support chunk and "the world." There is no corresponding "world chunk," but the bond
+represents a connection between the chunk and its external environment. All chunks with a support graph connected to the world
+will be put into the same actor. An expected use case is to make this actor static (or kinematic). Actors may be queried to
+determine if they are "world-bound."
+
+In order to take advantage of the chunk hieararchy to reduce the number of chunks which represent an actor physically and
+graphically, Blast&tm; calculates a list of <em>visible chunks</em> from the support chunks in an actor. These may be the support
+chunks, or they may be ancestors of support chunks if all descendant support chunks are in the actor.
Support chunks do not have to be leaves in the chunk hierarchy, nor do they have to be at the same depth in the hierarchy. Children
-of support chunks will always be the sole chunk in their actor, since there is no bond defined between them. If an actor consists of
-of a <em>subsupport chunk</em> (see \ref pagedefinitions), the visible chunk is the same chunk.
+of support chunks will always be the sole chunk in their actor, since there are no bonds defined between them. If an actor consists
+of a <em>subsupport chunk</em> (see \ref pagedefinitions), the visible chunk is the same chunk. The same is true if an actor consists
+of a <em>single</em> support chunk.
\section damage_model Damage Model
@@ -51,9 +57,9 @@ chunks in the support graph. The user applies damage to an actor at a given loc
loss of bond and chunk health is determined by a user-defined <em>material function</em>. In this way the user can customize the
effect of damage based upon the bonds' properties such as normal and area, as well as distance from impact location.
-Damage is applied from a damage event buffer. After all damage events are processed, bonds with non-positive healths are considered
-to be broken. Blast&tm; performs island detection on the support graph to find all groups of support chunks that are connected by unbroken
-bonds, and any new islands found result in new actors.
+Damage is applied during the processing of a damage event buffer. After all damage events are processed, bonds with non-positive
+healths are considered to be broken. Blast&tm; performs island detection on the support graph to find all groups of support chunks
+that are connected by unbroken bonds, and any new islands found result in new actors.
If an actor is composed of a single support or subsupport chunk with subsupport descendants, then there is no bond structure to model
damage. Instead, such a chunk is considered to have its own health value, which may be decreased by damage. When such a lower-support
diff --git a/docs/_source/legacy_converter.txt b/docs/_source/legacy_converter.txt
new file mode 100644
index 0000000..ff7048b
--- /dev/null
+++ b/docs/_source/legacy_converter.txt
@@ -0,0 +1,28 @@
+/*! \page pageconverter LegacyConverter
+
+\verbatim
+
+USAGE:
+
+ LegacyConverter <infile> [-t <type>] [-o <outfile>] [-e <encoding>]
+
+Where:
+
+ <infile> (required) Input legacy format file.
+
+ -t <type>
+ (optional) The file format of <infile>. Must be one of: {llasset, tkasset, bpxa, pllasset, ptkasset, pbpxa} (case insensitive).
+ If not given, the file extension of <infile> is used.
+
+ -outfile <outfile>
+ (optional) Filename (including path) of the output converted file.
+ If not given, the filename <infile> is used, with extension (if it has one) changed to .blast.
+
+ -e <encoding>
+ (optional) Encoding to use for output file. Must be one of: {cpnb, raw} (case insensitive).
+ If not given, cpnb (Cap'n Proto binary) is used.
+
+\endverbatim
+
+<br>
+*/
diff --git a/docs/_source/sample_asset_viewer.txt b/docs/_source/sample_asset_viewer.txt
index dd8b64c..61405d6 100644
--- a/docs/_source/sample_asset_viewer.txt
+++ b/docs/_source/sample_asset_viewer.txt
@@ -61,16 +61,15 @@ In Append mode (the other radio button), selecting a new asset will insert its a
You may also select actors in the Scene Actors list, and remove (or reload) the actor using the buttons below the list. Reloading an actor will restore it to its
unfractured state.
-Note, in addition to destructible actors, the Scene Actors list shows the boxes that were fired into the scene using the 'F' key. You may remove those using this
-UI as well.
+Note, in addition to destructible actors, the Scene Actors list shows the boxes that were fired into the scene using the 'F' key. Holding down the 'F' key "charges"
+the throw, increasing the cube's speed the longer you hold down the kye. You may remove the cubes using the scene controls. All cubes will be removed when the scene
+is reset.
The Blast Material properties are used by the various damage tools available.
-- singleChunkThreadhold = the damage a single lower-support chunk must take in order to fracture
-- graphChunkThreshold = the damage a support chunk must take in order to fracture
-- bondNormalThreshold = the damage a bond must take using compressive (e.g. radial damage) in order to break
-- bondTangentialThreshold = the damage a bond must take using shear (e.g. from directional damage) in order to break
-- damageAttenuation = how fast damage falls off in the materal from an impact location
+- Health = the value which damage must exceed to break a bond or chunk
+- Min Damage Threshold = a fraction of Health, below which damage has no effect
+- Max Damage Threshold = a fraction of Health, equal to the maximum damage that can be applied per damage event
A stress solver may be enabled by selcting the Stress Solver Enabled checkbox. When enabled you will be presented with several options.
NOTE: you must then select the Stress Damage Enabled checkbox in order to allow stress to do damage to the actors in the scene.
diff --git a/docs/_source/tools.txt b/docs/_source/tools.txt
index ffb3fc3..3ac7ebd 100644
--- a/docs/_source/tools.txt
+++ b/docs/_source/tools.txt
@@ -5,26 +5,15 @@
See \ref pagecopyrights for license information regarding third-party software used by the tools.
<br>
+\subpage pageimporter - Import Apex assets into Blast format.
-\section importer Apex Importer
-Import Apex assets into Blast format.
-
-\subpage pageimporter
-
-
-\section converter Data Converter
-
-Convert serialized data from an old format to the current format.
-
-\subpage pageconverter
-
-
-\section authoring Authoring Tool
+<br>
+\subpage pageauthoring - Command line authoring tool.
-Command line authoring tool.
-\subpage pageauthoring
+<br>
+\subpage pageconverter - Convert serialized data from legacy formats (.llasset, .tkasset, .bpxa, .pllasset, .ptkasset, .pbpxa) to the current unified (.blast) format.
<br>