Anonymous-ahole
Anonymous-ahole

Reputation: 7

GLB animation in three.js is too fast

I have uploaded a glb file with an animation, and the animation is moving extremely fast, and I do not know why.

This is my character's animation code:

class MainChar extends THREE.Object3D {
    constructor() {
        super();
       this.object = new THREE.Object3D();
        this.object.position.set(0, 1, 50);
        this.object.scale.x=20;
        this.object.scale.y=20;
        this.object.scale.z=20;

        //load house model form blender file
    
    /*  
        loader.setPath('../../models/characters/');
        
        const gltf = loader.load('Douglas.glb', (gltf) => {
          gltf.scene.traverse(c => {
            c.castShadow = true;
          });
          this.object.add( gltf.scene);
        });
    
    */  

        const loader = new THREE.GLTFLoader();
    loader.setPath('../../models/characters/');
    
    const gltf = loader.load('walk.glb', (gltf) => {
        gltf.scene.traverse(c => {
            c.castShadow = true;
          });
        this.mixer = new THREE.AnimationMixer( gltf.scene );
        this.mixer.timeScale=1/5;
        var action = this.mixer.clipAction( gltf.animations[ 0 ] );
        action.play();

        this.object.add( gltf.scene );
    });

        //save keyboard bindings
        this.keyboard = new THREEx.KeyboardState();
        /*
        //creating a box (need to change it to a character with animations)
        const geometry = new THREE.BoxGeometry( 1, 1, 1 );
        const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
        this.object = new THREE.Mesh( geometry, material );
        
        this.object.scale.x=5;
        this.object.scale.y=10;
        this.object.scale.z=5;
            //starting position for character
        this.object.position.set(0, 10, 50);

        */
        
    

        
        this.update = function (time) {
            if ( this.mixer ){

             this.mixer.update( time );
             console.log(time);
             
            }
            //MOVEMENT OF BOX

            //speed
            var moveDistance = 0.5 ; 
        //  var rotateAngle = Math.PI / 2 * 0.05;   
            
            // move forwards/backwards/left/right
            if ( this.keyboard.pressed("W") ){
                this.object.translateZ( -moveDistance );
            }
            if (  this.keyboard.pressed("S") ){
                this.object.translateZ(  moveDistance );
            }
            if (  this.keyboard.pressed("A") ){
                this.object.translateX( -moveDistance );
            }
            if (  this.keyboard.pressed("D") ){
                this.object.translateX( moveDistance );
            }

            // move forwards/backwards/left/right
            if ( this.keyboard.pressed("up") ){
                this.object.translateZ( -moveDistance );
            }
            if (  this.keyboard.pressed("down") ){
                this.object.translateZ(  moveDistance );
            }
            if (  this.keyboard.pressed("left") ){
                this.object.translateX( -moveDistance );
            }
            if (  this.keyboard.pressed("right") ){
                this.object.translateX( moveDistance );
            }
            
        
            // FOR CAMERA ROTATIONS
            //this.object.rotateOnAxis( new THREE.Vector3(0,1,0), -rotateAngle);
            //this.object.rotateOnAxis( new THREE.Vector3(0,1,0), rotateAngle);
            //var rotation_matrix = new THREE.Matrix4().identity();
            
            
            if (  this.keyboard.pressed("Z") )
            {
                this.object.position.set(0, 1, 50);
                this.object.rotation.set(0,0,0);
            }
                
            /*
            // global coordinates
            if (  this.keyboard.pressed("left") )
            this.object.position.x -= moveDistance;
            if (  this.keyboard.pressed("right") )
            this.object.position.x += moveDistance;
            if (  this.keyboard.pressed("up") )
            this.object.position.z -= moveDistance;
            if (  this.keyboard.pressed("down") )
            this.object.position.z += moveDistance;
            */

        };
    }
}

This is the time class that allows the game to be paused, as well as returns the delta time:

class Time {
constructor(){
    this.is_pause = false;
    this.accumalated_run_time = 0;
    this.clock = new THREE.Clock();
    this.pause_clock = new THREE.Clock();
}


getRunTime()
{
    this.accumalated_run_time += this.clock.getDelta();

    return this.accumalated_run_time
}

pause()
{
    this.is_pause = true;

}

unpause()
{
    this.is_pause = false;
    this.clock.getDelta();
}



    


}

This is the sceneManager that calls up my character for updating animations:

class SceneManager {
    constructor(canvas) {
        //this entire function renders a scene where you can add as many items as you want to it (e.g. we can create the house and add as
        //many items as we want to the house). It renders objects from other javascript files
        //------------------------------------------------------------------------------------------------------------------------------------------
        //These are supposed to act like constants. DO NOT CHANGE
        this.GAME_PAUSE = "pause";
        this.GAME_RUN = "run";
        //------------------------------------------------------------------------------------------------------------------------------------------
    //we use (this) to make variables accessible in other classes
    this.time = new Time();

    

    this.game_state = this.GAME_RUN;


    this.screenDimensions = {
        width: canvas.width,
        height: canvas.height
    };

    //the essentials for rendering a scene
    this.scene = this.buildScene();
    this.renderer = this.buildRender(this.screenDimensions);
    this.camera = this.buildCamera(this.screenDimensions);
    this.managers = this.createManagers();
    this.loadToScene(this.managers[0].entities);
    //allow camera to orbit target (player)
    this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
    this.controls.target.set(0, 20, 0);
    this.controls.update();

}

loadToScene(entities)
{
    for (let i = 0 ; i < entities.length ; i++)
    {
        console.log("before" +i.toString());
        this.scene.add(entities[i].object);
        console.log("after");
    }
}
    //this function creates our scene
    buildScene() {
        //create a new scene
        const scene = new THREE.Scene();

        //set the scene's background-> in this case it is our skybox
        const loader = new THREE.CubeTextureLoader();
        //it uses different textures per face of cube
        const texture = loader.load([
            '../skybox/House/posx.jpg',
            '../skybox/House/negx.jpg',
            '../skybox/House/posy.jpg',
            '../skybox/House/negy.jpg',
            '../skybox/House/posz.jpg',
            '../skybox/House/negz.jpg'
        ]);
        scene.background = texture;

        //if we wanted it to be a colour, it would have been this commented code:
        //scene.background = new THREE.Color("#000");
        return scene;
    }

    //this creates a renderer for us
    buildRender({ width, height }) {

        const renderer = new THREE.WebGLRenderer({
            canvas: canvas,
            antialias: true, alpha: true
        });
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);

        return renderer;
    }

    //create a camera for the screen
    buildCamera({ width, height }) {

        //SETTING FIELD OF VIEW, ASPECT RATIO (which should generally be width/ height), NEAR AND FAR (anything outside near/ far is clipped)
        const aspectRatio = width / height;
        const fieldOfView = 60;
        const nearPlane = 1;
        const farPlane = 1000;

        //there are 2 types of cameras: orthographic and perspective- we will use perspective (more realistic)
        const camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane);

        //set where the camera is
        camera.position.set(-50, 50, 70);

        return camera;
    }

    //add subjects to the scene
    createManagers() {

        const managers=[new EntityManager()];
        //can be altered so we can add multiple entities, and depending on which position
        //it is, certain ones won't be paused, and some will be
        managers[0].register(new GeneralLights());
        managers[0].register(new House());
        managers[0].register(new MainChar());
        managers[0].register(new SceneSubject())


        return managers;
    }

    //this updates the subject/model every frame
    update() {
        
        //won't call this loop if it's paused-> only for objects that need to be paused (managers that need to be paused)
        if (this.game_state == this.GAME_RUN)
        {
            const runTime = this.time.getRunTime();
            this.managers[0].update(runTime);
        }
  
        //update orbit controls
        this.controls.update();

        this.renderer.render(this.scene, this.camera);
    }

    //this resizes our game when screen size changed
    onWindowResize() {

        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();

        this.renderer.setSize(window.innerWidth, window.innerHeight);

    }

    pause(){ //when pause mode is entered. The pause menu needs to be rendered.
        this.game_state = this.GAME_PAUSE;
        this.time.pause();

    }

    unpause(){
        this.game_state = this.GAME_RUN;
        this.time.unpause();

        }
    
}

Upvotes: 0

Views: 1474

Answers (1)

M -
M -

Reputation: 28492

I think the issue is with your AnimationMixer.update() call. If you look at the docs, update is expecting a time-delta in seconds, but it looks like you're passing the total running time. This means it should receive the time passed since the last frame. You can fix this by using clock.getDelta(); as the argument:

this.update = function (time) {
    if ( this.mixer ){
        const delta = this.clock.getDelta();
        this.mixer.update(delta);
    }
    
    // ...
}

Upvotes: 1

Related Questions