==================
Runtime Interfaces
==================

.. highlight:: c++

This chapter shows how to use the Clothing Module by explaining the
essential part of the SimpleClothing sample application in APEX/samples.
It shows how to load an asset, instance an actor, keep it synchronized
with the character and render the simulated clothing part through the
clothing actor.

Initialization
==============

An APEX application needs to first initialize PhysX. In the following code
samples it is assumed that a PhysX SDK has been created (see the PhysX
documentation)::

    PxPhysics* m_physxSDK;
    PxFoundation* m_foundation;
    m_foundation = PxCreateFoundation(PX_PHYSICS_VERSION, ...);
    m_physxSDK = PxCreatePhysics( ... );
    PxInitExtensions(*m_physxSDK);

and that we have a cooking library::

    PxCookingParams params;
    PxCooking* m_cooking;
    m_cooking = PxCreateCooking(PX_PHYSICS_VERSION, m_physicsSDK->getFoundation(), params);

After initializing the PhysX SDK, an APEX application needs to initialize
the APEX SDK. See APEX SDK Documentation.

This is done as follows::

    nvidia::apex::ApexSDKDesc apexSdkDesc;

    // Let Apex know about our PhysX SDK and cooking library
    apexSdkDesc.physXSDK = mPhysicsSDK;
    apexSdkDesc.cooking = mCookingInterface;

    // The output stream is used to report any errors back to the user
    apexSdkDesc.outputStream = mErrorReport;

    // Our custom render resource manager
    apexSdkDesc.renderResourceManager = mRenderResourceManager;

    // Our custom named resource handler (NRP)
    apexSdkDesc.resourceCallback = mResourceCallback;

    // Apex needs an allocator and error stream.
    // By default it uses those of the PhysX SDK.
    apexSdkDesc.allocator = mApexAllocator;

    // Finally, create the Apex SDK
    ApexCreateError errorCode;
    mApexSDK = nvidia::apex::CreateApexSDK(apexSdkDesc, &errorCode);

The render resource manager SampleApexRenderResourceManager is used.
It is common to the APEX samples. 

Also an Scene has to be created to hold APEX actors and renderables.
It can be initialized with a PhysX scene::

    // Create an APEX scene with a PhysX scene
    nvidia::apex::SceneDesc sceneDesc;
    sceneDesc.scene = mPhysxScene;
    nvidia::apex::Scene* apexScene = mApexSDK->createScene( sceneDesc );

An APEX application then needs to create the APEX modules it will use. 


Loading the Clothing Module
===========================

First the clothing module ModuleClothing is created::

    mApexClothingModule = static_cast<nvidia::apex::ModuleClothing*>(mApexSDK->createModule("Clothing"));

Then it is initialized with an ModuleClothingDesc::

    #include <NvParamUtils.h>
    if (mApexClothingModule != NULL)
    {
        NvParameterized::Interface* moduleDesc = mApexClothingModule->getDefaultModuleDesc();

        // Know what you're doing when playing with these values!

        // should not be 0 for every platform except PC.
        NvParameterized::setParamU32(*moduleDesc, "maxNumCompartments", 3);

        // Can be tuned for switching between more memory and more spikes.
        NvParameterized::setParamU32(*moduleDesc, "maxUnusedPhysXResources", 5);

        mApexClothingModule->init(moduleDesc);
    }

ModuleClothingDesc holds the field maxNumCompartments that lets you define
the number of PxCompartments to which the simulated cloth instances are
supposed to be distributed. This is good to parallelize the CPU work of
the cloth simulation for both CPU and GPU cloth.


Loading Assets
==============

First a clothing asset (ClothingAsset) needs to be created or loaded.
The clothing authoring tool (ClothingTool) or the PhysX plug-in for Autodesk
Max and Maya can be used to create and save ClothingAssets.


Loading Assets the NRP way
--------------------------

This will get a callback to the NRP, much as if APEX requests a resource,
allowing to gather all resource loading code in one place.

::

    nvidia::apex::Asset* asset = reinterpret_cast<nvidia::apex::Asset*>(mApexSDK->getNamedResourceProvider()->getResource(nameSpace, fullname));
    if( asset )
    {
        mApexSDK->getNamedResourceProvider()->setResource(nameSpace, fullname, asset, true);
    }

