====================
Framework Interfaces
====================

.. highlight:: c++

Initialization
--------------

In order to use APEX, the first thing that must be done by the
application is to create a single instance of the ApexSDK class:

::

    #include "Apex.h"
     
	extern PxFoundation* 		gFoundation;
    extern PxPhysics*        	gPhysicsSDK;
    extern PxCookingInterface*  gCooking;
    extern PxUserOutputStream*  gOutputStream;
    ApexSDK*                  	gApexSDK;

    ...
     
    ApexSDKDesc               	apexDesc;
    ApexCreateError            	errorCode;
    apexDesc.outputStream = gOutputStream;
	apexDesc.foundation = gFoundation;
    apexDesc.physXSDK = gPhysicsSDK;
    apexDesc.cooking = gCooking;
    apexDesc.renderResourceManager = new UserRenderResourceManager();
     
    gApexSDK = CreateApexSDK(apexDesc, &errorCode);

The PhysX SDK must have already been initialized, so you that you
have a PxPhysics\*. Most functionality of APEX is provided directly
or indirectly through the ApexSDK class. For example, scene
creation and APEX module initialization is performed by calling
methods of the ApexSDK class.

Loading Modules
---------------

The ApexSDK class provides a single generic public API for loading
modules, called createModule(). Providing a single generic API makes
it possible for third-parties to develop modules and ship module
binaries (libs and DLL's) that are compatible with a particular
version of the APEX SDK and of the PhysX SDK.

The module is identified by its filename, without path and without
suffix/extension, which is the first argument to createModule().
The second argument to createModule() is a pointer to an
error result. The APEX SDK will ensure that the loaded module matches
the APEX and PhysX SDK versions. Module specific parameters, if
any, must be passed to the module using a subsequent call to the
module's init() method.

Here is an example::

    #include "ApexSDK.h"
    #include "ModuleDestructible.h"
    #include "NvParamUtils.h"
     
    ModuleDestructible*       gModuleDestructible;
     
    ...

    ApexCreateError            errorCode;
    NvParameterized::Interface* moduleDesc;
    #if MODULE_STATIC_LINKED
        instantiateModuleDestructible();
    #endif
     
    gModuleDestructible = static_cast<ModuleDestructible*> ( GetApexSDK()->createModule("Destructible", &errorCode) );
    PX_ASSERT(gModuleDestructible);
    
    moduleDesc = gModuleDestructible->getDefaultModuleDesc();
    
    NvParameterized::setU16( *moduleDesc, "maxActorCreatesPerFrame", 50 ); // 50 is just a random number for demonstration purposes
    gModuleDestructible->init( *moduleDesc );


Creating Scenes
---------------

The APEX scene (class Scene) represents a unique physics world
in which various types of objects can be instantiated. It mirrors
the PhysX SDK PxScene class. An instance of the Scene class
should be created for each PxScene in which APEX will be used.

The APEX scene provides a centralized interface for advancing the
simulation and accessing the rendering data output from APEX.

The Scene derives from Context, and therefore can contain
(or be the context for) APEX actors. In fact, all \*asset::create\*Actor()
methods must take an Scene argument.

The Scene operates in similar fashion to the PhysX SDK scene,
however, the APEX scene can exist, and even contain APEX actors,
without having an associated PhysX SDK scene. But in order to
actually perform simulation in the PhysX SDK, an PhysX scene must be
associated with the APEX scene, either by providing a pointer to
it in the SceneDesc descriptor structure, or by using the
setPhysXScene() method.

Using CUDA
~~~~~~~~~~
.. only:: SDKver3X

    An APEX scene will use CUDA if the associated PhysX scene is given a GpuDispatcher.
    See the PhysX 3.x documentation on GPU Resource Management for more information.



Loading Assets
--------------

At run-time, asset creation is typically performed by the game
engine's "level loader" using the Named Resource Provider's user
defined *ResourceCallback::requestResource()* method. The level
loader typically processes a set of asset instances that have been
placed in the level. At a minimum, the game engine must be capable
of storing the following information for each asset instance in the
level: name of the asset, the type of the asset, and position and
orientation of the instance. For each asset instance found in a
level, the level loader should query the NRP to determine whether
or not the named asset has been already loaded. It should use the
*ResourceProvider::getResource()* method to do so. If the asset has
not been loaded, a callback to *ResourceCallback::requestResource()*
will be immediately triggered to request that the asset be loaded.
Either way, *getResource()* will return a void pointer to the loaded
asset that can subsequently be used to create the instance of the
asset: the Actor.

Assets use NvParameterized classes to store all of their serialized data.
APEX provides a serializer which will serialize and deserialize to either an
ASCII XML format or a binary format.

To load APEX assets, the *ResourceCallback::requestResource()* callback should first create a PxFileBuf data stream using *ApexSDK::createStream()* for reading the asset from non-volatile storage.  In the APEX samples the assets are mapped to a single file and not bundled into packages, though a game engine can interpret an asset name from *::requestResource()* however it wishes.

If the APEX default stream implementation is being used (e.g.: the APEX samples), a stream can be created with the ApexSDK::createStream()
method::

    physx::PxFileBuf* stream = GetApexSDK()->createStream( "asset.xml", physx::PxFileBuf::OPEN_READ_ONLY );

Otherwise, an instance of a user defined stream class (derived from the pure virtual PxFileBuf base class) should be created.

Create the NvParameterized::Serializer, specifying the serialization format (this may or may not be part of the asset name in the callback)::
    
    // NvParameterized::Serializer * ApexSDK::createSerializer(NvParameterized::Serializer::SerializeType type)
    NvParameterized::Serializer * ser = GetApexSDK()->createSerializer(serType); // serType is either NST_XML or NST_BINARY

You may also specify custom Traits object if you want to change some aspects of serializer behavior (see NvParameterized Guide for more details)::

    // NvParameterized::Serializer * ApexSDK::createSerializer(NvParameterized::Serializer::SerializeType type, NvParameterized::Traits *traits)
    NvParameterized::Serializer * ser = GetApexSDK()->createSerializer(serType, customTraits);

You may determine stream format using ApexSdk::getSerializeType() method::

    NvParameterized::Serializer::SerializeType serType = GetApexSDK()->getSerializeType(*stream);
	PX_ASSERT( serType != NvParameterized::SerializeType::NST_LAST );

You may also check target platform for your binary file (e.g. before you do inplace deserialization)::

    NvParameterized::SerializePlatform platform;
    GetApexSDK()->getSerializePlatform(*stream, platform);

    if( platform == NvParameterized::SerializePlatform::GetCurrentPlatform() )
        ...

The NvParameterized asset classes must be deserialized using the *NvParameterized::Serializer::deserialize()* method.  The parameters required are the data stream and an instance of the *NvParameterized::Serializer::DeserializedData* class.  All assets which are serialized in the stream will be deserialized and stored as NvParameterized classes which can be accessed through the *DeserializedData* object.

The NvParameterized class(es) serialized in the PxFileBuf may be accessed from the *DeserializedData* object and created using the *ApexSDK::createAsset(NvParameterized::Interface* parameters, const char * name)* method::

    const char *assetName; // input parameter in ::requestResource()
    Asset *asset;
    NvParameterized::Serializer::DeserializedData data;
    
    serializer->deserialize(*stream, data); // assume there is one asset in the stream for this case
    NvParameterized::Interface *params = data[0];
    asset = GetApexSDK()->createAsset( params, assetName );

The NvParameterized object(s) retrieved from the serializer should not be released or destroyed by the application.  The act of creating an asset from an NvParameterized object passes ownership of the object to the asset.

The asset can be released using *ApexSDK::releaseAsset()* or *Asset::release()*.  If the asset was loaded as a result of manually calling the *ResourceCallback::requestResource()* callback, then it should be released using *ResourceProvider::releaseResource()*.

Asset Authoring
~~~~~~~~~~~~~~~
Generic asset authoring creation methods are used to create an asset authoring class::

    AssetAuthoring * ApexSDK::createAssetAuthoring( const char *authorableTypeName );
    AssetAuthoring * ApexSDK::createAssetAuthoring( const char *authorableTypeName, const char *name );

Asset authoring type names are retrieved from the individual APEX asset header files::
    
    // DestructibleAsset.h
    #define DESTRUCTIBLE_AUTHORING_TYPE_NAME "DestructibleAsset"

Asset authoring classes should be released using::

    void ApexSDK::releaseAssetAuthoring( AssetAuthoring& );
    
Since all asset data is stored in NvParameterized classes, it is all available to be edited from the NvParameterized object retrieved from the asset author using the *AssetAuthoring::getNvParameterized()* method.

Creating an Asset from an Authoring Class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An APEX Asset and Asset Authoring basically contain the same NvParameterized class, but ownership must be considered.

If one wanted to keep the Asset Authoring class and create a new Asset, the ApexSDK::createAsset( AssetAuthoring&, const char \*name ) method may be used.  This will perform a copy of the NvParameterized class data::

	AssetAuthoring *author; // initialized elsewhere
	Asset *asset = GetApexSDK()->createAsset( *author, "uniqueAssetName" );
	
If one no longer needed the Asset Authoring class and wanted to create a new Asset, a more efficient process may be used (no NvParameterized data copy required)::
	
	AssetAuthoring *author; // initialized elsewhere
	NvParameterized::Interface* oldInterface = author->releaseAndReturnNvParameterizedInterface();
	
	Asset *asset = GetApexSDK()->createAsset( oldInterface, "uniqueAssetName" );
	
Creating an Authoring from an Asset Class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An APEX Asset and Asset Authoring basically contain the same NvParameterized class, but ownership must be considered.

If one wanted to keep the Asset class and create a new Asset Authoring, a copy of the NvParameterized class data must be made::

	Asset *asset; // initialized elsewhere
	NvParameterized::Interface* oldInterface = asset->getAssetNvParameterized();
	
	// make the copy
	NvParameterized::Interface* newInterface = GetApexSDK()->getParameterizedTraits()->createNvParameterized(oldInterface->className());
	newInterface->copy( oldInterface );
	
	AssetAuthoring *author = GetApexSDK()->createAssetAuthoring( newInterface, "uniqueAssetAuthoringName" );
	
If one no longer needed the Asset class and wanted to create a new Asset Authoring, a more efficient process may be used (no NvParameterized data copy required)::
	
	Asset *asset; // initialized elsewhere
	NvParameterized::Interface* oldInterface = asset->releaseAndReturnNvParameterizedInterface();
	AssetAuthoring *author = GetApexSDK()->createAssetAuthoring( oldInterface, "uniqueAssetAuthoringName" );


Loading All Assets at Once
~~~~~~~~~~~~~~~~~~~~~~~~~~

There are several scenarios where a game may require all assets to
be loaded at once:

* Some games may require that APEX loads all of its assets at level
  load time (possibly in a deterministic order) to avoid asset loading
  during game play.

* Some games may require that APEX load all of its assets at one
  time so that they have information about which asset files to bundle
  into a "cooked build" of a level.

* Some games may require assets to be loaded asynchronously
  (e.g.: over a slow network connection).  They need to be able to start
  streaming all their assets during the "level loading" time.

Since APEX assets can reference other APEX assets by name, it is
not normally possible for the level loading code to know, up front,
about all assets that are going to be needed.  In order to solve this
problem, APEX provides an API that can be used to force the immediate
loading of all referenced, but not yet loaded assets.

The game engine is responsible for calling ApexSDK::forceLoadAssets()
as many times as it returns a number greater than 0.  Each time it
calls forceLoadAssets() it should expect calls to its registered
ResourceCallback::requestResource() callback to load the requested
asset::

    PxU32 ApexSDK::forceLoadAssets()

This method returns the number of assets force loaded by all of the
existing APEX modules.  It will also force load Render Mesh assets,
which are not contained in a module.

Instantiating Actors
--------------------

Once an asset has been created, de-serialized, and registered with
the Named Resource Provider, instantiating it in a scene is done by 
calling the *Asset::createApexActor()* method. Additional information,
such as its global pose (position and orientation in the scene),
that is commonly available to the level loader can be provided in
an NvParameterized descriptor data structure that is passed to the createApexActor()
method along with a pointer to the APEX Scene::

    NvParameterized::Interface * destructibleDesc = asset->getDefaultActorDesc();
 
    /* Set the actor's pose */
    NvParameterized::setParamMat44( *destructibleDesc, "globalPose", pose );
 
    /* Create the destructible actor in the APEX scene */
    DestructibleActor* actor = asset->createApexActor( *destructibleDesc, *gApexScene );

The Asset classes own the NvParameterized::Interface object that is retrieved
from *Asset::getDefaultActorDesc()*, so there is no need for the application to destroy it.

Named Resource Provider
-----------------------

The Named Resource Provider (NRP) is a public interface class in
the APEX Framework (class ApexResourceProvider). It's purpose is
to provide name to address mapping for APEX assets (Asset and
derived classes) and for miscellaneous game engine resources that
APEX authorable objects refer to by name, such as materials/textures.
It also provides a callback interface to allow the application to
load the named asset and thus resolve the mapping.

The NRP maintains mappings from a namespace/name pair to a resource
pointer. Namespaces and names are both null terminated character
strings (char*), and resource pointers are void pointers (void*).

Internally to APEX, a unique integer is associated with every
namespace/name pair. This integer is used to efficiently access the
current value of a resource pointer, without requiring the NRP to
perform string operations everytime the resource pointer is queried.

.. image:: images/Apex_NRP.gif
   :width: 75%

Every module, when created, creates a new namespace for each
type of authorable object (asset) that it implements. The namespace
for an authorable object will not be changed, because it is through
this name that game developers, as well as other modules, will
reference assets of this type. 

Whenever any asset is referenced by name (e.g.: when some other
asset is loaded), APEX uses the createResource()
method to create a mapping from the namespace/name pair to a unique
resource identifier. This only needs to be done once, as resource
identifiers are permanently (for the lifetime of the APEX SDK)
associated with the namespace/name pair. The referencing object
should save the assigned resource identifier for subsequent use
with the getResource() method to query the current value of the
resource pointer. APEX modules must, however, not save the resource
pointer for future use. Rather, they must call getResource() every
time they need to access the resource pointer. This allows the
application to call setResource() at any time to change the value
of the resource pointer. When the referencing object is done
referencing the resource (e.g.: when the referencing object is
deleted), it must call releaseResource(), which will call the
ResourceCallback::releaseResource() callback if the number of
references is now zero.

The public interface consists of a single method, setResource(),
and two callback functions, requestResource() and releaseResource(),
that are implemented in a user defined subclass of the pure virtual
base class, ResourceCallback. The application may call setResource()
at any time, to create a mapping between a namespace/name pair and
a resource pointer. This can be safely done before the createNameSpace()
or createResource() calls are made by the APEX modules. If the
application has not yet called setResource() to create a mapping
(for a particular namespace/name pair) when getResource() is called
for the first time from within APEX, then the NRP will call the
requestResource() callback to request the resource pointer to use
for the mapping. The callback must return a value, however, the
value may be 0 (NULL). The callback will only be called once for a
given namespace/name pair. If the application wants to subsequently
change the mapping, it must call setResource(). This may be done
as often as the application wishes, and getResource() will always
return the correct (most recent) resource pointer. The user class
implementing ResourceCallback must be provided in the descriptor
when the APEX SDK is initialized, in the call to CreateApexSDK().

NRP Well Known Namespaces
~~~~~~~~~~~~~~~~~~~~~~~~~

NSCollisionGroup
^^^^^^^^^^^^^^^^

A namespace for names of collision groups (CollisionGroup).  Each
name in this namespace must map to a 5-bit integer in the range
[0..31] (stored in a void*).  The NRP will not automatically generate
release requests for names in this namespace::

    #define APEX_COLLISION_GROUP_NAME_SPACE             "NSCollisionGroup"

NSCollisionGroup128
^^^^^^^^^^^^^^^^^^^

A namespace for names of GroupsMasks.  Each name in this namespace
must map to a pointer to a persistent 128-bit GroupsMask type.
The NRP will not automatically generate release requests for names
in this namespace::

    #define APEX_COLLISION_GROUP_128_NAME_SPACE         "NSCollisionGroup128"

NSCollisionGroupMask
^^^^^^^^^^^^^^^^^^^^

A namespace for names of collision group masks.  Each name in this
namespace must map to a 32-bit integer (stored in a void*), wherein
each bit represents a collision group (CollisionGroup).  The NRP
will not automatically generate release requests for names in this
namespace::

    #define APEX_COLLISION_GROUP_MASK_NAME_SPACE        "NSCollisionGroupMask"

ApexMaterials
^^^^^^^^^^^^^

A namespace for graphical material names.  Each name in this namespace
maps to a pointer to a game-engine defined graphical material data
structure.  APEX does not interpret or dereference this pointer in
any way.  APEX provides this pointer to the
UserRenderResource::setMaterial(void \*material) callback to the
rendering engine.  This mapping allows APEX assets to refer to game
engine materials (e.g.: texture maps and shader programs) without
imposing any limitations on what a game engine graphical material
can contain.  The NRP will not automatically generate release
requests for names in this namespace::

    #define APEX_MATERIALS_NAME_SPACE                   "ApexMaterials"

NSPhysicalMaterial
^^^^^^^^^^^^^^^^^^

A namespace for physical material names.  Each name in this namespace
maps to MaterialID, which is a data type defined by the PhysX
SDK.  The NRP will not automatically generate release requests for
names in this namespace::

    #define APEX_PHYSICS_MATERIAL_NAME_SPACE            "NSPhysicalMaterial"

NSCustomVBNames
^^^^^^^^^^^^^^^

A namespace for custom vertex buffer semantics names.  Each name
in this namespace maps to a pointer to a game-engine defined data
structure identifying a custom vertex buffer semantic.  APEX does
not interpret or dereference this pointer in any way.  APEX provides
an array of these pointers in
UserRenderVertexBufferDesc::customBuffersIdents, which is passed
the rendering engine when requesting allocation of vertex buffers::

    #define APEX_CUSTOM_VB_NAME_SPACE                   "NSCustomVBNames"

Namespaces for Asset names
^^^^^^^^^^^^^^^^^^^^^^^^^^

A new namespace is created for each type of Authorable Object (i.e. Asset).

The names in this namespace will be the names of assets of the
specified type.  Each entry maps to a pointer to the asset class
for the named asset.

The NRP will automatically generate release requests for names in
this namespace when the APEX SDK is released.

* ApexRenderMesh
* ClothingAsset
* DestructibleAsset
* ApexEmitterAsset
* GroundEmitterAsset
* ImpactEmitterAsset
* IofxAsset

Render Mesh Asset
-----------------

The RenderMeshAsset class, and the associated RenderMeshAssetAuthoring
and RenderMeshActor classes, implement a general purpose triangle
mesh asset. These classes are provided by the APEX Framework, and
can be used, by named reference, or by inclusion by assets in other
modules.

The RenderMeshAsset stores a vertex buffer accessible through
an VertexBuffer interface.  This vertex buffer supports a wide
variety of attributes: position, normal, tangent, binormal, color,
bone indices, bone weights, and up to 4 sets of [U,V] coordinates.
It also supports a variety of formats for each attribute.  See
Render Mesh Asset Interfaces.
 
.. image:: images/Apex_rendermesh.gif
   :width: 60%

The mesh can be subdivided in two orthogonal ways: by "part" and
by "sub-mesh".  Furthermore, each vertex of the mesh can be associated
with one or more "bones" (transformation matrices).

Each "part" is a unique subset of the triangles of the mesh for
which rendering can be individually enabled or disabled. This is
called "visibility", and is controlled, per instance, using the
RenderMeshActor::setVisibility(..) method. A part can span several
sub-meshes (see below), such that it can use different materials
for different triangles.

Each "sub-mesh" is a unique subset of the vertices and triangles
of the mesh that is assigned a particular material name. At run-time,
the material name is mapped to a user-defined pointer, using the
Named Resource Provider. This pointer is subsequently passed to the
rendering engine through the Render Resources Interface. A sub-mesh
can contain triangles from many different parts.

Each "bone" is a transform matrix (position, rotation, and scale)
that can be used at run-time to transform the position of the
vertices of the mesh. Each vertex can be associated with one or
more bones using the "bone index" vertex semantic. If a vertex is
associated with more than one bone, the "bone weight" semantic is
also used to provide a weighting factor that determines the proportion
in which the vertex position is transformed by each bone.  If all
the vertices of a part are associated with a single common bone,
the part will be rigid.  If they are associated with different
bones, the part will be "skinned".

Render Resources Interface
--------------------------

The APEX Framework provides a standard interface for modules to
interface with the game's rendering engine. The purpose of the
interface is to pass data (e.g.: vertex buffers, index buffers,
transform buffers) from APEX to the rendering engine for rendering.
APEX does not directly render anything (i.e.: no calls to D3D or
OpenGL), nor does specify or control how or when things are rendered.
It simply seeks to pass data that it generates or updates to the
game's rendering engine in a flexible yet efficient manner.

.. image:: images/Apex_render_resources.gif
   :width: 75%

Renderable Actor Interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

All transactions with the "Interface to Rendering" are initiated
by the game calling an APEX API. This interface is thread-safe, and
can be called at any time during the frame, including during
simulation, and while calls are being made from other game threads
to other APEX API's (assuming the locking semantics described below
are respected). These calls are all methods of the Renderable
class, which all renderable APEX actors derive from::

    class Renderable
    {
    public:
        const PxBounds3& getBounds() const;
        void updateRenderResources();
        void dispatchRenderResources( UserRenderer &renderer, PxReal lod );
    }

