Hello everyone,
I continue my “3d project”.
My goal is to display a CHANGING forest with MOVING animals.
Something like “50k plants” + “100 animals”
My only way yet to successfully display something at 60 fps was to use “points”
naive Algorithm :
Animals = list of points…
Tree = list of points…
engine loop:
animals are moving : animal.X++ ,animal.Y++ …
tree are growing (having more points) and so on
refresh draw loop
- delete all points
- foeach animal / tree : redraw all points
It works but it’s miles away the minimum quality i am aiming for,
So i tried objects instancing instead of using points
-
For some reasons, depending on camera angle, everything become invisible
-
I have moving & changing objects, my algorithm is now
- init instances once with maximum count
- loop : change all positionMatrice according to animal positions, and set exact draw range
Initial draw is good; but refresh is not performant (4 fps vs 60 with points)
// the exact code portion
// called once, init 2 instances
initInstances()
{
for (let i = 0 ; i < this.geometry.length ; i++) {
this.geometry[i] = new THREE.OctahedronGeometry( 0.35, 0);
this.material[i] = new THREE.MeshBasicMaterial( { map: this.textures[i] } );
this.matrix[i] = new THREE.Matrix4();
this.mesh[i] = new THREE.InstancedMesh( this.geometry[i], this.material[i], this.maxCount[i] );
this.mesh[i].instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame
this.mesh[i].userData = { "animalInstance" : true };
this.objRender3D.scene.add(this.mesh[i]);
}
}
// call in refresh loop : moving all instance position according to simulation x,y
drawInstances()
{
const scale = 0.9;
var xPlayer = this.objRender3D.objMonde.objPlayer.positionX;
var yPlayer = this.objRender3D.objMonde.objPlayer.positionY;
var seuil = 64;
for (let h = 0 ; h < this.geometry.length ; h++) {
let indiceMatrice=0;
for (var i = 0 ; i < this.objRender3D.objMonde.objFaune.tabAnimals.length ; ++i) {
var objAnimal = this.objRender3D.objMonde.objFaune.tabAnimals[i];
var posVegX = objAnimal.positionX;
var posVegY = objAnimal.positionY;
if (
Math.abs( posVegX - xPlayer ) <= seuil &&
Math.abs( posVegY - yPlayer ) <= seuil
)
{
var posX = Math.floor(objAnimal.positionX);
var posY = Math.floor(objAnimal.positionY);
var posZ = this.objRender3D.objMonde.objTerrain.tabTuiles[posX][posY].altitude * 55.0 + 5.0 + ( 0.4* 1);
for (var o = 0 ; o < objAnimal.objModRender.listeOrganes.length ; o++) {
if (objAnimal.objModRender.listeOrganes[o].texture != h)
continue;
for (var j = 0 ; j < objAnimal.objModRender.listeOrganes[o].listeVertices.length ; ++j) {
this.matrix[h].setPosition( posX + scale * objAnimal.objModRender.listeOrganes[o].listeVertices[j].x + objAnimal.objModRender.listeOrganes[o].organX,
posZ + scale * objAnimal.objModRender.listeOrganes[o].listeVertices[j].z + objAnimal.objModRender.listeOrganes[o].organY,
posY + scale * objAnimal.objModRender.listeOrganes[o].listeVertices[j].y + objAnimal.objModRender.listeOrganes[o].organZ
);
this.mesh[h].setMatrixAt( indiceMatrice, this.matrix[h] );
++indiceMatrice;
}
}
}
}
this.mesh[h].count = indiceMatrice;
this.mesh[h].instanceMatrix.needsUpdate = true;
// console.log("Draw H" + h + " = " + indiceMatrice + " points ");
}
}
Thanks for any help & advice !