The NRP would look something like this::

    void* MyResourceCallback::requestResource(const char *nameSpace, const char *filename)
    {
        if( !strcmp(nameSpace, CLOTHING_AUTHORING_TYPE_NAME) ||
            !strcmp(nameSpace, <SOME OTHER TYPE>))
        {
            return loadParameterized(filename);
        }
    }



Loading Assets the NvParameterized way
--------------------------------------

::

    nvidia::apex::Asset* loadParameterized(const char* fullpath)
    {
        nvidia::apex::Asset* result = NULL;
        NvParameterized::Serializer::DeserializedData deserializedData;
        
        // A FileBuffer needs to be created.
        // This can also be a customized subclass of physx::PxFileBuf
        physx::PxFileBuf* fileBuf = mApexSDK->createStream(fullpath, physx::PxFileBuf::OPEN_READ_ONLY);
        
        if (fileBuf != NULL)
        {
            if (fileBuf->isOpen())
            {
                char peekData[32];
                stream->peek(peekData, 32);

                // The method returns either Serializer::NST_BINARY or Serializer::NST_XML, or Serializer::NST_LAST for unknown files.
                NvParameterized::Serializer::SerializeType serType = mApexSDK->getSerializeType(peekData, 32);

                physx::Serializer* serializer = mApexSDK->createSerializer(serType);
                
                if (serializer != NULL)
                {
                    physx::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
                    serError = serializer->deserialize(*fileBuf, deserializedData);

                    // do some error checking here
                    if (serError != NvParameterized::Serializer::ERROR_NONE)
                    {
                        processError(serError);
                    }

                    serializer->release();
                }
            }
            fileBuf->release();
        }

        // Now deserializedData contains one or more NvParameterized objects.
        for (unsigned int i = 0; i < deserializedData.size(); i++)
        {
            NvParameterized::Interface* data = deserializedData[i];
            printf("Creating Asset of type %s\n", data->className());

            if (result == NULL)
            {
                result = mApexSDK->createAsset(data, "some unique name");
            }
            else
            {
                // we have to handle files with multiple assets differently, for now, let's get rid of it
                deserializedData[i]->destroy();
            }
        }
        
        return result;
    }

Loading Assets the old way
--------------------------

Apex versions older than 1.0 used to have per asset file formats. In Clothing
this was the .aca file. In the sample there is the function loadClothingAsset
to load a stored aca file (Apex Clothing Asset) from disk. These files can no
longer be loaded with Apex 1.1. They can be converted to .apx/.apb files using
The ParamTool from Apex 1.0.


Instantiating Actors
====================

The clothing assets can be instanced by creating clothing actors. A
descriptor has to be provided to the creation function. The descriptor
is a NvParameterized object::

    #include <NvParamUtils.h>
    #define VERIFY_PARAM(_A) { NvParameterized::ErrorType error = _A; PX_ASSERT(error == NvParameterized::ERROR_NONE); }

    // Get the (singleton!) default actor descriptor.
    NvParameterized::Interface* actorDesc = mAsset->getDefaultActorDesc();
    PX_ASSERT(actorDesc != NULL);

    // Run Cloth on the GPU
    NvParameterized::setParamBool(*actorDesc, "useHardwareCloth", mGpuSimulation));
    NvParameterized::setParamBool(*actorDesc, "flags.ParallelPhysXMeshSkinning", true);

    // Initialize the global pose
    NvParameterized::setParamMat44(*actorDesc, "globalPose", currentPose);

    {
        NvParameterized::Handle actorHandle(*actorDesc);
        
        // No util method for this
        VERIFY_PARAM(actorHandle.getParameter("boneMatrices"));
        VERIFY_PARAM(actorHandle.resizeArray(skinningMatrices.size()));
        VERIFY_PARAM(actorHandle.setParamMat44Array(&skinningMatrices[0], skinningMatrices.size()));
    }

    // create the actor
    nvidia::apex::Actor* apexActor = mAsset->createApexActor(*actorDesc, *mApexScene);
    nvidia::apex::ClothingActor* clothingActor = static_cast<nvidia::apex::ClothingActor*>(apexActor);

    doSomething(clothingActor);


