#javascript #three.js
Вопрос:
Я новичок в THREE.js.
С целью изучения JavaScript и THREE.js Я сделал эту (своего рода) мини-игру, в которой игрок может исследовать космос и различные космические объекты (работа в процессе).
В любом случае, моя проблема в том, что когда сцена и объекты визуализируются, и вы начинаете перемещать свой кубоид, камера не перемещается вместе с ним (на самом деле она не удаляется от источника мира), а только вращается на месте, глядя на объект игрока.
Это и есть код:
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);
...
}
Камера движется вместе с кубом, но через несколько секунд поворачивается назад, чтобы посмотреть на происхождение мира.
Second attempt:
// 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 );
});
Камера действительно следует за моим кубом,но когда я поворачиваю ее на 180 градусов по оси x, она переворачивается вверх дном, она прикреплена к проигрывателю и движется не плавно, и она смотрит прямо на игрока (задняя сторона куба).
Это вдохновило меня прочитать больше о вращении/переводе в 3d-пространстве, об углах Эйлера, кватернионах, карданном замке. Я просто не совсем уверен, как применить эти страшные кватернионы к моему проекту…
Любая помощь, рекомендации, все, что угодно, было бы очень признательно.
Заранее спасибо.
Ответ №1:
Если вы используете OrbitControls, просто обновите .target
свойство до положения объекта, на котором вы хотите его сфокусировать. Когда куб движется, камера будет двигаться вместе с ним. Смотрите здесь для получения дополнительной информации о документах:
orbitControls.target = cube.position;
Я не совсем понимаю, зачем ты это делаешь: cameraObject.add(perspectiveCamera);
. Это ничего не даст, если вы не внесете никаких изменений cameraObject
.
Комментарии:
1. Спасибо за быстрый ответ. Это не дало мне желаемого результата. Камера по-прежнему приклеена к центру. Что касается «объекта камеры»… ну, я экспериментировал с перспективной камерой и кватернионами…и я забыл удалить эти две строки перед отправкой кода. Я отредактировал свой вопрос, чтобы показать вам, что я пытался.