Managing impact in THREE.js

Hello everyone, I've been working on a personal project lately that involves the amazing library three.js.

Specifically, I've been exploring collision detection using the example from this GitHub repository, focusing on detecting overlaps between objects using voxels.

To illustrate my issue, I've been referencing the interactive voxel painter example.

When rendering a voxel on the screen, I noticed that placing another voxel above the cube works fine, but doing so below a certain radius doesn't allow me to render it:

https://i.sstatic.net/A8B1n.png

Above is an image of a rendered "cube": https://i.sstatic.net/XKRWb.png

Here is a function I created based on stemkoski's example:

checkOverlapObject: function(voxel) //This function checks for overlapping objects
{
    var originPoint = voxel.position.clone();
    var collidableObjs = this.rooms;
    for (var vertexIndex = 0; vertexIndex < voxel.geometry.vertices.length; vertexIndex++)
    {       
        var localVertex = voxel.geometry.vertices[vertexIndex].clone();
        console.log(localVertex);
        var globalVertex = localVertex.applyMatrix4( voxel.matrix );
        console.log(globalVertex);

        var directionVector = globalVertex.sub(voxel.position);
        console.log(directionVector);

        console.log(originPoint);
        console.log(directionVector.clone().normalize());
        if(collidableObjs.length > 0)
        {
            var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
            var collisionResults = ray.intersectObjects(collidableObjs);
            if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length())
            {
                console.log(collisionResults);
                console.log(collisionResults[0].distance);
                console.log(directionVector.length());
                return false;
            }
        }
    }
    return true;
},

Prior to adding a rendered voxel, users can preview whether they have permission to add it. This is achieved by passing a voxel created as follows:


var voxel = new THREE.Mesh(this.room.cubeGeometry, this.room.cubeTmpHoverMaterial);
voxel.geometry.computeBoundingBox();
voxel.position.copy(intersect.point).add(intersect.face.normal);
voxel.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
voxel.material.color.setHex(this.colorTmpHover);

Into our checkOverlapObject function to detect any overlap with already rendered objects on the screen or grid.

Following the creation of this neat little function, I added several console.log outputs for debugging purposes. Here are some of the results:

T…E.Vector3 {x: 25, y: 25, z: 25} <!-- our localVertex
T…E.Vector3 {x: 25, y: 25, z: 25} <!-- our globalVertex
T…E.Vector3 {x: 0, y: 0, z: -350} <!-- our directionVector
T…E.Vector3 {x: 25, y: 25, z: 375} <!-- our originPoint
T…E.Vector3 {x: 0, y: 0, z: -1} <!-- our directionVector.clone().normalize()
[Object, Object] <!-- our collisionResults
225 <!-- our collisionResults[0].distance
350 <!-- our directionVector.length()

This data is based on the first picture provided in the post.

I should mention that I have other voxels occupying more than one block on the grid. Thus, the function needs to consider the entire object when checking for overlaps with existing voxels. Touching adjacent objects is allowed.

If anyone has suggestions or thoughts on what might be causing the issue, please feel free to share.

Answer №1

After searching extensively, I have finally come up with a solution. I have developed a custom function for handling object collisions and overlaps.

The issue with the existing collision code is that it only checks if a ray projected from the object's origin intersects with any other objects, without considering if any part of the object is actually touching another object.

My approach involves evaluating the coordinates of the objects in terms of width (x) and depth/length (z). By iterating through the minimum and maximum x/z values of both the new object to be added and the already rendered objects on the plane, we can determine if there is any overlap or collision.

Here is the basic idea:

For each object, we start at the minimum z position and incrementally move through the length/z using a for loop. Then, we move on to the width/x by starting at the minimum x position and again using a for loop to traverse through the width.

The purpose of this method is to compare every exact point of the new object with the already existing objects on the plane to identify any matches indicating an overlap.

Below is the implementation of the method:


