aboutsummaryrefslogtreecommitdiff
path: root/docs/_source/api_hl_users_guide.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/_source/api_hl_users_guide.txt')
-rwxr-xr-x[-rw-r--r--]docs/_source/api_hl_users_guide.txt1410
1 files changed, 705 insertions, 705 deletions
diff --git a/docs/_source/api_hl_users_guide.txt b/docs/_source/api_hl_users_guide.txt
index ae8dd4a..34d843e 100644..100755
--- a/docs/_source/api_hl_users_guide.txt
+++ b/docs/_source/api_hl_users_guide.txt
@@ -1,705 +1,705 @@
-/*! \page pagehlapi High Level (Toolkit) API (NvBlastTk)
-
-<b>Table of Contents</b>
-
-\subpage tkintroduction
-
-\subpage tk_class_hierarchy
-
-\subpage tk_include_and_library
-
-\subpage framework_init
-
-\subpage tkasset_creation
-
-\subpage tkasset_instancing
-
-\subpage tkgroups
-
-\subpage damage_in_tk
-
-\subpage tkjoints
-
-\subpage tkevents
-
-\subpage tktypes
-
-<br>
-\section tkintroduction Introduction to NvBlastTk
-
-The high-level API, NvBlastTk (Tk stands for "toolkit"), is intended to be a more powerful library and a much more convenient entry point
-into the use of Blast&tm;. Like the low-level library, Tk is physics and graphics-agnostic. Whereas the low-level API is C-style, Tk uses
-a C++ API. Everything in Tk is in the namespace:
-
-\code
-Nv::Blast
-\endcode
-
-(the only exceptions are global-scope functions to create and access a framework singleton, see below).
-Every object in Tk is prefixed with 'Tk'. For example, the Tk framework interface is:
-
-\code
-Nv::Blast::TkFramework
-\endcode
-
-<b>
-For the remainder of this page we will be in the Nv::Blast namespace, and will drop the explicit scope Nv::Blast:: from our names.
-</b>
-<br>
-<br>
-
-
-BlastTk adds:
-
-- An object class hierarchy (see \ref tk_class_hierarchy, below).
-- 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.
-- 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, these "joints" only hold descriptor data, since physical objects are not handled by BlastTk.
-
-<br>
-\section tk_class_hierarchy NvBlastTk Class Hierarchy
-
-- There are two abstract interfaces, one of which deriving from the other: <b>TkObject <- TkIdentifiable</b>.
- - Lightweight objects are derived from <b>TkObject</b>.
- - Objects which use a GUID and class identification are derieved from <b>TkIdentifiable</b>.
-- <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 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>. <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
-
-To use the BlastTk library, the application need only inlclude the header NvBlastTk.h, found in the <b>include/toolkit</b> folder, and link
-against the appropriate version of the NvBlastTk library. Depending on the platform and configuration, various suffixes will be added to the library
-name. The general naming scheme is
-
-NvBlastTk(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 framework_init Creating the TkFramework
-
-As a reminder, in this document we assume we are in the Nv::Blast namespace:
-
-\code
-using namespace Nv::Blast;
-\endcode
-
-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();
-\endcode
-
-The framework may be accessed via:
-
-\code
-TkFramework* framework = NvBlastTkFrameworkGet();
-\endcode
-
-In the sections that follow, it is assumed that a framework has been created, and we have a pointer to it named 'framework' within scope.
-
-Finally, to release the framework, use
-
-\code
-framework->release();
-\endcode
-
-This will release all assets, families, actors, joints, and groups.
-
-<br>
-\section tkasset_creation Creating a TkAsset
-
-The TkAsset object is a high-level wrapper for the low-level NvBlastAsset (see \ref assets). The descriptor used to create a TkAsset, a TkAssetDesc, is derived from
-NvBlastAssetDesc. The base fields should be filled in as described in (\ref assets). The new field is an optional array of flags to be associated with each bond in
-the base descriptor. Currently the only flag is "BondJointed," and if set will cause an "internal joint" to be created in actors (TkActor type) created from the asset.
-See (\ref tkjoints) for more on joints in BlastTk.
-
-\code
-TkAssetDesc desc;
-
-myFunctionToFillInLowLevelAssetFields(desc); // Fill in the low-level (NvBlastAssetDesc) fields as usual
-
-std::vector<uint8_t*> bondFlags(desc.bondCount, 0); // Clear all flags
-
-// Set BondJointed flags corresponding to joints selected by the user (assumes a myBondIsJointedFunction to make this selection)
-for (uint32_t i = 0; i < desc.bondCount; ++i)
-{
- if (myBondIsJointedFunction(i)) // User-authored
- {
- bondFlags[i] |= TkAssetDesc::BondJointed;
- }
-}
-
-TkAsset* asset = framework->createAsset(desc); // Create a new TkAsset
-\endcode
-
-The createAsset function used above creates a low-level NvBlastAsset from the base fields of the descriptor, and then adds internal joint descriptors based
-upon the bonds' centroids and attached chunks. An alternative method to create a TkAsset allows the user to pass in a pre-existing NvBlastAsset, and a list
-of joint descriptors. If the TkAsset is to have no internal joints, then the joint descriptors are not necessary and with an NvBlastAsset
-pointer <b>llAsset</b>, a TkAsset may be created simply by using
-
-\code
-TkAsset* asset = framework->createAsset(llAsset);
-\endcode
-
-By default, such a TkAsset will not "own" the llAsset. When the TkAsset is released, the llAsset memory will be untouched. You can pass ownership to the
-TkAsset using all of the default parameters of the createAsset function:
-
-\code
-TkAsset* asset = framework->createAsset(llAsset, nullptr, 0, true);
-\endcode
-
-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
-the nodes indices are those of the graph nodes that correspond to support chunks. These indices are not, in general, the same as the chunk indices.
-An example of initialization of the joint descriptors is given below.
-
-\code
-std::vector<TkAssetJointDesc> jointDescs(jointCount); // Assume jointCount = the number of joints to add
-jointDescs[0].nodeIndices[0] = 0; // Attach node 0 to node 1
-jointDescs[0].nodeIndices[1] = 1;
-jointDescs[0].attachPoistions[0] = physx::PxVec3( 1.0f, 2.0f, 3.0f ); // Attachment positions are often the same within an asset, but they don't have to be
-jointDescs[0].attachPoistions[1] = physx::PxVec3( 1.0f, 2.0f, 3.0f );
-// ... etc.
-
-TkAsset* asset = framework->createAsset(llAsset, jointDescs.data(), jointDescs.size());
-\endcode
-
-The code above assumes you know the support graph nodes to which you'd like to attach joints. Often, the user only knows the corresponding chunk indices.
-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, 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
-
-\code
-uint32_t nodeIndex = map[chunkIndex];
-\endcode
-
-If the chunk indexed by <b>chunkIndex</b> does <em>not</em> correspond to a support chunk, then the mapped value will be UINT32_MAX, the invalid index.
-Otherwise, the mapped value will be a valid graph node index.
-
-Finally, to release a TkAsset, as with any TkObject-derived object, use the release() method:
-
-\code
-asset->release();
-\endcode
-
-<br>
-\section tkasset_instancing Instancing a TkAsset: Creation of a TkActor and a TkFamily
-
-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 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 role in NvBlastTk, holding user-supplied event listeners (\ref 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
-child actors from it. TkActor creation or release that occurs from an explicit API call do not produce events. For example when creating a first unfractured
-instance of an asset using createAsset, or when calling the release() method on a TkActor. TkJoint events are similarly broadcast to
-receivers (TkJointEvent). These signal when the actors which are joined by the joints change, so that the user may update a corresponding physical joint.
-They also signal when a joint no longer attaches actors and is therefore unreferenced. The user may invalidate or release the joint using the TkObject
-release() method when this occurs (more on joint ownership in \ref tkjoints).
-
-To create an unfractured TkActor instance from a TkAsset, one first fills in a descriptor (\ref TkActorDesc) and passes it to the framework's createActor function.
-As with the TkAssetDesc, the TkActorDesc is derived from its low-level counterpart, the NvBlastActorDesc. In addition the TkActorDesc holds a pointer to
-the TkAsset being instanced. An example of TkActor creation is given below, given a TkAsset pointer <b>asset</b>.
-
-\code
-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
-
-The TkFamily created with the actor above may be accessed through the actor's getFamily field:
-
-\code
-TkFamily& family = actor->getFamily();
-\endcode
-
-The returned value is a reference since a TkActor's family can never be NULL. Actors resulting from the split of a "parent" actor will always belong to the
-parent's family.
-
-For most applications, the user will need to create a listener object to pass to every family created, in order to keep their physics and graphics representations
-in sync with the splitting of the TkActor. For more on this, see \ref tkevents.
-
-<br>
-\section tkgroups Groups
-
-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.
-
-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::ExtGroupTaskManager (in NvBlastExtPxTask.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.
-
-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.
-
-A typical usage is outlined below. See \ref damage_in_tk for methods of applying damage to actors.
-
-\code
-// Create actors from descriptors desc1, desc2, ... etc., and attach a listener to each new family created
-TkActor* actor1 = framework->createActor(desc1);
-actor1->getFamily().addListener(gMyReceiver); // gMyReceiver is a TkEventListener-derived object. More on events in a subsequent section.
-TkActor* actor2 = framework->createActor(desc2);
-actor2->getFamily().addListener(gMyReceiver);
-TkActor* actor3 = framework->createActor(desc3);
-actor3->getFamily().addListener(gMyReceiver);
-// etc...
-
-// Let's create two groups. First, create a group descriptor. This may be used to create both groups.
-TkGroupDesc groupDesc;
-groupDesc.workerCount = 1; // this example processes groups on the calling thread only
-
-// Now create the groups
-TkGroup* group1 = framework->createGroup(groupDesc);
-TkGroup* group2 = framework->createGroup(groupDesc);
-
-// Add actor1 and actor2 to group1, and actor2 to group3...
-group1->addActor(actor1);
-group1->addActor(actor2);
-group2->addActor(actor3);
-// etc...
-
-// Now apply damage to all actors - *NOTE* damage is described in detail in the next section.
-// For now we will just assume a "myDamageFunction" to apply the damage.
-myDamageFunction(actor1);
-myDamageFunction(actor2);
-myDamageFunction(actor3);
-// etc...
-
-// Calling the groups' process functions will (synchronously) run all jobs to process damage taken by the contained actors.
-group1->process();
-group2->process();
-
-// When the groups are no longer needed, they may be released with the usual release method.
-group1->release();
-group2->release();
-\endcode
-
-<br>
-<b>Multithreaded processing</b>
-
-When distributing the jobs as mentioned above, every job must be processed exactly once (over all user tasks).
-
-The number of jobs processed per worker can range from a single job (resulting in a user task per job) to all jobs (like Nv::Blast::TkGroup::process() does).
-
-At any point in time, no more than the set workerCount amount of workers may have been acquired. Return the worker at the end of each task.
-
-\code
-Nv::Blast::TkGroupWorker* worker = group->acquireWorker();
-// process some jobs
-group->returnWorker(worker);
-\endcode
-
-<br>
-\section damage_in_tk Applying Damage to Actors and Families
-
-Damage in NvBlastTk uses the same damage program scheme as the low-level SDK (see \ref splitting). One passes the program
-(NvBlastDamageProgram), damage descriptor (program-dependent), and material (also program-dependent) to a TkActor::damage
-function. Ultimately, the damage descriptor and material data are all parameters used by the damage program. The distinction
-is that the damage descriptor should describe properties of the thing doing the damage, while the material should
-describe properties of the actor (the thing being damaged). The interpretation of this data is entirely up to the program's
-functions, however.
-
-For convenience, the user may set a default material in the actor's family. This assumes, of course, that the material parameters
-for this default are compatible with the program being used to damage the family's actors.
-
-Examples of the three TkActor damage methods are given below.
-
-<br>
-\subsection multiple_damage Multiple Damage Descriptors using NvBlastProgramParams
-
-<b>N.B. - with this method of damage, the lifetime of the NvBlastProgramParams <em>must</em> extend at
-least until the TkGroup::endProcess call for the actor.</b>
-
-\code
-NvBlastDamageProgram program =
-{
- myGraphShaderFunction, // A function with the NvBlastGraphShaderFunction signature
- mySubgraphShaderFunction // A function with the NvBlastSubgraphShaderFunction signature
-};
-
-// The example struct "RadialDamageDesc" is modeled after NvBlastExtRadialDamageDesc in the NvBlastExtShaders extension
-RadialDamageDesc damageDescs[2];
-
-damageDescs[0].compressive = 10.0f;
-damageDescs[0].position[0] = 1.0f;
-damageDescs[0].position[1] = 2.0f;
-damageDescs[0].position[2] = 3.0f;
-damageDescs[0].minRadius = 0.0f;
-damageDescs[0].maxRadius = 1.0f;
-
-damageDescs[1].compressive = 100.0f;
-damageDescs[1].position[0] = 3.0f;
-damageDescs[1].position[1] = 4.0f;
-damageDescs[1].position[2] = 5.0f;
-damageDescs[1].minRadius = 0.0f;
-damageDescs[1].maxRadius = 5.0f;
-
-// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
-Material material;
-
-material.health = 10.0f;
-material.minDamageThreshold = 0.1f;
-material.maxDamageThreshold = 0.8f;
-
-// Set the damage params struct
-NvBlastProgramParams params = { damageDescs, 2, &material };
-
-// Apply damage
-actor->damage(program, &params); // params must be kept around until TkGroup::endProcess is called!
-\endcode
-
-<br>
-\subsection single_damage_desc_default_material Single Damage Descriptor with Default TkFamily Material
-
-This method of damage copies the damage descriptor into a buffer, so the user need <em>not</em> hold onto
-a copy after the damage function call. Only one damage descriptor may be passed in at once.
-
-To use this method, the user must first set a default material in the actor's family. For example:
-
-\code
-// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
-Material material;
-
-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);
-\endcode
-
-<b>N.B. the lifetime of the material set <em>must</em> extend at least until the TkGroup::endProcess call for the actor.</b>
-
-Then to apply damage, use:
-
-\code
-NvBlastDamageProgram program =
-{
- myGraphShaderFunction, // A function with the NvBlastGraphShaderFunction signature
- mySubgraphShaderFunction // A function with the NvBlastSubgraphShaderFunction signature
-};
-
-// The example struct "RadialDamageDesc" is modeled after NvBlastExtRadialDamageDesc in the NvBlastExtShaders extension
-RadialDamageDesc damageDesc;
-
-damageDesc.compressive = 10.0f;
-damageDesc.position[0] = 1.0f;
-damageDesc.position[1] = 2.0f;
-damageDesc.position[2] = 3.0f;
-damageDesc.minRadius = 0.0f;
-damageDesc.maxRadius = 1.0f;
-
-// Apply damage
-actor->damage(program, &damageDesc, (uint32_t)sizeof(RadialDamageDesc));
-\endcode
-
-<br>
-\subsection single_damage_desc_with_material Single Damage Descriptor with Specified Material
-
-This method is just like the one above, except that the user has the opportunity to override the material used during damage.
-
-<b>N.B. - the lifetime of the material passed in <em>must</em> extend at least until the TkGroup::endProcess call for the actor.</b>
-
-This call is just like the one above with an extra material parameter:
-
-\code
-actor->damage(program, &damageDesc, (uint32_t)sizeof(RadialDamageDesc), &material);
-\endcode
-
-<br>
-\section tkjoints Joints
-
-Joints in NvBlastTk are abstract representations of physical joints. When joints become active, change the actors they join,
-or become unreferenced (the actors they join disappear), the user will receive notification via a TkJointUpdateEvent
-(see \ref tkevents).
-
-Joints may be defined as a part of a TkAsset, in which case they are consisdered "internal" joints. (See \ref tkasset_creation.)
-Since the first instance of a TkAsset is a single TkActor, internal joints are defined between chunks within the same actor.
-Therefore they are not active (there is no point in joining two locations in a single rigid body). Upon splitting into multiple
-actors, however, an internal joint's chunks may now belong to two different TkActors. When this happens, the user will receive a
-TkJointUpdateEvent of subtype TkJointUpdateEvent::External. The event contains a pointer to the TkJoint, and from that the user
-has access to the information needed to create a physical joint between the rigid bodies that correspond to the joined TkActors.
-
-Joints may also be created externally at runtime, using the TkFramework::createJoint function. A joint created this way must
-be between two different TkActors. Because of this, the joint is immediately considered active, and so no TkJointUpdateEvent
-is generated from its creation. The user should create a physical joint to correspond to the joint returned by createJoint.
-An externally created joint of this type has another distinguishing characteristic: it may join an actor to "the world," or
-"Newtonial Reference Frame" (NRF). To do this, one TkFamily pointer in the joint descriptor is set to NULL. Examples are
-given below.
-
-\code
-TkJointDesc desc;
-desc.families[0] = &actor0->getFamily(); // Assume we have a valid actor0 pointer
-desc.chunkIndices[0] = 1; // This chunk *must* be a support chunk in the asset that created desc.families[0]
-desc.attachPositions[0] = physx::PxVec3(1.0f, 2.0f; 3.0f); // The attach position is in asset space
-desc.families[1] = &actor1->getFamily(); // Assume we have a valid actor1 pointer... note, actor0 and actor1 could have the same family
-desc.chunkIndices[1] = 10; // This chunk *must* be a support chunk in the asset that created desc.families[1]
-desc.attachPositions[1] = physx::PxVec3(4.0f, 5.0f; 6.0f); // The attach position is in asset space
-
-// Create the external joint from the descriptor, which joins actor0 and actor1
-TkJoint* joint = framework->createJoint(desc);
-
-// Now join actor0 to the NRF
-// desc.families[0] already contains actor0's family
-desc.chunkIndices[0] = 2; // Again, this chunk must be a support chunk in the asset that created desc.families[0]
-desc.attachPositions[0] = physx::PxVec3(0.0f, 0.0f; 0.0f); // The attach position is in asset space
-desc.families[1] = nullptr; // Setting the family to NULL designates the world (NRF)
-// The value of desc.chunkIndices[1] is not used, since desc.families[1] is NULL
-desc.attachPositions[1] = physx::PxVec3(0.0f, 0.0f, 10.0f); // Attach position in the world
-
-// Create the external joint which joins actor0 to the world
-TkJoint* jointNRF = framework->createJoint(desc);
-\endcode
-
-<br>
-\subsection releasing_joints Releasing Joints
-
-TkJoints are not released by Blast&tm;, except when the TkFramework is released. Otherwise, the user is responsible for
-releasing TkJoints after they become unreferenced. This is facilitated by the Unreferenced subtype of the TkJointUpdateEvent. After
-receiving this event for joint, the user may choose to release, using the typical TkObject::release() method.
-
-\code
-joint->release();
-\endcode
-
-Note, this method can be called <em>at any time</em>, even before the joint is unreferenced. When called, it will remove its
-references to its attached actors first, causing the joint to then become unreferenced. For example, if the user wishes to break
-a physical joint in their simulation, they can then release the corresponding TkJoint.
-
-It should be mentioned, however, that joints created with an asset are allocated differently from external joints created using
-TkFramework::createJoint. Internal joints created from the joint descriptors in a TkAsset are <em>block allocated</em> with every
-TkFamily that instances the asset. Calling the release() method on those joints will remove any remaining references to them
-(as mentioned above), but will not perform any deallocation. Only when the TkFamily itself is released will the internal joint
-memory for that family be released. <b>This is true even if the internal joints become "external" from actor splitting.</b> Joints
-that <em>become</em> external are still associated with a single family and their memory still resides with that family.
-
-On the other hand, joints that start out life external by way of the TkFramework::createJoint function have a separate allocation,
-and do not have memory tied to any TkFamily (even if both actors joined are in the same family). Releasing a family holding one
-of the actors in such a "purely external" joint will trigger a TkJointUpdateEvent of subtype Unreferenced, however, signalling that
-the joint is ready for user release.
-
-<br>
-\section tkevents Events
-
-NvBlastTk uses events to communicate the results of actor splitting, joint updates from actor splitting, and fracture event buffers
-that can be used to synchronize fracturing between multiple clients.
-
-Events are broadcast to listeners which implement the TkEventListener interface. Listeners are held by TkFamily objects. During
-a TkGroup::endProcess call (see \ref tkgroups), relevant events are broadcast to the listeners in the families associated with the actors
-in the group.
-
-A typical user's receiver implementation might take on the form shown below.
-
-\code
-class MyActorAndJointListener : public TkEventListener
-{
- // TkEventListener interface
- void receive(const TkEvent* events, uint32_t eventCount) override
- {
- // Events are batched into an event buffer. Loop over all events:
- for (uint32_t i = 0; i < eventCount; ++i)
- {
- const TkEvent& event = events[i];
-
- // See TkEvent documentation for event types
- switch (event.type)
- {
- case TkSplitEvent::EVENT_TYPE: // A TkActor has split into smaller actors
- {
- const TkSplitEvent* splitEvent = event.getPayload<TkSplitEvent>(); // Split event payload
-
- // The parent actor may no longer be valid. Instead, we receive the information it held
- // which we need to update our app's representation (e.g. removal of the corresponding physics actor)
- myRemoveActorFunction(splitEvent->parentData.family, splitEvent->parentData.index, splitEvent->parentData.userData);
-
- // The split event contains an array of "child" actors that came from the parent. These are valid
- // TkActor pointers and may be used to create physics and graphics representations in our application
- for (uint32_t j = 0; j < splitEvent->numChildren; ++j)
- {
- myCreateActorFunction(splitEvent->children[j]);
- }
- }
- break;
-
- case TkJointUpdateEvent::EVENT_TYPE:
- {
- const TkJointUpdateEvent* jointEvent = event.getPayload<TkJointUpdateEvent>(); // Joint update event payload
-
- // Joint events have three subtypes, see which one we have
- switch (jointEvent->subtype)
- {
- case TkJointUpdateEvent::External:
- myCreateJointFunction(jointEvent->joint); // An internal joint has been "exposed" (now joins two different actors). Create a physics joint.
- break;
- case TkJointUpdateEvent::Changed:
- myUpdatejointFunction(jointEvent->joint); // A joint's actors have changed, so we need to update its corresponding physics joint.
- break;
- case TkJointUpdateEvent::Unreferenced:
- myDestroyJointFunction(jointEvent->joint); // This joint is no longer referenced, so we may delete the corresponding physics joint.
- break;
- }
- }
-
- // Unhandled:
- case TkFractureCommands::EVENT_TYPE:
- case TkFractureEvents::EVENT_TYPE:
- default:
- break;
- }
- }
- }
-};
-\endcode
-
-Whenever a new TkActor is created by the user (via TkFramework::createActor, see \ref tkasset_instancing), its newly-made family should
-be given whatever listeners the user wishes to attach. For example,
-
-\code
-TkActor* actor = framework->createActor(actorDesc);
-
-actor->getFamily().addListener(myListener); // myListener is an object which implements TkEventListener (see MyActorAndJointListener above, for example)
-\endcode
-
-Listeners may also be removed from families at any time.
-
-<br>
-\section tktypes Object and Type Identification
-
-NvBlastTk objects that are derived from TkIdentifiable (TkAsset, TkFamily, and TkGroup) support an object and class (type) identification
-system. The TkIdentifiable interfaces setID and getID allow the user to set and access an NvBlastID for each object. The NvBlastID
-is a 128-bit identifier. TkIdentifiable objects are tracked by the TkFramework, which may be used to look up an object by its NvBlastID.
-
-Upon creation, TkIdentifiable objects are given a GUID, a unique NvBlastID. The user is welcome to change the object's guid at any time, with
-the restriction that the GUID cannot be all zero bytes.
-
-With an object's GUID, one may look up the object using the TkFramework function findObjectByID:
-
-\code
-TkIdentifiable* object = framework->findObjectByID(id); // id = an NvBlastID GUID
-\endcode
-
-If the object is found, a non-NULL pointer will be returned.
-
-TkIdentifiable-derived classes also have a class identification system, the TkType interface. From an individual object one may use the
-TkIdentifiable interface getType to access the class's TkType interface. Alternatively, one may use the TkFramework getType function
-with TkTypeIndex::Enum argument. For example, to get the TkType interface for the TkAsset class, use
-
-\code
-const TkType* assetType = framework->getType(TkTypeIndex::Asset);
-\endcode
-
-The type interface may be used:
-
- - to access class-specific object lists in the framework,
- - identify the class of a TkIdentifiable obtained through ID lookup or deserialization, or
- - to obtain the class's name and format version number.
-
-For example, to access a list of all families:
-
-\code
-// Get the TkFamily type interface
-const TkType* familyType = framework->getType(TkTypeIndex::Family);
-
-// Get the family count to allocate a buffer
-const uint32_t familyCount = framework->getObjectCount(familyType);
-std::vector<TkIdentifiable*> families(familyCount);
-
-// Write the families to the buffer
-const uint32_t familiesFound = framework->getObjects(families.data(), familyCount, familyType);
-\endcode
-
-In the above code, the values of familyCount and familiesFound should be equal. An alternative usage of TkFramework::getObjects allows the
-user to write to a (potentially) smaller buffer, iteratively. For example:
-
-\code
-uint32_t familiesFound;
-uint32_t totalFamilyCount = 0;
-do
-{
- // Write to a fixed-size buffer
- TkIdentifiable* familyBuffer[16];
- familiesFound = framework->getObjects(familyBuffer, 16, familyType, totalFamilyCount);
- totalFamilyCount += familiesFound;
-
- // Process the families found so far
- myProcessFamiliesFunction(familyBuffer, familiesFound);
-} while (familiesFound == 16);
-\endcode
-
-To use the type interface to identify a class, perhaps after serialization or lookup by ID, one may do something like:
-
-\code
-\\ Assume we have a TkIdentifiable pointer called "object"
-
-// Get the type interfaces of interest
-const TkType* assetType = framework->getType(TkTypeIndex::Asset);
-const TkType* familyType = framework->getType(TkTypeIndex::Family);
-
-if (object->getType() == *assetType)
-{
- TkAsset* asset = static_cast<TkAsset*>(object);
-
- // Process the object as a TkAsset
-}
-if (object->getType() == *familyType)
-else
-{
- TkFamily* family = static_cast<TkFamily*>(object);
-
- // Process the object as a TkFamily
-}
-\endcode
-
-A TkIdentifiable-derived class may be queried for its name using the TkType interface, using TkType::getName().
-This function returns a const char pointer to a string.
-
-Finally, one may query the class for its current format version number using TkType::getVersion().
-
-<br>
-*/
+/*! \page pagehlapi High Level (Toolkit) API (NvBlastTk)
+
+<b>Table of Contents</b>
+
+\subpage tkintroduction
+
+\subpage tk_class_hierarchy
+
+\subpage tk_include_and_library
+
+\subpage framework_init
+
+\subpage tkasset_creation
+
+\subpage tkasset_instancing
+
+\subpage tkgroups
+
+\subpage damage_in_tk
+
+\subpage tkjoints
+
+\subpage tkevents
+
+\subpage tktypes
+
+<br>
+\section tkintroduction Introduction to NvBlastTk
+
+The high-level API, NvBlastTk (Tk stands for "toolkit"), is intended to be a more powerful library and a much more convenient entry point
+into the use of Blast&tm;. Like the low-level library, Tk is physics and graphics-agnostic. Whereas the low-level API is C-style, Tk uses
+a C++ API. Everything in Tk is in the namespace:
+
+\code
+Nv::Blast
+\endcode
+
+(the only exceptions are global-scope functions to create and access a framework singleton, see below).
+Every object in Tk is prefixed with 'Tk'. For example, the Tk framework interface is:
+
+\code
+Nv::Blast::TkFramework
+\endcode
+
+<b>
+For the remainder of this page we will be in the Nv::Blast namespace, and will drop the explicit scope Nv::Blast:: from our names.
+</b>
+<br>
+<br>
+
+
+BlastTk adds:
+
+- An object class hierarchy (see \ref tk_class_hierarchy, below).
+- 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.
+- 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, these "joints" only hold descriptor data, since physical objects are not handled by BlastTk.
+
+<br>
+\section tk_class_hierarchy NvBlastTk Class Hierarchy
+
+- There are two abstract interfaces, one of which deriving from the other: <b>TkObject <- TkIdentifiable</b>.
+ - Lightweight objects are derived from <b>TkObject</b>.
+ - Objects which use a GUID and class identification are derieved from <b>TkIdentifiable</b>.
+- <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 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>. <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
+
+To use the BlastTk library, the application need only inlclude the header NvBlastTk.h, found in the <b>include/toolkit</b> folder, and link
+against the appropriate version of the NvBlastTk library. Depending on the platform and configuration, various suffixes will be added to the library
+name. The general naming scheme is
+
+NvBlastTk(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 framework_init Creating the TkFramework
+
+As a reminder, in this document we assume we are in the Nv::Blast namespace:
+
+\code
+using namespace Nv::Blast;
+\endcode
+
+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();
+\endcode
+
+The framework may be accessed via:
+
+\code
+TkFramework* framework = NvBlastTkFrameworkGet();
+\endcode
+
+In the sections that follow, it is assumed that a framework has been created, and we have a pointer to it named 'framework' within scope.
+
+Finally, to release the framework, use
+
+\code
+framework->release();
+\endcode
+
+This will release all assets, families, actors, joints, and groups.
+
+<br>
+\section tkasset_creation Creating a TkAsset
+
+The TkAsset object is a high-level wrapper for the low-level NvBlastAsset (see \ref assets). The descriptor used to create a TkAsset, a TkAssetDesc, is derived from
+NvBlastAssetDesc. The base fields should be filled in as described in (\ref assets). The new field is an optional array of flags to be associated with each bond in
+the base descriptor. Currently the only flag is "BondJointed," and if set will cause an "internal joint" to be created in actors (TkActor type) created from the asset.
+See (\ref tkjoints) for more on joints in BlastTk.
+
+\code
+TkAssetDesc desc;
+
+myFunctionToFillInLowLevelAssetFields(desc); // Fill in the low-level (NvBlastAssetDesc) fields as usual
+
+std::vector<uint8_t*> bondFlags(desc.bondCount, 0); // Clear all flags
+
+// Set BondJointed flags corresponding to joints selected by the user (assumes a myBondIsJointedFunction to make this selection)
+for (uint32_t i = 0; i < desc.bondCount; ++i)
+{
+ if (myBondIsJointedFunction(i)) // User-authored
+ {
+ bondFlags[i] |= TkAssetDesc::BondJointed;
+ }
+}
+
+TkAsset* asset = framework->createAsset(desc); // Create a new TkAsset
+\endcode
+
+The createAsset function used above creates a low-level NvBlastAsset from the base fields of the descriptor, and then adds internal joint descriptors based
+upon the bonds' centroids and attached chunks. An alternative method to create a TkAsset allows the user to pass in a pre-existing NvBlastAsset, and a list
+of joint descriptors. If the TkAsset is to have no internal joints, then the joint descriptors are not necessary and with an NvBlastAsset
+pointer <b>llAsset</b>, a TkAsset may be created simply by using
+
+\code
+TkAsset* asset = framework->createAsset(llAsset);
+\endcode
+
+By default, such a TkAsset will not "own" the llAsset. When the TkAsset is released, the llAsset memory will be untouched. You can pass ownership to the
+TkAsset using all of the default parameters of the createAsset function:
+
+\code
+TkAsset* asset = framework->createAsset(llAsset, nullptr, 0, true);
+\endcode
+
+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
+the nodes indices are those of the graph nodes that correspond to support chunks. These indices are not, in general, the same as the chunk indices.
+An example of initialization of the joint descriptors is given below.
+
+\code
+std::vector<TkAssetJointDesc> jointDescs(jointCount); // Assume jointCount = the number of joints to add
+jointDescs[0].nodeIndices[0] = 0; // Attach node 0 to node 1
+jointDescs[0].nodeIndices[1] = 1;
+jointDescs[0].attachPoistions[0] = physx::PxVec3( 1.0f, 2.0f, 3.0f ); // Attachment positions are often the same within an asset, but they don't have to be
+jointDescs[0].attachPoistions[1] = physx::PxVec3( 1.0f, 2.0f, 3.0f );
+// ... etc.
+
+TkAsset* asset = framework->createAsset(llAsset, jointDescs.data(), jointDescs.size());
+\endcode
+
+The code above assumes you know the support graph nodes to which you'd like to attach joints. Often, the user only knows the corresponding chunk indices.
+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, 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
+
+\code
+uint32_t nodeIndex = map[chunkIndex];
+\endcode
+
+If the chunk indexed by <b>chunkIndex</b> does <em>not</em> correspond to a support chunk, then the mapped value will be UINT32_MAX, the invalid index.
+Otherwise, the mapped value will be a valid graph node index.
+
+Finally, to release a TkAsset, as with any TkObject-derived object, use the release() method:
+
+\code
+asset->release();
+\endcode
+
+<br>
+\section tkasset_instancing Instancing a TkAsset: Creation of a TkActor and a TkFamily
+
+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 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 role in NvBlastTk, holding user-supplied event listeners (\ref 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
+child actors from it. TkActor creation or release that occurs from an explicit API call do not produce events. For example when creating a first unfractured
+instance of an asset using createAsset, or when calling the release() method on a TkActor. TkJoint events are similarly broadcast to
+receivers (TkJointEvent). These signal when the actors which are joined by the joints change, so that the user may update a corresponding physical joint.
+They also signal when a joint no longer attaches actors and is therefore unreferenced. The user may invalidate or release the joint using the TkObject
+release() method when this occurs (more on joint ownership in \ref tkjoints).
+
+To create an unfractured TkActor instance from a TkAsset, one first fills in a descriptor (\ref TkActorDesc) and passes it to the framework's createActor function.
+As with the TkAssetDesc, the TkActorDesc is derived from its low-level counterpart, the NvBlastActorDesc. In addition the TkActorDesc holds a pointer to
+the TkAsset being instanced. An example of TkActor creation is given below, given a TkAsset pointer <b>asset</b>.
+
+\code
+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
+
+The TkFamily created with the actor above may be accessed through the actor's getFamily field:
+
+\code
+TkFamily& family = actor->getFamily();
+\endcode
+
+The returned value is a reference since a TkActor's family can never be NULL. Actors resulting from the split of a "parent" actor will always belong to the
+parent's family.
+
+For most applications, the user will need to create a listener object to pass to every family created, in order to keep their physics and graphics representations
+in sync with the splitting of the TkActor. For more on this, see \ref tkevents.
+
+<br>
+\section tkgroups Groups
+
+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.
+
+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::ExtGroupTaskManager (in NvBlastExtPxTask.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.
+
+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.
+
+A typical usage is outlined below. See \ref damage_in_tk for methods of applying damage to actors.
+
+\code
+// Create actors from descriptors desc1, desc2, ... etc., and attach a listener to each new family created
+TkActor* actor1 = framework->createActor(desc1);
+actor1->getFamily().addListener(gMyReceiver); // gMyReceiver is a TkEventListener-derived object. More on events in a subsequent section.
+TkActor* actor2 = framework->createActor(desc2);
+actor2->getFamily().addListener(gMyReceiver);
+TkActor* actor3 = framework->createActor(desc3);
+actor3->getFamily().addListener(gMyReceiver);
+// etc...
+
+// Let's create two groups. First, create a group descriptor. This may be used to create both groups.
+TkGroupDesc groupDesc;
+groupDesc.workerCount = 1; // this example processes groups on the calling thread only
+
+// Now create the groups
+TkGroup* group1 = framework->createGroup(groupDesc);
+TkGroup* group2 = framework->createGroup(groupDesc);
+
+// Add actor1 and actor2 to group1, and actor2 to group3...
+group1->addActor(actor1);
+group1->addActor(actor2);
+group2->addActor(actor3);
+// etc...
+
+// Now apply damage to all actors - *NOTE* damage is described in detail in the next section.
+// For now we will just assume a "myDamageFunction" to apply the damage.
+myDamageFunction(actor1);
+myDamageFunction(actor2);
+myDamageFunction(actor3);
+// etc...
+
+// Calling the groups' process functions will (synchronously) run all jobs to process damage taken by the contained actors.
+group1->process();
+group2->process();
+
+// When the groups are no longer needed, they may be released with the usual release method.
+group1->release();
+group2->release();
+\endcode
+
+<br>
+<b>Multithreaded processing</b>
+
+When distributing the jobs as mentioned above, every job must be processed exactly once (over all user tasks).
+
+The number of jobs processed per worker can range from a single job (resulting in a user task per job) to all jobs (like Nv::Blast::TkGroup::process() does).
+
+At any point in time, no more than the set workerCount amount of workers may have been acquired. Return the worker at the end of each task.
+
+\code
+Nv::Blast::TkGroupWorker* worker = group->acquireWorker();
+// process some jobs
+group->returnWorker(worker);
+\endcode
+
+<br>
+\section damage_in_tk Applying Damage to Actors and Families
+
+Damage in NvBlastTk uses the same damage program scheme as the low-level SDK (see \ref splitting). One passes the program
+(NvBlastDamageProgram), damage descriptor (program-dependent), and material (also program-dependent) to a TkActor::damage
+function. Ultimately, the damage descriptor and material data are all parameters used by the damage program. The distinction
+is that the damage descriptor should describe properties of the thing doing the damage, while the material should
+describe properties of the actor (the thing being damaged). The interpretation of this data is entirely up to the program's
+functions, however.
+
+For convenience, the user may set a default material in the actor's family. This assumes, of course, that the material parameters
+for this default are compatible with the program being used to damage the family's actors.
+
+Examples of the three TkActor damage methods are given below.
+
+<br>
+\subsection multiple_damage Multiple Damage Descriptors using NvBlastProgramParams
+
+<b>N.B. - with this method of damage, the lifetime of the NvBlastProgramParams <em>must</em> extend at
+least until the TkGroup::endProcess call for the actor.</b>
+
+\code
+NvBlastDamageProgram program =
+{
+ myGraphShaderFunction, // A function with the NvBlastGraphShaderFunction signature
+ mySubgraphShaderFunction // A function with the NvBlastSubgraphShaderFunction signature
+};
+
+// The example struct "RadialDamageDesc" is modeled after NvBlastExtRadialDamageDesc in the NvBlastExtShaders extension
+RadialDamageDesc damageDescs[2];
+
+damageDescs[0].compressive = 10.0f;
+damageDescs[0].position[0] = 1.0f;
+damageDescs[0].position[1] = 2.0f;
+damageDescs[0].position[2] = 3.0f;
+damageDescs[0].minRadius = 0.0f;
+damageDescs[0].maxRadius = 1.0f;
+
+damageDescs[1].compressive = 100.0f;
+damageDescs[1].position[0] = 3.0f;
+damageDescs[1].position[1] = 4.0f;
+damageDescs[1].position[2] = 5.0f;
+damageDescs[1].minRadius = 0.0f;
+damageDescs[1].maxRadius = 5.0f;
+
+// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
+Material material;
+
+material.health = 10.0f;
+material.minDamageThreshold = 0.1f;
+material.maxDamageThreshold = 0.8f;
+
+// Set the damage params struct
+NvBlastProgramParams params = { damageDescs, 2, &material };
+
+// Apply damage
+actor->damage(program, &params); // params must be kept around until TkGroup::endProcess is called!
+\endcode
+
+<br>
+\subsection single_damage_desc_default_material Single Damage Descriptor with Default TkFamily Material
+
+This method of damage copies the damage descriptor into a buffer, so the user need <em>not</em> hold onto
+a copy after the damage function call. Only one damage descriptor may be passed in at once.
+
+To use this method, the user must first set a default material in the actor's family. For example:
+
+\code
+// The example material "Material" is modeled after NvBlastExtMaterial in the NvBlastExtShaders extension
+Material material;
+
+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);
+\endcode
+
+<b>N.B. the lifetime of the material set <em>must</em> extend at least until the TkGroup::endProcess call for the actor.</b>
+
+Then to apply damage, use:
+
+\code
+NvBlastDamageProgram program =
+{
+ myGraphShaderFunction, // A function with the NvBlastGraphShaderFunction signature
+ mySubgraphShaderFunction // A function with the NvBlastSubgraphShaderFunction signature
+};
+
+// The example struct "RadialDamageDesc" is modeled after NvBlastExtRadialDamageDesc in the NvBlastExtShaders extension
+RadialDamageDesc damageDesc;
+
+damageDesc.compressive = 10.0f;
+damageDesc.position[0] = 1.0f;
+damageDesc.position[1] = 2.0f;
+damageDesc.position[2] = 3.0f;
+damageDesc.minRadius = 0.0f;
+damageDesc.maxRadius = 1.0f;
+
+// Apply damage
+actor->damage(program, &damageDesc, (uint32_t)sizeof(RadialDamageDesc));
+\endcode
+
+<br>
+\subsection single_damage_desc_with_material Single Damage Descriptor with Specified Material
+
+This method is just like the one above, except that the user has the opportunity to override the material used during damage.
+
+<b>N.B. - the lifetime of the material passed in <em>must</em> extend at least until the TkGroup::endProcess call for the actor.</b>
+
+This call is just like the one above with an extra material parameter:
+
+\code
+actor->damage(program, &damageDesc, (uint32_t)sizeof(RadialDamageDesc), &material);
+\endcode
+
+<br>
+\section tkjoints Joints
+
+Joints in NvBlastTk are abstract representations of physical joints. When joints become active, change the actors they join,
+or become unreferenced (the actors they join disappear), the user will receive notification via a TkJointUpdateEvent
+(see \ref tkevents).
+
+Joints may be defined as a part of a TkAsset, in which case they are consisdered "internal" joints. (See \ref tkasset_creation.)
+Since the first instance of a TkAsset is a single TkActor, internal joints are defined between chunks within the same actor.
+Therefore they are not active (there is no point in joining two locations in a single rigid body). Upon splitting into multiple
+actors, however, an internal joint's chunks may now belong to two different TkActors. When this happens, the user will receive a
+TkJointUpdateEvent of subtype TkJointUpdateEvent::External. The event contains a pointer to the TkJoint, and from that the user
+has access to the information needed to create a physical joint between the rigid bodies that correspond to the joined TkActors.
+
+Joints may also be created externally at runtime, using the TkFramework::createJoint function. A joint created this way must
+be between two different TkActors. Because of this, the joint is immediately considered active, and so no TkJointUpdateEvent
+is generated from its creation. The user should create a physical joint to correspond to the joint returned by createJoint.
+An externally created joint of this type has another distinguishing characteristic: it may join an actor to "the world," or
+"Newtonial Reference Frame" (NRF). To do this, one TkFamily pointer in the joint descriptor is set to NULL. Examples are
+given below.
+
+\code
+TkJointDesc desc;
+desc.families[0] = &actor0->getFamily(); // Assume we have a valid actor0 pointer
+desc.chunkIndices[0] = 1; // This chunk *must* be a support chunk in the asset that created desc.families[0]
+desc.attachPositions[0] = physx::PxVec3(1.0f, 2.0f; 3.0f); // The attach position is in asset space
+desc.families[1] = &actor1->getFamily(); // Assume we have a valid actor1 pointer... note, actor0 and actor1 could have the same family
+desc.chunkIndices[1] = 10; // This chunk *must* be a support chunk in the asset that created desc.families[1]
+desc.attachPositions[1] = physx::PxVec3(4.0f, 5.0f; 6.0f); // The attach position is in asset space
+
+// Create the external joint from the descriptor, which joins actor0 and actor1
+TkJoint* joint = framework->createJoint(desc);
+
+// Now join actor0 to the NRF
+// desc.families[0] already contains actor0's family
+desc.chunkIndices[0] = 2; // Again, this chunk must be a support chunk in the asset that created desc.families[0]
+desc.attachPositions[0] = physx::PxVec3(0.0f, 0.0f; 0.0f); // The attach position is in asset space
+desc.families[1] = nullptr; // Setting the family to NULL designates the world (NRF)
+// The value of desc.chunkIndices[1] is not used, since desc.families[1] is NULL
+desc.attachPositions[1] = physx::PxVec3(0.0f, 0.0f, 10.0f); // Attach position in the world
+
+// Create the external joint which joins actor0 to the world
+TkJoint* jointNRF = framework->createJoint(desc);
+\endcode
+
+<br>
+\subsection releasing_joints Releasing Joints
+
+TkJoints are not released by Blast&tm;, except when the TkFramework is released. Otherwise, the user is responsible for
+releasing TkJoints after they become unreferenced. This is facilitated by the Unreferenced subtype of the TkJointUpdateEvent. After
+receiving this event for joint, the user may choose to release, using the typical TkObject::release() method.
+
+\code
+joint->release();
+\endcode
+
+Note, this method can be called <em>at any time</em>, even before the joint is unreferenced. When called, it will remove its
+references to its attached actors first, causing the joint to then become unreferenced. For example, if the user wishes to break
+a physical joint in their simulation, they can then release the corresponding TkJoint.
+
+It should be mentioned, however, that joints created with an asset are allocated differently from external joints created using
+TkFramework::createJoint. Internal joints created from the joint descriptors in a TkAsset are <em>block allocated</em> with every
+TkFamily that instances the asset. Calling the release() method on those joints will remove any remaining references to them
+(as mentioned above), but will not perform any deallocation. Only when the TkFamily itself is released will the internal joint
+memory for that family be released. <b>This is true even if the internal joints become "external" from actor splitting.</b> Joints
+that <em>become</em> external are still associated with a single family and their memory still resides with that family.
+
+On the other hand, joints that start out life external by way of the TkFramework::createJoint function have a separate allocation,
+and do not have memory tied to any TkFamily (even if both actors joined are in the same family). Releasing a family holding one
+of the actors in such a "purely external" joint will trigger a TkJointUpdateEvent of subtype Unreferenced, however, signalling that
+the joint is ready for user release.
+
+<br>
+\section tkevents Events
+
+NvBlastTk uses events to communicate the results of actor splitting, joint updates from actor splitting, and fracture event buffers
+that can be used to synchronize fracturing between multiple clients.
+
+Events are broadcast to listeners which implement the TkEventListener interface. Listeners are held by TkFamily objects. During
+a TkGroup::endProcess call (see \ref tkgroups), relevant events are broadcast to the listeners in the families associated with the actors
+in the group.
+
+A typical user's receiver implementation might take on the form shown below.
+
+\code
+class MyActorAndJointListener : public TkEventListener
+{
+ // TkEventListener interface
+ void receive(const TkEvent* events, uint32_t eventCount) override
+ {
+ // Events are batched into an event buffer. Loop over all events:
+ for (uint32_t i = 0; i < eventCount; ++i)
+ {
+ const TkEvent& event = events[i];
+
+ // See TkEvent documentation for event types
+ switch (event.type)
+ {
+ case TkSplitEvent::EVENT_TYPE: // A TkActor has split into smaller actors
+ {
+ const TkSplitEvent* splitEvent = event.getPayload<TkSplitEvent>(); // Split event payload
+
+ // The parent actor may no longer be valid. Instead, we receive the information it held
+ // which we need to update our app's representation (e.g. removal of the corresponding physics actor)
+ myRemoveActorFunction(splitEvent->parentData.family, splitEvent->parentData.index, splitEvent->parentData.userData);
+
+ // The split event contains an array of "child" actors that came from the parent. These are valid
+ // TkActor pointers and may be used to create physics and graphics representations in our application
+ for (uint32_t j = 0; j < splitEvent->numChildren; ++j)
+ {
+ myCreateActorFunction(splitEvent->children[j]);
+ }
+ }
+ break;
+
+ case TkJointUpdateEvent::EVENT_TYPE:
+ {
+ const TkJointUpdateEvent* jointEvent = event.getPayload<TkJointUpdateEvent>(); // Joint update event payload
+
+ // Joint events have three subtypes, see which one we have
+ switch (jointEvent->subtype)
+ {
+ case TkJointUpdateEvent::External:
+ myCreateJointFunction(jointEvent->joint); // An internal joint has been "exposed" (now joins two different actors). Create a physics joint.
+ break;
+ case TkJointUpdateEvent::Changed:
+ myUpdatejointFunction(jointEvent->joint); // A joint's actors have changed, so we need to update its corresponding physics joint.
+ break;
+ case TkJointUpdateEvent::Unreferenced:
+ myDestroyJointFunction(jointEvent->joint); // This joint is no longer referenced, so we may delete the corresponding physics joint.
+ break;
+ }
+ }
+
+ // Unhandled:
+ case TkFractureCommands::EVENT_TYPE:
+ case TkFractureEvents::EVENT_TYPE:
+ default:
+ break;
+ }
+ }
+ }
+};
+\endcode
+
+Whenever a new TkActor is created by the user (via TkFramework::createActor, see \ref tkasset_instancing), its newly-made family should
+be given whatever listeners the user wishes to attach. For example,
+
+\code
+TkActor* actor = framework->createActor(actorDesc);
+
+actor->getFamily().addListener(myListener); // myListener is an object which implements TkEventListener (see MyActorAndJointListener above, for example)
+\endcode
+
+Listeners may also be removed from families at any time.
+
+<br>
+\section tktypes Object and Type Identification
+
+NvBlastTk objects that are derived from TkIdentifiable (TkAsset, TkFamily, and TkGroup) support an object and class (type) identification
+system. The TkIdentifiable interfaces setID and getID allow the user to set and access an NvBlastID for each object. The NvBlastID
+is a 128-bit identifier. TkIdentifiable objects are tracked by the TkFramework, which may be used to look up an object by its NvBlastID.
+
+Upon creation, TkIdentifiable objects are given a GUID, a unique NvBlastID. The user is welcome to change the object's guid at any time, with
+the restriction that the GUID cannot be all zero bytes.
+
+With an object's GUID, one may look up the object using the TkFramework function findObjectByID:
+
+\code
+TkIdentifiable* object = framework->findObjectByID(id); // id = an NvBlastID GUID
+\endcode
+
+If the object is found, a non-NULL pointer will be returned.
+
+TkIdentifiable-derived classes also have a class identification system, the TkType interface. From an individual object one may use the
+TkIdentifiable interface getType to access the class's TkType interface. Alternatively, one may use the TkFramework getType function
+with TkTypeIndex::Enum argument. For example, to get the TkType interface for the TkAsset class, use
+
+\code
+const TkType* assetType = framework->getType(TkTypeIndex::Asset);
+\endcode
+
+The type interface may be used:
+
+ - to access class-specific object lists in the framework,
+ - identify the class of a TkIdentifiable obtained through ID lookup or deserialization, or
+ - to obtain the class's name and format version number.
+
+For example, to access a list of all families:
+
+\code
+// Get the TkFamily type interface
+const TkType* familyType = framework->getType(TkTypeIndex::Family);
+
+// Get the family count to allocate a buffer
+const uint32_t familyCount = framework->getObjectCount(familyType);
+std::vector<TkIdentifiable*> families(familyCount);
+
+// Write the families to the buffer
+const uint32_t familiesFound = framework->getObjects(families.data(), familyCount, familyType);
+\endcode
+
+In the above code, the values of familyCount and familiesFound should be equal. An alternative usage of TkFramework::getObjects allows the
+user to write to a (potentially) smaller buffer, iteratively. For example:
+
+\code
+uint32_t familiesFound;
+uint32_t totalFamilyCount = 0;
+do
+{
+ // Write to a fixed-size buffer
+ TkIdentifiable* familyBuffer[16];
+ familiesFound = framework->getObjects(familyBuffer, 16, familyType, totalFamilyCount);
+ totalFamilyCount += familiesFound;
+
+ // Process the families found so far
+ myProcessFamiliesFunction(familyBuffer, familiesFound);
+} while (familiesFound == 16);
+\endcode
+
+To use the type interface to identify a class, perhaps after serialization or lookup by ID, one may do something like:
+
+\code
+\\ Assume we have a TkIdentifiable pointer called "object"
+
+// Get the type interfaces of interest
+const TkType* assetType = framework->getType(TkTypeIndex::Asset);
+const TkType* familyType = framework->getType(TkTypeIndex::Family);
+
+if (object->getType() == *assetType)
+{
+ TkAsset* asset = static_cast<TkAsset*>(object);
+
+ // Process the object as a TkAsset
+}
+if (object->getType() == *familyType)
+else
+{
+ TkFamily* family = static_cast<TkFamily*>(object);
+
+ // Process the object as a TkFamily
+}
+\endcode
+
+A TkIdentifiable-derived class may be queried for its name using the TkType interface, using TkType::getName().
+This function returns a const char pointer to a string.
+
+Finally, one may query the class for its current format version number using TkType::getVersion().
+
+<br>
+*/