Discovering collisions with THREE.js through the use of Raycaster and BufferGeometry

As a newcomer to 3D programming and THREE.js, I am in need of assistance with proper collision detection.

I have been using a method to detect collisions between sourceElements and targetElements

detect(): void {
    if (!this.sourceElements.length || !this.targetElements.length) {
       return;
    }

    for (let i = 0; i < this.sourceElements.length; i+= 1) {
        const originPoint = this.sourceElements[i].position.clone();

        for (let vertexIndex = 0; vertexIndex < (<Geometry>this.sourceElements[i].geometry).vertices.length; vertexIndex++) {
            let localVertex = (<Geometry>this.sourceElements[i].geometry).vertices[vertexIndex].clone();
            let globalVertex = localVertex.applyMatrix4(this.sourceElements[i].matrix);
            let directionVector = globalVertex.sub(this.sourceElements[i].position);
            let ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
            let collisionResults = ray.intersectObjects(this.targetElements, false); // @TODO create method
            if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
                console.log('<<<<HIT>>>>>', collisionResults[0].object.name);

                // if hit was detected there's no need to analyze more
                return;
            }
        }
    }
  }

This approach works successfully when source elements have Geometry. However, the issue arises when importing larger Gltf models that utilize BufferGeometry for performance reasons. BufferGeometry does not contain vertices but instead has attributes.position.array with coordinates.

To address this change, I attempted to generate vertices based on this attribute data

let v: Vector3 = new THREE.Vector3();
// iterate over source elements        
for (let i = 0; i < sourceElements.length; i += 1) {
    let geometry = sourceElements[i].geometry;
    // if BufferGeometry is present, generate vertices based on positions
    if ( geometry instanceof THREE.BufferGeometry ) {
        const vertices: Array<Vector3> = [];
        const positions = geometry.attributes.position.array;
                
        console.log('CollisionDetector BufferGeometry detected', geometry);

        for ( let k = 0; k < positions.length; k += 3 ) {
            v.set(positions[ k ],positions[ k + 1 ], positions[ k + 2 ]);
            vertices.push(v);
        }
    }
}

Although the above code executes without errors and produces an array of Vector3 objects for raycasting, collisions are unfortunately never detected.

What modifications should I make to my code to establish a universal collision detection method regardless of the type of Geometry utilized by objects?

Thank you for your anticipated help.

Answer №1

When adding elements to your vertices array in your code, you are actually adding references to the variable v. This means that any changes made to v will reflect in all those references as well, leading to comparisons being done only with the last vertex rather than unique ones for the shape(s).

To ensure that you have distinct Vector3s, you can easily achieve this by using Vector3.clone().

let v: Vector3 = new THREE.Vector3();
// iterate over source elements        
for (let i = 0; i < sourceElements.length; i += 1) {
    let geometry = sourceElements[i].geometry;
    // if there's any with BufferGeometry generate vertices based on 
    if ( geometry instanceof THREE.BufferGeometry ) {
        const vertices: Array<Vector3> = [];
        const positions = geometry.attributes.position.array;
                
        console.log('CollisionDetector BufferGeometry detected', geometry);

        for ( let k = 0; k < positions.length; k += 3 ) {
            v.set(positions[ k ],positions[ k + 1 ], positions[ k + 2 ]);
            vertices.push(v.clone()); // <---- Creates a copy!
        }
    }
}

It is important to note that by invoking v.clone() when pushing the vertex into the array, you create a duplicate of the original v along with its assigned values.

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

When transitioning from Orbitcontrol to FirstPerson control in Three.js, the loaded model is mysteriously vanishing

When attempting to switch from Orbit control to FirstPerson control, I encountered an issue where my model disappeared from the scene. Below is the code I am using: controls = new THREE.FirstPersonControls( camera ); controls.movementSpeed = 70; control ...

Error in parsing template: The element 'mat-icon' is unrecognized and cannot be processed

I'm currently working on a project using Angular CLI and angular material v.5.2.5, and I'm encountering an issue when trying to implement mat-icon-button The console is showing the following error: Uncaught Error: Template parse errors: &apo ...

Angular - Implementing *ngIf based on URL parameters

Is it possible to display an element based on specific queryParams included in the URL? For example: ngOnInit() { this.route.queryParams.subscribe(params => { console.log(params); }); } If I want to achieve something similar to this: ...

What is the method for importing the merge function from "lodash/merge" in TypeScript?