checkOverlapObject: function(voxel) // THIS FUNCTION CHECKS FOR OVERLAPPING OBJECTS
{
    var collidableObjs = this.rooms;
    
    // Obtain bounding box dimensions of the voxel
    var voxelMX = voxel.geometry.boundingBox.max.x;
    var voxelMZ = voxel.geometry.boundingBox.max.z;
    var voxelmX = voxel.geometry.boundingBox.min.x;
    var voxelmZ = voxel.geometry.boundingBox.min.z;

    var voxelPX = voxel.position.x;
    var voxelPZ = voxel.position.z;

    var totalPositionVoxelminZ = (voxelPZ + voxelmZ);
    var totalPositionVoxelminX = (voxelPX + voxelmX);
    var totalPositionVoxelMAXZ = (voxelPZ + voxelMZ);
    var totalPositionVoxelMAXX = (voxelPX + voxelMX);

    for(var length = totalPositionVoxelminZ; length < totalPositionVoxelMAXZ; length++)
    {
        for(var width = totalPositionVoxelminX; width < totalPositionVoxelMAXX; width++)
        {
            for(var i = 0; i < collidableObjs.length; i++)
            {
                // Retrieve bounding box dimensions of existing objects
                var thisvoxelMX = this.rooms[i].geometry.boundingBox.max.x;
                var thisvoxelMZ = this.rooms[i].geometry.boundingBox.max.z;
                var thisvoxelmX = this.rooms[i].geometry.boundingBox.min.x;
                var thisvoxelmZ = this.rooms[i].geometry.boundingBox.min.z;
                
                var thisvoxelPX = this.rooms[i].position.x;
                var thisvoxelPZ = this.rooms[i].position.z;

                var thistotalPositionVoxelminZ = (thisvoxelPZ + thisvoxelmZ);
                var thistotalPositionVoxelminX = (thisvoxelPX + thisvoxelmX);
                var thistotalPositionVoxelMAXZ = (thisvoxelPZ + thisvoxelMZ);
                var thistotalPositionVoxelMAXX = (thisvoxelPX + thisvoxelMX);

                for(var insideZ = thistotalPositionVoxelminZ; insideZ < thistotalPositionVoxelMAXZ; insideZ++)
                {
                    for(var insideX = thistotalPositionVoxelminX; insideX < thistotalPositionVoxelMAXX; insideX++)
                    {
                        if(insideZ == length && insideX == width)
                        {
                            return false; 
                        }
                    }
                }
            }
        }
    }

    return true;
}

Result visualization:

https://i.sstatic.net/rWRLS.png

This method allows for precise detection of object interactions and potential collisions due to its point-by-point analysis.

If you encounter performance issues especially when dealing with multiple objects, I am open to suggestions on enhancing and optimizing the code for better efficiency. Feel free to share your insights!

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

What method can be employed to eliminate choice selection lacking any value?

Currently, I am encountering difficulties in my attempt to remove or hide the first option value from a ransack code. Would you be able to assist me in addressing this concern? Here is the HTML CODE that I am working with: <select id="q_c_0_a_0_name" ...

Updating the data when session begins

I am having an issue with two PHP files (index.php & data.php). The first file sends data to the second file, which runs every second to display the data. However, the problem is that the data is not updating. Perhaps looking at the code will provide a be ...

Adding data to a multidimensional array in JavaScript

I am in need of creating a multidimensional JavaScript array dynamically, following this specific structure: array_answers[0][1]:"yes" array_answers[1][2]:"no" array_answers[2][2-subquestion]:"text input" array_answers[3][8]:"yes" array_answers[4] ...

Is there a way to get rid of this awful hover effect on this button?

My friend and I have been developing a Chrome extension for the Roblox Devforum with some initial success. We started working on it yesterday, and already have our button placed in the header similar to extensions like Roblox+ or RoPro. However, we encoun ...

The ajax POST method fails to trigger in a Node.js environment

Having an issue with the POST request. It's necessary for updating info without page reload. Below is my pug code: .tinder--buttons form(id="form1") button#love(type="submit") i.fa.fa ...