Clothing Preview
----------------

Instead of creating clothing actors, it is also possible to create
clothing previews::

    NvParameterized::Interface* previewDesc = mAssets->getDefaultAssetPreviewDesc();
    PX_ASSERT(previewDesc != NULL);

    // Initialize the global pose
    NvParameterized::setParamMat44(*previewDesc, "globalPose", currentPose);

    nvidia::apex::AssetPreview* apexPreview = mAssets->createApexAssetPreview(*previewDesc);
    nvidia::apex::ClothingPreview* clothingPreview = static_cast<nvidia::apex::ClothingPreview*>(apexPreview);


The clothing preview is basically the same as a clothing actor, except that
there is no simulation running. So it is possible to show the animated version
of the clothing actor without having an PxScene around. Updating the animation
state and rendering works just like with the normal clothing actor
(updateState, updateRenderResources and dispatchRenderResources).


Stepping the Simulation
=======================

When using an APEX application, the simulate and fetchResults functions of
the PhysX scene need to be replaced by the corresponding simulate and
fetchResults functions of the APEX scene. The APEX scene wraps the PhysX
scene and ticks all the APEX actors additionally.

.. note:: This also applies to the checkResults method.

::

    // start the simulation
    mApexScene->simulate(dtime);

    doSomethingInBetween();

    // finish the simulation
    physx::PxU32 errorState = 0;
    mApexScene->fetchResults(true, &errorState);


Prior to the simulate call the actor state has to be updated.


Updating Actor Benefit for LoD
------------------------------

For each actor, the benefit is calculated according to this equation:

::

    benefit = lodWeights.distanceWeight * angularImportance(distanceFromEye, assetRadius) + lodWeights.benefitsBias

The angularImportance function just linearly blends down from 1.0 to 0.0
basically measuring screen space size. The size is estimated as the amount
the asset's diagonal (assuming it's a sphere) is covering across the screen.

If lodWeights.maxDistance is provided, the benefit will reach 0.0 once the
actor has said distance, otherwise it will only reach 0.0 for infinitely
far away actors.

The lodWeights.distanceWeight marks the importance of a clothing actor relative
to others. Actors with a lower weight will be turned off more quickly even if
they have the same maxDistance and distanceFromEye. A character having both
hair and a cape should have the weight of the hair significantly lower than
the weight of the cape as the cape is much more noticeable whether it's
being simulated.

distanceFromEye is the distance from the eye position, as computed in
Scene::setViewMatrix() and the center of the bounding box of a clothing
actor.

The lodWeights.benefitBias should be a value between 0.0 and 1.0. Benefit
is defined as being in the [0.0, 1.0] range across all modules, however
larger values still work, they just lead to proportionally larger amounts
of simulation resources.

.. note::
   The maxDistance parameter can be changed based on the fact whether a
   clothing actor is visible. Setting it to 0 for invisible characters
   however is not recommended at all since it takes a while to enable
   clothing again once it is disabled. Reducing the maxDistance to half
   for invisible actors can lead to good results though.

::

    // requests the actors current configuration
    // The object does not have to be returned, it is directly modified
    NvParameterized::Interface* actorDesc = mActor->getActorDesc();

    NvParameterized::setParamF32(*actorDesc, "lodWeights.maxDistance", maxDistance);
    NvParameterized::setParamF32(*actorDesc, "lodWeights.distanceWeight", distanceWeight);
    NvParameterized::setParamF32(*actorDesc, "lodWeights.benefitsBias", benefitBias);



Distribution of simulation resources
------------------------------------

Simulation resources are an abstract unit. They are set through the
Scene. Additionally two parameters need to be carefully chosen. The
first describes the inter-module importance and the second describes how
the abstract resources are then turned into resources allowing the clothing
to decide whether it should simulate or not::

    Scene* scene = getApexScene();
    // assuming the abstract unit is milliseconds, giving the simulation 15ms to run
    scene->setLODResourceBudget(15.0f);
    
    ModuleClothing* clothingModule = getClothingModule();
    
    // no special importance to clothing module (relative to other modules)
    clothingModule->setLODBenefitValue(1.0f);
    
    // This value needs to be carefully tweaked and will differ for different platforms (or even PC processors).
    // Here we assume that each millisecond we can simulate 10'000 vertices.
    clothingModule->setLODUnitCost(0.0001f);


