When developing my game, I encountered a challenge. I'm loading 4 different buildings and creating 15 clones of each within a for
loop. These clones are then added to an array called masterBuildingArray
, which I iterate through using a forEach
loop. The buildings are loaded using the .MTL
and .OBJ
loaders.
Since the buildings are meant for a city environment, I implemented a randomization algorithm to shuffle the order of the buildings in the array. I then used if
statements to arrange every 10 buildings into 3 rows on either side of a central road.
The Challenge I'm Facing
I need the ability to remove specific objects from the array, especially landmark buildings that should be placed in certain positions. For instance, I know the building closest to the camera on the right side has a position of approximately (550, -75, 800)
. Although the X
and Z
positions have slight variations.
The code snippet is included at the end of this question
Possible Solutions
To address this issue, I inserted an index counter into my forEach
loop and assigned it to each building as userData
to facilitate access. My approach was to use a conditional statement within the forEach
loop as follows:
if (highriseBuilding.userData.index == 31) {
initialBuildingName = highriseBuilding.name;
highriseBuilding.name = highriseBuilding.name + "_toBeRemoved";
}
By appending "_toBeRemoved"
to the building name in the desired position, my objective was to remove that object from the scene.
I attempted to remove it using the following code snippet:
scene.remove(scene.getObjectByName(initialBuildingName + "_toBeRemoved"));
However, this approach proved ineffective regardless of where I placed it (inside the initial forEach
loop, in a separate loop that iterated over the masterBuildingArray
after the initial loop, etc.).
See the code below:
Sample code for loading a building:
function createHighrise4() {
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader(loadingManager) );
var mtlLoader = new THREE.MTLLoader(loadingManager);
mtlLoader.setPath( '/objects/highrise4_white_curved/' );
mtlLoader.load( 'highrise4_white_curved.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader(loadingManager);
objLoader.setMaterials( materials );
objLoader.setPath( '/objects/highrise4_white_curved/' );
objLoader.load( 'highrise4_white_curved.obj', function ( highrise4_white_curved ) {
highrise4_white_curved.scale.set(10,10,10);
highrise4_white_curved.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.receiveShadow = true;
child.castShadow = true;
}
} );
for (let i = 0; i < 15; i++) {
clonedHighrise4 = highrise4_white_curved.clone();
clonedHighrise4.name = "highrise4_white_curved";
masterBuildingArray.push(clonedHighrise4);
}
}, onProgress, onError );
});
}
Building placement logic + attempted solution:
function loopThroughBuildingArray() {
randomShuffle(masterBuildingArray);
masterBuildingArray.forEach(function(highriseBuilding, i){
let building_randomYScale = Math.floor(Math.random() * (15 - 10) + 10);
highriseBuilding.userData.index = i;
if (i < 10) {
rowLeft1.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (950 - 850) + 850);
highriseBuilding.position.x = incrementLeft1;
incrementLeft1 -= Math.floor(Math.random() * (800 - 550) + 550);
}
if (i >= 10 && i < 20) {
rowLeft2.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (50 - -50) + -50);
highriseBuilding.position.x = incrementLeft2;
incrementLeft2 -= Math.floor(Math.random() * (800 - 550) + 550);
}
if (i >= 20 && i < 30) {
rowLeft3.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (-950 - -850) + -850);
highriseBuilding.position.x = incrementLeft3;
incrementLeft3 -= Math.floor(Math.random() * (800 - 550) + 550);
}
if (i >= 30 && i < 40) {
rowRight1.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (950 - 850) + 850);
highriseBuilding.position.x = incrementRight1;
incrementRight1 += Math.floor(Math.random() * (800 - 550) + 550);
}
if (i >= 40 && i < 50) {
rowRight2.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (50 - -50) + -50);
highriseBuilding.position.x = incrementRight2;
incrementRight2 += Math.floor(Math.random() * (800 - 550) + 550);
}
if (i >= 50 && i < 60) {
rowRight3.push(highriseBuilding);
highriseBuilding.position.z = Math.floor(Math.random() * (-950 - -850) + -850);
highriseBuilding.position.x = incrementRight3;
incrementRight3 += Math.floor(Math.random() * (800 - 550) + 550);
}
// 31 is building in position: right side, bottom left corner (closest to camera & road on right side)
if (highriseBuilding.userData.index == 31) {
initialBuildingName = highriseBuilding.name;
highriseBuilding.name = highriseBuilding.name + "_toBeRemoved";
}
highriseBuilding.scale.y = building_randomYScale;
highriseBuilding.position.y = -75;
// highriseBuilding.position.y = (highriseBuildingBoundingBox.max.y * highriseBuilding.scale.y) / 2;
cityScape.add(highriseBuilding);
});
cityScape.position.z = -9300;
cityScape.scale.set(0.5, 0.5, 0.5);
scene.add(cityScape);
scene.remove(scene.getObjectByName(initialBuildingName + "_toBeRemoved"));
}
I would greatly appreciate any insights or assistance with this seemingly simple issue that has me stumped!