Calling updateRenderResources() on an APEX actor allows APEX to
issue callbacks to allocate any buffers that need to be allocated,
and to update (fill-in) any buffers that need to be updated.
Other than issuing these callbacks, updateRenderResources() will not
perform any additional computations, so as not to adversely impact
the performance of the thread that called it.

.. note::
    By performing these tasks in callbacks from updateRenderResources(),
    APEX allows the game to control when buffers are allocated and
    written to, as well as the thread context in which this occurs.
    These buffers can therefore be directly allocated from the graphics
    subsystem (e.g.: from D3D), even when the graphics API is not
    thread-safe, thus avoiding additional buffer copies.

updateRenderResources() must be called before dispatchRenderResources(),
but can be skipped entirely if the actor will not be rendered that
frame.

Calling dispatchRenderResources() on an APEX actor triggers APEX
to call the provided renderer's renderResource() method for each
of the actor's UserRenderResources. It will not update or allocate
any new rendering resources. It can be called as many times as the
game wishes to generate the same set of RenderContexts.

.. warning::
    APEX is completely unaware of D3D device resets and will not
    replay writeBuffer() calls into static vertex or bone buffers.
    It is the user's responsibility to request for buffers to be
    rewritten. For this, updateRenderResources() accepts an optional
    boolean flag (rewriteBuffers). When set to true, updateRenderResources()
    will make the necessary writeBuffer() calls to rewrite affected
    buffer data.

    Examples of scenarios that might lead to a device reset include:
    resizing the application window, switching to full screen mode or
    changing the screen resolution while the application is running.

    There are two important things to note when using the rewriteBuffers
    flag.

    1. Do not set rewireBuffers to true the first time UpdateRenderResources() is called.
    
    2. UpdateRenderResources should be called twice when the buffers need to be rewritten.
    First with rewriteBuffers=true, then with rewriteBuffers=false.


