我正在尝试用three.js创建一个行走的3D模型
3D model
以及
in place fbx walking animation
从Mixamo导入到我的项目中。模型和动画按预期工作;模型由于加载的动画而“行走”,但保持在相同的位置。我的问题是试图让模型的位置增加每一帧,给人一种模型向前走的错觉。
这是我的代码:
import './style.css'
import * as THREE from 'three';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { Reflector } from 'three/examples/jsm/objects/Reflector.js';
import { FirstPersonControls } from 'three/examples/jsm/controls/FirstPersonControls.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
let glow = 0.05;
let clock = new THREE.Clock();
/* CREATE CAMERA */
const camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.01, 4000);
camera.position.setZ(1);
camera.position.setX(200);
camera.position.setY(10);
// camera.lookAt(50, 0, -1200);
/* END CAMERA */
/* CREATE SCENE & FOG */
const scene = new THREE.Scene();
var setcolor = 0x3A4544;
scene.background = new THREE.Color(setcolor);
//scene.fog = new THREE.Fog(setcolor, 0, 4000);
/* END SCENE & FOG */
/* CREATE RENDERER */
const renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.shadowMap.enabled = true;
renderer.outputEncoding = THREE.sRGBEncoding;
document.body.appendChild( renderer.domElement );
/* END RENDERER */
/* CREATE ORBIT CONTROLS */
const controls = new OrbitControls( camera, renderer.domElement );
// const controls = new FirstPersonControls( camera, renderer.domElement );
// controls.movementSpeed = 50;
// controls.lookSpeed = 0.05;
// controls.lookVertical = true;
// controls.constrainVertical = true
/* END ORBIT CONTROLS */
/* CREATE LIGHTS */
const rectLight = new THREE.RectAreaLight( 0xf9d71c, glow, 150, 100 );
scene.add( rectLight );
rectLight.position.set( -8, 100, -290 );
rectLight.lookAt( 0, 0, 0 );
const ambientLight = new THREE.AmbientLight(0xaaaaaa, 0.15)
ambientLight.position.set( 200, 100, 0 );
ambientLight.lookAt( -300, -300, -300 );
scene.add(ambientLight)
/* END LIGHTS */
/* CREATE CITY */
// Floor
let groundMirror1, geometry;
geometry = new THREE.PlaneGeometry( 2500, 2500 );
groundMirror1 = new Reflector( geometry, {
clipBias: 0.003,
color: new THREE.Color(0x212227),
side: THREE.DoubleSide,
mixBlur: 5
});
groundMirror1.position.y = -50
groundMirror1.rotateX( - Math.PI / 2);
scene.add( groundMirror1 );
// 3D Building Font
let text = "JOHN JACOBS";
let textMesh;
const loader = new FontLoader();
loader.load('node_modules/three/examples/fonts/droid/droid_serif_regular.typeface.json', function (font) {
const textGeometry = new TextGeometry(text, {
font: font,
size: 40,
height: 1,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 2,
bevelSize: 2,
bevelOffset: 2,
bevelSegments: 2
});
textMesh = new THREE.Mesh(textGeometry, [
new THREE.MeshPhongMaterial({ emissive: 0xf9d71c, emissiveIntensity: glow }),
new THREE.MeshPhongMaterial({ color: 0xffffff })
]);
scene.add( textMesh );
textMesh.position.y = 1685;
textMesh.position.x = -2000;
textMesh.position.z = 250;
textMesh.rotation.y = ( Math.PI / 2 );
});
// 3D Models
const gltfLoader1 = new GLTFLoader();
gltfLoader1.load('models/building2/scene.gltf', (gltfScene1) => {
gltfScene1.scene.scale.set( 20, 20, 20 );
gltfScene1.scene.position.x = 20;
gltfScene1.scene.position.z = 180;
gltfScene1.scene.position.y = -50;
scene.add(gltfScene1.scene);
});
const gltfLoader2 = new GLTFLoader();
gltfLoader2.load('models/building3/scene.gltf', (gltfScene2) => {
gltfScene2.scene.scale.set( 80, 80, 80 );
gltfScene2.scene.position.x = -75;
gltfScene2.scene.position.z = -400;
gltfScene2.scene.position.y = -1410;
gltfScene2.scene.rotation.y = ( - Math.PI / 2 )
scene.add(gltfScene2.scene);
});
const gltfLoader3 = new GLTFLoader();
gltfLoader3.load('models/building4/scene.gltf', (gltfScene3) => {
gltfScene3.scene.scale.set( 70, 70, 70 );
gltfScene3.scene.position.x = -500;
gltfScene3.scene.position.z = 300;
gltfScene3.scene.position.y = 75;
scene.add(gltfScene3.scene);
});
const gltfLoader4 = new GLTFLoader();
gltfLoader4.load('models/main_building/scene.gltf', (gltfScene4) => {
gltfScene4.scene.scale.set( 10, 10, 10 );
gltfScene4.scene.position.x = -2600;
gltfScene4.scene.position.z = -450;
gltfScene4.scene.position.y = 75;
gltfScene4.scene.rotation.y = ( Math.PI / 2);
scene.add(gltfScene4.scene);
});
const gltfLoader5 = new GLTFLoader();
gltfLoader5.load('models/building5/scene.gltf', (gltfScene5) => {
gltfScene5.scene.scale.set( 10, 10, 10 );
gltfScene5.scene.position.x = -2600;
gltfScene5.scene.position.z = -500;
gltfScene5.scene.position.y = 275;
scene.add(gltfScene5.scene);
});
// 3D model and walking animation
let mixer;
const zomLoader = new FBXLoader();
zomLoader.load('models/characters/Ch44_nonPBR.fbx', (fbx) => {
fbx.position.x = -500;
fbx.position.z = 0;
fbx.position.y = -50;
fbx.rotation.y = ( Math.PI / 2 );
fbx.scale.set( 1, 1, 1 );
const anim = new FBXLoader();
anim.load('models/characters/Walking.fbx', (anim) => {
mixer = new THREE.AnimationMixer(fbx);
const idle = mixer.clipAction(anim.animations[0]);
idle.play();
})
scene.add(fbx)
});
/* END CITY */
/* CREATE WINDOW RESIZE FUNCTION */
window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
animation()
}
/* END WINDOW RESIZE FUNCTION */
/* CREATE MAIN ANIMATION FUNCTION */
animation();
function animation() {
requestAnimationFrame( animation );
//I've tried these two options
//fbx.position.x += 0.5;
//zomLoader(fbx).position.x += 0.5;
glow = Math.random() - 0.01;
textMesh.material[0].emissiveIntensity = glow;
rectLight.intensity = glow;
if(mixer){
mixer.update(clock.getDelta());
}
//controls.update( clock.getDelta() );
controls.update();
renderer.render( scene, camera );
}
/* END MAIN ANIMATION FUNCTION */
我对three.js还是个新手,我唯一移动过任何对象的时候都是网格,而不是导入的3D模型。我习惯于使用
mesh.position.x += 1
在主动画函数中,但当我尝试使用
fbx.position.x += 1
,场景消失。我如何移动3D模型的位置,以产生模型沿x轴行走的错觉?
编辑
我想明白了。我添加了一个全局变量
let human;
,将其分配给
fbx
和使用
human.position.x += 1
在主动画功能中。干杯