Turning off the automatic LOD
-----------------------------

This can be done either for the entire clothing module, or for each clothing
actor separately::

    ModuleClothing* moduleClothing = getClothingModule();
    
    // turn off LOD for all clothing actors
    moduleClothing->setLODEnabled(false);
    
    for (unsigned int i = 0; i < getNumClothingActors(); i++)
    {
        ClothingActor* clothingActor = getClothingActor(i);
        
        // turn off automatic LOD for this actor only
        clothingActor->forceLod(0);

        // turn on automatic LOD for this actor only
        clothingActor->forceLod(-1);
    }



Updating the Animation State
----------------------------

When a character is animated the animation transforms have to be provided to
the Clothing Actor::

    physx::PxMat44 globalPose = getGlobalPose();
    physx::PxMat44* boneMatrices = getBoneMatrices();
    actor->updateState(globalPose, boneMatrices, sizeof(physx::PxMat44), getNumBoneMatrices(), isContinuous);

In updateState a global pose and the current state of the animation bones are
provided. In the SimpleClothing sample the asset doesn't have an animation
skeleton, so just the pose is updated. The matrices to provide here are the
same as the ones needed to specify the initial state in the
ClothingActorDesc if you have animation on that mesh.

The *isContinuous* flag tells the actor if the motion is smooth or not. If
it is set to true the normal simulation procedure is applied. Setting it to
false marks a special frame in the animation where the character is
teleported to a different location or orientation. In that case the
clothing is reset to its animated, skinned state, replacing the simulation.
If isContinuous is set to false multiple subsequent frames, it always forces
the simulation to the animation and will look very awkward. The flag helps a
lot whenever either animation cannot be blended every once in a while or a
character is teleported.


Updating the Max Distance Scale
-------------------------------

Each Clothing Actor can have an individually changing Max Distance Scale::

    NvParameterized::Interface* actorDesc = mActor->getActorDesc();

    NvParameterized::setParamF32(*actorDesc, "maxDistanceScale.Scale", scale);
    NvParameterized::setParamBool(*actorDesc, "maxDistanceScale.Multipliable", multipliable);

The *scale* parameter must be in the [0,1] range and denotes the scale
applied. The *multipliable* parameter switches between two modes of scale.
Multipliable will multiply all max distances with the scale, otherwise the
same fraction of the maximum Max Distance will be subtracted from all
vertices, leading to some regions of the mesh not being simulated.

Remap Bone Indices
------------------

The function updateState takes an array of transformation matrices
representing the current state of the animation skeleton. It is possible that
the animation system and the internally stored bones in APEX do not have the
same order. Therefore it can be necessary to map the list of animation
matrices of the application to the bones stored in APEX using the
remapBoneIndex function::

   const std::vector<SkeletalBone>& bones = mSkeleton.getBones();
   for (PxU32 i = 0; i < bones.size(); i++)
   {
       mAsset->remapBoneIndex(bones[i].name.c_str(), i);
   }

This needs to be done before the first updateState call.


Use Internal Bone Order
-----------------------

This is the orthogonal feature to Bone Index Remapping. The game engine will
provide the skinning matrices in the same order as the Clothing Actor expects
it, the same order as the bones are stored in the Clothing Asset.

It needs to be activated in the Clothing Actor Descriptor::

    NvParameterized::Interface* actorDesc = mAsset->getDefaultNvParameterizedInterface();
    PX_ASSERT(actorDesc != NULL);

    NvParameterized::setParamBool(*actorDesc, "useInternalBoneOrder", true); // default is false

Then, the game engine needs to find out what bones are at what location::

    const unsigned int boneNumber = mClothingAsset->getNumUsedBones();
    
    for (unsigned int internalIndex = 0; internalIndex < boneNumber; internalIndex++)
    {
        const char* boneName = mClothingAsset->getBoneName(internalIndex);  

        // create a mapping table now
        // ...
    }

