Resetting objModel position after user interaction in Three.js

Hello!

I am facing a challenge with user interactions and model positioning in my Three.js application, and I am seeking your guidance to resolve this issue.

Here is the scenario:

  1. I load a obj model into the scene, and it renders perfectly at the center of the screen with an appropriate size.
  2. The user can interact with the model, including repositioning it using a mouse right-click drag.
  3. After the user repositions the model, if they select a different model or reload the current model, the new or reloaded model appears at the last position set by the user, instead of being reset to the original central position.

What I want to achieve is to have the model always load or reload at its initial position, regardless of any previous user interactions. I want the model to appear at the center of the screen with the appropriate size every time it is loaded or reloaded.

I have tried resetting the camera position to its initial state, and while this works for the camera, it does not affect the position of the model.

Here is a snippet of my code for loading the OBJ model:

// Change ObjModel
const selectWork = (_work: Work) => {
  worksStore.selectWork(_work);
  meshChecked = false;
  checkedQuestions = [];

  resetCameraToInitialState();
  removeAllObjectsFromScene();
};

function resetCameraToInitialState() {
  camera.position.copy(initialCameraState.position);
  camera.rotation.copy(initialCameraState.rotation);
  camera.zoom = initialCameraState.zoom;
  camera.position.z = 70;
  camera.updateProjectionMatrix();
}

function removeAllObjectsFromScene() {
  const objectsToRemove = [...scene.children];
  for (const object of objectsToRemove) {
    scene.remove(object);
  }

  const ambientLight: THREE.AmbientLight = new THREE.AmbientLight(0x404040);
  scene.add(ambientLight);
  const directionalLight: THREE.DirectionalLight = new THREE.DirectionalLight(
    0xffffff,
    0.5
  );
  directionalLight.position.set(0, 1, 1);
  scene.add(directionalLight);
}

// render Obj model
function loadObj(scene: THREE.Scene): void {
  const objLoader: OBJLoader = new OBJLoader();

  objLoader.load($mesh_url, (object: THREE.Object3D) => {
    object.traverse((e) => e.isMesh && (e.material.side = THREE));

    const box: THREE.Box3 = new THREE.Box3().setFromObject(object);
    const size = box.getSize(new THREE.Vector3());
    const center = box.getCenter(new THREE.Vector3());

    object.position.x += object.position.x - center.x;
    object.position.y += object.position.y - center.y;
    object.position.z += object.position.z - center.z;

    const maxDim = Math.max(size.x, size.y, size.z);
    const fov = camera.fov * (Math.PI / 180);
    let cameraZ = Math.abs((maxDim / 2) * Math.tan(fov * 2));
    cameraZ *= 1.1;
    const minZ = box.min.z;
    const cameraToFarEdge = minZ < 0 ? -minZ + cameraZ : cameraZ - minZ;

    const far = camera.position.z + cameraToFarEdge * 3;
    camera.far = far;
    camera.updateProjectionMatrix();

    scene.add(object);
    updateCameraAndRenderer();
  });
}


Could you please provide guidance on how to reset the model’s position after user interactions, so that it always appears at its initial central position when loaded or reloaded?

Thank you in advance for your help!

When utilizing the OrbitControls in Three.js for camera manipulation, invoking the controls.reset(); function resets the camera to its initial state. This initial state is determined by the camera’s position and rotation at the moment when OrbitControls is instantiated. In other words, the state of the camera right after the creation of OrbitControls is considered the “initial state.”

However, an issue arises when new models are loaded into the scene, and controls.reset(); is called thereafter. The camera reverts back to this “initial state,” which may not be optimal for viewing the newly loaded model. For example, the camera might only be focused on the head portion of the model, not giving a proper view of the entire object.

To resolve this issue, a two-fold approach was taken:

  1. Adjusting the Camera’s Initial State: Before loading the new model, we programmatically adjusted the camera’s position and rotation to ensure that it would be in a suitable state to view the model once loaded. This way, when controls.reset(); is called, it brings the camera back to this well-adjusted state rather than an arbitrary starting position.
  2. Re-calculating the Camera’s Position After Model Load: After the new model is loaded into the scene, we re-calculate the camera’s position based on the dimensions and position of the new model. This ensures that when the user interacts with the model using the mouse controls, and subsequently when controls.reset(); is invoked, the camera maintains a proper viewing angle and distance relative to the model.

By implementing this approach, we ensure a seamless user experience, as the camera consistently provides an optimal view of the models, regardless of their size or position within the scene, and retains this view even after the camera is reset.