User Implemented Classes
~~~~~~~~~~~~~~~~~~~~~~~~

APEX interfaces with the game engine via several classes which are
implemented by the user. The first class manages the creation and
deletion of render resources. A user defined instance of
UserRenderResourceManager is provided to the ApexSDK at startup,
and is used globally by APEX to request/release render resources
from the game.

::

    class UserRenderResourceManager
    {
    public:
        virtual UserRenderVertexBuffer*   createVertexBuffer( const UserRenderVertexBufferDesc& desc );
        virtual void                        releaseVertexBuffer( UserRenderVertexBuffer& buffer );

        virtual UserRenderIndexBuffer*    createIndexBuffer( const UserRenderIndexBufferDesc& desc );
        virtual void                        releaseIndexBuffer( UserRenderIndexBuffer& buffer );

        virtual UserRenderBoneBuffer*     createBoneBuffer( const UserRenderBoneBufferDesc& desc );
        virtual void                        releaseBoneBuffer( UserRenderBoneBuffer& buffer );

        virtual UserRenderInstanceBuffer* createInstanceBuffer( const UserRenderInstanceBufferDesc& desc );
        virtual void                        releaseInstanceBuffer( UserRenderInstanceBuffer& buffer );

        virtual UserRenderSpriteBuffer*   createSpriteBuffer( const UserRenderSpriteBufferDesc& desc );
        virtual void                        releaseSpriteBuffer( UserRenderSpriteBuffer& buffer );

        virtual UserRenderSurfaceBuffer*  createSurfaceBuffer( const UserRenderSurfaceBufferDesc& desc );
        virtual void                        releaseSurfaceBuffer( UserRenderSurfaceBuffer& buffer );

        virtual UserRenderResource*       createResource( const UserRenderResourceDesc& desc );
        virtual void                        releaseResource( UserRenderResource& resource );
    };

