Disfigure is a library for animating human figures by modifying a matrix field of the space around them. Here is an absurdly minimal demo – see it live.
import * as Happy from 'disfigure'
new Happy.World
new Happy.Man
Disfigure defines figures as instances of classes Man
, Woman
and Child
– see it.
The optional parameter height defines the height of a figure
in meters – see it.
By default a man is 1.80m, a woman is 1.70m and a child is 1.35m.
var man = new Happy.Man( 1.90 );
var woman = new Happy.Woman( );
All types of figures have the exact same structure with names
corresponding to body parts, like head
and chest
. Left and
right body parts are always in respect to the figure. Their
names have prefixes l_···
for left and r_···
for right, so
there is l_knee
and r_knee
– see it:
torso
head
, chest
, waist
arm
, elbow
, forearm
, wrist
leg
, thigh
, knee
, shin
, ankle
, foot
The motion of a figure is done by manipulating properties of body parts. Motions are just rotations measured in degrees.
The torso
is the root body part and its rotation affects
the whole body. Torso has properties bend
, turn
and tilt
– see it. The central
body parts are head
, chest
and waist
. They have the
same set of properties as the torso –
see it.
bend
– bends foreward or backwardturn
– turns to the left or righttilt
– tilts sideways to the left or rightfigure.torso.bend = 40;
figure.head.bend = 40;
figure.chest.turn = -20;
figure.waist.tilt = 35;
The upper limbs are symmetrical body parts with multiple joints
and rotation properties that recreate a complex and flexible
motion – see it.
Arms have foreward
, turn
and straddle
–
see it.
foreward
– moves an arm foreward (or backward)turn
– turns an arm inwards (or outwards)straddle
– moves an arm sideways to the body (or away from the body)figure.r_arm.foreward = 70;
figure.r_arm.straddle = -30;
figure.r_arm.turn = 5;
Elbows l_elbow
and r_elbow
have limited motions. Elbows
have only bend
– see it.
bend
– bends an elbow towards the body (or away from the body)figure.r_elbow.bend = 45;
Forearms l_forearm
and r_forearm
have limited motions.
Forearms have only turn
– see it.
turn
– turns a forearm inwards (or outwards)figure.r_forearm.turn = -20;
Wrists l_wrist
and r_wrist
support bend
and tilt
–
see it. Wrist have no turns,
as turning is done in the forearm or the arm.
Motions of l_wrist
and r_wrist
:
bend
– bends a wrist down or upturn
– turns a wrist foreward or backwardman.r_wrist.bend = -60;
man.r_wrist.tilt = 10;
The lower limbs are symmetrical body parts with multiple joints
and rotation properties that recreate a complex and flexible
motion – see it.
Legs have foreward
, straddle
and turn
– see it.
foreward
– moves a leg foreward (or backward)straddle
– moves a leg sideways away from the body (or to the body)turn
– turns a leg inward (or outward)figure.r_leg.foreward = -10;
figure.r_leg.straddle = 50;
figure.r_leg.turn = 20;
Thighs l_thigh
and r_thigh
have limited motions.
Thighs have only turn
– see it.
turn
– turns a thigh outwards (or inwards)figure.r_thigh.turn = 20;
Knees l_knee
and r_knee
support bend
and tilt
–
see it. Knee have no turns,
as turning is done in the thigh or the shin. However, their
tilting is used to model bowlegs
and knock knees.
Motions of l_knee
and r_knee
:
bend
– bends a knee backwardtilt
– tilts a knee sidewaysman.r_knee.bend = 40;
man.r_knee.tilt = 0;
Shins l_shin
and r_shin
have limited motions, just like thighs.
Shins have only turn
– see it.
turn
– turns a shin outwards (or inwards)figure.r_shin.turn = 20;
Ankles l_ankle
and r_ankle
support bend
and tilt
–
see it. Ankle have no turns,
as turning is done in the shin.
Motions of l_ankle
and r_ankle
:
bend
– bends an ankle foreward or backwardtilt
– tilts a ankle outward or inwardman.r_ankle.bend = 40;
man.r_ankle.tilt = -10;
Feet l_foot
and r_foot
have limited motions. Feet have only
bend
– see it.
bend
– bends a foot downward (or upward)figure.r_foot.bend = 20;
The posture of a figure is defined by the rotation properties of its body parts. By default, when a figure is created, it is set to a default posture.
When a posture is defined programmatically, it might be easier to define it step by step. To recreate a Tai Chi Chuan posture – see it, first the whole body position is defined:
figure.torso.bend = 10;
figure.torso.tilt = -5;
:
Then the orientations of the legs are set:
figure.l_leg.straddle = 25;
figure.l_knee.bend = 50;
:
Finally, the arms are fixed:
figure.l_arm.straddle = 12;
figure.l_elbow.bend = 140;
:
A dynamic posture is when is changes over time. If a predefined world is used, it manages posture animation in two ways – via animation loop function or via timer events. In both ways the user program should provide angles at a given time.
The function setAnimationLoop
registers a user-defind function that is
called automatically each frame. This user function accepts a parameter
time with the current time in miliseconds
– see it. The alternative
approach is to let the window
object listen to the animate
events via the addEventListener
method. The event.time
holds the current time in miliseconds –
see it.
setAnimationLoop( animate );
function animate( time ) {
// executed once per frame
}
window.addEventListener( 'animate', animate );
function animate ( event ) {
// executed once per frame
var time = event.time;
}
The animate event is triggered to each figure. In this case
the activating figure is stored in the property event.target
.
This allows the same animation to be applied to several figures
– see it.
figure.addEventListener( 'animate', animate );
function animate ( event ) {
// executed once per frame
var time = event.time;
var figure = event.target;
}
A posture could be extracted from a figure with the posture
property.
The posture object contains properties version
of the posture data
format, positio
for the coordinates of the figure, rotation
for its
orientation and data
with joint angles. The posture
property can be
used to push a posture to a figure – see it.
figure.posture = {
version: 8,
position: [0,-0.29,0.5],
rotation: [0,0,0,"XYZ"],
angles: [8,0,0,-4,4,-6,3,-34,0,-5,-60,...]
};
A read-only property postureString
retrieves the posture as a string.
var str = figure.postureString;
A posture could be defined as a blend of other postures. The
method blend
mixes the initial postureA and the final
postureB with a coefficient k∈[0,1]. When k=0 the
result is postureA, when k=1 the result is postureB,
when k is between 0 and 1 the result is a posture between
postureA and postureB – see it.
var A = manA.posture;
var B = manB.posture;
manZ.blend(A,B,0.5);
Apart for moving body parts, Disfigure provides basic functionality for additional modification of a figure – adding accessories or changing colors.
Accessories are Three.js objects attached to a specific body part.
They do not deform, but move as if attached to the body. The position
of accessory is defined by the optional parameters x, y and z.
The position is in respect to the origin point of the body part –
see it. Alternatively, the position
of an accessory could be set via its Three.js position
property.
figure.l_arm.attach(spike);
When just the final coordinates are needed it is faster to use point
,
which calculates the position and ignores the orientation –
see it.
v = figure.l_arm.point(0,0.1,0);
The function lockTo
moves the whole figure so that the local point
(localX, localY, localZ) of bodypart is mapped to the global
point (globalX, globalY, globalZ). This can be used to keep a
figure standing on the ground (by locking its feet to level 0). The
following examples shows two floating figures touching the same spot
with their fingers – see it.
figure.l_wrist.lockTo(0.2,-0.01,0.01, 0, 1.5, 0 );
Creates a predefined default 3D world with all basic attributes, like camera, lights, ground, user navigations and so on. The optional parameter features defines what attribute to create. It is a set of the following options:
new World( {ground: false, stats: true} );
Sets the user-defined function animate to be called from the main animation loop at every frame. This function has one parameter of the elapsed time, measured in milliseconds (one second is 1000 milliseconds).
function animate( ms ) {...}
setAnimationLoop( animate );
These are core rendering variables that are created only for
a default world. The light
is a static light casting shadows,
while cameraLight
is attached to the camera
. These variables
are instances of the following Three.js classes: THREE.Scene
,THREE.PerspectiveCamera
and
THREE.DirectionalLight
.
They are used to modify the predefined world – see it:
This variable is the ground for the default world. It creates
the illusion of a solid surface and hosts bodies’ shadows.
It is an instance of THREE.Mesh
shaped by PlaneGeometry
.
The navigation controls for the default world. It allows the
user to rotate and move the camera within the world. It is
an instance of OrbitControls
.
A statistics panel used to show the current the performance
of rendering the default world. It is an instance of Stats
.
Generates uniformly distributed random numbers in the interval [min,max) – see it. By default min=-1 and max=1. Internally uses a pseudo-random function.
figure.head.turn = random( -60, 60 );
Generates an oscilating sequence of numbers in the interval [min,max] – see it. By default offset=0, min=-1 and max=1. Internally uses the sine function. Parameter offset shifts the oscillation foreward or backward in time.
figure.head.turn = regular( time, 0, -60, 60 );
Generates a chaotic (random, but gradually changing) sequence of numbers in the interval [min,max] – see it. By default offset=0, min=-1 and max=1. Internally uses a simplex noise function. Parameter offset shifts the sequence across the time, i.e. two generators with different offsets produce different sequences.
figure.head.turn = chaotic( time, 0, -60, 60 );
An array of all created bodies. Usually used to traverse them and do some operation on all bodies.