Reposition group of glbs to position of other group

greetings all!

I have a script that

  1. builds walls on a scene
  2. 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);
}

You can use Box3 to calculate the bounding box, then use getCenter to find the average center of that box - and move the entire group in the opposite direction, so that center is again at 0/0/0.

Hi @mjurczyk

Thanks for the reply!

That’s what I thought I did, but they keep sitting in the same place.

 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 furns = scene.getObjectByName("furnitures");
  // Calculate the bounding box of the group
  const furn = new THREE.Box3().setFromObject(furns);
  // Calculate the center of the bounding box
  const centerf = furn.getCenter(new THREE.Vector3());

  furns.position.set(center.x, center.y, center.z);

grouping all groups into 1, and looking at that position fixed it also.

 const walls = scene.getObjectByName("walls");
  const furnitures = scene.getObjectByName("furnitures");

  const room = new THREE.Group();
  room.add(walls).add(furnitures);

  scene.add(room);

  new THREE.Box3()
    .setFromObject(room)
    .getCenter(room.position)
    .multiplyScalar(-1);

  room.position.y = room.position.y + WALL_HEIGHT / 2;

  // Calculate the bounding box of the group
  const box = new THREE.Box3().setFromObject(room);

  // 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);