APEX only requests new resources from this interface in the context
of calls to updateRenderResources(), so those functions generally
do not need to be thread safe.

.. warning::
    Any APEX API call that results in actor deletion can result
    in an immediate callback to UserRenderResourceManager (in the
    context of the calling thread) to release the associated render
    resources. Therefore, the release methods of this user implemented
    class **MUST be thread safe**.

Each of the UserRender*Buffer classes are also abstract and must
be implemented by the user. The buffer descriptor passed to the
create methods will describe the data format of each semantic (or
member) of that buffer, so the user class has the ability to pack
or interleave that data into as many or as few GPU buffers as
necessary. The descriptor will also contain a hint from APEX on the
usage of that buffer; whether it is static or dynamic. Each render
buffer class has a user-implemented write buffer method that can
be called by APEX (only from within the context of updateRenderResources())
to update the data in that buffer. The write methods are defined
as follows::

    // new implementation so the renderer receives all semantics at once
    void writeBuffer(const RenderVertexBufferData &data, physx::PxU32 firstVertex, physx::PxU32 numVertices)


APEX provides a pointer to the new source data (srcData) and it's
stride (srcStride), plus the ranges of values in the target buffer
to be updated (firstDestElement, numElements). The user is expected
to know the size of the APEX data from the descriptor used to create
the buffer. If locking and unlocking of buffers is expensive for
the game, they can cache the writeBuffer() calls made during
updateRenderResources() and then play them back all in a single
lock/write/unlock pass. Caching multiple writeBuffer() calls is
guaranteed to generate coherent data so long as the actor remains
locked until all of the writes are completed.

