• path-control demo js


    THREE.Spline = function(a) {
    function b(a, b, c, d, e, f, g) {
    a = 0.5 * (c - a);
    d = 0.5 * (d - b);
    return (2 * (b - c) + a + d) * g + (-3 * (b - c) - 2 * a - d) * f + a * e + b
    }
    this.points = a;
    var c = [], d = {
    x: 0,
    y: 0,
    z: 0
    }, e, f, g, h, i, j, m, p, l;
    this.initFromArray = function(a) {
    this.points = [];
    for (var b = 0; b < a.length; b++)
    this.points[b] = {
    x: a[b][0],
    y: a[b][1],
    z: a[b][2]
    }
    }
    ;
    this.getPoint = function(a) {
    e = (this.points.length - 1) * a;
    f = Math.floor(e);
    g = e - f;
    c[0] = 0 === f ? f : f - 1;
    c[1] = f;
    c[2] = f > this.points.length - 2 ? this.points.length - 1 : f + 1;
    c[3] = f > this.points.length - 3 ? this.points.length - 1 : f + 2;
    j = this.points[c[0]];
    m = this.points[c[1]];
    p = this.points[c[2]];
    l = this.points[c[3]];
    h = g * g;
    i = g * h;
    d.x = b(j.x, m.x, p.x, l.x, g, h, i);
    d.y = b(j.y, m.y, p.y, l.y, g, h, i);
    d.z = b(j.z, m.z, p.z, l.z, g, h, i);
    return d
    }
    ;
    this.getControlPointsArray = function() {
    var a, b, c = this.points.length, d = [];
    for (a = 0; a < c; a++)
    b = this.points[a],
    d[a] = [b.x, b.y, b.z];
    return d
    }
    ;
    this.getLength = function(a) {
    var b, c, d, e = b = b = 0, f = new THREE.Vector3, g = new THREE.Vector3, h = [], i = 0;
    h[0] = 0;
    a || (a = 100);
    c = this.points.length * a;
    f.copy(this.points[0]);
    for (a = 1; a < c; a++)
    b = a / c,
    d = this.getPoint(b),
    g.copy(d),
    i += g.distanceTo(f),
    f.copy(d),
    b *= this.points.length - 1,
    b = Math.floor(b),
    b != e && (h[b] = i,
    e = b);
    h[h.length] = i;
    return {
    chunks: h,
    total: i
    }
    }
    ;
    this.reparametrizeByArcLength = function(a) {
    var b, c, d, e, f, g, h = [], i = new THREE.Vector3, j = this.getLength();
    h.push(i.copy(this.points[0]).clone());
    for (b = 1; b < this.points.length; b++) {
    c = j.chunks[b] - j.chunks[b - 1];
    g = Math.ceil(a * c / j.total);
    e = (b - 1) / (this.points.length - 1);
    f = b / (this.points.length - 1);
    for (c = 1; c < g - 1; c++)
    d = e + c * (1 / g) * (f - e),
    d = this.getPoint(d),
    h.push(i.copy(d).clone());
    h.push(i.copy(this.points[b]).clone())
    }
    this.points = h
    }
    }
    ;


    THREE.Animation2Handler = function() {
    var a = []
    , b = {}
    , c = {
    update: function(b) {
    for (var c = 0; c < a.length; c++)
    a[c].update(b)
    },
    addToUpdate: function(b) {
    -1 === a.indexOf(b) && a.push(b)
    },
    removeFromUpdate: function(b) {
    b = a.indexOf(b);
    -1 !== b && a.splice(b, 1)
    },
    add: function(a) {
    void 0 !== b[a.name] && console.log("THREE.Animation2Handler.add: Warning! " + a.name + " already exists in library. Overwriting.");
    b[a.name] = a;
    if (!0 !== a.initialized) {
    for (var c = 0; c < a.hierarchy.length; c++) {
    for (var d = 0; d < a.hierarchy[c].keys.length; d++)
    if (0 > a.hierarchy[c].keys[d].time && (a.hierarchy[c].keys[d].time = 0),
    void 0 !== a.hierarchy[c].keys[d].rot && !(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)) {
    var h = a.hierarchy[c].keys[d].rot;
    a.hierarchy[c].keys[d].rot = new THREE.Quaternion(h[0],h[1],h[2],h[3])
    }
    if (a.hierarchy[c].keys.length && void 0 !== a.hierarchy[c].keys[0].morphTargets) {
    h = {};
    for (d = 0; d < a.hierarchy[c].keys.length; d++)
    for (var i = 0; i < a.hierarchy[c].keys[d].morphTargets.length; i++) {
    var j = a.hierarchy[c].keys[d].morphTargets[i];
    h[j] = -1
    }
    a.hierarchy[c].usedMorphTargets = h;
    for (d = 0; d < a.hierarchy[c].keys.length; d++) {
    var m = {};
    for (j in h) {
    for (i = 0; i < a.hierarchy[c].keys[d].morphTargets.length; i++)
    if (a.hierarchy[c].keys[d].morphTargets[i] === j) {
    m[j] = a.hierarchy[c].keys[d].morphTargetsInfluences[i];
    break
    }
    i === a.hierarchy[c].keys[d].morphTargets.length && (m[j] = 0)
    }
    a.hierarchy[c].keys[d].morphTargetsInfluences = m
    }
    }
    for (d = 1; d < a.hierarchy[c].keys.length; d++)
    a.hierarchy[c].keys[d].time === a.hierarchy[c].keys[d - 1].time && (a.hierarchy[c].keys.splice(d, 1),
    d--);
    for (d = 0; d < a.hierarchy[c].keys.length; d++)
    a.hierarchy[c].keys[d].index = d
    }
    d = parseInt(a.length * a.fps, 10);
    a.JIT = {};
    a.JIT.hierarchy = [];
    for (c = 0; c < a.hierarchy.length; c++)
    a.JIT.hierarchy.push(Array(d));
    a.initialized = !0
    }
    },
    get: function(a) {
    if ("string" === typeof a) {
    if (b[a])
    return b[a];
    console.log("THREE.Animation2Handler.get: Couldn't find animation " + a);
    return null
    }
    },
    parse: function(a) {
    var b = [];
    if (a instanceof THREE.SkinnedMesh)
    for (var c = 0; c < a.bones.length; c++)
    b.push(a.bones[c]);
    else
    d(a, b);
    return b
    }
    }
    , d = function(a, b) {
    b.push(a);
    for (var c = 0; c < a.children.length; c++)
    d(a.children[c], b)
    };
    c.LINEAR = 0;
    c.CATMULLROM = 1;
    c.CATMULLROM_FORWARD = 2;
    return c
    }();


    THREE.Animation2 = function(a, b, c) {
    this.root = a;
    this.data = THREE.Animation2Handler.get(b);
    this.hierarchy = THREE.Animation2Handler.parse(a);
    this.currentTime = 0;
    this.timeScale = 1;
    this.isPlaying = !1;
    this.loop = this.isPaused = !0;
    this.interpolationType = void 0 !== c ? c : THREE.Animation2Handler.LINEAR;
    this.points = [];
    this.target = new THREE.Vector3
    }
    ;
    THREE.Animation2.prototype.play = function(a, b) {
    if (!1 === this.isPlaying) {
    this.isPlaying = !0;
    this.loop = void 0 !== a ? a : !0;
    this.currentTime = void 0 !== b ? b : 0;
    var c, d = this.hierarchy.length, e;
    for (c = 0; c < d; c++) {
    e = this.hierarchy[c];
    this.interpolationType !== THREE.Animation2Handler.CATMULLROM_FORWARD && (e.useQuaternion = !0);
    e.matrixAutoUpdate = !0;
    void 0 === e.animationCache && (e.animationCache = {},
    e.animationCache.prevKey = {
    pos: 0,
    rot: 0,
    scl: 0
    },
    e.animationCache.nextKey = {
    pos: 0,
    rot: 0,
    scl: 0
    },
    e.animationCache.originalMatrix = e instanceof THREE.Bone ? e.skinMatrix : e.matrix);
    var f = e.animationCache.prevKey;
    e = e.animationCache.nextKey;
    f.pos = this.data.hierarchy[c].keys[0];
    f.rot = this.data.hierarchy[c].keys[0];
    f.scl = this.data.hierarchy[c].keys[0];
    e.pos = this.getNextKeyWith("pos", c, 1);
    e.rot = this.getNextKeyWith("rot", c, 1);
    e.scl = this.getNextKeyWith("scl", c, 1)
    }
    this.update(0)
    }
    this.isPaused = !1;
    THREE.Animation2Handler.addToUpdate(this)
    }
    ;
    THREE.Animation2.prototype.pause = function() {
    !0 === this.isPaused ? THREE.Animation2Handler.addToUpdate(this) : THREE.Animation2Handler.removeFromUpdate(this);
    this.isPaused = !this.isPaused
    }
    ;
    THREE.Animation2.prototype.stop = function() {
    this.isPaused = this.isPlaying = !1;
    THREE.Animation2Handler.removeFromUpdate(this)
    }
    ;
    THREE.Animation2.prototype.update = function(a) {
    if (!1 !== this.isPlaying) {
    var b = ["pos", "rot", "scl"], c, d, e, f, g, h, i, j, m;
    m = this.currentTime += a * this.timeScale;
    j = this.currentTime %= this.data.length;
    parseInt(Math.min(j * this.data.fps, this.data.length * this.data.fps), 10);
    for (var p = 0, l = this.hierarchy.length; p < l; p++) {
    a = this.hierarchy[p];
    i = a.animationCache;
    for (var r = 0; 3 > r; r++) {
    c = b[r];
    g = i.prevKey[c];
    h = i.nextKey[c];
    if (h.time <= m) {
    if (j < m)
    if (this.loop) {
    g = this.data.hierarchy[p].keys[0];
    for (h = this.getNextKeyWith(c, p, 1); h.time < j; )
    g = h,
    h = this.getNextKeyWith(c, p, h.index + 1)
    } else {
    this.stop();
    return
    }
    else {
    do
    g = h,
    h = this.getNextKeyWith(c, p, h.index + 1);
    while (h.time < j)
    }
    i.prevKey[c] = g;
    i.nextKey[c] = h
    }
    a.matrixAutoUpdate = !0;
    a.matrixWorldNeedsUpdate = !0;
    d = (j - g.time) / (h.time - g.time);
    e = g[c];
    f = h[c];
    if (0 > d || 1 < d)
    console.log("THREE.Animation2.update: Warning! Scale out of bounds:" + d + " on bone " + p),
    d = 0 > d ? 0 : 1;
    if ("pos" === c)
    if (c = a.position,
    this.interpolationType === THREE.Animation2Handler.LINEAR)
    c.x = e[0] + (f[0] - e[0]) * d,
    c.y = e[1] + (f[1] - e[1]) * d,
    c.z = e[2] + (f[2] - e[2]) * d;
    else {
    if (this.interpolationType === THREE.Animation2Handler.CATMULLROM || this.interpolationType === THREE.Animation2Handler.CATMULLROM_FORWARD)
    this.points[0] = this.getPrevKeyWith("pos", p, g.index - 1).pos,
    this.points[1] = e,
    this.points[2] = f,
    this.points[3] = this.getNextKeyWith("pos", p, h.index + 1).pos,
    d = 0.33 * d + 0.33,
    e = this.interpolateCatmullRom(this.points, d),
    c.x = e[0],
    c.y = e[1],
    c.z = e[2],
    this.interpolationType === THREE.Animation2Handler.CATMULLROM_FORWARD && (d = this.interpolateCatmullRom(this.points, 1.01 * d),
    this.target.set(d[0], d[1], d[2]),
    this.target.sub(c),
    this.target.y = 0,
    this.target.normalize(),
    d = Math.atan2(this.target.x, this.target.z),
    a.rotation.set(0, d, 0))
    }
    else
    "rot" === c ? THREE.Quaternion.slerp(e, f, a.quaternion, d) : "scl" === c && (c = a.scale,
    c.x = e[0] + (f[0] - e[0]) * d,
    c.y = e[1] + (f[1] - e[1]) * d,
    c.z = e[2] + (f[2] - e[2]) * d)
    }
    }
    }
    }
    ;
    THREE.Animation2.prototype.interpolateCatmullRom = function(a, b) {
    var c = [], d = [], e, f, g, h, i, j;
    e = (a.length - 1) * b;
    f = Math.floor(e);
    e -= f;
    c[0] = 0 === f ? f : f - 1;
    c[1] = f;
    c[2] = f > a.length - 2 ? f : f + 1;
    c[3] = f > a.length - 3 ? f : f + 2;
    f = a[c[0]];
    h = a[c[1]];
    i = a[c[2]];
    j = a[c[3]];
    c = e * e;
    g = e * c;
    d[0] = this.interpolate(f[0], h[0], i[0], j[0], e, c, g);
    d[1] = this.interpolate(f[1], h[1], i[1], j[1], e, c, g);
    d[2] = this.interpolate(f[2], h[2], i[2], j[2], e, c, g);
    return d
    }
    ;
    THREE.Animation2.prototype.interpolate = function(a, b, c, d, e, f, g) {
    a = 0.5 * (c - a);
    d = 0.5 * (d - b);
    return (2 * (b - c) + a + d) * g + (-3 * (b - c) - 2 * a - d) * f + a * e + b
    }
    ;
    THREE.Animation2.prototype.getNextKeyWith = function(a, b, c) {
    for (var d = this.data.hierarchy[b].keys, c = this.interpolationType === THREE.Animation2Handler.CATMULLROM || this.interpolationType === THREE.Animation2Handler.CATMULLROM_FORWARD ? c < d.length - 1 ? c : d.length - 1 : c % d.length; c < d.length; c++)
    if (void 0 !== d[c][a])
    return d[c];
    return this.data.hierarchy[b].keys[0]
    }
    ;
    THREE.Animation2.prototype.getPrevKeyWith = function(a, b, c) {
    for (var d = this.data.hierarchy[b].keys, c = this.interpolationType === THREE.Animation2Handler.CATMULLROM || this.interpolationType === THREE.Animation2Handler.CATMULLROM_FORWARD ? 0 < c ? c : 0 : 0 <= c ? c : c + d.length; 0 <= c; c--)
    if (void 0 !== d[c][a])
    return d[c];
    return this.data.hierarchy[b].keys[d.length - 1]
    }
    ;

    path-control

    /**
    * @author alteredq / http://alteredqualia.com/
    */

    THREE.PathControls = function ( object, domElement ) {

    this.object = object;
    this.domElement = ( domElement !== undefined ) ? domElement : document;

    this.id = "PathControls" + THREE.PathControlsIdCounter ++;

    // API

    this.duration = 10 * 1000; // milliseconds
    this.waypoints = [];

    this.useConstantSpeed = true;
    this.resamplingCoef = 50;

    this.debugPath = new THREE.Object3D();
    this.debugDummy = new THREE.Object3D();

    this.animationParent = new THREE.Object3D();

    this.lookSpeed = 0.005;
    this.lookVertical = true;
    this.lookHorizontal = true;
    this.verticalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };
    this.horizontalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };

    // internals

    this.target = new THREE.Object3D();

    this.mouseX = 0;
    this.mouseY = 0;

    this.lat = 0;
    this.lon = 0;

    this.phi = 0;
    this.theta = 0;

    var PI2 = Math.PI * 2;

    this.viewHalfX = 0;
    this.viewHalfY = 0;

    if ( this.domElement !== document ) {

    this.domElement.setAttribute( 'tabindex', -1 );

    }

    // methods

    this.handleResize = function () {

    if ( this.domElement === document ) {

    this.viewHalfX = window.innerWidth / 2;
    this.viewHalfY = window.innerHeight / 2;

    } else {

    this.viewHalfX = this.domElement.offsetWidth / 2;
    this.viewHalfY = this.domElement.offsetHeight / 2;

    }

    };

    this.update = function ( delta ) {

    var srcRange, dstRange;

    if( this.lookHorizontal ) this.lon += this.mouseX * this.lookSpeed * delta;
    if( this.lookVertical ) this.lat -= this.mouseY * this.lookSpeed * delta;

    this.lon = Math.max( 0, Math.min( 360, this.lon ) );
    this.lat = Math.max( - 85, Math.min( 85, this.lat ) );

    this.phi = THREE.Math.degToRad( 90 - this.lat );
    this.theta = THREE.Math.degToRad( this.lon );

    this.phi = normalize_angle_rad( this.phi );

    // constrain vertical look angle

    srcRange = this.verticalAngleMap.srcRange;
    dstRange = this.verticalAngleMap.dstRange;

    var tmpPhi = THREE.Math.mapLinear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
    var tmpPhiFullRange = dstRange[ 1 ] - dstRange[ 0 ];
    var tmpPhiNormalized = ( tmpPhi - dstRange[ 0 ] ) / tmpPhiFullRange;

    this.phi = QuadraticEaseInOut( tmpPhiNormalized ) * tmpPhiFullRange + dstRange[ 0 ];

    // constrain horizontal look angle

    srcRange = this.horizontalAngleMap.srcRange;
    dstRange = this.horizontalAngleMap.dstRange;

    var tmpTheta = THREE.Math.mapLinear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
    var tmpThetaFullRange = dstRange[ 1 ] - dstRange[ 0 ];
    var tmpThetaNormalized = ( tmpTheta - dstRange[ 0 ] ) / tmpThetaFullRange;

    this.theta = QuadraticEaseInOut( tmpThetaNormalized ) * tmpThetaFullRange + dstRange[ 0 ];

    var targetPosition = this.target.position,
    position = this.object.position;

    targetPosition.x = 100 * Math.sin( this.phi ) * Math.cos( this.theta );
    targetPosition.y = 100 * Math.cos( this.phi );
    targetPosition.z = 100 * Math.sin( this.phi ) * Math.sin( this.theta );

    this.object.lookAt( this.target.position );

    };

    this.onMouseMove = function ( event ) {

    if ( this.domElement === document ) {

    this.mouseX = event.pageX - this.viewHalfX;
    this.mouseY = event.pageY - this.viewHalfY;

    } else {

    this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
    this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;

    }

    };

    // utils

    function normalize_angle_rad( a ) {

    var b = a % PI2;
    return b >= 0 ? b : b + PI2;

    };

    function distance( a, b ) {

    var dx = a[ 0 ] - b[ 0 ],
    dy = a[ 1 ] - b[ 1 ],
    dz = a[ 2 ] - b[ 2 ];

    return Math.sqrt( dx * dx + dy * dy + dz * dz );

    };

    function QuadraticEaseInOut ( k ) {

    if ( ( k *= 2 ) < 1 ) return 0.5 * k * k;
    return - 0.5 * ( --k * ( k - 2 ) - 1 );

    };

    function bind( scope, fn ) {

    return function () {

    fn.apply( scope, arguments );

    };

    };

    function initAnimationPath( parent, spline, name, duration ) {

    var animationData = {

    name: name,
    fps: 0.6,
    length: duration,

    hierarchy: []

    };

    var i,
    parentAnimation, childAnimation,
    path = spline.getControlPointsArray(),
    sl = spline.getLength(),
    pl = path.length,
    t = 0,
    first = 0,
    last = pl - 1;

    parentAnimation = { parent: -1, keys: [] };
    parentAnimation.keys[ first ] = { time: 0, pos: path[ first ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };
    parentAnimation.keys[ last ] = { time: duration, pos: path[ last ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };

    for ( i = 1; i < pl - 1; i++ ) {

    // real distance (approximation via linear segments)

    t = duration * sl.chunks[ i ] / sl.total;

    // equal distance

    //t = duration * ( i / pl );

    // linear distance

    //t += duration * distance( path[ i ], path[ i - 1 ] ) / sl.total;

    parentAnimation.keys[ i ] = { time: t, pos: path[ i ] };

    }

    animationData.hierarchy[ 0 ] = parentAnimation;

    THREE.Animation2Handler.add( animationData );

    return new THREE.Animation2( parent, name, THREE.Animation2Handler.CATMULLROM_FORWARD, false );

    };


    function createSplineGeometry( spline, n_sub ) {

    var i, index, position,
    geometry = new THREE.Geometry();

    for ( i = 0; i < spline.points.length * n_sub; i ++ ) {

    index = i / ( spline.points.length * n_sub );
    position = spline.getPoint( index );

    geometry.vertices[ i ] = new THREE.Vector3( position.x, position.y, position.z );

    }

    return geometry;

    };

    function createPath( parent, spline ) {

    var lineGeo = createSplineGeometry( spline, 10 ),
    particleGeo = createSplineGeometry( spline, 10 ),
    lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, line 3 } ),
    lineObj = new THREE.Line( lineGeo, lineMat ),
    particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleBasicMaterial( { color: 0xffaa00, size: 3 } ) );

    lineObj.scale.set( 1, 1, 1 );
    parent.add( lineObj );

    particleObj.scale.set( 1, 1, 1 );
    parent.add( particleObj );

    var waypoint,
    geo = new THREE.SphereGeometry( 1, 16, 8 ),
    mat = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );

    for ( var i = 0; i < spline.points.length; i ++ ) {

    waypoint = new THREE.Mesh( geo, mat );
    waypoint.position.copy( spline.points[ i ] );
    parent.add( waypoint );

    }

    };

    this.init = function ( ) {

    // constructor

    this.spline = new THREE.Spline();
    this.spline.initFromArray( this.waypoints );

    if ( this.useConstantSpeed ) {

    this.spline.reparametrizeByArcLength( this.resamplingCoef );

    }

    if ( this.createDebugDummy ) {

    var dummyParentMaterial = new THREE.MeshLambertMaterial( { color: 0x0077ff } ),
    dummyChildMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00 } ),
    dummyParentGeo = new THREE.CubeGeometry( 10, 10, 20 ),
    dummyChildGeo = new THREE.CubeGeometry( 2, 2, 10 );

    this.animationParent = new THREE.Mesh( dummyParentGeo, dummyParentMaterial );

    var dummyChild = new THREE.Mesh( dummyChildGeo, dummyChildMaterial );
    dummyChild.position.set( 0, 10, 0 );

    this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );

    this.animationParent.add( this.object );
    this.animationParent.add( this.target );
    this.animationParent.add( dummyChild );

    } else {

    this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );
    this.animationParent.add( this.target );
    this.animationParent.add( this.object );

    }

    if ( this.createDebugPath ) {

    createPath( this.debugPath, this.spline );

    }

    this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );

    };

    this.handleResize();

    };

    THREE.PathControlsIdCounter = 0;

  • 相关阅读:
    Tomcat配置JNDI
    (转)通过反编译深入理解Java String及intern
    (转)Java8内存模型-永久代(PermGen)和元空间(Metaspace)
    排序算法
    并发编程
    MySQL
    Go语言
    Go语言
    Go语言
    Go语言
  • 原文地址:https://www.cnblogs.com/shenwenkai/p/7116349.html
Copyright © 2020-2023  润新知