This has the advantage that the updateState call can copy the matrices
slightly more quickly. Also the number of bone matrices that need to be
handed to the clothing actor is reduced to only the set of bones that
are active within the clothing actor.


Frame Delay
-----------

When the simulation is updated serially in the usual order:
clothingActor->updateState(...)
scene->simulate(...)
scene->fetchResults(...)
clothingActor->updateRenderResources(...)
clothingActor->dispatchRenderResources(...)

there is no frame delay. The clothing actor is rendered corresponding
to the matrices provided in the updateState call.

There will be a frame delay when the provided matrices are based on a
rigid body simulation, and if these rigid bodies are simulated in the
same scene as the cloth. An example for such a scenario would be clothing
on a ragdoll, or a simulation based character controller.

There are two ways to handle such situations. One solution is to introduce a 
matching delay on all rendered objects, or at least on the character with clothing.
The second approach is to simulate the cloth in a separate scene later in the
frame. The advantages of the former solution are more parallelism and the
possibility to simulate interactions with other objects in the scene.
However such a frame delay is often hard to handle in a game engine and
the latter approach is more practicable. A selection of objects that need to be
interacted with can be mirrored into the clothing scene.


Wind
----

For clothing actors a wind vector can be set::

    NvParameterized::Interface* actorDesc = mActor->getActorDesc();

    NvParameterized::setParamVec3(*actorDesc, "windParams.Velocity", windVelocity);
    NvParameterized::setParamF32(*actorDesc, "windParams.Adaption", windAdaption);

    // This alternative code is deprecated with 1.1
    mActor->setWind(windAdaption, windVelocity);

The windVelocity parameter represents the target velocity of the wind. Best
results can be achieved when the velocity has a small random noise on top.
The windAdaption parameter represents how quickly the cloth piece adapts to
the wind velocity. With an adaption value of 1.0 it will take the piece of
cloth at least 1s to adapt fully to the velocity. If it takes longer than 1s
it means the cloth is not perpendicular to the wind direction. Increasing the
adaption to 10 will reduce the time to 1/10s whereas lowering the paramter to
0.5 will increase the time to 2s.

Since the wind velocity and adaption is part of the actor descriptor it can
be set before actor creation, and it can also be altered when the actor already
exists.

.. note::
    For better quality it is very much recommended to slightly vary the wind
    velocity in strength as well as in direction.

Even wind with zero velocity can be simulated, this will result in air
resistance (still modulated by dot product between vertex normal and wind
direction).

.. note::
    APEX Clothing has its own implementation of wind. This is orthogonal
    to the wind module and will work just by itself.


.. _clothing-render-proxy-label:

Rendering With Render Proxy
---------------------------

A clothing actor can be rendered by acquiring a render proxy from it,
getting the render data through updateRenderResources, and triggering the
render callback with dispatchRenderResources. After all render calls are
done, the render proxy needs to be released, so that the memory can be
reused again. The acquirer of the render proxy has exclusive access to
its data, so locking the render resources is not necessary. The render proxy
can only be acquired once per frame, otherwise NULL is returned::

    SampleApexRenderer apexRenderer;
    ClothingRenderProxy* renderProxy = clothingActor->acquireRenderProxy();
    if (renderProxy != NULL)
    {
        renderProxy->updateRenderResources();
        renderProxy->dispatchRenderResources(apexRenderer);
        renderProxy->release();
    }

The render proxy can be acquired at any time, even during simulate, and it
contains the latest simulation result. Note that it is better to release
the render proxy before the next simulate call so that the memory can be
reused. Otherwise, a new render proxy is allocated to double buffer the
result. That means it's good to acquire and release the render proxy after
every fetchResults, even if the actor is not rendered this frame.

An acquired render proxy contains valid data that stays unchanged until
it is released. A render proxy also stays valid after its corresponding
actor has been released. However, releasing the corresponding ClothingAsset
will invalidate the render proxy.

It is safe to call updateRenderResources on the render proxy in parallel, for example
in the render thread, if the APEX SDK parameter 'renderMeshActorLoadMaterialsLazily'
is set to false.


Rendering
---------

The old way of rendering a clothing actor is still supported. However note that
this way the render data is always double buffered, which allows
updateRenderResources to be called during simulate, but which also
might waste memory if you don't need the double buffering. Use the render proxy
and release it before the simulate call in order to prevent that.