Next, the user must implement an UserRenderResource class for
managing a renderable entity. The descriptor for the UserRenderResource
contains pointer to all the various user buffers allocated for this
renderable actor. Some of those buffers may be shared with other
actors. The public interface of the UserRenderResource has methods
to update indices in the various buffers, associate a material, and
to retrieve those user buffers. APEX will only call these methods
from within updateRenderResources() calls.

Note that when an UserRenderResource instance is released to the
UserRenderResourceManager, the resource manager should not
implicitly release the render buffers used by that render resource.
Instead, APEX will explicitly release those resources as required.
Only APEX understands all of the sharing semantics, so the the game
should not call any of those release methods itself.

The last class that the user must implement is UserRenderer::

    class UserRenderer
    {
    public:
        virtual void renderResource( const RenderContext &context ) = 0;
    };

An instance of this class must be passed to dispatchRenderResources()
(described below). From the context of dispatchRenderResources(),
APEX will call this renderResource() method a number of times to
pass RenderContexts back to the game engine. RenderContext
is not user-defined, but it is a simple structure::

    class RenderContext
    {
    public:
        UserRenderResource   *renderResource;
        PxMat44                 local2world;
        PxMat44                 world2local;
    };

It essentially informs the game engine that a particular
UserRenderResource instance should be rendered at a particular
world pose. These render contexts could be rendered immediately by
your UserRenderer, or it may cache them for later use. The render
contexts are guaranteed to be valid until the next updateRenderResources()
call is made on that actor.

APEX Scene Based Render Resource Updating
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ApexScene has an API for creating an iterator for the scene's
renderable actors. It is used in the following manner::

    MyCachedRenderer renderer;
    RenderableIterator *iter = gApexScene->createRenderableIterator();
    for( Renderable *r = iter->getFirst() ; r ; r = iter->getNext() )
    {
        if( earlyCullCheck( r->getBounds() ) )
            continue;
        r->updateRenderResources();
        r->dispatchRenderResources( renderer, 0 );
    }
    iter->release();
     
    renderer.render_pass_1();
    renderer.render_pass_2();


When the game is ready to begin rendering, it can acquire an iterator
from the ApexScene and use it to call updateRenderResources() and
dispatchRenderResources() on all renderables in the scene it wishes
to render. The iterator implicitly handles all of the actor locking
and will in fact temporarily skip over actors locked by other threads
so that the loop can be completed as efficiently as possible. If
the same iterator is used to make multiple passes through a scene's
actors, it will also safely deal with actor deletions.

With this method, the game can store all of the RenderContexts
passed to it's renderer and use them safely in as many rendering
passes as it needs without any worry of conflicting with the ApexScene
or other game threads making calls to the APEX API.

Ad-Hoc Render Resource Updating
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Commonly, the game rendering thread will already have a scene graph
for it's rendering purposes and this graph will contain pointers
to all the Renderable actors. In this case, the game will not
want to use an iterators to access the actors. Instead, it will
want to access them in an ad-hoc method.

::

    Renderable *r = getApexRenderable( gameActor );
    MyCachedRenderer gRenderer;
    r->lockRenderResources();
    if ( !earlyCullCheck( r->getBounds() ) )
    {
        r->updateRenderResources();
        r->dispatchRenderResources( gRenderer, 0 );
    }
    r->unlockRenderResources();

With this method, APEX is unable to ensure the actor has not been
deleted by another game thread, so the game engine must ensure the
actor still exists. While the actor is locked, it cannot be deleted
or modified in any way by APEX. It's rendering data is guaranteed
to stay in a consistent state until it is unlocked.

Example Overview
~~~~~~~~~~~~~~~~

From 1000 feet up, the situation looks like this:

1.  The game allocates an UserRenderResourceManager instance
    and provides it to the ApexSDK at creation
2.  The main game thread calls Scene::simulate() and
    Scene::fetchResults() each frame (probably not in that order)
3.  When Scene::fetchResults() is called, the APEX actor
    states are updated to their new world positions and world bounds.
4.  In the rendering thread, using either an Scene iterator
    or the ad-hoc locking method, the game finds actors which are close
    enough to the view frustrum to be renderable and calls their
    updateRenderResources() methods
5.  Inside updateRenderResources(), APEX (may) call back to the
    UserRenderResourceManager to allocate new render resources. APEX
    then calls buffer write methods to pass the latest ApexActor state
    to the game engine.
6.  Subsequent calls to updateRenderResources() before the next
    invocation of Scene::fetchResults() should equate to NOOPs
7.  The rendering thread can now call dispatchRenderResources()
    on any of the ApexActors which have been updated, and it can make
    this call as many times as it wishes. Each time, dispatchRenderResources()
    will generate the same list of RenderContexts.

Materials
---------

