Click here to Skip to main content
15,886,110 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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';

// Scene object
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;

// Camera object
const perspectiveCamera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 50, 1e7 )

// 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)

//Cube
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)

// 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)

//Controls
let keyState = {};
keys = {
  a: false,
  s: false,
  d: false,
  w: false,
  q: false,
  e: false,
  space: false,
  shiftleft: false,
};

//Event listeners
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
  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.
Posted
Updated 29-Aug-21 19:47pm

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900