Hi, in order to learn JavaScript and Three.js I created a small project where you fly the cube through space. I have huge problem with my third person camera.
1) I managed to get it to follow my cube but when I rotate it 180 DEG on x-axis it turns upside-down,
2) it's fixed to the player (like a GoPro on a helmet) and doesn't move smoothly following the player with a certain time delay
3) it looks directly at the player
I read a lot about rotating/translating in 3d space, about Euler angles, quaternions, gimbal lock...I just can't figure out how to apply that to my little project.
This is the video I was reffering to:
https://www.youtube.com/watch?v=3T0grb3O3O4
What I have tried:
This is my code:
import './style.css'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const scene = new THREE.Scene();
const clock = new THREE.Clock();
let thirdPersonCamera, keys;
let temp = new THREE.Vector3;
let distance = 0.3;
let velocity = 0.0;
let speed = 0.0;
const perspectiveCamera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 50, 1e7 )
const renderer = new THREE.WebGLRenderer({
});
document.body.appendChild( renderer.domElement );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.render( scene, perspectiveCamera )
const pointLight = new THREE.PointLight(0xffffff)
pointLight.position.set(20,20,20)
const ambientLight = new THREE.AmbientLight(0xffffff)
scene.add(pointLight, ambientLight)
const lightHelper = new THREE.PointLightHelper(pointLight);
const axesHelper = new THREE.AxesHelper(5);
scene.add(lightHelper, axesHelper)
const cubeGeometry = new THREE.BoxGeometry(3,10,3)
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x238423 })
const cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
scene.add(cube)
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;
});
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 );
});
Any help would be greatly appreciated.