APEX does not "know" anything about render materials. The details
of materials and shaders vary so much one renderer to the next, as
well as from one game engine to the next. It would be very difficult,
if not impossible, to abstract material handling in an useful way.

However, APEX must know something about materials, to the extent
that it groups render vertices according to different materials,
and informs the application as to which material is to be used with
a vertex buffer when render resources are dispatched (see Render
Resources Interface). It accomplishes this via the Named Resource
Provider, allowing the application to register all materials (as
void* pointers or integer handles) by their names. APEX render mesh
assets (RenderMeshAsset) group vertices by material, and refer
to the materials by name. Before the rendering resources are
dispatched to the user for a draw call, those material names are
matched to the user's material handles (void* or integer) using the
Named Resource Provider. In this way APEX has an efficient and
meaningful way to refer to the material at runtime.

This would be the end of the section on materials, except that APEX
has cases where it is its "own customer," that is, with applications
that need to render. One case is for authoring tools, another is
for sample or demo applications.

Default Material Library Implementation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As a utility for tools, samples, and demos, APEX has a common generic
material library class, ApexDefaultMaterialLibrary. This class can
create simple materials with texture maps (currently a diffuse,
bump, and normal map are supported). The texture maps may be read
in from a variety of file format (to support authoring), and stores
the texture maps in its own generic internal format.

The ApexDefaultMaterialLibrary is used to store material information
for fractured mesh authoring in the DestructionTool, and to load
materials for rendering in the Destruction module sample applications.
Our SimpleRenderer code, used by our tools and demos, interfaces
with ApexDefaultMaterialLibrary.

A ApexDefaultMaterialLibrary stores ApexDefaultMaterials, which in
turn can refer to ApexDefaultTextureMaps. These three classes are
defined in samples/common/include, and are based upon abstract base
classes.

Asynchronous Simulation Interface
---------------------------------

Simulation is controlled by the APEX scene. The Scene class
implements simulate(), checkResults(), and fetchResults() methods
that operate in similar fashion to the corresponding methods of the
PhysX SDK PxScene class.

Just as with scene creation, these three simulation methods
automatically call the corresponding PhysX SDK methods, eliminating
the need for the game to make duplicate calls. Taking control of
stepping the PhysX SDK simulations allows APEX modules to perform
tasks before, during, and after the PhysX SDK simulation.

In order to do all this, each Scene spawns a new simulation
thread, the "APEX scene thread".

When the game thread calls Scene::simulate(), a signal is
sent which unblocks the APEX scene thread. The APEX scene thread
then passes through three phases. In each phase, each APEX ModuleScene
(see above) is allowed to perform any asynchronous processing that
it desires. Furthermore, during the second phase, the PhysX SDK
simulation is allowed to proceed, by means of a call to
PxScene::simulate(), followed by a call to PxScene::checkResults(
block=true ).

The APEX scene in turns passes the execution context to each module
in turn.

Buffered API
------------

.. warning::
    The buffering feature is **NOT AVAILABLE** in this release of APEX.
    Calls to the API to change the simulation state must NOT
    be made between the calls to simulate() and fetchResults().

Changes to the simulation state (calls to "set" methods of the API)
must be made before the call to the simulate() method for the
timestep(s) in which the changes are to be effective. Changes that
are made after the call to simulate() are buffered until simulation
completes (i.e.: until fetchResults()). Changes are applied in the
order in which the API calls were originally made. This functionality
is similar to what is provided by the PxD wrapper for the PhysX
SDK, except that the functionality is built-in to APEX rather than
being implemented as a wrapper.

Deletion of scenes is also buffered. Deleting a scene during
simulation will not take effect until the simulation completes.
Even though the deletion is buffered, the application must not make
any more API calls that reference the scene, e.g.: don't call
fetchResults().

Calling fetchResults() before a corresponding simulate() call is
allowed but does nothing. This avoids the need for the application
to do a first-time check when calling fetchResults() for the previous
frame immediately before simulate() for the next frame.

View Matrix and the Projection Matrix
-------------------------------------
The APEX framework provides the following interfaces to allocate, set and get 
the View Matrix and the Projection Matrix.  Setting the View Matrix
and the Projection Matrix is **manditory** since various APEX features 
such as the Level of Detail and Debug rendering require the data.  This interface
has been designed to support multiple sets of matrices in order to provide
future APEX capabilities for multi-frame games on consoles.  The following 
API are in the APEX scene and may be found in 
`Scene.h <../_static/build_framework/_nx_apex_scene_8h.html>`_.::

    // first space must be allocated for the View Matrix and the Projection Matrix
    // These calls must be made one time only.
    const physx::PxU32 allocViewMatrix(ViewMatrixType::Enum);
    const physx::PxU32 allocProjMatrix(ProjMatrixType::Enum);

    // Next the transforms must be updated every time their values change
    void               setViewMatrix(const physx::PxMat44 & viewTransform, const physx::PxU32 viewID = 0);
    void               setProjMatrix(const physx::PxMat44 & projTransform, const physx::PxU32 projID = 0);

    // If the View Matrix type is USER_CUSTOMIZED the following call must be made every time the View Matrix is set.
    void               setViewParams(const physx::PxVec3 & eyePosition, const physx::PxVec3 & eyeDirection, 
                                     const physx::PxVec3 & worldUpDirection = PxVec3(0,1,0),
                                     const physx::PxU32 viewID = 0);
    // SetProjParams must be called every time the Projection Matrix is updated.
    void               setProjParams(physx::PxF32 nearPlaneDistance, physx::PxF32 farPlaneDistance, 
                                     physx::PxF32 fieldOfViewDegree, physx::PxU32 viewportWidth,
                                     physx::PxU32 viewportHeight, const physx::PxU32 projID = 0)

    // setUseViewProjMatrix must be called once.  Presently since only one of each matrix is supported
    // this function only needs to be called once.
	void               setUseViewProjMatrix(const physx::PxU32 viewID = 0, const physx::PxU32 projID = 0)

**NOTE:** Presently only one View Matrix and one Projection matrix may be set in each 
APEX scene.  Consequently the projID values for both of the above calls must presently
be set to 0 which is the only handle that the alloc functions will return.

When a view matrix is alocated the type must be specified.  It may be one of the following::

    struct ViewMatrixType
    {
        enum Enum
        {
            USER_CUSTOMIZED = 0,
            LOOK_AT_RH,
            LOOK_AT_LH,
        };
    };
    
    struct ProjMatrixType
    {
        enum Enum
        {
            USER_CUSTOMIZED = 0,
        };
    };


