Collision Detection within a THREE.Group in Three.js

Currently, I am tackling the challenge of detecting 3D AABB collisions between a box and a sphere.

An interesting observation: when a box is directly added to the scene, collisions are detected successfully. However, when the box is added to a group (THREE.Group) and rotated, collisions are not being detected.

Below is the code snippet used to add a box:

function addPlatforms() {

    var coreGroup = new THREE.Group(); // this is the group
    scene.add(coreGroup);

    var box = [];

    cube_box1 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
    box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
    box[0].position.set(-1.83, -0.22, 1.11);
    box[0].rotation.x += Math.PI / 2;
    box[0].rotation.z -= 0.78;
    box[0].receiveShadow = true;


    cube_box2 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
    box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
    box[1].position.set(-2.15, -0.22, 0.51);
    box[1].rotation.x += Math.PI / 2;
    box[1].receiveShadow = true;

    var platGroup = new THREE.Group();
    platGroup.add(box[0]);
    platGroup.add(box[1]);
    platGroup.rotation.y -= 2;
    platGroup.position.y  = 1;

    coreGroup.add(platGroup);


    cube_box1.setFromObject(box[0]);
    platformArr.push(cube_box1);

    cube_box2.setFromObject(box[1]);
    platformArr.push(cube_box2);
}

The code used to check for collision between a box and a sphere:

For detailed information on 3D collision detection with THREE.js, visit https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection/Bounding_volume_collision_detection_with_THREE.js

THREE.Sphere.__closest = new THREE.Vector3();
THREE.Sphere.prototype.intersectsBox = function(box) {
    // get box closest point to sphere center by clamping
    THREE.Sphere.__closest.set(this.center.x, this.center.y, this.center.z);
    THREE.Sphere.__closest.clamp(box.min, box.max);

    var distance = this.center.distanceToSquared(THREE.Sphere.__closest);
    return distance < (this.radius * this.radius);
};

function isCollision() {
    for (var i = 0; i < platformArr.length; i++) {
        _cubeBox = platformArr[i];
        return sphereBox.intersectsBox(_cubeBox);
    }
}

Here is how a sphere is added to the scene:

function addBall(){

    sphere = new THREE.Mesh(
        new THREE.SphereGeometry(0.19, 20, 20), materials.solid);
    sphere.position.set(0, 1, -2);
    sphere.geometry.computeBoundingSphere();
    scene.add(sphere);

    sphereBox = new THREE.Sphere(sphere.position, sphere.geometry.boundingSphere.radius);
    sphereBox.radius = sphere.geometry.boundingSphere.radius;

    cy = sphere.position.y;
}  

Logic for rendering and collision detection:

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);

    if (collision) { // ball is on surface
        vy = -vy;
        collision = false;
    }

    cy -= vy * dt;

    sphere.position.y = cy;

    if (vy <= mvy)
        vy += gravity;

    collision = isCollision();
}

To test collision between a box and a sphere that is added to the scene:

var _box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid);
_box.position.set(-1.83, -0.22, 1.11);
_box.rotation.x += Math.PI / 2;
_box.rotation.z -= 0.78;
_box.receiveShadow = true;

Check for collision in the update loop:

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);

    if (collision) { // ball is on surface
        vy = -vy;
        collision = false;
    }

    cy -= vy * dt;

    sphere.position.y = cy;

    if (vy <= mvy)
        vy += gravity;

    collision = sphereBox.intersectsBox(_box);
}

Answer №1

Typically, the object's world matrix will be updated on each frame. You are creating these boxes, applying transformations, and grouping them together. Then you immediately execute cube_box1.setFromObject(box[0]);, which relies on matrixWorld internally. However, the world matrices of the boxes have not been set at that point. You can either wait a frame for the matrices to be computed automatically, or manually trigger matrix updates:

//... your code ...
coreGroup.add(platGroup);

coreGroup.updateMatrixWorld( true );

cube_box1.setFromObject(box[0]);
platformArr.push(cube_box1);
//... your code ...

Three.js Docs Matrix Transformations

Whenever either the parent or the child object's transformation changes, you can request the child object's matrixWorld to be updated by calling updateMatrixWorld().

Three.js Docs Object3D

.matrixAutoUpdate : Boolean

When this is enabled, it calculates the matrix of position, (rotation or quaternion), and scale every frame, and also updates the matrixWorld property. The default value is Object3D.DefaultMatrixAutoUpdate (true).

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

Smoothly transition between the new and existing child elements in a React component with a