A clothing actor is rendered by updating the render resources, setting up a
renderer and calling dispatchRenderResources with it. The Renderer is the
same as for any other APEX module::

    SampleApexRenderer apexRenderer;
    actor->lockRenderResources();
    actor->updateRenderResources();
    actor->unlockRenderResources();
    
    // dispatch could also be called later on!
    actor->dispatchRenderResources(apexRenderer);

For general information on how to use debug visualization within APEX, please see
:ref:`debug-visualization-label`.


Implementing the Render Interface
=================================

As mentioned above a renderer needs to be set up for the clothing actor
rendering. Together with the renderer a bunch of render interface classes
need to be sub classed and implemented by the application. See the APEX
Programmer's Guide for details about the APEX render interface. The
SimpleClothing sample uses the SampleApexRenderer that is common to the samples.


A simple scenario
-----------------

These are the buffers typically created when rendering a clothing actor.
The order of creation can vary.

The formats specified in this document are an example. For normals it's
also possible to have more compressed formats like BYTE_SNORM3, SHORT_SNORM3,
or (in future versions) even a BYTE_SNORM4 containing a quaternion instead of the
normal/tangent buffers.

As of Apex 1.2 the tangent is now an FLOAT4 and the binormal semantic is gone.
The binormal can be reconstructed as cross(normal, tangent.xyz) * tangent.w but
been reduced to a single float. This reduces computational overhead inside apex
and less data going through the render API as well.

The hint flags indicate whether a buffer is updated frequently or once.

The fist vertex buffer is created from the clothing actor itself. It always
contains a position and normal, and it can contain tangents and bi-normals.
The formats are identical to the formats used by the render mesh asset::

    createVertexBuffer
      hint                = DYNAMIC
      uvOrigin            = ORIGIN_BOTTOM_LEFT
      Buffers Requested:
        POSITION          = FLOAT3
        NORMAL            = FLOAT3
        TANGENT           = FLOAT4

The next 3 vertex buffers are created by the render mesh asset within the
clothing asset. They are split into 3 different ones because the clothing
actor only ever needs a subset of them depending on its state.

The first buffer contains all the identical semantics as the buffer from
the clothing actor. This static buffer will only be used when the clothing
actor is not being simulated, and the fallback skinning flag is not set::

    createVertexBuffer
      hint                = STATIC
      uvOrigin            = ORIGIN_BOTTOM_LEFT
      Buffers Requested:
        POSITION          = FLOAT3
        NORMAL            = FLOAT3
        TANGENT           = FLOAT4

The second buffer contains the bone indices and bone weights weights if
present. It will only be used when the clothing actor is not simulated
and fallback skinning flag is not set::

    createVertexBuffer
      hint                = STATIC
      uvOrigin            = ORIGIN_BOTTOM_LEFT
      Buffers Requested:
        BONE_INDEX        = USHORT4
        BONE_WEIGHT       = FLOAT4

The third buffer contains everything else including custom vertex buffers.
As an example, VERTEX_ORIGINAL_INDEX is a buffer that contains old vertex
indices from the authoring pipeline. This is the order of the vertices in
which they were entered into the render mesh asset::

    createVertexBuffer
      hint                = STATIC
      uvOrigin            = ORIGIN_BOTTOM_LEFT
      Buffers Requested:
        TEXCOORD0         = FLOAT2
      Custom Buffers Requested:
        VERTEX_ORIGINAL_INDEX = UINT1

The index buffer is fairly straight forward. The hint will remain on STATIC
as long as clothing does not support tearing. The format will be one of 
UBYTE1, USHORT1 or UINT1, the primitives TRIANGLES and registerInCUDA will
be false for the time being (as well as no interopContext).

.. code-block:: text

    createIndexBuffer
      hint           = STATIC
      format         = UINT1
      primitives     = TRIANGLES
      registerInCUDA = false
      interopContext = 00000000

The render resource will then contain two or more of these vertex buffers.
The vertex semantics of those buffers will always be mutually exclusive::

    createRenderResource
      Vertex Buffers:
       TEXCOORD0 VERTEX_ORIGINAL_INDEX
       POSITION NORMAL TANGENT