When using ES6, it's possible to import only a single function from a library in order to reduce the overall bundle size. For example: import merge from "lodash/merge" But in TypeScript, the statement above can trigger a compile error: Cannot find m ...

Is there a way to ensure that the animation does not stop until it reaches the final frame when the pointer leaves?

My challenge lies in ensuring that an animation triggered by hovering over an element continues to play until it reaches its final frame, even after the mouse pointer leaves the element. How can I make this happen? <mesh name="rond-ui-item-01 ...

What is the method for invoking a function with a chosen date in the @syncfusion schedule with Angular 9?

capture of calendar display I am looking for a way to trigger a function with the selected date as a parameter. However, I am unable to locate the appropriate event to use within this module. Can someone provide assistance with this issue? Thanks! ...

Exploring disparities between the Client SDK and Admin SDK in conducting firestore queries

I am encountering difficulties with my query while running it in Firebase Functions. It functions perfectly on the client side, but fails to work in Functions. I am curious if there is a way to modify it to function with Admin SDK as well. Am I making any ...

Are camera controls determined by the size of the object's bounding box?

I am facing a challenge with the normal orbit controls from three.js when it comes to long objects, especially at close zoom levels. I am in search of a solution to address this issue. It's difficult to explain in words, so please take a look at this ...

Matrix that comprehensively captures the object's perspective

I am struggling to set up a projection matrix that will render an object from an arbitrary camera. I have successfully configured a viewMatrix to look at the object from an arbitrary eye position, but setting up the projection matrix is proving to be chall ...

Angular 8 shows an error message stating "Unknown Error" when making a REST API request

My goal is to retrieve data from the server using a REST API service. The code snippet below is from my service.ts file: getCategories(): Observable<Category> { const httpOptions = { headers: new HttpHeaders({ 'Content-Type&a ...

The Three.js loading bar fails to disappear after the model has finished loading

I have created a page that is inspired by this example and have incorporated relevant lines from the webgl_material_bumpmap example to implement a loading progress Dom Element. You can view the page (temporarily) here. If the information provided below is ...

Combining two sets of data into one powerful tool: ngx-charts for Angular 2

After successfully creating a component chart using ngx-charts in angular 2 and pulling data from data.ts, I am now looking to reuse the same component to display a second chart with a different data set (data2.ts). Is this even possible? Can someone guide ...

Name or Title of a Polygon/Polyhedron Using Three.js

My page contains a sample code that successfully retrieves the name of an object when a user clicks on it. However, the code works well with cubes and spheres but fails with polygons. To see how the clicks respond, you can check the console logs. What shou ...

What distinguishes between a public variable declared as var: any = []; versus a public variable declared as var: any[] =

I'm seeking clarification on the distinction between the following: public var: any = []; // versus public var: any[] = []; ...

Tips for Connecting Stiff Rigid Body Dynamics to Extruded SVG using React Three Rapier

I've also posted a question regarding this issue on the Three.js Discourse forum. I am attempting to achieve a precise inferred mesh using @react-three/rapier's <RigidBody> with an extruded SVG geometry, similar to the "hull" example in th ...

Using res.locals with TypeScript in Next.js and Express

In my express - next.js application, I am transferring some configuration from the server to the client using res.locals. My project is written in typescript and I am utilizing "@types/next": "^8.0.6". The issue at hand: typescript is throwing an error st ...

A guide on defining optional class parameters in Angular 2 using Typescript

In Typescript, optional parameters are indicated by a question mark. However, I have only found one way to instantiate the class using the new keyword. Interestingly, in Angular 2's "hero" tutorial, classes are not instantiated with the new keyword; ...

Error: Unable to locate specified column in Angular Material table

I don't understand why I am encountering this error in my code: ERROR Error: Could not find column with id "continent". I thought I had added the display column part correctly, so I'm unsure why this error is happening. <div class="exa ...

I'm having trouble retrieving the object value from a different function within my Typescript and Express application

Currently I am experimenting with utilizing typescript alongside express for my application development. I have created a function that I intend to utilize in various sections of my codebase. Upon invoking the function, I am able to observe the values thro ...

I can't figure out why I'm receiving undefined even though all the variables are populated with the necessary

I have been working on a project that involves implementing email and password authentication using Firebase. However, I encountered an error when the user submits their credentials: FirebaseError: Firebase: Error (auth/admin-restricted-operation). at ...