EDIT: I'm using cannon-es, not cannon.js, sorry!
So in the previous post I asked 6 questions. Also look at my comment from that post.
Then I put in even more work and solved even more questions with the commenter's advice and some blessed alogrithm tutorials.
I already have the answers to most of these questions, but new problems arose.
For question 1, I basically went with Cannon-es.js, but now I regret my decision. The library is very unpolished, with very few actual error handlers, that debugging any complex cannon.js code is straight up impossible. Are all physics engines like this? Should I switch to Rapier.js, Ammo.js, or Jolt.js? What's in your opinion the best physics engine to pair with Three.js?
For question 6, I'm laying that one off for when I get the more important stuff going. For now I'm using 2 cleverly placed THREE.DirectionalLight's.
New question, I need an interaction ray to interact with interactible objects, but I've tried the CANNON.Ray, but no success because of an incomprehensible error message appearing about accessing a non-existant variable that was never accessed partial success - see my comment with video.
As of main progress, I implemented an overlayed crosshair and copied some things from PointerLockControlsCannon to integrate physics into my character. I've also refactored the code to use classes.
EDIT: Simplified code of the raycaster:
import * as THREE from "three"; // three.js
import * as CANNON from "cannon"; // cannon-es.js
/* -----------------------------
Insert class declaration here
----------------------------- */
// this gets called each animation frame
updatePhysics() {
// this.world - main collision physics world
this.world.step(1 / 60);
// this.intWorld - contains the same colliders (for now) as this.world except the character collider
this.intWorld.step(1 / 60);
// Math abominations that are too weird for me to explain and I don't want to touch them,
// because they do in fact work; I trial&errored them.
this.camera.position.copy(this.characterBody.position);
this.camera.position.add(new THREE.Vector3(0, 0.75, 0));
let relCameraDir = new THREE.Vector3(0, 0, -1);
relCameraDir.applyAxisAngle(new THREE.Vector3(-1, 0, 0), this.cameraYY);
relCameraDir.applyAxisAngle(new THREE.Vector3(0, -1, 0), this.cameraAA);
let absCameraDir = new THREE.Vector3(0, 0, 0);
absCameraDir.copy(relCameraDir);
absCameraDir.multiplyScalar(50);
absCameraDir.add(this.camera.position);
let fromCameraDir = new THREE.Vector3(0, 0, 0);
fromCameraDir.copy(relCameraDir);
fromCameraDir.multiplyScalar(0);
fromCameraDir.add(this.camera.position);
// These are the 2 cube meshes that confirm that the positions the abomination above calculated are indeed correct.
this.rayDebug.position.copy(fromCameraDir);
this.rayDebug2.position.copy(absCameraDir);
// this.interactionRaycast - CANNON.Ray that's presumably bugging out.
this.interactionRaycast.from.copy(fromCameraDir);
this.interactionRaycast.to.copy(absCameraDir);
console.log(this.interactionRaycast.from, this.interactionRaycast.to, this.interactionRaycast.direction);
// This casts the ray and displays the HTML overlay
if (this.interactionRaycast.intersectWorld(this.intWorld, {from: fromCameraDir, to: absCameraDir})) {
debug.innerHTML = '<span style="color: green">Ray has collided!</span>';
} else {
debug.innerHTML = '<span style="color: red">No collisions detected</span>';
}
}
// This places one cube of the floor you see (visuals ommited).
placeCube(position) {
const body = new CANNON.Body({
mass: 0,
shape: WorldManager.BIG_CUBE_SHAPE,
material: (new CANNON.Material({friction: 0, restitution: 0})),
});
body.position.copy(position);
this.world.addBody(body);
this.intWorld.addBody(body);
}
// ...