diff options
| author | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
| commit | 7115f60b91b5717d90f643fd692010905c7004db (patch) | |
| tree | effd68c6978751c517d54c2f2bb5bb6e7dc93e18 /docs/_source/api_ll_users_guide.txt | |
| parent | Updating BlastTool zip (diff) | |
| download | blast-1.1.3_rc1.tar.xz blast-1.1.3_rc1.zip | |
Blast 1.1.3. See docs/release_notes.txt.v1.1.3_rc1
Diffstat (limited to 'docs/_source/api_ll_users_guide.txt')
| -rwxr-xr-x[-rw-r--r--] | docs/_source/api_ll_users_guide.txt | 786 |
1 files changed, 393 insertions, 393 deletions
diff --git a/docs/_source/api_ll_users_guide.txt b/docs/_source/api_ll_users_guide.txt index 8d04ee8..4626f8f 100644..100755 --- a/docs/_source/api_ll_users_guide.txt +++ b/docs/_source/api_ll_users_guide.txt @@ -1,393 +1,393 @@ -/*! \page pagellapi Low Level API (NvBlast) - -<b>Table of Contents</b> - -\subpage llintroduction - -\subpage include_and_library - -\subpage assets - -\subpage actors_and_families - -\subpage splitting - -<br> -\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, 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 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, 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 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. 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. -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. - -<br> -\section include_and_library Linking and Header Files - -To use the low-level Blast&tm; SDK, the application need only inlclude the header NvBlast.h, found in the top-level <b>include</b> folder, and link -against the appropriate version of the NvBlast library. Depending on the platform and configuration, various suffixes will be added to the library -name. The general naming scheme is - -NvBlast(config)(arch).(ext) - -(config) is DEBUG, CHECKED, OR PROFILE for the corresponding configurations. For a release configuration there is no (config) suffix. - -(arch) is _x86 or _x64 for Windows 32- and 64-bit builds, respectively, and empty for non-Windows platforms. - -(ext) is .lib for static linking and .dll for dynamic linking on Windows. On XBoxOne it is .lib, and on PS4 it is .a. - -<br> -\section assets Creating an Asset from a Descriptor (Authoring) - -The NvBlastAsset is an opaque type pointing to an object constructed by Blast&tm; in memory allocated by the user. -To create an asset from a descriptor, use the function \ref NvBlastCreateAsset. See the function documentation for a -description of its parameters. - -<b>N.B., there are strict rules for the ordering of chunks with an asset, and also conditions on the chunks marked as "support" -(using the NvBlastChunkDesc::SupportFlag). See the function documentation for these conditions. NvBlastCreateAsset does -<em>not</em> reorder chunks or modify support flags to meet these conditions. If the conditions are not met, NvBlastCreateAsset -fails and returns NULL. However, Blast&tm; provides helper functions to reorder chunk descriptors and modify the support flags -within those descriptors so that they are valid for asset creation. The helper functions return a mapping from the original -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. 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 - -chunkDescs[0].parentChunkIndex = UINT32_MAX; // invalid index denotes a chunk hierarchy root -chunkDescs[0].centroid[0] = 0.0f; // centroid position in asset-local space -chunkDescs[0].centroid[1] = 0.0f; -chunkDescs[0].centroid[2] = 0.0f; -chunkDescs[0].volume = 1.0f; // Unit volume -chunkDescs[0].flags = NvBlastChunkDesc::NoFlags; -chunkDescs[0].userData = 0; // User-supplied ID. For example, this can be the index of the chunkDesc. - // The userData can be left undefined. - -chunkDescs[1].parentChunkIndex = 0; // child of chunk described by chunkDescs[0] -chunkDescs[1].centroid[0] = 2.0f; // centroid position in asset-local space -chunkDescs[1].centroid[1] = 4.0f; -chunkDescs[1].centroid[2] = 6.0f; -chunkDescs[1].volume = 1.0f; // Unit volume -chunkDescs[1].flags = NvBlastChunkDesc::SupportFlag; // This chunk should be represented in the support graph -chunkDescs[1].userData = 1; - -// ... etc. for all chunks - -// Create bond descriptors -std::vector<NvBlastBondDesc> bondDescs; -bondDescs.resize( bondCount ); // bondCount > 0 - -bondDescs[0].chunkIndices[0] = 1; // chunkIndices refer to chunk descriptor indices for support chunks -bondDescs[0].chunkIndices[1] = 2; -bondDescs[0].bond.normal[0] = 1.0f; // normal in the +x direction -bondDescs[0].bond.normal[1] = 0.0f; -bondDescs[0].bond.normal[2] = 0.0f; -bondDescs[0].bond.area = 1.0f; // unit area -bondDescs[0].bond.centroid[0] = 1.0f; // centroid position in asset-local space -bondDescs[0].bond.centroid[1] = 2.0f; -bondDescs[0].bond.centroid[2] = 3.0f; -bondDescs[0].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 - -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; -assetDesc.chunkCount = chunkCount; -assetDesc.chunkDescs = chunkDescs.data(); -assetDesc.bondCount = bondCount; -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(), 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(), 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(), logFn ); -\endcode - -<br> -It should be noted that the geometric information (centroid, volume, area, normal) in chunks and bonds is only used by damage -shader functions (see \ref pageextshaders). Depending on the shader, some, all, or none of the geometric information will be needed. -The user may write damage shader functions that interpret this data in any way they wish. - -<br> -\subsection asset_copying Cloning an Asset - -To clone an asset, one only needs to copy the memory associated with the NvBlastAsset. - -\code -uint32_t assetSize = NvBlastAssetGetSize( asset ); - -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 <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 with memory allocated by <B>malloc</B> is simply done with a call to <B>free</B>: - -\code -free( asset ); -\endcode - -<br> -\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 descendant 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, logFn ) ); - -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: - -\code -// Set the fields of the descriptor -NvBlastActorDesc actorDesc; -actorDesc.asset = asset; // point to a valid asset -actorDesc.initialBondHealth = 1.0f; // this health value will be given to all bonds -actorDesc.initialChunkHealth = 1.0f; // this health value will be given to all lower-support chunks - -// Provide scratch memory -std::vector<char> scratch( NvBlastFamilyGetRequiredScratchForCreateFirstActor( &actorDesc ) ); - -// Create the first actor -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 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 Cloning a Family - -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, logFn ); -\endcode - -Then the size of the family may be obtained using: - -\code -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: - -\code -std::vector<char> buffer( size ); -NvBlastFamily* family2 = reinterpret_cast<NvBlastFamily*>( buffer.data() ); -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 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 = NvBlastFamilyGetAssetID( family2, logFn ); -// ... here the user must retrieve the asset using the GUID or by some other means -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, logFn ); -std::vector<NvBlastActor*> actors( actorCount ); -uint32_t actorsWritten = NvBlastFamilyGetActors( actors.data(), actorCount, family2, logFn ); -\endcode - -In the code above, actorsWritten should equal actorCount. - -<br> -\subsection single_actor_serialization Single Actor Serialization - -To perform single-actor serialization, first find the buffer size required to store the serialization data: - -\code -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, 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, 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 -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(), logFn ); -\endcode - -If newActor is not NULL, then the actor was successfully deserialized. - -<br> -\section actor_deactivating Deactivating an Actor - -Actors may not be released in the usual sense of deallocation. This is because actors' memory is stored as a block within the owning family. The -memory is only released when the family is released. However, one may deactivate an actor using NvBlastActorDeactivate. -This clears the actor's chunk lists and marks it as invalid, effectively disassociating it from the family. The user should consider this actor -to be destroyed. - -\code -bool success = NvBlastActorDeactivate( actor, logFn ); -\endcode - -<br> -\subsection family_releasing Releasing a family - -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 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 query -the number of active actors in a family using - -\code -uint32_t actorCount = NvBlastFamilyGetActorCount( family, logFn ); -\endcode - - -<br> -\section splitting Damage and Fracturing - -Damaging and fracturing is a staged process. -In a first step, a \ref NvBlastDamageProgram creates lists of Bonds and Chunks to damage - so called Fracture Commands. -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 parameters. -Different functions can have the effect of emulating different physical materials.<br> -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. - -The second stage is carried out with \ref NvBlastActorApplyFracture. This function takes the previously generated Fracture Commands and applies them to the NvBlastActor. -The result of every applied command is reported as a respective Fracture Event if requested. - -Fracture Commands and Fracture Events both are represented by \ref NvBlastFractureBuffers. -The splitting of the actor into child actors is not done until the third stage, \ref NvBlastActorSplit, is called. -Fractures may be repeatedly applied to an actor before splitting. - -The \ref NvBlastActorGenerateFracture, \ref NvBlastActorApplyFracture and \ref NvBlastActorSplit functions are profiled in Profile configurations. -This is done through a pointer to a NvBlastTimers struct passed into the functions. -If this pointer is not NULL, then timing values will be accumulated in the referenced struct. - -The following example illustrates the process: - -\code -// Step one: Generate Fracture Commands - -// Damage programs (shader functions), material properties and damage description relate to each other. -// Together they define how actors will break by generating the desired set of Fracture Commands for Bonds and Chunks. -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 ); - - -// Step two: Apply Fracture Commands - -// 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 ); - - -// Step three: Splitting - -// The Actor may be split into all its smallest pieces. -uint32_t maxNewActorCount = NvBlastActorGetMaxActorCountForSplit( actor, logFn ); -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, 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 ); -\endcode - -<br> -*/ +/*! \page pagellapi Low Level API (NvBlast)
+
+<b>Table of Contents</b>
+
+\subpage llintroduction
+
+\subpage include_and_library
+
+\subpage assets
+
+\subpage actors_and_families
+
+\subpage splitting
+
+<br>
+\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, 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 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, 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 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. 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.
+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.
+
+<br>
+\section include_and_library Linking and Header Files
+
+To use the low-level Blast&tm; SDK, the application need only inlclude the header NvBlast.h, found in the top-level <b>include</b> folder, and link
+against the appropriate version of the NvBlast library. Depending on the platform and configuration, various suffixes will be added to the library
+name. The general naming scheme is
+
+NvBlast(config)(arch).(ext)
+
+(config) is DEBUG, CHECKED, OR PROFILE for the corresponding configurations. For a release configuration there is no (config) suffix.
+
+(arch) is _x86 or _x64 for Windows 32- and 64-bit builds, respectively, and empty for non-Windows platforms.
+
+(ext) is .lib for static linking and .dll for dynamic linking on Windows. On XBoxOne it is .lib, and on PS4 it is .a.
+
+<br>
+\section assets Creating an Asset from a Descriptor (Authoring)
+
+The NvBlastAsset is an opaque type pointing to an object constructed by Blast&tm; in memory allocated by the user.
+To create an asset from a descriptor, use the function \ref NvBlastCreateAsset. See the function documentation for a
+description of its parameters.
+
+<b>N.B., there are strict rules for the ordering of chunks with an asset, and also conditions on the chunks marked as "support"
+(using the NvBlastChunkDesc::SupportFlag). See the function documentation for these conditions. NvBlastCreateAsset does
+<em>not</em> reorder chunks or modify support flags to meet these conditions. If the conditions are not met, NvBlastCreateAsset
+fails and returns NULL. However, Blast&tm; provides helper functions to reorder chunk descriptors and modify the support flags
+within those descriptors so that they are valid for asset creation. The helper functions return a mapping from the original
+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. 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
+
+chunkDescs[0].parentChunkIndex = UINT32_MAX; // invalid index denotes a chunk hierarchy root
+chunkDescs[0].centroid[0] = 0.0f; // centroid position in asset-local space
+chunkDescs[0].centroid[1] = 0.0f;
+chunkDescs[0].centroid[2] = 0.0f;
+chunkDescs[0].volume = 1.0f; // Unit volume
+chunkDescs[0].flags = NvBlastChunkDesc::NoFlags;
+chunkDescs[0].userData = 0; // User-supplied ID. For example, this can be the index of the chunkDesc.
+ // The userData can be left undefined.
+
+chunkDescs[1].parentChunkIndex = 0; // child of chunk described by chunkDescs[0]
+chunkDescs[1].centroid[0] = 2.0f; // centroid position in asset-local space
+chunkDescs[1].centroid[1] = 4.0f;
+chunkDescs[1].centroid[2] = 6.0f;
+chunkDescs[1].volume = 1.0f; // Unit volume
+chunkDescs[1].flags = NvBlastChunkDesc::SupportFlag; // This chunk should be represented in the support graph
+chunkDescs[1].userData = 1;
+
+// ... etc. for all chunks
+
+// Create bond descriptors
+std::vector<NvBlastBondDesc> bondDescs;
+bondDescs.resize( bondCount ); // bondCount > 0
+
+bondDescs[0].chunkIndices[0] = 1; // chunkIndices refer to chunk descriptor indices for support chunks
+bondDescs[0].chunkIndices[1] = 2;
+bondDescs[0].bond.normal[0] = 1.0f; // normal in the +x direction
+bondDescs[0].bond.normal[1] = 0.0f;
+bondDescs[0].bond.normal[2] = 0.0f;
+bondDescs[0].bond.area = 1.0f; // unit area
+bondDescs[0].bond.centroid[0] = 1.0f; // centroid position in asset-local space
+bondDescs[0].bond.centroid[1] = 2.0f;
+bondDescs[0].bond.centroid[2] = 3.0f;
+bondDescs[0].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
+
+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;
+assetDesc.chunkCount = chunkCount;
+assetDesc.chunkDescs = chunkDescs.data();
+assetDesc.bondCount = bondCount;
+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(), 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(), 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(), logFn );
+\endcode
+
+<br>
+It should be noted that the geometric information (centroid, volume, area, normal) in chunks and bonds is only used by damage
+shader functions (see \ref pageextshaders). Depending on the shader, some, all, or none of the geometric information will be needed.
+The user may write damage shader functions that interpret this data in any way they wish.
+
+<br>
+\subsection asset_copying Cloning an Asset
+
+To clone an asset, one only needs to copy the memory associated with the NvBlastAsset.
+
+\code
+uint32_t assetSize = NvBlastAssetGetSize( asset );
+
+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 <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 with memory allocated by <B>malloc</B> is simply done with a call to <B>free</B>:
+
+\code
+free( asset );
+\endcode
+
+<br>
+\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 descendant 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, logFn ) );
+
+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:
+
+\code
+// Set the fields of the descriptor
+NvBlastActorDesc actorDesc;
+actorDesc.asset = asset; // point to a valid asset
+actorDesc.initialBondHealth = 1.0f; // this health value will be given to all bonds
+actorDesc.initialChunkHealth = 1.0f; // this health value will be given to all lower-support chunks
+
+// Provide scratch memory
+std::vector<char> scratch( NvBlastFamilyGetRequiredScratchForCreateFirstActor( &actorDesc ) );
+
+// Create the first actor
+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 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 Cloning a Family
+
+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, logFn );
+\endcode
+
+Then the size of the family may be obtained using:
+
+\code
+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:
+
+\code
+std::vector<char> buffer( size );
+NvBlastFamily* family2 = reinterpret_cast<NvBlastFamily*>( buffer.data() );
+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 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 = NvBlastFamilyGetAssetID( family2, logFn );
+// ... here the user must retrieve the asset using the GUID or by some other means
+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, logFn );
+std::vector<NvBlastActor*> actors( actorCount );
+uint32_t actorsWritten = NvBlastFamilyGetActors( actors.data(), actorCount, family2, logFn );
+\endcode
+
+In the code above, actorsWritten should equal actorCount.
+
+<br>
+\subsection single_actor_serialization Single Actor Serialization
+
+To perform single-actor serialization, first find the buffer size required to store the serialization data:
+
+\code
+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, 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, 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
+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(), logFn );
+\endcode
+
+If newActor is not NULL, then the actor was successfully deserialized.
+
+<br>
+\section actor_deactivating Deactivating an Actor
+
+Actors may not be released in the usual sense of deallocation. This is because actors' memory is stored as a block within the owning family. The
+memory is only released when the family is released. However, one may deactivate an actor using NvBlastActorDeactivate.
+This clears the actor's chunk lists and marks it as invalid, effectively disassociating it from the family. The user should consider this actor
+to be destroyed.
+
+\code
+bool success = NvBlastActorDeactivate( actor, logFn );
+\endcode
+
+<br>
+\subsection family_releasing Releasing a family
+
+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 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 query
+the number of active actors in a family using
+
+\code
+uint32_t actorCount = NvBlastFamilyGetActorCount( family, logFn );
+\endcode
+
+
+<br>
+\section splitting Damage and Fracturing
+
+Damaging and fracturing is a staged process.
+In a first step, a \ref NvBlastDamageProgram creates lists of Bonds and Chunks to damage - so called Fracture Commands.
+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 parameters.
+Different functions can have the effect of emulating different physical materials.<br>
+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.
+
+The second stage is carried out with \ref NvBlastActorApplyFracture. This function takes the previously generated Fracture Commands and applies them to the NvBlastActor.
+The result of every applied command is reported as a respective Fracture Event if requested.
+
+Fracture Commands and Fracture Events both are represented by \ref NvBlastFractureBuffers.
+The splitting of the actor into child actors is not done until the third stage, \ref NvBlastActorSplit, is called.
+Fractures may be repeatedly applied to an actor before splitting.
+
+The \ref NvBlastActorGenerateFracture, \ref NvBlastActorApplyFracture and \ref NvBlastActorSplit functions are profiled in Profile configurations.
+This is done through a pointer to a NvBlastTimers struct passed into the functions.
+If this pointer is not NULL, then timing values will be accumulated in the referenced struct.
+
+The following example illustrates the process:
+
+\code
+// Step one: Generate Fracture Commands
+
+// Damage programs (shader functions), material properties and damage description relate to each other.
+// Together they define how actors will break by generating the desired set of Fracture Commands for Bonds and Chunks.
+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 );
+
+
+// Step two: Apply Fracture Commands
+
+// 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 );
+
+
+// Step three: Splitting
+
+// The Actor may be split into all its smallest pieces.
+uint32_t maxNewActorCount = NvBlastActorGetMaxActorCountForSplit( actor, logFn );
+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, 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 );
+\endcode
+
+<br>
+*/
|