Apply Physics (CANNON.JS) to Camera (Using Pointer Lock Controls) in THREE.js

837 views Asked by At

I wanted to ask. I have this goal to create a Pointer Lock Control but also apply physics to the control, so when the camera hit a wall it doesn't move to that direction (Where collision occur). My plan is to check for collision in the pointer lock control movement, if collision == false, than move to that direction. But idk how to do this, I'm quite new to this kind of stuff..

Here's the code for the physics for camera

import * as CANNON from 'cannon-es'
import Main from '../../Main.js'

export default class PhysicsCamera {
    constructor(world) {
        this.main = new Main()
        this.camera = this.main.camera.instance

        this.world = world
        this.setCamera()
    }

    setCamera() {
        this.cameraShape = new CANNON.Box(
            new CANNON.Vec3(0.05, 0.15, 0.05)
        )
        // console.log('finished creating shape...')
        this.cameraBody = new CANNON.Body({
            mass: 1,
            position: new CANNON.Vec3(
                this.camera.position.x, 
                this.camera.position.y - 0.1, 
                this.camera.position.z
            ),
            shape: this.cameraShape
        })
        // console.log('finished creating body')

        this.cameraBody.addEventListener('collide', (collision) => {
            console.log(collision)
        })

        this.world.addBody(this.cameraBody)
        // console.log('finished adding to the world')
    }


    update() { // tick function (update per fps)

        this.cameraBody.position.set(
            this.camera.position.x, 
            this.camera.position.y - 0.1, 
            this.camera.position.z
        )
        this.cameraBody.quaternion.copy(this.camera.quaternion)

        // console.log(this.cameraBody.position)

        // console.log('cube position: ', this.cameraBody.position)
        // console.log('camera position: ', this.camera.position)
    }
}

With this code, I were able to detect collision with the other physicsBody that I made. But the thing is, the physicsBody started to go wild (Spinning like crazy), I think it's because I set the physics camera position with the original camera position

But the plan is to update the camera position with pointer lock control, but also apply physics to it, here's my controls code

import Main from '../Main.js'
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js'

export default class Controls {
    constructor() {
        this.main = new Main()
        this.world = this.main.world
        this.camera = this.main.camera.instance
        this.canvas = this.main.canvas

        this.controls = new PointerLockControls(this.camera, this.canvas)

        this.keyboard = []
        this.setKeyboard()
    }

    setControls() {
        this.controls.lock()
        // console.log('Lock Controls')
    }

    setKeyboard() {
        addEventListener('keydown', (e) => {
            this.keyboard[e.key] = true
        })
        addEventListener('keyup', (e) => {
            this.keyboard[e.key] = false
        })
    }

    setMovement(delta) {
        // TODO: Create algorithm to stop when collusion occur
        this.speed = 0.0008 * delta

        if (this.keyboard['w']) {
            this.controls.moveForward(this.speed)
            // console.log('forward');
        } else if (this.keyboard['s']) {
            this.controls.moveForward(-this.speed)
        } else if (this.keyboard['d']) {
            this.controls.moveRight(this.speed)
        } else if (this.keyboard['a']) {
            this.controls.moveRight(-this.speed)
        }
    }

    update() { // tick function (update per fps)
        this.delta = this.main.time.delta
        this.setMovement(this.delta)
    }
}

I'm planning to make the movement stop in certain direction when collision occur. How to do this, I'm quite loss :)

Is there any better way to solve this ? I wanted to try raycaster, but I don't think raycaster is the best way to do this, some suggestion stated that doing with Physics is the best way to go. But Idk how to apply physics to the pointer lock control

I've made the physics body for the wall and for the camera. I just need to find out how to stop when collision occur

1

There are 1 answers

0
Ben Razor On

Cannon-es has an FPS example with source in the examples repo on Github.

In that example PointerLockControls is modified to create PointerLockControlsCannon.

  • The camera and a cannon body are supplied
  • The mouse moves are converted into rotations of internal objects (yaw and pitch) that rotate the camera
  • The velocity of the cannon object is set based on those rotations
  • Finally, the camera position is set to the position of the cannon object

The example contains some basic collision resolution which will work for the wall collisions when the other objects are high enough.