Guide for combining two geometries or meshes in three.js version r71

Encountering a problem when attempting to merge two geometries (or meshes) into one, as the previously used function in earlier versions of three.js is no longer available.

In an effort to merge the <code>pendulum and ball, I implemented the following code:

ball represents a mesh.

var ballGeo = new THREE.SphereGeometry(24,35,35);
var ballMat = new THREE.MeshPhongMaterial({color: 0xF7FE2E}); 
var ball = new THREE.Mesh(ballGeo, ballMat); 
ball.position.set(0,0,0);

var pendulum = new THREE.CylinderGeometry(1, 1, 20, 16);
ball.updateMatrix();
pendulum.merge(ball.geometry, ball.matrix);
scene.add(pendulum);

This resulted in the following error message:

THREE.Object3D.add: object not an instance of THREE.Object3D. THREE.CylinderGeometry {uuid: "688B0EB1-70F7-4C51-86DB-5B1B90A8A24C", name: "", type: "CylinderGeometry", vertices: Array[1332], colors: Array[0]…}THREE.error @ three_r71.js:35THREE.Object3D.add @ three_r71.js:7770(anonymous function) @ pendulum.js:20

Answer №1

Clarifying Darius' explanation (which I found challenging while updating a version of Mr Doob's procedural city to function with Face3 boxes):

Basically, you are consolidating all your Meshes into one Geometry. For example, if you want to merge a box and a sphere:

var box = new THREE.BoxGeometry(1, 1, 1);
var sphere = new THREE.SphereGeometry(.65, 32, 32);

...into a single geometry:

var singleGeometry = new THREE.Geometry();

...you would create a Mesh for each geometry:

var boxMesh = new THREE.Mesh(box);
var sphereMesh = new THREE.Mesh(sphere);

...then utilize the merge method of the single geometry for each, passing in the geometry and matrix of each:

boxMesh.updateMatrix(); // as needed
singleGeometry.merge(boxMesh.geometry, boxMesh.matrix);

sphereMesh.updateMatrix(); // as needed
singleGeometry.merge(sphereMesh.geometry, sphereMesh.matrix);

Once merged, generate a mesh from the single geometry and add it to the scene:

var material = new THREE.MeshPhongMaterial({color: 0xFF0000});
var mesh = new THREE.Mesh(singleGeometry, material);
scene.add(mesh);

A functional demonstration:

<!DOCTYPE html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
<!-- OrbitControls.js is not versioned and may stop working with r77 -->
<script src='http://threejs.org/examples/js/controls/OrbitControls.js'></script>

<body style='margin: 0px; background-color: #bbbbbb; overflow: hidden;'>
  <script>
    // init renderer
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // init scene and camera
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 3000);
    camera.position.z = 5;
    var controls = new THREE.OrbitControls(camera)
   
    // our code
    var box = new THREE.BoxGeometry(1, 1, 1);
    var sphere = new THREE.SphereGeometry(.65, 32, 32);

    var singleGeometry = new THREE.Geometry();

    var boxMesh = new THREE.Mesh(box);
    var sphereMesh = new THREE.Mesh(sphere);

    boxMesh.updateMatrix(); // as needed
    singleGeometry.merge(boxMesh.geometry, boxMesh.matrix);

    sphereMesh.updateMatrix(); // as needed
    singleGeometry.merge(sphereMesh.geometry, sphereMesh.matrix);

    var material = new THREE.MeshPhongMaterial({color: 0xFF0000});
    var mesh = new THREE.Mesh(singleGeometry, material);
    scene.add(mesh);

    // a light
    var light = new THREE.HemisphereLight(0xfffff0, 0x101020, 1.25);
    light.position.set(0.75, 1, 0.25);
    scene.add(light);

    // render
    requestAnimationFrame(function animate(){
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
    })
  </script>
</body>

This is my understanding of the process; any errors here are unintentional as I am still learning three.js and far from an expert. My attempt at customizing Mr. Doob's procedural city code ran into issues with the latest version changes (such as the merge functionality and the switch from quads to triangles for cube geometries), resulting in challenges to achieve proper shading and other visuals.

Answer №2

After countless hours of trial and error, I have stumbled upon a potential solution that may help others facing the same issue. The key lies in understanding how to manipulate meshes and geometries:

var ballGeometry = new THREE.SphereGeometry(10, 35, 35);
var material = new THREE.MeshPhongMaterial({color: 0xF7FE2E}); 
var ballMesh = new THREE.Mesh(ballGeometry, material);

var pendulumGeometry = new THREE.CylinderGeometry(1, 1, 50, 16);
ballMesh.updateMatrix();
pendulumGeometry.merge(ballMesh.geometry, ballMesh.matrix);

var pendulumMesh = new THREE.Mesh(pendulumGeometry, material);
scene.add(pendulumMesh);

Answer №3

The error message is correct. CylinderGeometry is not considered an Object3D, unlike Mesh which is. A Mesh is created using a Geometry and a Material, and can be placed in the scene, whereas a Geometry cannot.

In the latest releases of three.js, Geometry now includes two merge methods: merge and mergeMesh.

  • merge requires the argument geometry, as well as optional arguments matrix and materialIndexOffset.
  • geom.mergeMesh(mesh) is essentially a shortcut for geom.merge(mesh.geometry, mesh.matrix), as mentioned in other responses. ('geom' and 'mesh' are placeholders for a Geometry and a Mesh, respectively.) The Mesh's Material is disregarded in this process.

Answer №4

Presenting my top compact version in three (or four) lines while referencing material from elsewhere and utilizing mergeMesh:

let geometry = new THREE.Geometry();
geometry.mergeMesh(new THREE.Mesh(new THREE.BoxGeometry(2,20,2)));
geometry.mergeMesh(new THREE.Mesh(new THREE.BoxGeometry(5,5,5)));
geometry.mergeVertices(); // optional
scene.add(new THREE.Mesh(geometry, material));

Note: Included an optional step to eliminate duplicate vertices for potential performance improvement.

Update: Utilizing the latest version, 94.

Answer №5

The solutions and snippets I've come across on this platform are not effective due to the merge method requiring an integer as the second argument, rather than a matrix. It seems like the merge method is not operating as intended. To work around this issue, I devised a straightforward technique for creating a rocket with a pointed nose cone.

import * as BufferGeometryUtils from '../three.js/examples/jsm/utils/BufferGeometryUtils.js'

lengthSegments = 2
radius = 5
radialSegments = 32
const bodyLength = dParamWithUnits['launchVehicleBodyLength'].value
const noseConeLength = dParamWithUnits['launchVehicleNoseConeLength'].value

// Craft the main body of the vehicle
const launchVehicleBodyGeometry = new THREE.CylinderGeometry(radius, radius, bodyLength, radialSegments, lengthSegments, false)
launchVehicleBodyGeometry.name = "body";
// Construct the nose cone
const launchVehicleNoseConeGeometry = new THREE.CylinderGeometry(0, radius, noseConeLength, radialSegments, lengthSegments, false)
launchVehicleNoseConeGeometry.name = "noseCone";
launchVehicleNoseConeGeometry.translate(0, (bodyLength + noseConeLength) / 2, 0)
// Combine the nose cone with the main body
const launchVehicleGeometry = BufferGeometryUtils.mergeBufferGeometries([launchVehicleBodyGeometry, launchVehicleNoseConeGeometry])
// Orient the vehicle horizontally
launchVehicleGeometry.rotateX(-Math.PI/2)
const launchVehicleMaterial = new THREE.MeshPhongMaterial({ color: 0x7f3f00 })
const launchVehicleMesh = new THREE.Mesh(launchVehicleGeometry, launchVehicleMaterial)

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 pressing the next or previous button on the slider, an error message pops up saying "$curr[action] is not a

I found this interesting Js fiddle that I am currently following: http://jsfiddle.net/ryt3nu1v/10/ This is my current result: https://i.sstatic.net/VygSy.png My project involves creating a slider to display different ages from an array, such as 15, 25, ...

Combining arrays in Laravel using the map function

Looking to create a new array using the map function and then merge it with another one? Let's consider an initial array: $arr1=['x' => 0 , 'y' => 0] Now, imagine we have a query that will generate a new array with its keys. ...

Explication of syntax not functioning

Following the instructions provided here but encountering issues, any assistance? <script type="text/javascript" src="sh/src/shCore.js"></script> <script type="text/javascript" src="sh/scripts/shBrushJScript.js"></script> <lin ...