If the matrix type is set to LOOK_AT_RH or LOOK_AT_LH the eye position, direction, and 
world up direction are automatically computed based on a left handed or right handed 
world.  If the type is set to USER_CUSTOMIZED then the eye position **must** be set using the 
setProjMatrix API.

If the above calls are not made or are made incorrectly the following error messages will be output 
to the error stream.

+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| ERROR CODE             | MESSAGE                                                                   | Explanation                                                                           |
+========================+===========================================================================+=======================================================================================+
| APEX_INVALID_PARAMETER | view matrix for viewID %d is not initialized! see allocViewMatrix()       | A view matrix is required but has not yet been set.                                   |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | projection matrix for projID %d is not initialized! see allocProjMatrix() | A projection matrix is required but has not yet been set.                             |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Invalid ViewMatrixType!                                                   | View Matrix types must be set to one of the ViewMatrixType enumeration values.        |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Invalid ProjMatrixType!                                                   | Projection Matrix types must be set to one of the ViewMatrixType enumeration values.  |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | instantiating more than %d view matrices is not allowed!                  | Presently only 1 view matrix may be allocated.                                        |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | instantiating more than %d projection matrices is not allowed!            | Presently only 1 projection matrix may be allocated.                                  |
+------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------------------+

Level of Detail
---------------

APEX Modules will frequently implement Level of Detail (LoD) systems.
LoD systems are simply algorithms that determine the best way to
distribute limited resources over a set of objects in a scene. They
typically use criteria such as distance the object from the camera,
size of the object, age of the object, or relevance to game-play,
to determine the optimal distribution of resources.

APEX LOD defines resources roughly as computational load required to
accomplish a task to achieve a certain level of benefit.  A high
fidelity APEX asset that is near the eye position has greater
benefit than one that is located far from the eye position.  The APEX
modules that participate in the LOD resource distribution calculate sum of 
the benefits of all of their actors.  The LOD system distributes the available 
resources to the various APEX module scenes based on each modules total benefits
and a user supplied weighting for each of the modules.  The module weighting
feature is provided to allow the LOD system to be tuned based upon the priority
that the game developer places on the benefit of the actors that the various modules
provide.

The following APIs allows the total resource budget to be set and provides a
query to determine the actual resources consumed in the last simulation frame.
These functions are in APEX scene and can be found in
`Scene.h <../_static/build_framework/_nx_apex_scene_8h.html>`_.::

    void setLODResourceBudget(physx::PxF32 totalResource);
    physx::PxF32 getLODResourceConsumed()

The LOD resource budget should be adjusted based on the system that on which the
game is running.  On platforms such as Microsoft Windows that support a wide range
of CPU and GPU computational capabilities the budget could be set using a slider 
in a configuration window or perhaps by a benchmark.  Since the computational 
capabilities of any one console type is the same the game developer could set
the budget to a fixed value to achieve the desired balance between the fidelity
of the simulation and frame rate.

Every APEX module that participates in the APEX LOD resource distribution system
computes the benefit of its actors in a module specific way.  Setting the module 
weights both sets the priority and normalizes the benefits.  It should be noted
that resources and benefit are unique quantities.  The resources required to implent
an actor at a certain level of fidelity is the same no matter where the actor is
located relative to the eye position.  However the benefit of the actor will be 
much higher if it is located directly in front of the user than if the actor was 
far away and not visible.  The resource weight can also be normalized between APEX
modules using the same API call.  The following APIs allows the benefit and resource
weights of a module to be set and retrieved and are defined in 
`Module.h <../_static/build_framework/_nx_module_8h.html>`_.::

    // Sets scaling factors that determine how the units of benefit and resource used by 
    // this module relate to those of other modules.
    void setLODWeights(physx::PxF32 benefitWeight, physx::PxF32 resourceWeight);
    // Retrieves the currently used LOD Weights.
    void getLODWeights(physx::PxF32 & benefitWeight, physx::PxF32 & resourceWeight);

Further details of how the various APEX modules implement LOD is included in the
documentation for each module.  Clothing LOD is described here 
`Clothing Physical LOD <../APEX_Clothing/Clothing_Module_Doc.html#physical-lod>`_,
and here
`Clothing Actor Benefit <../APEX_Clothing/Clothing_PG_Runtime_Interfaces.html#updating-actor-benefit-for-lod>`_.
Destruction LOD features are described in 
`Destruction LOD Scalable Parameters <../APEX_Destruction/Destruction_Module.html>`_,
and 
`Destruction Debug Visualization LOD Features <../APEX_Destruction/Destruction_Module.html#debug-visualization>`_.
APEX Particles LOD is documented in 
`APEX Particles LOD <../APEX_Particles/Emitter_UG.html#common-parameters>`_.

Scalable Parameters
-------------------
Each APEX feature has one or more Scalable Parameters.  Due to the hierarchical relationship 
of many Authorable Objects not all Authorable Objects implement a scalable parameter. 
A Scalable Parameter is the specification of a range of values that is authored 
and saved in asset. Scalable Parameters may be found in any kind of asset, including those that
are only instantiated once per-module or per-module-scene. In other words, a module may define 
Scalable Parameters that are "global" to the module, or that are authored on a per-scene basis. 

Scalable Parameters do not inherently have anything to do with Level of Detail(LoD), but 
they can be used to configure various LoD settings. For example, a simple LoD system might
simulate the N most important widgets in the scene, while leaving the remaining widgets static.
In such a scenario N is a Scalable Parameter. 

Ownership of PhysX SDK Objects
------------------------------

The APEX SDK provides a mechanism for the application to make queries
about PhysX SDK objects, such as Actors, that have been created
by APEX.  For example::

    void myOnContactNotify(ContactPair & pair, PxU32 events)
    {
        const PhysXObjectDesc *desc0 = GetApexSDK()->getPhysXObjectInfo(pair[0]);
        const PhysXObjectDesc *desc1 = GetApexSDK()->getPhysXObjectInfo(pair[1]);

        if (desc0)
        {
            if (desc0->getActor()->getOwner()->getObjectTypeID() == gModuleDestructible->getModuleID())
            {
                DestructibleActor *da = static_cast<DestructibleActor*> (desc0->getActor());
                //...
            }
        }
    }


Serialization
-------------

