0
votes

I have a 3D model of my home town. I would like to use real time data to change the height of the buildings. In my first try, I loaded the buildings as individual meshes and called scene.add(buildingMesh) during setup.

var threeObjects = []
var buildingMesh = new THREE.Mesh(geometry, material)       
threeObjects.push(buildingMesh);
$.each(threeObjects,function(i, buildingMesh)
{
    buildingMesh.rotation.x += -3.1415*0.5;
    buildingMesh.castShadow = true;
    buildingMesh.receiveShadow = true;
    scene.add(buildingMesh);
});

Which is too slow as my dataset consists of roughly 10.000 building. So I took the approach to add all the (geometries of the) meshes to a single geometry and wrap that in a mesh to be added to the scene

singleGeometry.merge(buildingMesh.geometry, buildingMesh.matrix); //in a loop


var faceColorMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, vertexColors: THREE.VertexColors } );
combinedMesh = new THREE.Mesh(singleGeometry, faceColorMaterial);

scene.add(combinedMesh);

Just to make a proof of concept, I'm trying to change the height of a building when I click it. Alas, this is not working. By adding a new id field, I can get a reference to the faces and vertices and change the color of the building, but I can not for the life of me, get them to to change height.

In my first version, I would just use something like:

buildingMesh.scale.z=2;

But as I have no meshes anymore, I'm kinda lost.

Can anybody help?

disclaimer: I'm new to Three.js, so my question might be stupid...hope it's not :)

2

2 Answers

0
votes

If you combine all of your buildings into a single geometry, you're obliterating everything that makes the buildings distinct from each other. Now you can't tell building A from building B because it's all one big geometry, and geometry at its basic level is literally just arrays of points and polygons with no way of telling any of it apart. So I think it's the wrong approach to merge it all together.

Instead, you should take advantage of three.js's efficient scene graph architecture. You had the right idea at first to just add all the buildings to a single root Object3D ("scene"). That way you get all the efficiencies of the scene graph but can still individually address the buildings.

To make it load more efficiently, instead of creating the scene graph in three.js every time you load the app, you should do it ahead of time in a 3D modeling program. Build the parent/child relationships there, and export it as a single model containing all of the buildings as child nodes. When you import it into three.js, it should retain its structure.

0
votes

JCD: That was not quite the question I asked. But anyhow, I found a solution to the problem.

What I did was to merge all the geometries, but in stead of using the standard clone function in geometry.merge() I used a shallow reference, which made it possible for me to use the reference in threeObjects to find the correct building and resize the part of the geometry using Mesh.scale, followed by a geometry.verticesNeedUpdate = true; For further optimization, I split the model into 5 different geometries and only updated the geometry that contained the building