This guide highlights the significant API changes that have occured between APEX 1.2 and APEX 1.3. This guide is aimed at a developer already using APEX 1.2.x who wants to know the minimum amount of work to upgrade to APEX 1.3. Note that the PhysX API has also changed from PhysX 3.2.x to 3.3. Refer to the PhysX documentation for a description of PhysX API changes.
The deprecated ExampleFS and Wind modules were removed in APEX 1.3. Note that the Wind module is not the same thing as the wind feature of clothing. The clothing wind feature is not deprecated and still exists in APEX 1.3.
In general, assets created with APEX 1.1 or 1.2 should “just work” with APEX 1.3. The application must load the legacy module, which contains all the code that allows APEX to automatically upgrade assets to the latest version.
In APEX 1.3 there is a single legacy module (APEX_Legacy). In APEX 1.2 every module had its own legacy module. For example, if an application uses APEX clothing and destruction, in APEX 1.2 the application would need to load both APEX_Clothing_Legacy and APEX_Destructible_Legacy. In APEX 1.3 there is a single APEX_Legacy module, for convenience. All the legacy module loads on platforms that use dynamic linking (Windows for example), are replaced with a single call:
apexSDK->createModule("Legacy");
Likewise, there is a single legacy module header file NxModuleLegacy.h. On platforms that use static linking (consoles for example), the application only needs to include NxModuleLegacy.h and make single call:
physx::apex::instantiateModuleLegacy();
There have been some changes to the rendering interface in APEX 1.3 for sprite buffers and instance buffers. Instance buffers are only used by destructibles and IOFX, and sprite buffers are only used by IOFX.
NxUserRenderResourceManager has two new methods that are required to be implemented no matter which APEX modules are used, getSpriteLayoutData and getInstanceLayoutData. They are only used by IOFX (part of APEX particles). If the application is not using APEX particles, or if the application is using APEX particles but can handle the default data layout, the application should simply return false:
class AppRenderResourceManager: public NxUserRenderResourceManager
{
...
virtual bool getSpriteLayoutData(physx::PxU32, physx::PxU32, NxUserRenderSpriteBufferDesc*) {return false;}
virtual bool getInstanceLayoutData(physx::PxU32, physx::PxU32, NxUserRenderInstanceBufferDesc*) {return false;}
};
NxUserRenderInstanceBuffer::writeBuffer formerly took an NxApexRenderInstanceBufferData as its first argument, and NxUserRenderSpriteBuffer::writeBuffer took an NxApexRenderSpriteBufferData as its first argument. They are both now given a const void* pointer to APEX’s output buffer as the first argument instead. The application should know the format of the output data because APEX described it in the createInstanceBuffer or createSpriteBuffer callback.
In the case of IOFX, the application can also set its own layout for the data in the getInstanceLayoutData or getSpriteLayoutData callback. See IOFX Semantics for details. Here is an example getInstanceLayoutData callback implementation for an application that is requesting a particular layout:
class AppRenderResourceManager: public NxUserRenderResourceManager
{
...
bool getInstanceLayoutData(physx::PxU32 instanceCount, physx::PxU32 semanticsBitmap, NxUserRenderInstanceBufferDesc* instanceBufferDesc)
{
NxRenderDataFormat::Enum positionFormat = NxRenderInstanceLayoutElement::getSemanticFormat(NxRenderInstanceLayoutElement::POSITION_FLOAT3);
NxRenderDataFormat::Enum rotationFormat = NxRenderInstanceLayoutElement::getSemanticFormat(NxRenderInstanceLayoutElement::ROTATION_SCALE_FLOAT3x3);
NxRenderDataFormat::Enum velocityFormat = NxRenderInstanceLayoutElement::getSemanticFormat(NxRenderInstanceLayoutElement::VELOCITY_LIFE_FLOAT4);
const physx::PxU32 positionElementSize = NxRenderDataFormat::getFormatDataSize(positionFormat);
const physx::PxU32 rotationElementSize = NxRenderDataFormat::getFormatDataSize(rotationFormat);
const physx::PxU32 velocityElementSize = NxRenderDataFormat::getFormatDataSize(velocityFormat);
instanceBufferDesc->semanticOffsets[NxRenderInstanceLayoutElement::POSITION_FLOAT3] = 0;
instanceBufferDesc->semanticOffsets[NxRenderInstanceLayoutElement::ROTATION_SCALE_FLOAT3x3] = positionElementSize;
instanceBufferDesc->semanticOffsets[NxRenderInstanceLayoutElement::VELOCITY_LIFE_FLOAT4] = positionElementSize + rotationElementSize;
physx::PxU32 strideInBytes = positionElementSize + rotationElementSize + velocityElementSize;
instanceBufferDesc->stride = strideInBytes;
instanceBufferDesc->maxInstances = instanceCount;
instanceBufferDesc->registerInCUDA = false;
return true;
}
};
The NxUserRenderSpriteBufferDesc and NxUserRenderInstanceBufferDesc have changed as well. A new NxRenderSpriteLayoutElement and NxRenderInstanceLayoutElement have been added. This allows APEX to communicate the combination of semantic and format in a single enum, and also makes it explicit which combination of semantics and formats are supported by APEX.
NxUserRenderSpriteTextureDesc/getSpriteTextureData have been replaced with NxUserRenderSpriteBufferDesc/getSpriteLayoutData.
In APEX 1.3.1, the NxUserRenderResourceManager’s surface buffer create and release virtual methods must be implemented by the user:
class NxUserRenderResourceManager
{
public:
...
virtual NxUserRenderSurfaceBuffer* createSurfaceBuffer(const NxUserRenderSurfaceBufferDesc& desc) = 0;
virtual void releaseSurfaceBuffer(NxUserRenderSurfaceBuffer& buffer) = 0;
...
}
In APEX 1.3.1, the NxUserRenderSurfaceBuffer::writeBuffer parameters have changed to support writing to offsets in any of three dimensions.
The physx::pxtask classes and functions were all renamed and moved to the physx namespace. For example, physx::pxtask::CudaContextManager was renamed to physx::PxCudaContextManager. A search-and-replace of pxtask:: with Px should fix most issues. Some capitalization will also be needed on function names.
The outputStream member of the NxApexSDKDesc has been removed when using PhysX 3.x. APEX will automatically use the same output stream as PhysX.
PVD connection flags were renamed.
APEX 1.2 old name | APEX 1.3 new name |
---|---|
PxVisualDebuggerConnectionFlag::Debug | PxVisualDebuggerConnectionFlag::eDEBUG |
PxVisualDebuggerConnectionFlag::Profile | PxVisualDebuggerConnectionFlag::ePROFILE |
PxVisualDebuggerConnectionFlag::Memory | PxVisualDebuggerConnectionFlag::eMEMORY |
NxApexAsset::createApexAssetPreview now takes an NxApexAssetPreviewScene as a second argument. The NxApexAssetPreviewScene allows the user to set the view matrix for the generated preview and control what information is displayed in the preview. See NxApexAssetPreviewScene for details.
Asset preview scene support has not yet been implemented for NxDestructibleAsset, so for now it’s safe to pass a NULL preview scene when creating a destructible asset preview.
APEX 1.3 changes the damage detection method used for destruction. The exact chunk collision volumes are used for hit testing (point and radius damage). This gives better consistency when applying damage to destructibles at different LODs. However, this does mean a change in behavior. To keep the old behavior, use NxModuleDestructible::setUseLegacyChunkBoundsTesting.
APEX 1.3 also changes the damage spread behavior. The damageToRadius parameter is no longer used for point and radius damage. The DamageSpreadFunction is used instead. To get the old behavior, use NxModuleDestructible::setUseLegacyDamageRadiusSpread.
The damageToRadius parameter is still used for impact damage, but it is no longer scaled by the size of the destructible. To recover the old behavior, multiply the damageToRadius by the approximate radius of the destructible.
With the addition of BehaviorGroups to Destruction in 1.3, some parameters that used to be in DestructibleParameters now reside in BehaviorGroups. There is a default BehaviorGroup that all chunks reference unless a custom BehaviorGroup is defined. For migration to 1.3, you will need to change those parameters in the default BehaviorGroup instead. These parameter names, and their new locations are given below.
APEX 1.2 old name | APEX 1.3 new name |
---|---|
damageThreshold | defaultBehaviorGroup.damageThreshold |
damageToRadius | defaultBehaviorGroup.damageToRadius |
materialStrength | defaultBehaviorGroup.materialStrength |
APEX 1.3 adds support for a clothing render proxy. It is recommended but not required to use the new renderProxy method for rendering. The old method is still supported. See Rendering With Render Proxy for details on the new clothing render proxy. Since render proxies containing the render mesh actors are now pooled and released after a specified number of frames being unused, the callback to release clothing render resources can now happen during simulate.
Names of clothing debug visualization parameters changed from APEX 1.2 to 1.3. See the ClothingDebugRenderParams for a full description of APEX 1.3 debug visualization parameters.
APEX 1.2 old name | APEX 1.3 new name |
---|---|
VISUALIZE_CLOTHING_ACTOR | Actors |
VISUALIZE_CLOTHING_SKINNED_POSITIONS | SkinnedPositions |
VISUALIZE_CLOTHING_BACKSTOP | Backstop |
VISUALIZE_CLOTHING_MAX_DISTANCE | MaxDistance |
VISUALIZE_CLOTHING_MAX_DISTANCE_IN | MaxDistanceInwards |
VISUALIZE_CLOTHING_ALL_SKIN_MAP | SkinMapAll |
VISUALIZE_CLOTHING_BAD_SKIN_MAP | SkinMapBad |
VISUALIZE_CLOTHING_SKIN_MAP | SkinMapActual |
VISUALIZE_CLOTHING_SKIN_MAP_INVALID_BARY | SkinMapInvalidBary |
VISUALIZE_CLOTHING_PHYSICS_MESH_WIRE | PhysicsMeshWire |
VISUALIZE_CLOTHING_PHYSICS_MESH_SOLID | PhysicsMeshSolid |
VISUALIZE_CLOTHING_PHYSICS_MESH_NORMALS | PhysicsMeshNormals |
VISUALIZE_CLOTHING_SKELETON | Skeleton |
VISUALIZE_CLOTHING_BONE_FRAMES | BoneFrames |
VISUALIZE_CLOTHING_BONE_NAMES | BoneNames |
VISUALIZE_CLOTHING_VELOCITIES | Velocities |
VISUALIZE_CLOTHING_WIND | Wind |
VISUALIZE_CLOTHING_GRAPHICAL_VERTEX_BONES | GraphicalVertexBones |
VISUALIZE_CLOTHING_PHYSICAL_VERTEX_BONES | PhysicalVertexBones |
VISUALIZE_CLOTHING_BACKSTOP_UMBRELLAS | BackstopPrecise |
VISUALIZE_CLOTHING_COLLISION_VOLUMES | CollisionShapes |
VISUALIZE_CLOTHING_COLLISION_VOLUMES_WIRE | CollisionShapesWire |
VISUALIZE_CLOTHING_STRETCHING_V_PHASES | LengthFibers |
VISUALIZE_CLOTHING_STRETCHING_H_PHASES | CrossSectionFibers |
VISUALIZE_CLOTHING_BENDING_PHASES | BendingFibers |
VISUALIZE_CLOTHING_SHEARING_PHASES | ShearingFibers |
VISUALIZE_CLOTHING_ZEROSTRETCH_PHASES | ZerostretchFibers |
VISUALIZE_CLOTHING_SEMIIMPLICIT_PHASES | removed |
VISUALIZE_CLOTHING_GAUSSSEIDEL_PHASES | removed |
VISUALIZE_CLOTHING_TETHERS_ACTIVE | TethersActive |
VISUALIZE_CLOTHING_TETHERS_INACTIVE | TethersInactive |
VISUALIZE_CLOTHING_VIRTUAL_PARTICLES | VirtualCollision |
VISUALIZE_CLOTHING_STIFFNESS_SCALING | FiberRange |
VISUALIZE_CLOTHING_SHOW_LOCAL_SPACE | ShowInLocalSpace |
VISUALIZE_CLOTHING_SHOW_GLOBAL_POSE | GlobalPose |
VISUALIZE_CLOTHING_RECOMPUTE_SUBMESHES | RecomputeSubmeshes |
VISUALIZE_CLOTHING_RECOMPUTE_VERTICES | RecomputeVertices |
PhysicsMeshIndices | PhysicsMeshIndices |
VISUALIZE_CLOTHING_MASS_SCALE | MassScale |
VISUALIZE_CLOTHING_SELF_COLLISION | SelfCollision |
VISUALIZE_CLOTHING_SOLVER_MODE | SolverMode |
In APEX 1.3, several particle-related modules were merged into one APEX_Particles module. This greatly reduces the number of APEX DLLs that need to be shipped with a game and the amount of code necessary to load the modules. These APEX 1.2 DLLs were replaced by a single APEX_Particles DLL in APEX 1.3:
To load all of these in APEX 1.3, you only need a single call:
NxModuleParticles* particlesModule = static_cast<NxModuleParticles*>(apexSDK->createModule("Particles"));
Although the old modules are linked into a single library, the individual module headers are still there. The only reason the application would include the old headers is if it needs to access something specific to the individual modules. The merged particles module provides a method getModule() to access the old module data. For example, to customize the field sampler filtering, a handle to the field sampler sub-module is needed. The code could look like this:
NxModuleFieldSampler* fieldSamplerModule = static_cast<NxModuleFieldSampler*>(particlesModule->getModule("FieldSampler"));
NxGroupsFilteringParams64 params64;
param.const0.bits0 = 0;
param.const0.bits1 = 0;
param.const1.bits0 = 0;
param.const1.bits1 = 0;
param.op0 = NxGroupsFilterOp::OR;
param.op1 = NxGroupsFilterOp::OR;
param.op2 = NxGroupsFilterOp::SWAP_AND;
param.flag = true;
fieldSamplerModule->setFieldSamplerGroupsFilteringParams(apexScene, params64);