【发布时间】:2021-08-30 10:17:46
【问题描述】:
我是 THREE.js 的新手。
出于学习 JavaScript 和 THREE.js 的目的,我制作了这个(某种)小游戏,玩家可以在其中探索太空和不同的太空物体(正在进行中)。
无论如何,我的问题是当场景和对象被渲染时,当你开始移动你的长方体时,相机并没有随之移动(实际上它并没有从world origin) 只在原地旋转并看着玩家的对象。
这是代码:
import './style.css'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// Scene object
const scene = new THREE.Scene();
const clock = new THREE.Clock();
var cameraObject, keys;
var temp = new THREE.Vector3;
var dir = new THREE.Vector3;
var a = new THREE.Vector3;
var b = new THREE.Vector3;
var distance = 0.3;
var velocity = 0.0;
var speed = 0.0;
// Camera object
const perspectiveCamera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 50, 1e7 )
perspectiveCamera.position.setZ(80);
cameraObject = new THREE.Object3D;
cameraObject.add(perspectiveCamera);
// perspectiveCamera.lookAt(scene.position)
// Renderer object
const renderer = new THREE.WebGLRenderer({
});
document.body.appendChild( renderer.domElement );
// Renderer
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.render( scene, perspectiveCamera )
// Light
// PointLight
const pointLight = new THREE.PointLight(0xffffff)
pointLight.position.set(20,20,20)
// AmbientLight
const ambientLight = new THREE.AmbientLight(0xffffff)
scene.add(pointLight, ambientLight)
// Helper classes
const lightHelper = new THREE.PointLightHelper(pointLight);
const axesHelper = new THREE.AxesHelper(5);
scene.add(lightHelper, axesHelper)
// Controls
const controls = new OrbitControls(perspectiveCamera, renderer.domElement);
controls.movementSpeed = 1000;
controls.domElement = renderer.domElement;
controls.rollSpeed = Math.PI / 24;
controls.autoForward = false;
controls.dragToLook = false;
let cube = new THREE.Group();
const cubeGeometry = new THREE.BoxGeometry(3,10,3)
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x238423 })
const cube1 = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube.add(cube1)
scene.add(cube)
// Objects
// Stars
function addStar() {
const geometry = new THREE.SphereGeometry(0.25, 24, 24);
const material = new THREE.MeshStandardMaterial( { color: 0xffffff })
const star = new THREE.Mesh( geometry, material );
const [x, y, z] = Array(3).fill().map(() => THREE.MathUtils.randFloatSpread( 500 ));
star.position.set(x,y,z);
scene.add(star)
}
Array(1500).fill().forEach(addStar)
let keyState = {};
keys = {
a: false,
s: false,
d: false,
w: false,
q: false,
e: false,
space: false,
shiftleft: false,
};
document.addEventListener("keydown", function(e) {
console.log(e.code);
const key = e.code.replace('Key', '').toLowerCase();
if ( keys[ key ] !== undefined )
keys[ key ] = true;
});
document.body.addEventListener( 'keyup', function(e) {
const key = e.code.replace('Key', '').toLowerCase();
if ( keys[ key ] !== undefined )
keys[ key ] = false;
});
// Animate objects
function animate() {
const delta = clock.getDelta();
requestAnimationFrame( animate );
speed = 0.0;
if ( keys.w )
cube.rotateX(-0.03);
if ( keys.s )
cube.rotateX(0.03);
if ( keys.a )
cube.rotateZ(0.03);
if ( keys.d )
cube.rotateZ(-0.03);
if ( keys.q )
cube.rotateY(-0.06);
if ( keys.e )
cube.rotateY(0.06);
if ( keys.space )
speed = 0.9;
velocity += ( speed - velocity ) * .3;
cube.translateY( velocity );
if ( keys.shiftleft )
speed = 0.9*5;
velocity += ( speed - velocity ) * .3;
cube.translateY( velocity );
perspectiveCamera.lookAt( cube.position );
controls.update(delta);
renderer.render( scene, perspectiveCamera );
}
animate();
我实际上是在尝试制作某种第三人称相机。为了使相机跟随这个小长方体并随着物体在屏幕上旋转而旋转。
第一次尝试:
const idealOffset = new THREE.Vector3(0, 0, -80);
function animate(){
...
perspectiveCamera.position.set(0, 0, -80);
perspectiveCamera.applyQuaternion(cube.rotation);
perspectiveCamera.position.add(cube.position);
perspectiveCamera.lookAt(idealOffset);
...
}
相机随着立方体移动,但几秒钟后转回来查看世界原点。
第二次尝试:
// Animate objects
requestAnimationFrame( function animate(milliseconds) {
const delta = clock.getDelta();
let moveDistance = 10*delta;
let rotateAngle = Math.PI/2*delta;
requestAnimationFrame( animate );
speed = 0.0;
if ( keys.w ){
cube.rotateX(-0.03);
}
if ( keys.s ){
cube.rotateX(0.03);
}
let rotation_matrix = new THREE.Matrix4().identity();
if ( keys.a ){
cube.rotateZ(rotateAngle);
}
if ( keys.d ){
cube.rotateZ(-rotateAngle);
}
if ( keys.q ){
cube.rotateY(-rotateAngle);
}
if ( keys.e ){
cube.rotateY(rotateAngle);
}
if ( keys.space ){
speed = 0.9;
velocity += ( speed - velocity ) * .3;
cube.translateY( velocity );
}
if ( keys.shiftleft ){
speed = 0.9*5;
velocity += ( speed - velocity ) * .3;
cube.translateY( velocity );
}
var relativeCameraOffset = new THREE.Vector3(0,-80,0);
var cameraOffset = relativeCameraOffset.applyMatrix4(cube.matrixWorld);
perspectiveCamera.position.x = cameraOffset.x;
perspectiveCamera.position.y = cameraOffset.y;
perspectiveCamera.position.z = cameraOffset.z;
perspectiveCamera.lookAt(cube.position);
renderer.render( scene, perspectiveCamera );
});
相机确实跟随我的立方体,但是当我在 x 轴上将它旋转 180 度时,它会倒置,它固定在播放器上,移动不顺畅,它直接看着播放器(立方体的背面) .
这激发了我阅读更多关于 3d 空间中的旋转/平移、欧拉角、四元数、万向节锁的信息。我只是不太确定如何将这些可怕的四元数应用到我的项目中......
任何帮助,参考,任何将不胜感激。
提前致谢。
【问题讨论】:
标签: javascript three.js