Error: Primefaces ajax status failure (dialog has not been defined)

I incorporated the same code found on primefaces.org, specifically this link: http://www.primefaces.org/showcase/ui/ajaxStatusScript.jsf <p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/> <p:dialog modal="true" ...

Setting the initial viewer position in Panolens: A step-by-step guide

I've been working on setting the initial viewer position for panolens.js for a while now. Here's how the set-up looks: const panoPhoto1 = 'https://conceptcityiasi.ro/assets/images/tours/tip1/apartamente-noi-de-vanzare-iasi-dacia-1_camera-ti ...

Ways to locate the final child in a sequence

Can someone assist me in finding the last element of this chain, which is represented as an array in the code (Symptomaster history array)? I have implemented a recursive approach to solve this. Let me demonstrate it in the code snippet below. //example ...

Understanding Variable Scoping in Node.js

NodeJS is a new programming language that I am just starting to explore. One thing that has been tricky for me to understand is variable scope and referencing. I encountered an issue while working with the code snippet below, where even after slicing var ...

Using AngularJS to show content based on a callback function

I'm a beginner in angular and it seems like I might be overlooking something. For the registration form, I need users to provide their location. Depending on whether they allow/support navigator.geolocation, I want to display a drop-down menu for cho ...

Incorporate a button into your Django formset application

Working with Django 5, I am in the process of creating a web application for managing a Secret Santa gift exchange project. One issue I'm facing is that formsets are not dynamic, meaning I cannot generate a variable number of forms based on user inpu ...

When the overflow-y property is set to hidden, the page unexpectedly scrolls to the top in Firefox

I have a javascript code that is responsible for opening modal popups on my website. It also manipulates the overflow-y property of the <html> element by setting it to hidden. Interestingly, in Chrome and IE, this functionality works as intended. The ...

Ensuring Vue.js components are updated only after animation completion

My website combines static HTML and jQuery with certain sections written in Vue.js. One of the features on my site is a basic Vue counter component that monitors an array from a reactive store and displays its length. There's also a button that adds ...

Warning: Obsolete Warning: Unresolved promise rejections are no longer supported. - Exploring Javascript Promises with Selenium

I recently encountered an issue while setting up test cases with Selenium in Javascript for a basic login page test. I am currently working on implementing proper error handling by rejecting within a Promise. Here is the code snippet in question: //Test Ca ...

Extract the ID from the array, save it, and then delete it from the local storage

I am currently developing a mobile application using Angular, JavaScript, Ionic, and Cordova. Within one of my functions, I make use of an array called existingEntries, which is stored as a variable. categories: Array [276] [0...99] 0: Object id ...

Are Bootstrap Input groups inconsistent?

Hey there! I've been working on the sign-in example, but I seem to have hit a roadblock. In my local setup, the top image is what I see in my browser after running the code, while the desired layout that I found on the Bootstrap site is the one below ...

Is it possible to include 'file.php' along with the 'id' using php?

I have constructed my website using php include and the structure of the index is as follows: Menu.php (menu system) main.php (Main page) footer.php (footer section) On the main.php (main page), I have incorporated a news script that utilizes $_GET t ...

How can I use jQuery to target elements other than the vertical scrollbar when

Here is how I am utilizing the mouseleave jquery event $(document).ready(function(){ $(document).mouseleave(function(event) { //perform a task }); }); Is there any method to prevent this event from triggering when a user scrolls ...

Angular 6: Harnessing the Power of Subject

In my angular applications, I have been utilizing the Subject feature from the rxjs library to create an event emitter. However, upon migrating to Angular 6, I encountered the issue that this module is no longer available. Cannot find module 'rxjs/Su ...

How can a groovy script help in extracting the Version Number using Parse()?

Seeking guidance on parsing a version number using a groovy script When extracting a payload from Ariba, encountering an issue with the ItemNumber field Initially, it parsed as a float, but now returning a version instead Struggling to update this part ...