如何在threejs中发生按键时旋转3D模型并开始动画制作

问题描述 投票:0回答:1

我正在做一个项目,其中的人 (gltf对象) 是基于按键的行走。我可以根据按键更新对象的位置。

但是,当物体在行走时,我无法旋转物体。向左向右 鍵,並繼續朝該方向走。

附上代码供参考。

import { OrbitControls } from '../assets/js/OrbitControls.js';
import { GLTFLoader } from '../assets/js/GLTFLoader.js';
import { OBJLoader } from '../assets/js/OBJLoader.js';

var camera, scene, renderer, clock, man_walk, gltfLoader, mixer, action, objLoader, keyboard;

init();
animate();

function init(){

    // Renderer
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.gammaOutput = true
    clock = new THREE.Clock();
    document.body.appendChild(renderer.domElement);

    // Scene
    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0xC3D8D6 );
    // scene.fog = new THREE.Fog( 0xffffff, 0, 750 );

    // Camera
    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.y = 250;
    camera.position.z = 600;

    // Light
    const light = new THREE.AmbientLight( 0x404040);
    scene.add(light);

    //keyevents
    keyboard = new THREEx.KeyboardState();
    // console.log(keyboard);
    // // Controls
    // var controls = new OrbitControls(camera, renderer.domElement);
    // controls.enableDampling = true;
    // controls.campingFactor = 0.25;
    // controls.enableZoom = true;
    // var vector = camera.getWorldDirection();
    // console.log(vector);

    getAlternateTiles();
    getFloorMaterialByImage();

    gltfLoader = new GLTFLoader();
    objLoader = new OBJLoader();
    loadDoor();
    loadMan();
}

function loadDoor(){

    objLoader.load('/assets/3d_models/Doorway/Doorway.obj', object => {
        object.traverse(function (child) {
            if (child.type == "Mesh") {
              child.material = new THREE.MeshNormalMaterial();
            }
        });
        
        scene.add(object);
        object.rotation.z = -Math.PI / 2;
        object.rotation.x = -Math.PI / 2;
    
        object.scale.multiplyScalar(30);
        object.position.z = 100
    });

}

function loadMan(){
    
    gltfLoader.load('/assets/3d_models/boy_animated/scene.gltf', gltf => {
        man_walk = gltf.scene;
        man_walk.position.set(0, 0, 60);
        man_walk.rotateY(210.5);
        scene.add(man_walk);
        mixer = new THREE.AnimationMixer(man_walk);
        mixer.clipAction(gltf.animations[0]).play();
    });
}

function getAlternateTiles() {
    var segments = 50;
    var geometry = new THREE.PlaneGeometry(5000, 5000, segments, segments);
    geometry.rotateX( - Math.PI / 2 );
    var materialEven = new THREE.MeshBasicMaterial({color: 0x85A95D});
    var materialOdd = new THREE.MeshBasicMaterial({color: 0x93BC54});
    
    // #485C64
    var materials = [materialEven, materialOdd];
    
    for(var x=0; x<segments; x++) {
        for(var y=0; y<segments; y++) {
            var i = x * segments + y;
            var j = 2 * i;
            geometry.faces[ j ].materialIndex = geometry.faces[ j + 1 ].materialIndex = (x + y) % 2;
        }
    }
    var mesh = new THREE.Mesh(geometry, materials);
    scene.add(mesh);
}

function getFloorMaterialByImage() {
    var geometry = new THREE.PlaneGeometry( 1000, 1000, 10, 10 );
    geometry.rotateX( - Math.PI / 2 );
    // lightwood.jpg, whitetiles.jpg, floorline.jpg, woodsheet.jpg, Carpet.jpeg, Wood_Bamboo.jpeg, corporate.jpg
    var floorTexture = new THREE.TextureLoader().load( '/assets/img/floorline.jpg' );
    floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
    floorTexture.repeat.set(20, 20);
    var material = new THREE.MeshBasicMaterial({map: floorTexture});
    var mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );
}

// Animate
function animate() {
    requestAnimationFrame(animate);
    render();
    updateMan();
}


function updateMan(){

var delta = clock.getDelta(); // seconds.
var rotateAngle = Math.PI / 2 * delta; 

var moveDistance = 150 * delta; // 100 pixels per second
var rotateAngle = Math.PI / 2 * delta;   // pi/2 radians (90 degrees) per second

if ( keyboard.pressed("a") ){
    man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), rotateAngle);
}
if ( keyboard.pressed("d") ){
    man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), -rotateAngle);
}	
if ( keyboard.pressed("w") ){
    man_walk.translateZ(- moveDistance);
    mixer.update(delta);
}
var relativeCameraOffset = new THREE.Vector3(0,250,600);
var cameraOffset = relativeCameraOffset.applyMatrix4( man_walk.matrixWorld );
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(man_walk.position);
}

function render() 
{
	renderer.render( scene, camera );
}

动画使用为项目。

https:/sketchfab.com3d-modelsnathan-animated-003-walking-3d-man-143a2b1ea5eb4385ae90a73657aca3bc。

先谢谢你的时间。

javascript animation three.js 3d
1个回答
0
投票

我更新了我的 updateMan() 函数,以使摄像机始终注视着人物模型。而且相对CameraOffset应该与实际相机位置的方向相反。

请看后面的代码。

如果有什么不对的地方,请纠正我。

function updateMan(){

    var delta = clock.getDelta(); // seconds.
    var rotateAngle = Math.PI / 2 * delta; 

	var moveDistance = 150 * delta; // 100 pixels per second
    var rotateAngle = Math.PI / 2 * delta;   // pi/2 radians (90 degrees) per second
    
    if ( keyboard.pressed("a") ){
        man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), rotateAngle);
    }
	if ( keyboard.pressed("d") ){
        man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), -rotateAngle);
    }	
	if ( keyboard.pressed("w") ){
        man_walk.translateZ(moveDistance);
        mixer.update(delta);
    }
    var relativeCameraOffset = new THREE.Vector3(0,250,-600);
	var cameraOffset = relativeCameraOffset.applyMatrix4( man_walk.matrixWorld );
    camera.position.x = cameraOffset.x;
    camera.position.y = cameraOffset.y;
    camera.position.z = cameraOffset.z;
    camera.lookAt(man_walk.position);
}
© www.soinside.com 2019 - 2024. All rights reserved.