extensions

POV


#Point of View Movement and Rotation

Movement

AbstractMesh has a pair of functions which allow you to move it relative to the mesh's current position, but without regard to its current rotation. Amounts are expressed in terms so as to provide the point of view of: behind the front of the mesh.

Here are their function definitions:

/**
 * Perform relative position change from the point of view of behind the front of the mesh.
 * This is performed taking into account the meshes current rotation, so you do not have to care.
 * Supports definition of mesh facing forward or backward.
 * @param {number} amountRight
 * @param {number} amountUp
 * @param {number} amountForward
 */
movePOV(amountRight: number, amountUp: number, amountForward: number): void;
/**
 * Calculate relative position change from the point of view of behind the front of the mesh.
 * This is performed taking into account the meshes current rotation, so you do not have to care.
 * Supports definition of mesh facing forward or backward.
 * @param {number} amountRight
 * @param {number} amountUp
 * @param {number} amountForward
 */
calcMovePOV(amountRight: number, amountUp: number, amountForward: number): BABYLON.Vector3;

Moving a mesh without having to take into account current rotation, frees application code from doing so at the time, and facilitates more reusable application code.

Also consider that most things in the real world move in the "Forward" direction the vast majority of the time. This is true even of the airplane you just shot down in your FPS shooter. Maybe it was even spiraling as well, but all you coded was "Forward".

It is believed that most meshes are defined with their "front side" facing the viewer, much the same way they are defined with their "bottom" below their "top". However, there is a switch in AbstractMesh, definedFacingForward, which can be set to false. Doing so implies it is defined facing backwards instead.

Rotation

to do: make an image for rotation

There are also similar functions for rotation. Rotation does not have as strong a relationship with Point-of-View as positioning, but they do take into account definedFacingForward. Their argument terminology is also less "alien" than that of either pilot (yaw-pitch-roll) or mathematics (alpha-beta-gamma). This is even more helpful if rotating in multiple axis's.

/**
 * Perform relative rotation change from the point of view of behind the front of the mesh.
 * Supports definition of mesh facing forward or backward.
 * @param {number} flipBack
 * @param {number} twirlClockwise
 * @param {number} tiltRight
 */
rotatePOV(flipBack: number, twirlClockwise: number, tiltRight: number): void;
/**
 * Calculate relative rotation change from the point of view of behind the front of the mesh.
 * Supports definition of mesh facing forward or backward.
 * @param {number} flipBack
 * @param {number} twirlClockwise
 * @param {number} tiltRight
 */
calcRotatePOV(flipBack: number, twirlClockwise: number, tiltRight: number): BABYLON.Vector3;

#POV Before Render Extension

##Introduction## The functions inside of AbstractMesh are just raw material, so that they could be called under any circumstance. A queue based, POV before render animation system uses these methods to achieve coordinated, stepwise, movement & rotation. It can be found in the Extensions repository.

This enables meshes to move more like they do in the real world. Most people and vehicles turn (twirl) at the same time as moving forward, not behave as if they are marching. Babylon's animation system can perform concurrent animations, but since animations are independent, it would just move in a single direction while twirling.

It is also crucial that "Forward" be redefined every frame, or stepwise. Even if a POV move was made for Babylon's animation system, without a rewrite, "Forward" and the final position based on it would be defined only once at the beginning.

POV was developed for MORPH. Conveniently, MORPH already was using a before renderer, so adding on inside the render fit like a glove. This made the overall system quite large though, and harder to document. Meshes which perform no morphing also could not use it. It has now been made standalone, and MORPH now subclasses it.

##Motion Event## A MotionEvent is the base unit of the system. It holds the directions to perform an animation. They can be made in advance and reused, but it is not a good idea to share them across meshes. This is because they manage state when they are the event currently being performed.

/**
 * Take in all the motion event info. Movement & rotation are both optional, but both being null is usually for sub-classing.
 * 
 * @param {number} _milliDuration - The number of milli seconds the event is to be completed in
 * @param {number} _millisBefore - Fixed wait period, once a syncPartner (if any) is also ready (default 0)
 * When negative, no delay if being repeated in an EventSeries
 * @param {Vector3} movePOV - Mesh movement relative to its current position/rotation to be performed or null
 * right-up-forward
 * @param {Vector3} rotatePOV - Incremental Mesh rotation to be performed or null
 * flipBack-twirlClockwise-tiltRight
 * @param {Pace} _pace - Any Object with the function: getCompletionMilestone(currentDurationRatio) (default Pace.LINEAR)
 */
constructor(
    private _milliDuration : number, 
    private _millisBefore : number, 
    public movePOV : BABYLON.Vector3, 
    public rotatePOV : BABYLON.Vector3, 
    private _pace : Pace = Pace.LINEAR)

##Event Series# An EventSeries, consisting of an array of 'MotionEvent's, is the unit placed in the render queue.

/**
 * Validate each of the events passed.
 * @param {Array} _eventSeries - Elements must either be a MotionEvent, Action, or function.
 * @param {number} _nRepeats - Number of times to run through series elements. There is sync across runs. (Default 1)
 * @param {number} _initialWallclockProrating - The factor to multiply the duration of a MotionEvent before returning.
 * Amount is decreased or increased across repeats, so that it is 1 for the final repeat. Facilitates
 * acceleration when > 1, & deceleration when < 1. (Default 1)
 */
constructor(public _eventSeries : Array<any>, public _nRepeats = 1, public _initialWallclockProrating = 1.0)

##Series Queue##

##Attaching to Mesh##

##Playground Example##

##Advanced Features##

###Action System Integration###

###Synchronized movement between meshes### Different meshes can move in coordination with each other. A MotionEvent of each is said to be a sync partner of the other. Using this can cause hangs unless the EventSeries of each is queued on each mesh at the same time.

The sync partner of a MotionEvent cannot be part of the constructor, since how would the partner of the first to be instanced be passed? After construction, the setSyncPartner function of each is then called:

/**
 * @param {MotionEvent} syncPartner - MotionEvent which should start at the same time as this one.
 */
public setSyncPartner(syncPartner : MotionEvent) : void{

###Non-Linear Pacing###

###Series Level Acceleration-Deceleration###

##Up Coming Features for Version 1.1## The first new feature is a method to clear what the mesh is currently doing and or clear what is queued to do next.

The second is to integrate optional sound to start playing at the beginning of a MotionEvent. Timing of audio to motion is very often important to make things believable. The Sound object is passed in the MotionEvent constructor. When the MotionEvent is activated by the before-renderer, the sound will be checked if it is ready to play. If not, the event will enter a wait state until the frame that the sound indicates ready. Should a sound be part of an event that is stopped, the playing will also be stopped.