Leveraging THREE.Raycaster for collision detection

In the render loop of my first-person game, I call a function to detect collisions and move the player/camera. This function uses a CubeGeometry called pCube, which is constantly updated to match the camera's position:

// Function for player movements
function pMovements() {
    mPlayer.colBottom = false;

    pCube.position.x = mPlayer.yawObject.position.x + 50; // The cube is offset by +50 for visibility/debugging.
    pCube.position.y = mPlayer.yawObject.position.y - 10;
    pCube.position.z = mPlayer.yawObject.position.z;

    // -- COLLISION DETECTION START --
    var originPoint = pCube.position.clone();

    for (var vertexIndex = 0; vertexIndex < pCube.geometry.vertices.length; vertexIndex++)
    {       
        var localVertex = pCube.geometry.vertices[vertexIndex].clone();
        var globalVertex = localVertex.applyMatrix4( pCube.matrix );
        var directionVector = globalVertex.sub( pCube.position );

        var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
        var collisionResults = ray.intersectObjects( collidableMeshList );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) {

            // Detect collisions with bottom vertices
            if (vertexIndex == 2 || vertexIndex == 3 || vertexIndex == 6 || vertexIndex == 7) {
                mPlayer.colBottom = true;
                mPlayer.velocity.y = Math.max( 0, mPlayer.velocity.y ); // Stop falling
            }
        }
    }
    // -- COLLISION DETECTION END --

    var delta = (Date.now() - time) * 0.1;

    mPlayer.velocity.x += (-mPlayer.velocity.x) * 0.08 * delta; // Movement in x-axis
    mPlayer.velocity.z += (-mPlayer.velocity.z) * 0.08 * delta; // Movement in z-axis
    if (mPlayer.colBottom == false) {
        mPlayer.velocity.y -= 0.1 * delta; // Falling
    }

    if (mPlayer.moveForward) mPlayer.velocity.z -= mPlayer.speed * delta;
    if (mPlayer.moveBack) mPlayer.velocity.z += mPlayer.speed * delta;
    if (mPlayer.moveLeft) mPlayer.velocity.x -= mPlayer.speed * delta;
    if (mPlayer.moveRight) mPlayer.velocity.x += mPlayer.speed * delta;

    mPlayer.yawObject.translateX(mPlayer.velocity.x);
    mPlayer.yawObject.translateY(mPlayer.velocity.y); 
    mPlayer.yawObject.translateZ(mPlayer.velocity.z);

    if (mPlayer.yawObject.position.y < -2000) {
        // Reset player's position if fallen out of bounds
        mPlayer.velocity.y = 0;
        mPlayer.yawObject.position.y = 100;
        mPlayer.yawObject.position.x = 0;
        mPlayer.yawObject.position.z = 0;

        mPlayer.yawObject.rotation.y = 0;
        mPlayer.pitchObject.rotation.x = 0;
    }

    if (mPlayer.moveDown) {
        mPlayer.yawObject.position.y -= 1;
    }
    if (mPlayer.moveUp) {
        mPlayer.yawObject.position.y += 1;
    }
}

Check out the demo here.
Use WASD keys to move and Space bar to jump. Discover that the black cube/rectangle mirrors the camera's position with an offset of +50 on the x-axis. Collisions are detected based on this cube geometry.

Two questions arise from this setup. Should collision detection be based on the vertices or faces of the cube? If an object is smaller than the cube, collisions may not be detected as it won't hit any vertices. Would it be better to rewrite it to detect collisions based on faces instead?

Secondly, how can the issue of the cube falling too far down when a collision is detected be addressed? In the demo, the cube continues to fall for some time after a collision, possibly due to mPlayer.velocity.y. Despite attempts to fix it, even jumping causes the cube to sink too deeply into the floor. Any suggestions on how to prevent this behavior?

Answer №1

If you want to enhance the accuracy of your collision detection, consider adding additional vertices to the cube by adjusting the parameters when creating pCube like this:

pCube = new THREE.CubeGeometry(100,100,100, 5,5,5);

There is no need to make any changes to the rest of your code.

When it comes to preventing smaller objects from slipping through the rays used for collision detection, one effective approach is having the small object generate the rays itself. This method usually results in more precise collision detection.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The HTML remains unchanged after making an AJAX request

I have a process where I update a database entry by clicking on a select dropdown. Once I confirm the selection, an AJAX POST request is sent to another view which implements the necessary changes in the database and then redirects back to the previous pag ...

extract information from a JavaScript array using regular expressions

