greetings all!
I have a script that
- builds walls on a scene
- sets furnitures on a scene
The problem is that my furnitures coordinates are way off from where the walls are.
Now, the walls are grouped in ‘walls’ and the furnitures are grouped in “furniture”,
How can I reset the size and position of the furniture group to match the center of the walls group so that they are inside the room?
thanks for the insights, all!
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import room from "./data.json";
const data = room.floors[0];
let camera, controls, scene, renderer;
const WALL_HEIGHT = 3;
function createLight(x, y, z, intensity = 50, mapSize = 1024) {
var light = new THREE.DirectionalLight(0xffffff, intensity);
light.position.set(x, y, z);
light.castShadow = true;
light.shadow.camera.top = 2;
light.shadow.camera.bottom = -2;
light.shadow.camera.left = -2;
light.shadow.camera.right = 2;
light.shadow.camera.near = 0.5;
light.shadow.camera.far = 7;
light.shadow.mapSize.width = mapSize;
light.shadow.mapSize.height = mapSize;
/* light.shadow.camera.near = 0.5;
light.shadow.camera.far = 25;
light.shadow.camera.left = -10;
light.shadow.camera.right = 10;
light.shadow.camera.top = 10;
light.shadow.camera.bottom = -10;*/
light.shadow.radius = 25;
light.shadow.blurSamples = 25;
scene.add(new THREE.DirectionalLightHelper(light, 2, 0xff0000));
return light;
}
// Function to create a wall
function createWall(x1, y1, x2, y2, height) {
const length = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
const geometry = new THREE.PlaneGeometry(length, height);
const material = new THREE.MeshStandardMaterial({
color: "#FFFFFF",
roughness: 0,
metalness: 0,
});
const wall = new THREE.Mesh(geometry, material);
wall.castShadow = true;
wall.receiveShadow = true;
const centerX = (x1 + x2) / 2;
const centerY = (y1 + y2) / 2;
const angle = Math.atan2(y2 - y1, x2 - x1);
// Correcting the position and rotation for standing up walls
wall.position.set(centerX, height / 2, centerY); // Adjust Y for height / 2 to elevate it
wall.rotation.set(0, -angle, 0); // Rotate around Y-axis to align properly
return wall;
}
function addFurniture() {
const manager = new THREE.LoadingManager();
const furnitures = new THREE.Group();
furnitures.name = "furnitures";
const loader = new GLTFLoader(manager);
manager.onLoad = function () {
console.log("Loading complete!");
position();
};
data.furnitureArray.forEach((furniture) => {
// Load a glTF resource
loader.load(
// resource URL
"/glbs/GLB_testscene_meubelset_high.glb",
// called when the resource is loaded
function (gltf) {
var object = gltf.scene;
object.receiveShadow = true;
object.castShadow = true;
object.traverse((n) => {
n.castShadow = true;
n.receiveShadow = true;
if (n.isMesh) {
n.geometry.computeVertexNormals();
if (n.material.map)
n.material.map.anisotropy =
renderer.capabilities.getMaxAnisotropy();
}
});
object.position.set(furniture.x / 100, 0, furniture.y / 100);
object.rotation.set(0, furniture.rotation, 0);
object.updateMatrixWorld(true);
furnitures.add(object);
}
);
});
scene.add(furnitures);
}
function position() {
const walls = scene.getObjectByName("walls");
new THREE.Box3()
.setFromObject(walls)
.getCenter(walls.position)
.multiplyScalar(-1);
walls.position.y = walls.position.y + WALL_HEIGHT / 2;
// Calculate the bounding box of the group
const box = new THREE.Box3().setFromObject(walls);
// Calculate the center of the bounding box
const center = box.getCenter(new THREE.Vector3());
// Adjust camera position to ensure the group is in view
// This example moves the camera back along the z-axis and up slightly
camera.position.set(center.x, center.y + 5, center.z + 10);
// Use OrbitControls to target the center of the group
controls.target.set(center.x, center.y, center.z);
// Update the camera to look at the center of the group
camera.lookAt(center.x, center.y, center.z);
const furnitures = scene.getObjectByName("furnitures");
furnitures.position.set(center.x, center.y, center.z);
}
init();
addFurniture();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xcccccc);
//default, done
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
//done, default
renderer.toneMapping = THREE.ACESFilmicToneMapping;
//done
renderer.toneMappingExposure = 0.8;
//done
renderer.shadowMap.enabled = true;
//done
renderer.shadowMap.type = THREE.VSMShadowMap;
// ND
renderer.gammaFactor = 2.2;
//done, default
//renderer.outputColorSpace = THREE.sRGBEncoding;
renderer.powerPreference = "high-performance";
renderer.physicallyCorrectLights = true;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const size = 10;
const divisions = 5;
const gridHelper = new THREE.GridHelper(size, divisions);
scene.add(gridHelper);
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.set(1, 1, 7);
// controls
controls = new OrbitControls(camera, renderer.domElement);
controls.listenToKeyEvents(window); // optional
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 500;
const pmremGenerator = new THREE.PMREMGenerator(renderer);
const hdriLoader = new RGBELoader();
hdriLoader.load("/test_HDRI.hdr", function (texture) {
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
texture.dispose();
scene.environment = envMap;
});
// lights
const HemisphereLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
scene.add(HemisphereLight);
const spotLight = new THREE.SpotLight(0xffffff, 100);
spotLight.position.set(0, 10, 0);
spotLight.rotation.y = 20;
spotLight.angle = Math.PI / 6;
spotLight.penumbra = 1;
spotLight.distance = 10;
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 10;
spotLight.shadow.focus = 1;
scene.add(spotLight);
const lightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(lightHelper);
// Create and add walls based on your coordinates
const wallNodes = data.wallNodes;
const wallNodeLinks = data.wallNodeLinks;
const group = new THREE.Group();
group.name = "walls";
for (let i = 0; i < wallNodeLinks.length - 1; i++) {
const startNode = wallNodes.filter(
(item) => item.id === wallNodeLinks[i][0]
)[0];
for (let j = 0; j < wallNodeLinks[i][1].length; j++) {
const endNode = wallNodes.filter(
(item) => item.id === wallNodeLinks[i][1][j]
)[0];
const wall = createWall(
startNode.x / 100,
startNode.y / 100,
endNode.x / 100,
endNode.y / 100,
WALL_HEIGHT
);
group.add(wall);
}
}
scene.add(group);
scene.add(createLight(WALL_HEIGHT, WALL_HEIGHT, -WALL_HEIGHT, 20));
scene.add(createLight(-WALL_HEIGHT, WALL_HEIGHT, -WALL_HEIGHT, 20));
scene.add(createLight(WALL_HEIGHT, WALL_HEIGHT, WALL_HEIGHT, 20));
scene.add(createLight(-WALL_HEIGHT, WALL_HEIGHT, WALL_HEIGHT, 20));
window.addEventListener("resize", onWindowResize);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
render();
}
function render() {
renderer.render(scene, camera);
}