Noobie question about instanceMesh

Hi, new to 3 and 3D, so just need some basic pointers. I was able to follow along the examples and get a basic scene with some box items displayed as below:

this.geometry = new THREE.BoxGeometry( 1, 1, 1 );
				this.geometry.translate( 0, 0.5, 0 );
				this.material = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } );

				for ( let i = 0; i < 500; i ++ ) {

					const mesh = new THREE.Mesh( this.geometry, this.material );
					mesh.position.x = Math.random() * 1600 - 800;
					mesh.position.y = 0;
					mesh.position.z = Math.random() * 1600 - 800;
					mesh.scale.x = 20;
					mesh.scale.y = Math.random() * 80 + 10;
					mesh.scale.z = 20;
					mesh.updateMatrix();
					mesh.matrixAutoUpdate = false;
					this.scene.add( mesh );

				}

But, I was thinking instance mesh might be smarter/better performance since all of my items will just be boxes. They’ll need to have different sizes and colors however, so maybe that’s not a good fit for instance mesh? So, I tried the following and I just get one box displayed on screen. My render function isn’t doing anything other than a call to render the scene right now. So, I’m def doing something wrong when I’m trying to use an instance mesh and iterate over the instances and change their shape and position… Thanks for any help!

				this.geometry = new THREE.BoxGeometry( 1, 1, 1 );
				this.geometry.translate( 0, 0.5, 0 );
				this.material = new THREE.MeshPhongMaterial( { color: 0x0020ee, flatShading: true, shininess: 150 } );
                this.mesh = new THREE.InstancedMesh( this.geometry, this.material, 500 );
                var matrix = new THREE.Matrix4();
                
                this.mesh.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); 
                console.log("created instance mesh");
                this.scene.add( this.mesh );

                for ( let i = 0; i < 500; i ++ ) 
                {

                    //var matrix = new THREE.Matrix4();

					//this.mesh.getMatrixAt(i, matrix);

					var x = Math.random() * 1600 - 800;
					var y = 0;
					var z = Math.random() * 1600 - 800;
                    matrix.setPosition(x,y,z);
                    this.mesh.setMatrixAt(i, matrix);
                    
                    x = 20;
					y = Math.random() * 80 + 10;
					z = 20;
                    matrix.makeScale(x, y, z);
					this.mesh.setMatrixAt(i, matrix);

                    //itemMesh.updateMatrix();
					//mesh.matrixAutoUpdate = false;
					

				}

                this.mesh.instanceMatrix.needsUpdate = true;

When you use setMatrixAt you are supposed to provide the matrix containing position/scale/rotation for an instance - all in one matrix.

In your case you set the matrix twice, makeScale overwrites setPosition, so your cubes are at the same place and you see only the outer cube with the biggest scale.

Try this:

for ( let i = 0; i < 500; i ++ ) {

const x = Math.random() * 1600 - 800;
const y = 0;
const z = Math.random() * 1600 - 800;

const scx = 20;
const scy = Math.random() * 80 + 10;
const scz = 20;

matrix.makeScale(scx, scy, scz).setPosition(x,y,z);
this.mesh.setMatrixAt(i, matrix);
                    
}
1 Like

AWESOME!!! THANK YOU!! i’ll try asap

working great, thanks again! for any other beginner like that wants to know how to change the size (only, so far) during render of instanceMesh items, here’s what I have and it’s working… i’m guessing this can optimized quite a bit but for now this works great with 2000 items in a scene…

render: function() {
                    var matrix = new THREE.Matrix4();
                    var vectorSize = new THREE.Vector3();
                    var vectorPos = new THREE.Vector3();
                    for (let i = 0; i < 2000; i++)
                    {
                        this.mesh.getMatrixAt(i, matrix);
                        vectorSize.setFromMatrixScale(matrix);
                        vectorPos.setFromMatrixPosition(matrix);

                        if (vectorSize.y > 100) {
                            vectorSize.y = 0;
                        }
                        else
                        {
                            vectorSize.y = vectorSize.y + 1;
                        }

                        matrix.makeScale(vectorSize.x, vectorSize.y, vectorSize.z).setPosition(vectorPos.x, vectorPos.y, vectorPos.z);
                        this.mesh.setMatrixAt(i, matrix);
                    }
                    this.mesh.instanceMatrix.needsUpdate = true;
                    this.renderer.render( this.scene, this.camera );
            }