After struggling for hours, I decided to seek assistance from the stackoverflow community. While I understand that regex could solve my problem, I lack the necessary expertise and time to learn before my deadline. The challenge lies in extracting the 6-di ...

Unexpected Ordering of Knockout Observable Array

Background: In my current project, I am engrossed in developing a user interface powered by Knockout. While I have some experience with Knockout, one particular challenge has left me puzzled. My objective is to sort an observable array named Actions and bi ...

Node.js refusing to acknowledge the get request handler for the homepage of the website

My Node.js server setup is quite simple: const express = require('express'); const app = express(); const http = require("http"); const path = require('path'); const favicon = require('serve-favicon'); // Public fil ...

What is the best way to obtain the actual name of a component's method?

Just to clarify the next part: payU serves as the Internet payment operator I'm currently facing a significant challenge when it comes to integrating my Angular app with payU payments. Due to security reasons, I have opted not to store or pass credit ...

Issues arise with the functionality of a basic Vue.js script

I've attempted to execute the following code, which is supposedly the simplest example of Vue.js, but it doesn't seem to be working: <div id="app"> {{ message }} </div> <script> var app = new Vue({ el: '#app', d ...

Trouble with JS/JQUERY string array value not getting updated

I have encountered a dilemma while developing a web application. My backend is built using node.js and the server is sending a string (using socket.io) that looks like this "00100001100". On the client side, my code snippet is: $(document).on("pageinit" ...

What is the method to execute a function on the existing page when the browser goes back?

DESCRIPTION: In order to create a seamless transition between pages on my website, I have implemented a white opaque overlay layer that fades in and out. When a user clicks on a link, a script is activated which prevents the default behavior, fades the inv ...

Is it possible to send arguments to a debounced function using _.lodash?

Utilizing _lodash.debounce() has been a bit of a challenge for me. While I have managed to get it working, I can't help but feel that there might be a better way to implement it. The examples provided on the lodash website are quite basic and don&apos ...

Transferring an array from PHP to JavaScript via an Ajax response

Welcome to my first post on stackoverflow. I usually find answers from existing posts, but this time I'm facing a problem that none of the suggested solutions have been able to fix. Currently, I have a JavaScript function that makes an AJAX request t ...

Executing Basic Authentication in Javascript through window.open()

After a user logs into my app, they have the option to download a CSV file from the server by clicking on a button. The URL for the download is secured with basic authentication. When attempting to open the URL using the code below: window.open('http ...

Understanding the asynchronous behavior of Mongoose's findById method

I want to discuss the code I am currently working on: const checkForRecord = async (id) => { let model = mongoose.model('User'); let query = {} query.dummy = false; <== This particular field is causing an error intentionally, ...

Generating a PDF file from HTML div content using a button click

I am looking to export a specific div section as a PDF file. The div contains a mix of text, images, and charts. <div id="newdiv"> <img src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/ ...

Using ShaderMaterial in Three.js to simulate a void in shapes

During Release 53 of Three.js, I was able to create a simulated hole in a geometry by using a shader material with the following code: vertex:void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } and fragment:void ma ...

What is the method of adding a child to the outerHTML of the parent element instead of within it?

Is there a way to use the outerHTML method on a parent element to append a child element so that the icons appear outside of the targeted element rather than inside it? The current code snippet shows the icons inside the box, but I want them to be placed o ...

What is the best way to transform URLs into clickable links without altering the anchor text and anchor href?

$str="hello there http://facebook.com <a href="http: //twitter.com">http://twitter.com</a>"; Is there a way to transform into a clickable link within the given text without affecting existing anchor tags and URLs? Anyone know how to accomp ...

Full Calendar is not receiving events from URL in JSON format

We're having some trouble loading our events into Full Calendar from a specific URL. Despite including the necessary JS code and receiving a JSON response from our API, the events are not showing up as expected. Thank you for your assistance! JSON ...

Steps to Display a Popup When an Asp.Net Button is Clicked

One feature I am working on involves a popup that will display a message to the user confirming that their information has been successfully submitted. The ID of this popup is NewCustomerStatusPopUp, and I want it to be triggered once the information has b ...

Generate a Promise instance tailored to the specific platform in use

While working with Apache Cordova, I encountered a cross-platform challenge related to the Promise object. At present, I am initializing a promise in the following manner: var promise = new Promise(...) { //Implementation } Although this method work ...

Dimensions of div tags that are nested within each other

I have a container div that contains three inner divs, each with a width of 33%. When they don't have borders, they align perfectly in line. However, when I add a 1px border to each of the inner divs, it causes them to go out of alignment and pushes ...