Buffered calls & Multithreading
===============================

The API in the Clothing Module is not thread safe. It is not allowed at any
time to call two methods on the same or two different APEX objects. 

Also, none of the calls inside the clothing module are buffered. For some
methods it is safe to call them even while the simulation is running but
these methods mention this fact explicitly. Any other method should not be
called during simulation.

For example it is allowed to load assets while the simulation is running,
but it's not allowed to create actors from these assets while the simulation
is running. Also it's not allowed to load two assets at the same time.



Using Morph Targets (also known as Blend Shapes)
================================================

When characters need to be customized after being exported from DCC tools it
is usually for MMO like character customization. These are done by blending
between deformed meshes of the original character.

These changes have to be applied on the fly as there is no way to store all
possible configurations as pre-backed asset files. Apex Clothing does this
by allowing the game engine to provide the displacements of the original
positions to each ClothingActor upon creation. It can't be modified later
on because the changes need to be cooked into the simulation mesh.

First, the asset needs to be aware which order those displacements will be
applied. To do so, the original positions need to be passed to the asset
such that it can create the mapping from external to internal ordering. This
requires that the original positions have to be identical to the ones provided
by the DCC tool at export time, including the same animation pose::

    ClothingAsset* clothingAsset = getClothingAsset();

    physx::PxF32 epsilon = 0.0f;

    physx::PxU32 numMapped = clothingAsset->prepareMorphTargetMapping(&morphVertices[0], morphVertices.size(), epsilon);

    if (numMapped < morphVertices.size())
    {
        // The mapping still worked, but some vertices were mapped to an origianl vertex with more than epsilon differences.
        // Either bump the epsilon or, if too many failed, emit an error message about a potentially bad mapping
    }


Second, upon actor creation the displaced vertices need to be passed through
the actor descriptor::


    NvParameterized::Interface* actorDesc = clothingAsset->getDefaultActorDesc();

    // [...] Some initialization of the actorDesc

    physx::PxU32 numMorphDisplacements = 0;
    physx::PxVec3* morphDisplacements = NULL;
    getMorphDisplacements(morphDisplacements, numMorphDisplacements);

    if (numMorphDisplacements > 0)
    {
        NvParameterized::Handle md(*actorDesc, "morphDisplacements");
        md.resizeArray(numMorphDisplacements);
        md.setParamVec3Array(morphDisplacements, numMorphDisplacements);
    }

    physx::Actor* actor = clothingAsset->createApexActor(*actorDesc, apexScene);


This actor will most likely not immediately start to simulate. It will cook
the simulation mesh during the first couple of simulation frames in a
background thread. This however can be modified by setting the
*allowAsyncCooking* bool in the Clothing Module Parameters.

The convex volumes are also adapted as good as possible, however the capsule
volumes are not. As long as the morph target is only applying moderate
changes this is usually no problem.

It is still not allowed to have scales on certain bones.



Colliding with the Environment
==============================

The 3x cloth solver does not support automatic collision with a scene. Each clothing actor will just collide with its own collision volumes, specified in the clothing asset. If additional collision is required, for example to collide with the ground, there is an interface on the clothing actor to add this::

    ClothingPlane*        createCollisionPlane(const PxPlane& plane)
    ClothingConvex*       createCollisionConvex(ClothingPlane** planes, PxU32 numPlanes)
    ClothingSphere*       createCollisionSphere(const PxVec3& position, PxF32 radius)
    ClothingCapsule*      createCollisionCapsule(ClothingSphere& sphere1, ClothingSphere& sphere2)
    ClothingTriangleMesh* createCollisionTriangleMesh()

Each of those collision objects provide functions to release, edit and position the objects.

To implement generic collision with the environment, a scene can be queried around the clothing actor and corresponding clothing collision objects can be created for the actor. Some bookkeeping is required to keep track of the mirrored objects, in order to update and release them in time.

ClothingTriangleMesh has a few limitations. It should be kept small for performance reasons, it should be closed (at least when including the bounding box of the cloth), and it is currently not possible to dynamically remove triangles from it. Therefore it is recommended to use planes or convexes to approximate collision with the ground.

