PathEngine home previous: Moving to Release 5.34next: Content Creators Guide
Contents, Programmers Guide, Moving to Release 6

Moving to Release 6


Moving from release 5.36 to release 6.00.

There's some interface refactoring, and changes to the way SDK object lifetimes are managed, for release 6.00, and most projects will need some minor updates in order to compile and work correctly with newer versions of the SDK.

What has changed

So the changes can be divided into two parts then, with a first set of changes relating to the PathEngine object ownership model, and then some additional changes to tidy up some remaining rough edges of the API, based on new face vertex mesh and solid objects builder interface classes.

There are some changes to the snapshot loading and hull generation features of the 3D content processing interface, and the 3D content processing header has now been merged into the main i_pathengine.h API header.

Motivations for the ownership model and lifetime management changes

The ownership model for interactions between some of the PathEngine API objects (such as agents and collision contexts) was unnecessarily complicated.

In many cases this ownership model included object deletion side effects (which is not ideal API design).
In many cases where objects would automatically and implicitly trigger the destruction of other objects this meant the invalidation of pointers potentially held to those objects elsewhere in client code, with the client code ultimately responsible for tracking this change in state and knowing not to call in to those objects after that point (again, not ideal API design). And, finally, tracking lifetimes and maintain the ownership model as previously designed was unnecessarily complicating the interactions between PathEngine API objects, internally, particularly with respect to multithreaded use cases.

Internally, switching to a consistent, reference counted paradigm simplifies PathEngine's API object management internally and removes the need for mutex locking in many cases (in favour of atomic reference counting interactions).

And then, on the client application side, API object pointers now each hold a reference to the corresponding API object. The API object cannot be destroyed while that reference is held. As a result, API object pointers can now be wrapped by C++ smart pointer classes (e.g. std::unique_ptr or std::shared_ptr), for automatic lifetime management, if this is desired.

Motivations for other API changes, based on new builder interface classes

So the API has also been updated to remove a few remaining cases where SDK functionality depended on PathEngine passing raw pointers to data structures built and managed internally by PathEngine code.

So previously, for example, when placing a 'content chunk instance' through the API, PathEngine would make it's own instance of the iFaceVertexMesh interface class. A method was then available to obtain a raw pointer to this internally managed object, which could be passed back in to the API together with pointers to other, client code managed face vertex meshes.

This is kind of messy API design, with the onus on the client to remember which face vertex mesh instances can and cannot be deleted, and track the lifetime of PathEngine owned face vertex meshes (linked to the owning content chunk instance object).

In each of the (small number of) cases where these kinds of interactions were still required in order to provide SDK functionality, 'builder' interfaces have been added to move the construction of the relevant objects entirely over to the client side.

So instead of asking a content chunk instance for a pointer to its internally managed face vertex mesh instance, then, you now pass a builder object into iContentChunkInstance::buildGround() to build the same ground data on the client side.

Together with the general API object lifetime changes this makes the SDK more robust and removes the possibility for a whole bunch of lifetime related errors. But this also improves interface consistency, and then enables us to extend the interface mappings for Microsoft Common Language Runtime (.net languages) and Java Native Interface (for languages based on the Java Virtual Machine), to cover all of the objects and methods in the API.

Changes, in detail

release() replaces destroy()

If previously calling the destroy() method for API objects directly, you should replace these calls with calls to release().

Calls to destroy() are currently still supported, but release() better describes the new semantics, and the destroy() method should be considered depreciated.

If deleting API object pointers directly, no changes are required (although you should now be aware that this is actually just releasing a reference, and not forcing immediate destruction of the object).

Deleting agents no longer removes them from containing contexts

In previous releases, deleting agents that were still included in collision contexts would remove the agents from all containing contexts and force immediate deletion.

From release 6, if you want to force the immediate deletion of an agent, it is now necessary to remove the agent from any containing collision contexts manually.

(Note that this is not an issue if you are deleting the collision contexts and the agent together. In this case just release all your pointers and reference counting will take care of the rest.)

Deleting a mesh no longer forces deletion of everything on that mesh

Before release 6 you could destroy an iMesh object and PathEngine would then automatically clean up everything on that mesh (agents, paths, collision contexts, etc..).

This now works the other way around, i.e. deleting a mesh will only release your reference to that mesh, but any other pointers you hold will keep the mesh object alive and in memory.

So you need to make sure that all of the objects you created on a mesh have themselves been released. But, you can check this with iMesh::hasRefs(). (If this returns true, there is some other object still referencing the mesh.)

(Note that the end result is effectively the same, but with the possibility to now guarantee that there are no dangling refs hanging around waiting to cause a crash.)

iCollisionInfo has been removed

The iCollisionInfo API object has been removed, in favour of more direct access to the corresponding collision information.

This API object was notably returned, previously, by advance along path methods, to serve both as an indicator that there was a collision, and to then provide access to details about the collision, if required.

Since, in many cases, collision details were not actually required, the basic advance along path methods now just return a bool (indicating only if there was a collision or not).

Extended versions of the advance along path methods are available, then, to provide collision details (coordinates of the colliding line, blocking agent) as out arguments, where these are required. (See iAgent::advanceAlongPathWithCollisionInfo() and iPath::advanceAlongWithCollisionInfo().)

In other cases where iCollisionInfo was previously returned, e.g. from first collision queries, colliding line and blocking agent are provided directly as out arguments.

Other methods that forced immediate object destruction

iPathEngine::deleteAllObjects() has been removed.

iContentChunk::deleteAllInstances() has been removed.

(Use hasRefs() to assert that all referencing objects have been cleaned up instead, as described here, instead.)

Direct access to iPath internal buffers has been removed

The iPath::getPositionArray() and iPath::getConnectionIndexArray() methods have been removed, as well as also iPath::constructPath_Reversed().

If you were using these to copy path objects, use the newly added iMesh::copyPath() method for this, instead.

If you were using these to reverse path objects, use the newly added iMesh::reversePath() method for this, instead.

Direct access to content chunk instance ground has been removed

The iContentChunkInstance::getGroundPointer() method, (which provided direct access to and internally constructed face vertex mesh instance), has been removed.

Use iContentChunkInstance::buildGround(), together with a client constructed face vertex mesh builder instead.

Direct access to content chunk instance anchors and shapes has been removed

The iContentChunkInstance::getAnchorsAndShapesPointer() method, (which provided direct access to and internally constructed anchors and shapes instance), has been removed.

Use iContentChunkInstance::addAnchorsAndShapes() (which adds the anchors and shapes directly to a mesh), instead.

Methods for getting/setting error handler have been removed

The iPathEngine::getErrorHandler() and iPathEngine::setErrorHandler() methods have been removed.

A single, immutable error handler object should now be passed in to PathEngine on SDK initialisation. If you want to change error handler state, this is something that should now be done outside of PathEngine (by delegating from a top level error handler to other error handlers, for example).

Documentation for PathEngine release 6.03 - Copyright © 2002-2021 PathEnginenext: Content Creators Guide