Serialization is the process by which APEX assets are saved
(serialized) by an authoring tool and loaded (de-serialized) by the
APEX run-time.

Every APEX Authorable Object defines a set of data that makes up
the serialized asset in an NvParameterized class.  The *NvParameterized::Serializer*
class serializes and deserializes using the PxFileBuf interface for I/O. 
APEX provides both a file and memory buffer based implementation
of PxFileBuf, retrieved with *ApexSDK::createStream()* and 
*ApexSDK::createMemory[Read, Write]Stream()*, respectively.

The *NvParameterized::Serializer* can output XML formatted assets, which
are useful for smaller assets where a user might want to do hand editing or tweaking.
The serializer can also output platform-specific binary assets, which are
significantly smaller and deserialize much more quickly.  Binary assets can be serialized
for any platform and deserialized on any platform, but if the target platform 
matches the current platform, the *Serializer::deserializeInplace()* method 
may be used to perform in-place deserialization, which is significantly faster 
than the traditional method of processing an asset one parameter at a time.


Asset Preview
-------------

Before creating an asset preview, the NvParameterized preview descriptors have
to be set.  Specific details on descriptor parameters can be found in their
respective module's programmers guides. The following code illustrates the
general steps in creating an asset preview.

.. note::
    To modify asset preview parameters after creation, member set functions of
    the asset preview will have to be used, instead of modifying the NvParameterized
    descriptor values. Refer to individual modules programmers guides for more details.    

Asset Preview Colors
~~~~~~~~~~~~~~~~~~~~

Preview rendering colors are fixed, and cannot be modified by the application.


Errors and Warnings
-------------------

The APEX Framework outputs the following error and warning messages using the standard APEX error stream. 

+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| ERROR CODE             | MESSAGE                                                                                | Explanation                                                                                             |
+========================+========================================================================================+=========================================================================================================+
| APEX_INTERNAL_ERROR    | Cuda Error %d                                                                          | A CUDA driver API call returned the error number %d.                                                    |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Internal Error: GPU device memory allocation failure of %s in file '%s' in line %i.    | Memory allocation on the GPU accelerating PhysX & APEX failed.                                          |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Internal Error: CPU host memory allocation failure of %s in file '%s' in line %i.      | Memory allocation on the CPU failed.                                                                    |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Stream version (%d) is newer than this library (%d)                                    | The APEX asset being deserialized has a more recent version number than the corresponding APEX module.  |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Asset type name mismatch.  File <%s> != asset name <%s>                                | The named file does not contain the expected asset type                                                 |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Stream version (%d) does not contain a universal named asset header,                   | Loading a legacy asset without  the universal named asset header is not supported using the APEX        |
|                        | use a specific asset creation method to load this asset                                | generic asset loading.  The module specific asset load must be used for this asset.                     |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Unknown authorable type: %s, please load all required modules.                         | Attempting to create an asset that is not supported by currently loaded modules.                        |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Cannot create IOS asset <%s>, its module is not loaded.                                | The specified IOS module must be loaded before creating an IOS asset.                                   |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Invalid abortionRatio when doing infinite steps (%f)                                   | The abortion ratio for iso meshes must be greater than or equal to 0 and less than 1.                   |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Several parts and multiple bones per vertex are conflicting!                           |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | several submeshes have different custom buffers                                        |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | Conflicting parameterized objects!                                                     |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INTERNAL_ERROR    | simulation is still running                                                            | Unable to query debug visualization while simulation is running, not thread safe.                       |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_OPERATION | MeshDesc is not valid!                                                                 | The mesh data indicates that there are submeshes but there are no submeshes.                            |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_OPERATION | instantiating more than %d view matrices is not allowed!                               |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_OPERATION | instantiating more than %d projection matrices is not allowed!                         |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_OPERATION | view-projection matrix is not yet set! see setUseViewProjMatrix()                      |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_OPERATION | no vertices available                                                                  |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | isoGridSubdivision must be bigger than 0, setting it to 10                             |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Wrong input stream. The provided stream has to contain %s.                             |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | value is out of range (%d not in [%d, %d])                                             | The specified parameter is out of range.                                                                |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Cannot add (%p), another vertex buffer (%p) is already assigned!                       |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Cannot remove (%p), another vertex buffer(%p) is assigned                              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Invalid ViewMatrixType!                                                                |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | Invalid ProjMatrixType!                                                                |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | view matrix for viewID %d is not initialized! see allocViewMatrix()                    |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | projection matrix for projID %d is not initialized! see allocProjMatrix()              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | view matrix for viewID %d is not initialized! see allocViewMatrix()                    |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | view matrix for viewID %d is not a LookAt type! see allocViewMatrix()                  |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | view matrix for viewID %d is not a user-customized type! see allocViewMatrix()         |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | projection matrix for projID %d is not initialized! see allocProjMatrix()              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | projection matrix for projID %d is not a user-customized type! see allocProjMatrix()   |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_INVALID_PARAMETER | projection matrix for projID %d is a not a perspective FOV type! see allocProjMatrix() |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_INFO        | ApexAssetHelper::getAssetFromName: Could not create resource ID asset: %s              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Asset <%s> already exists                                                              | The authorable object specified by <%s> has already been loaded                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Deprecated interface, use ApexSDK::createAsset( physx::PxFileBuf&, const char * )      |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Deprecated interface, use ApexSDK::createAsset( AssetAuthoring&, const char * )        |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Deprecated interface, use ApexSDK::releaseAsset( Asset& )                              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Deprecated interface, use ApexSDK::createAssetAuthoring( )                             |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Deprecated interface, use ApexSDK::releaseAssetAuthoring( AssetAuthoring& )            |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Removed %d physX actor descriptor(s) still remaining in destroyed ApexScene.           |                                                                                                         |  
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Removed %d physX softbody descriptor(s) still remaining in destroyed ApexScene.        |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | createObjectDesc: Px Object already registered                                         |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | createObjectDesc: Px Object already registered with the given Actor                    |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | releaseObjectDesc: Unable to release object descriptor                                 |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Asset <%s> already exists                                                              |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | No NvParameterized::Factory is registered for %s                                       |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Some conversions for class %s were not released                                        |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Some factories for class %s were not released                                          |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | NvParameterized::Factory does not have a valid name                                    |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | Schema checksum is different, results may be invalid                                   |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
| APEX_DEBUG_WARNING     | NvParameterized ENUM value not correct: %s, substituting: %s                           |                                                                                                         |
+------------------------+----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+
