Formulate a CANNON entity utilizing the THREE.Mesh technique

I have a THREE.js plane where the points are manipulated using Perlin noise to create terrain. I now need to implement physics for the camera to prevent it from falling through the plane.

My goal is to develop a function that can extract the vertices and faces from the mesh and transfer them to a CANNON body as a Convex Polyhedron. Here's my current attempt that is not functioning as expected:

function setPhysicsGeometry(mesh, body) {
    const vertices = mesh.geometry.vertices;
    const shape = new CANNON.ConvexPolyhedron();

    vertices.forEach(function(vertex) {
        vertex.z = 0; 
        shape.vertices.push(new CANNON.Vec3(vertex.x, vertex.y, vertex.z));
    });

    const faces = [];
    for (let i = 0; i < mesh.geometry.faces.length; i++) {
        const face = mesh.geometry.faces[i];
        faces.push([face.a, face.b, face.c]);
    }
    shape.faces = faces;

    shape.updateNormals();
    shape.updateEdges();

    body.addShape(shape);
}

I'm encountering the following error:

Uncaught TypeError: shape.updateNormals is not a function

The same issue arises with shape.updateEdges()

Is this a problem with these functions or am I oversimplifying a difficult/impossible task?

Thank you

UPDATE: I've created a function that somewhat functions but is extremely slow:

function createShape(geo) {
    const bufferedGeo = new THREE.BufferGeometry().fromGeometry(geo); 

    let position = bufferedGeo.attributes.position.array
    const points = []

    for (let i = 0; i < position.length; i += 3) {
        points.push(new CANNON.Vec3(position[i], position[i + 1], position[i + 2]))
    }
    const faces = []
    
    for (let i = 0; i < position.length / 3; i += 3) {
        faces.push([i, i + 1, i + 2])
    }

    const shape = new CANNON.ConvexPolyhedron(points, faces)
    
    return shape
}

Here's an error I'm encountering indicating that the normals are incorrectly ordered:

.faceNormals[1011] = Vec3(-0.38237948261368415,0.4673447646702331,-0.7971040096570934) looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.

I'm unsure how to rectify this issue since the normals are simply derived from the geometry

Answer №1