Using Jasmine to simulate multiple method calls in a testing environment

Currently, I am working on writing a JavaScript test for a method that involves making two function calls (model.expandChildren() and view.update();). // within the 'app' / 'RV.graph' var expandChildren = function(){ return model.e ...

What is the best way to showcase topojson using the fundamentals of three.js?

Looking to utilize an existing shapefile and extrude it using three.js. Created a basic topojson file that I want to extrude with three.js, similar to the example shown here Find the shapefile here... https://github.com/jamestknz/store/blob/master/house. ...

Is there a way to set the menu to automatically open when the page loads?

Looking for some help with a slide out menu that I want to be always open and cannot be closed. I tried changing the open=true setting to open=false but it didn't work as expected. Here's the code snippet below. I aim to remove the open and close ...

Add a new module to your project without having to rely on the initial

I'm looking to experiment with a module by making some adjustments for testing purposes. You can find the code here. Currently, all I need to do is type "npm install angular2-grid" in my terminal to add it to my project. Here's my concern: If ...

CSS linking causing pages to crumble

Out of nowhere, while working on my project today, my page suddenly collapsed. It was a frustrating sight to see. Immediately, I went back to Dreamweaver and used cmd+z to undo a few steps, but there was no visible issue. Despite this, my page continued t ...

What is the best way to fix multiple dropdown menus opening simultaneously in Vue.js?

I am working on an application that generates todo lists for tasks. These lists can be edited and deleted. I am trying to implement a dropdown menu in each list to provide options for updating or deleting the list individually. However, when I click on the ...

Obtaining HTML data with ajax within a WordPress post

Greetings! I've been putting together a website and I'm eager to include a unique timeline in each of my posts. I'm utilizing WordPress for this project. However, since the timeline I want to insert will vary from post to post, I am unable t ...

Reflective Raycaster on WebGl Sphere World

In my current thesis project, I am utilizing the DataArts WebGL Globe to create a web page for an upcoming exhibition that will be displayed on a touch monitor. In order to make the globe interactive and clickable for users to select individual countries a ...

There is no result being returned by Model.findOne()

Why does Model.findOne() return null even when a valid collection is present in the respective Model? app.post("/fleetManagement", (req, res) => { const requestedDriverID = req.body.driverId; console.log(requestedDriver ...

Tips for utilizing [(ngModel)] with an object that is empty, null, or undefined in Angular 4

When trying to assign [(ngModel)] inside my .html code to an empty (null or undefined) object, I encountered the error message _co.object is null. There are two scenarios: one where the object has a value and one where it does not. The ngModel works fine i ...

Building a single page web application using TypeScript and webpack - a step-by-step guide

For a while now, I've been working on single page applications using Angular. However, I'm interested in creating a single page application without utilizing the entire framework. My goal is to have just one .html file and one javascript file, w ...

Javascript function that sets the opacity to 0

Hello everyone, I'm new to SO and seeking some guidance on improving my post! I have a function that sets the opacity of an element to 0 in order to clear it. While this works fine, it becomes burdensome when dealing with multiple elements that requi ...

What could be causing the error "Cannot read the state property of undefined in react-native?"

I really need some assistance. I am attempting to create a JSON object called users in my state properties to test the functionality of my authentication system. However, when I tried to access it, I encountered the error "Cannot read property 'state& ...

Guide on comparing a string value with a date in the format of YYYY-MM-DD using protractor in a node js environment

In my application, I am retrieving the date field in string format using the getText() function. I need assistance in determining whether the captured date is earlier than the current date. Can someone provide guidance on this? var actDate = locator.getTex ...

Variations in jQuery's append method when dealing with a string, a reference to a jQuery object

Here are multiple ways to add a div element to the body of an HTML document. But what distinctions exist between them and in what scenarios should each be utilized for optimal performance? var newDiv = '<div id="divid"></div>'; $(&ap ...

Enhance the database with partial updates using the patch method in Django Rest Framework

I have a model called CustomUser that extends the AbstractUser class. class CustomUser(AbstractUser): detail = models.JSONField(default=dict) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=Tr ...

Efficiently map nested properties of this.props within the render method

When working in the render() method, I find myself passing numerous variables around. The recommended best practices suggest setting up variables before the return <div>...etc</div statement like this: const { products: mainProducts, ...