disfigure
Version:
A library to rig non-rigged 3D models
143 lines (66 loc) • 2.64 kB
JavaScript
// disfigure
//
// Functions to bend a body and the space it is in
import { Fn, If, mix, normalGeometry, positionGeometry, transformNormalToView } from "three/tsl";
import { SimplexNoise } from "three/addons/math/SimplexNoise.js";
// number generators
var simplex = new SimplexNoise( );
// generate chaotic but random sequence of numbers in [min.max]
function chaotic( time, offset=0, min=-1, max=1 ) {
return min + ( max-min )*( simplex.noise( time, offset )+1 )/2;
}
// generate repeated sequence of numbers in [min.max]
function regular( time, offset=0, min=-1, max=1 ) {
return min + ( max-min )*( Math.sin( time+offset )+1 )/2;
}
// generate random sequence of numbers in [min.max]
function random( min=-1, max=1 ) {
return min + ( max-min )*Math.random( );
}
// general DOF=3 rotator, used for most joints
var jointRotateMat= Fn( ([ pos, pivot, matrix, locus ])=>{
var p = pos.sub( pivot ).mul( matrix ).add( pivot );
return mix( pos, p, locus );
} );
// general DOF=3 rotator, used for most joints
var jointNormalMat= Fn( ([ pos, pivot, matrix, locus ])=>{ // eslint-disable-line no-unused-vars
var p = pos.mul( matrix );
return mix( pos, p, locus );
} );
// calculate vertices of bent body surface
function tslPositionNode( joints ) {
return disfigure( joints, jointRotateMat, positionGeometry );
}
// calculate normals of bent body surface
function tslNormalNode( joints ) {
return transformNormalToView( disfigure( joints, jointNormalMat, normalGeometry ) );
}
// implement the actual body bending
var disfigure = Fn( ([ joints, fn, p ])=>{
var p = p.toVar( ),
space = joints.space;
function chain( items ) {
for ( var item of items )
p.assign( fn( p, space[ item ].pivot, joints[ item ].umatrix, space[ item ].locus() ) );
}
// LEFT-UPPER BODY
If( space.l_arm.locus( ), ()=>{
chain([ 'l_wrist', 'l_forearm', 'l_elbow', 'l_arm' ]);
} );
// RIGHT-UPPER BODY
If( space.r_arm.locus( ), ()=>{
chain([ 'r_wrist', 'r_forearm', 'r_elbow', 'r_arm' ]);
} );
// LEFT-LOWER BODY
If( space.l_leg.locus( ), ()=>{
chain([ 'l_foot', 'l_ankle', 'l_shin', 'l_knee', 'l_thigh', 'l_leg' ]);
} );
// RIGHT-LOWER BODY
If( space.r_leg.locus( ), ()=>{
chain([ 'r_foot', 'r_ankle', 'r_shin', 'r_knee', 'r_thigh', 'r_leg' ]);
} );
// CENTRAL BODY AXIS
chain([ 'head', 'chest', 'waist', 'torso' ]);
return p;
} ); // disfigure
export { tslPositionNode, tslNormalNode, chaotic, regular, random };