aboutsummaryrefslogtreecommitdiff
path: root/docs/_source/api_ll_users_guide.txt
diff options
context:
space:
mode:
authorBryan Galdrikian <[email protected]>2017-02-24 09:32:20 -0800
committerBryan Galdrikian <[email protected]>2017-02-24 09:32:20 -0800
commite1bf674c16e3c8472b29574159c789cd3f0c64e0 (patch)
tree9f0cfce09c71a2c27ff19589fcad6cd83504477c /docs/_source/api_ll_users_guide.txt
parentfirst commit (diff)
downloadblast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.tar.xz
blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.zip
Updating to [email protected] and [email protected] with a new directory structure.
NvBlast folder is gone, files have been moved to top level directory. README is changed to reflect this.
Diffstat (limited to 'docs/_source/api_ll_users_guide.txt')
-rw-r--r--docs/_source/api_ll_users_guide.txt389
1 files changed, 389 insertions, 0 deletions
diff --git a/docs/_source/api_ll_users_guide.txt b/docs/_source/api_ll_users_guide.txt
new file mode 100644
index 0000000..33d12db
--- /dev/null
+++ b/docs/_source/api_ll_users_guide.txt
@@ -0,0 +1,389 @@
+/*! \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, or rather <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
+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.
+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.
+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
+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
+
+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 NvBlastAssetCreate. 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. NvBlastAssetCreate does
+<em>not</em> reorder chunks or modify support flags to meet these conditions. If the conditions are not met, NvBlastAssetCreate
+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.
+
+\code
+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.f; // centroid position in asset-local space
+chunkDescs[0].centroid[1] = 0.f;
+chunkDescs[0].centroid[2] = 0.f;
+chunkDescs[0].volume = 1.f; // Unit volume
+chunkDescs[0].flags = NvBlastChunkDesc::NoFlags;
+chunkDescs[0].ID = 0; // User-supplied ID. For example, this can be the index of the chunkDesc.
+ // The ID can be left undefined.
+
+chunkDescs[1].parentChunkIndex = 0; // child of chunk described by chunkDescs[0]
+chunkDescs[1].centroid[0] = 2.f; // centroid position in asset-local space
+chunkDescs[1].centroid[1] = 4.f;
+chunkDescs[1].centroid[2] = 6.f;
+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.
+
+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.m_normal[0] = 1.f; // normal in the +x direction
+bondDescs[0].bond.m_normal[1] = 0.f;
+bondDescs[0].bond.m_normal[2] = 0.f;
+bondDescs[0].bond.m_area = 1.0; // unit area
+bondDescs[0].bond.m_centroid[0] = 1.f; // centroid position in asset-local space
+bondDescs[0].bond.m_centroid[1] = 2.f;
+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.
+
+// 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(), nullptr );
+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 );
+
+// 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
+\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 (Serialization and Deserialization)
+
+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.
+
+\code
+uint32_t assetSize = NvBlastAssetGetSize( data );
+
+NvBlastAsset* newAsset = (NvBlastAsset*)malloc(assetSize); // NOTE: the memory buffer <em> must <\em> 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.
+
+<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:
+
+\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 descendent actors created by recursively fracturing the initial actor. Like 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 ) );
+
+NvBlastFamily* family = NvBlastAssetCreateFamily( mem, &asset, nullptr );
+\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(), nullptr ); // 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.
+
+<br>
+\subsection family_serialization Family Serialization
+
+To serialize 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 );
+\endcode
+
+Then the size of the family may be obtained using:
+
+\code
+size_t size = NvBlastFamilyGetSize( family, nullptr );
+\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 GUID, 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 );
+// ... here the user must retrieve the asset using the GUID or by some other means
+NvBlastFamilySetAsset( family2, asset, nullptr );
+\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 );
+std::vector<NvBlastActor*> actors( actorCount );
+uint32_t actorsWritten = NvBlastFamilyGetActors( actors.data(), actorCount, family2, nullptr );
+\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, nullptr );
+\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 );
+\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 );
+\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 );
+\endcode
+
+Then deserialize into the family:
+
+\code
+NvBlastActor* newActor = NvBlastFamilyDeserializeActor( family, buffer.data(), nullptr );
+\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 ); // actor should always be a pointer, as it is an opaque type
+\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 NvBlastAsse, memory is
+allocated by the user, so to release the family simply free that memory:
+
+\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
+
+\code
+uint32_t actorCount = NvBlastFamilyGetActorCount( family, nullptr );
+\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
+
+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 paramters.
+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.
+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 = NvBlastActorSplitMaxActorCount(actor);
+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));
+
+// 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>
+*/