spark-procedural-animations
v0.9.4
Published
Procedural animations for 3D characters in Spark AR Studio
Downloads
319
Readme
Spark Procedural Animation
AR Library for using procedural animations with 3D characters
Procedural Animations are the kind of animations that use mathematical algorithms to generate animation in real-time, rather than using predefined animations that are stored in memory. Procedural animation allows for more diverse and realistic actions and movements of characters and objects in a virtual environments. Procedural animations can use techniques such as inverse kinematics, physics simulation, noise functions, and aligning motion to input, as well as introduce randomness.
The goal is not to replace the traditional ways of working with rigged 3D models but rather to offer an alternative approach that may be more suitable in some case and less so in others.
Technical Documentation and Source Files
Modules, Classes, Interfaces, Functions - Documentation
- core.ts - core functions
- messenger.ts - messenger object to be used for sending and receiving events
- pool.ts - object pool provider used to reduce heap allocations
- behaviors.ts - animation management and scheduling infrastructure
- math-2d.ts - 2D math objects and functions
- math-3d.ts - 3D math objects and functions
- objects.ts - infrastructure for working with SceneObjectBase
- base-character.ts - base character infrastructure and inverse kinematics
- humanoid-characters.ts - humanoid character specific infrastructure
Common Abbreviations
a
- actuator - property of every Object3D responsible for scheduling movements or rotationsv
- view - property of every Object3D that describesideal
forward and up rotations of an object that might be different from thereal
rotationp
- parent - if used in a view means the parent view,v.p
meand the view of the parent objecto
,obj
- objectdn
- downlt
- leftrt
- rightfw
- forwardbk
- backV3
- vector 3D - V3V2
- vector 2D - V2Qt
- Quaternion - Qtpos
- positionrot
- rotationsca
- scaleini
- initial
Common Actuator Expressions
We can use actuators to schedule declaratively motion or rotation on a given object. By default actuators always work in local space unless it is specified otherwise.
The following code executes for someObject
object those steps:
Schedule motion 0.1 towards whatever current object view considers to be left
NOTE: if the object has factor defined, 0.1 will be fraction of that factor, otherwise it will be absolute local length.
Schedule rotation facing 30 degree down (pitch) to and 10 degrees tilt to the right (roll) from what the normal object view rotation, relative to it's parent
Execute these actions for next 3 seconds following smoothstep function and using the using object pool
someObject.actuator
.move
.to(v => v.o.iniPos.addLt(0.1, v))
.rotation
.to(v => v.lookAt(v.fw.rotDn(30, v.p), v.up.rotRt(10, v.p)))
;
this.playFor(3, x => apply(smoothstep01(x), someObject), objPool);
The following code is fixing the leg position and rotation on the ground. Note how we always use view to describe rotation, so that we can define what is forward and up in the view independently of a given rig.
const legPos = leg.worldPos;
const legRot = leg.worldRot;
leg.actuator
.move.asWorld()
.to(v => legPos)
.rotation.asWorld()
.to(v => v.lookAt(legRot.fw, legRot.up))
;
this.playFor(3, x => apply(x, someObject), objPool);
Object Pooling
Major performance challange for JavaScript that executes on every frame is the allocation of large number of heap objects that then need to be garbage collected. To minimize this effect we use object pooling.
Common way to use object pool
import {objPool} from 'spark-procedural-animations';
this.playFor(2, x => {
someObj.rot = lookAt(someObj.worldPos.dirTo(target.pos), V3.up);
}, objPool);
Currently object pool can only be used in scope frame. Meaning that any V3, V3, Qt objects will be recycled within given frame. If you expect and object to span mode that one frame you can define it as permanent, for example:
import {objPool} from 'spark-procedural-animations';
this.playFor(2, x => {
if(someCondition)
someTargetPos = V3.createPermanent(0, 10, 0);
someObj.rot = lookAt(someObj.worldPos.dirTo(someTargetPos), V3.up);
}, objPool);
In the example above object pooling is being applied by the playFor
function. You can also apply it manualy around any snippet of code this way:
import {objPool} from 'spark-procedural-animations';
const sid = objPool.begin(mainBehaviorExecutor.frame);
try {
// any code to use V2, V3, Qt objects from the pool within current frame
} catch (error) {
// if needed take care of any error handling here
throw;
} finally {
objPool.end(sid);
}
License
The spark-procedural-animations library is MIT licensed.