param y0 param y1 param t0 param t1 param x const hermiteSpline = ( y0 , y1 , t0 , t1 , x ) : number => { const xc = x * x * x ; const xs = x * x ; const dy = y1 - y0 ; const h01 = - 2.0 * xc + 3.0 * xs ; const h10 = xc - 2.0 * xs + x ; const h11 = xc - xs ; return y0 + dy * h01 + t0 * h10 + t1 * h11 ; } ; param arr param x const evaluateCurve = ( arr , x ) : number => { if ( arr . length < 8 ) { throw new Error ( 'evaluateCurve: Invalid curve detected! (Array length must be 8 at least)' ) ; } if ( arr . length % 4 !== 0 ) { throw new Error ( 'evaluateCurve: Invalid curve detected! (Array length must be multiples of 4' ) ; } let outNode ; for ( outNode = 0 ; ; outNode ++ ) { if ( arr . length <= 4 * outNode ) { return arr [ 4 * outNode - 3 ] ; } else if ( x <= arr [ 4 * outNode ] ) { break ; } } const inNode = outNode - 1 ; if ( inNode < 0 ) { return arr [ 4 * inNode + 5 ] ; } const x0 = arr [ 4 * inNode ] ; const x1 = arr [ 4 * outNode ] ; const xHermite = ( x - x0 ) / ( x1 - x0 ) ; const y0 = arr [ 4 * inNode + 1 ] ; const y1 = arr [ 4 * outNode + 1 ] ; const t0 = arr [ 4 * inNode + 3 ] ; const t1 = arr [ 4 * outNode + 2 ] ; return hermiteSpline ( y0 , y1 , t0 , t1 , xHermite ) ; } ; /**
 * This is an equivalent of CurveMapper class defined in UniVRM.
 * Will be used for [[VRMLookAtApplyer]]s, to define behavior of LookAt.
 *
 * See: https://github.com/vrm-c/UniVRM/blob/master/Assets/VRM/UniVRM/Scripts/LookAt/CurveMapper.cs
 */ export class VRMCurveMapper { /**
     * An array represents the curve. See AnimationCurve class of Unity for its details.
     *
     * See: https://docs.unity3d.com/ja/current/ScriptReference/AnimationCurve.html
     */ public curve : number [ ] = [ 0.0 , 0.0 , 0.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.0 ] ; /**
     * The maximum input range of the [[VRMCurveMapper]].
     */ public curveXRangeDegree = 90.0 ; /**
     * The maximum output value of the [[VRMCurveMapper]].
     */ public curveYRangeDegree = 10.0 ; param xRange param yRange param curve constructor ( xRange ? , yRange ? , curve ? ) { if ( xRange !== undefined ) { this . curveXRangeDegree = xRange ; } if ( yRange !== undefined ) { this . curveYRangeDegree = yRange ; } if ( curve !== undefined ) { this . curve = curve ; } } param src public map ( src ) { const clampedSrc = Math . min ( Math . max ( src , 0.0 ) , this . curveXRangeDegree ) ; const x = clampedSrc / this . curveXRangeDegree ; return this . curveYRangeDegree * evaluateCurve ( this . curve , x ) ; } }