Currently, I am utilizing a React component that renders a child element through props.children. The content within this child element varies dynamically. I am looking for the most effective method to smoothly transition (fade out the old element and fad ...

Transferring a JavaScript variable to C# to execute an SQL SELECT query, then sending the returned result back to JavaScript

I am facing an issue while trying to execute code in my Code Behind to query my SQL Server using a JavaScript variable and then return the result as an Integer back to my Javascript. My approach involves running some Javascript code initially to obtain a ...

I want to learn how to display the rupee symbol instead of the default dollar symbol in AngularJS for specific currency symbols

When using 'currency' in AngularJS, I noticed that a dollar symbol is displayed. How can I change this to show the required currency symbol based on different requirements? Currently, I am looking for information on how to display a rupee symbol ...

Turn off escape option when PointerLockControls are in use

Is there a way to prevent the ESCAPE option from being activated (when using PointerLockControls and ThreeJS) by pressing the escape key on the keyboard? I have a different function in mind for this key in my project! Appreciate any assistance in advance ...

Routes for Express are throwing a 500 internal server error

My server is unable to locate the APIs that I have created in the API directory, which is resulting in a 500 internal server error. I have thoroughly checked routes.js and everything appears to be correct. Additionally, I have an error.js file for handlin ...

Display a progress bar that shows completion based on the maximum value supplied

I successfully created a progress bar using HTML, CSS, and Javascript. It functions perfectly up to a provided value of 100. However, if a value higher than 100 is given, the progress completes but the value continues to change until it reaches the maximum ...

Issue "cannot update headers after they have been sent"

I've been working on a node.js application to retrieve movie listings using the omdb api. However, I'm encountering an error when attempting to access the /result route. The error message is as follows: Error: Can't set headers after they ar ...

MenuIcon Component is experiencing difficulty being rendered

I am attempting to construct an IconMenu within the AppBar Component. My project is being developed using create-react-app. This is how my code appears: index.js import React from 'react'; import ReactDOM from 'react-dom'; import &a ...

Unknown Parameters Issue with Vue.js Router Links

Within my Vue.js project, I am utilizing params in my navigation.vue component to pass data onto the next page for dynamic routing purposes. Below is an example of how I am using this: <router-link tag="p" :to="{name: 'Main', ...

New Trainee - Error: document has not been defined

Encountering an Error message while attempting to run Intern tests from the test files directory. The structure of the directory is as follows: test resources rest pickup.js cashManagement.js gitignore intern.js packages.js ...

Toggling the form's value to true upon displaying the popup

I have developed an HTML page that handles the creation of new users on my website. Once a user is successfully created, I want to display a pop-up message confirming their creation. Although everything works fine, I had to add the attribute "onsubmit= re ...

Ensure that the React Material UI Textfield with the type "number" is validated to have exactly 10 characters

<TextField variant="outlined" required fullWidth id="accno" label="Main Account Number" type="number" name="accno" //inputProps={{ className:"input-acc", pattern: "^.{0,10}$"}} autoComplete="accno" onChange={(e) = ...

Creating a multi-dimensional array in order to store multiple sets of data

To generate a multidimensional array similar to the example below: var serviceCoors = [ [50, 40], [50, 50], [50, 60], ]; We have elements with latitude and longitude data: <div data-latitude="10" data-longitude="20" clas ...

Having trouble retrieving AJAX response data using jQuery

I have been searching and attempting for hours without success. On my current page, I am displaying basic data from a database using PHP in an HTML table. However, I now want to incorporate AJAX functionality to refresh the data without reloading the page ...

Getting the current URL in InApp browser on Phonegap 3.0: A quick guide

Hey there, I am having trouble retrieving the current URL of an in-app browser when clicking the close button or at any time after loading a URL. Here's my code: var ref = window.open('http://google.com', '_blank', 'hidden=y ...

empty responseText from GET request using AJAX

I've been working on a chatbox using AJAX and I've encountered an issue where my xhttp.responseText is coming back empty. In firebug, I can see that the GET request is being sent and the correct text is being returned, but for some reason it&apos ...

Turn off the ability to view the content of .css and .js files within the browser

Earlier, I inquired about how to disable file and folder listing and discovered that it can be achieved using a file named .htaccess. To disable folder listing, I entered Options -Indexes in the .htaccess file located in the parent folder. Additionally, to ...

Where do I find the resultant value following the completion of a video production through editly?

Hey there, I have a quick question... I was following the instructions in the README for editly, and I successfully created videos by calling editly like this: // creating video editly(editSpec) .catch(console.error); The only issue is that I am using Ex ...

What method is most effective for duplicating objects in Angular 2?

Is it just me, or does Angular 1.x have methods on the global angular object like angular.copy and angular.shallowCopy that are missing in Angular 2? It seems like there is no equivalent version in Angular 2 documentation. If Angular 2 doesn't plan on ...

What methods do Google and Facebook use to manage user sessions effectively?

I'm looking to incorporate a session in my asp.net application that remains active until the user logs out. I've come across this feature on websites like Google, where the session persists even after a computer restart. How do they achieve this ...