Three times merge with several materials, only one material is used

I searched this and found some examples in stackoverflow, but the answers did not solve my problem.

What I tried:

First, I create a geometric bucket that will be used for the group, and an array for storing my materials.

var totalGeom = new THREE.Geometry(); var materials = []; 

Then I run my data (strData) with a for loop and call addMapMarker3d.

  for(var i=0; i<strData.length;i++){ addMapMarker3d([strData[i].lat,strData[i].lon], strData[i].time, measureColors[i]); } 

The addMapMarker3d function is as follows:

 addMapMarker3d = function(latLng, height, color){ var max = 600; var dist = 25; var opacity = (height/max); var geometry = new THREE.BoxGeometry( Math.floor(dist), height, Math.floor(dist)); //create the material and add it to the materials array var material = new THREE.MeshBasicMaterial({ transparent:true, color: Number(color), opacity:opacity}); this.materials.push(material); //create a mesh from the geometry and material. var cube = new THREE.Mesh( geometry, material); //leaf is a simple lat/lng to pixel position converter var actualMarkerPos = leaf.getPoint(latLng); //apply the position on a 5000x5000 cartesian plane var extent = 5000; cube.position.setZ((actualMarkerPos[1] * extent) - extent/2); cube.position.setX(-((actualMarkerPos[0] * extent) - extent/2)); cube.position.setY(height/2); //update the matrix and add the cube to the totalGeom bucket cube.updateMatrix(); totalGeom.merge( cube.geometry, cube.matrix); } 

After starting the for loop and creating all the cubes:

  var mats = new THREE.MeshFaceMaterial(materials) var total = new THREE.Mesh(totalGeom, mats); world.scene.add(total); 

Question

While the geometry merge functions and my view port work with significantly improved FPS, all the cubes have exactly the same color and opacity. It seems that the merge uses one material from 10k I. Is there a way to make sure that the geometry uses the material supplied in the array ? Am I doing something wrong?

If I try this in addMapMarker3d:

 totalGeom.merge( cube.geometry, cube.matrix, materials.length-1); 

I get "Uncaught TypeError: I can not read the property" transparently "undefined", and does not display anything, which I do not understand, because by the examples each geometry should index the material in the array of materials.

three.js r.70

+4
source share
3 answers

My initial question did not answer: Is there a way to make sure that the geometry uses the material supplied in the array?

The answer is yes. During the merge, you can apply multiple materials to the same grid. After clicking a material into an array of materials, the merge will use the geometry index of the material. The merge will apply multiple materials when the array is transferred to the new THREE.MeshFaceMaterial ([materialArray]) file as the overall mesh is created. This solves the secret syntax. Just because you supply an array of materials does not mean that the merge will use each material in iterative mode, since the objects are merged with r71. Persons must report the merger of the material that is used in the material array.

I use this for an unrealized scene, and the final obj is exported. If you need rendering performance, see One of the other answers for some options.

A simple loop on a face array on geometry reports a merge to which the material applies:

  addMapMarker3d = function(latLng, height, color){ var max = 600; var dist = 25; var opacity = (height/max); var geometry = new THREE.BoxGeometry( Math.floor(dist), height, Math.floor(dist)); //create the material and add it to the materials array var material = new THREE.MeshBasicMaterial({ transparent:true, color: Number(color), opacity:opacity}); this.materials.push(material); //set the material index of each face so a merge knows which material to apply for ( var i = 0; i < geometry.faces.length; i ++ ) { geometry.faces[i].materialIndex = this.materials.length-1; } //create a mesh from the geometry and material. var cube = new THREE.Mesh( geometry, material); //leaf is a simple lat/lng to pixel position converter var actualMarkerPos = leaf.getPoint(latLng); //apply the position on a 5000x5000 cartesian plane var extent = 5000; cube.position.setZ((actualMarkerPos[1] * extent) - extent/2); cube.position.setX(-((actualMarkerPos[0] * extent) - extent/2)); cube.position.setY(height/2); //update the matrix and add the cube to the totalGeom bucket cube.updateMatrix(); totalGeom.merge( cube.geometry, cube.matrix); } 
+4
source

The following method uses only one material, but allows you to save the individual color of each combined object. I do not know whether it is possible to preserve the individual alpha of each merged object.

http://jsfiddle.net/looshi/nsknn53p/61/

For each grid, specify each of its geometry.faces colors:

 function makeCube(size, color) { var geom = new THREE.BoxGeometry(size, size, size); for (var i = 0; i < geom.faces.length; i++) { face = geom.faces[i]; face.color.setHex(color); } var cube = new THREE.Mesh(geom); return cube; } 

Then, in the parent geometry you are about to join, set its property to the vertexColors property.

 var parentGeometry = new THREE.Geometry(); var parentMatrial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.SmoothShading, vertexColors: THREE.VertexColors }); // in a loop you could create many objects and merge them for (var i = 0; i < 1000; i++) { cube = makeCube(size, color); cube.position.set(x, y, z); cube.rotation.set(rotation,rotation,rotation); cube.updateMatrix() parentGeometry.merge(cube.geometry, cube.matrix); } // after you're done creating objects and merging them, add the parent to the scene parentMesh = new THREE.Mesh(parentGeometry, parentMatrial); scene.add(parentMesh); 
+4
source

The only reason you see improved performance is because there is only one material after the merger. If you want several materials in your scene, you should not merge.

Adding to the same group:

 var group = new THREE.Object3D(); group.add (object1); group.add (object2); group.add (object3); 
+2
source

All Articles