I managed to figure it out (although there are still some issues with the physics, but that's a separate issue).

A big thank you to This Guy for providing me with a fantastic example that helped me find the solution. I initially tried to use ConvexPolyhedron to define my own body shape. While it's possible to do that, arranging the faces and normals in the correct syntax proved to be quite challenging. Instead, I opted for Trimesh, which was a much simpler approach.

In the example, new THREE.TorusKnotGeometry() was used followed by createTrimesh(). However, this approach resulted in an error for me because the THREE.js geometry was not a buffer geometry. I made a simple adjustment by creating a function, and this resolved the errors. Despite this, the physics still weren't functioning properly for the object. After spending what seemed like an eternity on it, I ended up copying the position and quaternion from the THREE.js mesh to the CANNON body, and it worked quite well. Here is the finalized code:

Function to Copy position and quaternion:

function copy(threeMesh, cannonBody) {
    // Copy position
    const position = new CANNON.Vec3(
        threeMesh.position.x,
        threeMesh.position.y,
        threeMesh.position.z
    );
    cannonBody.position.copy(position);

    // Copy rotation
    const quaternion = new CANNON.Quaternion(
        threeMesh.quaternion.x,
        threeMesh.quaternion.y,
        threeMesh.quaternion.z,
        threeMesh.quaternion.w
    );
    cannonBody.quaternion.copy(quaternion);
}

Function to create Trimesh:

function buffer(geo) {
    const bufferedGeo = new THREE.BufferGeometry().fromGeometry(geo);
    return bufferedGeo;
}

function CreateTrimesh(geometry) {
    const vertices = buffer(geometry).attributes.position.array
    const indices = Object.keys(vertices).map(Number)
    return new CANNON.Trimesh(vertices, indices)
}

Mesh and Body code:

var platformGeometry = createCustomGeometry(terrain, size + 1, size + 1)
var platformMaterial = new THREE.MeshPhongMaterial({ color: 0x00ff00, wireframe: false, side: THREE.DoubleSide});
var platform = new THREE.Mesh(platformGeometry, platformMaterial);
platform.receiveShadow = true;
platform.castShadow = true;
platform.position.set(0, 0, 0);
platform.rotation.x = Math.PI / 2;
scene.add(platform);

var platShape = CreateTrimesh(platformGeometry, platform);
var platBody = new CANNON.Body({ mass: 0, shape: platShape });
copy(platform, platBody);
world.addBody(platBody);

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

Reviewing and Implementing React and Material-UI Autocomplete for Selecting Multiple

Having trouble using Formik and MUI Autocomplete with multiple items. Specifically, when searching for "Pencil", it doesn't highlight the item. Also, you can select it twice by clicking on it. Desired outcome: Being able to select one or more items. ...

Issues with Angular JS page loading when utilizing session and local storage in Google Chrome

I'm currently learning about AngularJS and I stumbled upon this helpful tutorial http://embed.plnkr.co/dd8Nk9PDFotCQu4yrnDg/ for building a simple SPA page. Everything was working smoothly in Firefox and IE, except when it came to using Local and Sess ...

In express.js, cookies automatically expire upon the browser being closed

When working with express.js, I typically set cookies using the command: res.cookie("name", "value"); However, upon closing and reopening the browser, I noticed that the cookie is no longer there. Could someone advise me on how to mak ...

obtaining information from newly added form elements in an Angular application

I'm currently working on an app with the MEAN stack. I've managed to dynamically add form elements, but I'm running into an issue where all dynamically added elements are taking the same data when I use ng-model="something.something". What I ...

Is it possible to utilize personalized functionalities in the main.js file of the Firefox Addon SDK?

Why am I encountering difficulties accessing custom functions with the Firefox Addon SDK? In the code snippet provided below, whenever I click on context menu Sub Item 1, it does not work as intended; It is trying to access the custom function verifyTest( ...

Modifying the background hues in React using the useState hook

Hello there, I'm in need of some clarification on the following code snippet. I've come across a piece of code that I can't quite grasp, even though it was recommended to me. To style text colors based on checkbox status, I came up with thi ...

Prompt user to save changes or cancel before closing modal (if closed by pressing ESC or clicking the backdrop)

When I manually close the modal, everything works fine. I just create a prompt and only call the BsModalRef.hide() method when the prompt (sweetalert) is closed. However, when the modal is closed using the ESC key or click-outside events provided by Boots ...

Guide to selecting and clicking multiple elements with a specific class using jQuery

On my html page, I have the following elements: $(".pv-profile-section__card-action-bar").length 3 I want to click on all of these elements instead of just the first one. Currently, I am achieving this with the code: $(".pv-profile-section__card-action- ...

The pdf generation feature of pdf-creator-node in Linux seems to be malfunctioning

An error occurred with code EPIPE at afterWriteDispatched (internal/stream_base_commons.js:154:25) at writeGeneric (internal/stream_base_commons.js:145:3) at Socket._writeGeneric (net.js:784:11) at Socket._write (net.js:796:8) ...

Track the loading time of a webpage and the time it takes to render all subelements of

For my project, I need to track page load times for each individual visitor. My idea is to embed a JavaScript snippet into the page in order to achieve this goal. However, the task is more complex than I anticipated because I also need to measure the respo ...

Searching with jQuery UI Autocomplete

I am interested in implementing jQuery UI autocomplete to allow users to search for items on my website. I have a list of products that I want to convert into JSON data (or just include them directly in JavaScript like the jQuery UI demo does), but I&apos ...

Seamless transition of lightbox fading in and out

Looking to create a smooth fade in and out effect for my lightbox using CSS and a bit of JavaScript. I've managed to achieve the fading in part, but now I'm wondering how to make it fade out as well. Here is the CSS code: @-webkit-keyframes Fad ...

Facebook's Thumbs Down to My Code

I've been struggling to integrate a Facebook Like button on my blog using the following code: $("#fblike").append(" <iframe src='http://www.facebook.com/plugins/like.php?app_id=217624258276389&amp;" + window.location.href + "&amp;send ...

Is there a way to eliminate the border of an image attribute pulled from an input field?

Seeking assistance with a persistent issue I'm facing. I have an input for an image and a script to display the selected image. However, when the input is empty, a frustrating black border appears around the image attribute. How can I remove this bord ...

Effortlessly showcase JSON data in an HTML owl carousel

Is there a way to display JSON data in HTML format? I have a JSON file containing reviews from Facebook, and I would like to showcase them on my website. Each review should be placed in its own div element. The JSON data below is extracted from the Faceboo ...

Issue encountered while working with PostgreSQL and Sequelize when using the array_append function

I'm encountering issues with the following code snippet let user = req.user.id; await MyTable.update( {'interested': Sequelize.fn('array_append', Sequelize.col('interested'), user)}, {'where ...

Retrieve information stored in a component's data variable

After creating a Vue repository using vue init webpack my-app My main.js file looks like this -- // The Vue build version to load with the import command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue fro ...

Is it possible to retrieve JSON data and display only the entries with positive values in an HTML

I am working on a project that involves fetching JSON API data and displaying it in an HTML table, but only for values above 10. Below is the code snippet along with my JavaScript. I specifically want to exclude negative values and only display positive v ...

Creating a dynamic quiz with random images using text boxes in HTML and PHP

I am working on creating a 'guess the picture' style quiz where a random image is displayed as the question, and users must input their answer in a textbox. The question will be selected randomly from 3-5 options each time the page is refreshed o ...

In VueJS, the v-for directive allows you to access both parameters and the event object within

Imagine having nested elements that repeat using v-for in the following structure: <div id="container"> <div v-for="i in 3"> <div v-for="j in 3" v-on:click="clicked(i,j)"> {{i+&a ...