three.js - 360 degree rotation using orbit controls in threejs? - Stack Overflow

admin2025-04-27  3

I am building a panoramic viewer that combines a 3D model and panorama images. The viewer features hotspots within the 3D model, and when a user clicks a hotspot, the view switches from the 3D model to a 360-degree panorama view at the hotspot’s position. For reference, imagine standing on a tower and rotating in place to look around in 360 degrees.

Here’s the workflow: The user clicks a hotspot. The camera moves to the hotspot's position in the 3D model. The view switches to a spherical panorama view where the user can freely rotate the camera in 360 degrees.

I currently have a working solution for a Y-UP model, but it breaks when the model is Z-UP. I want to make the solution generic so it works with any model orientation (Y-UP, Z-UP, or others

Problem: To achieve spherical movement, I use the following logic in my code (simplified):

Get the current camera direction.
Calculate the point the camera is looking at.
Set that point as the controls' target for the spherical view.

Here’s the code for switching to the spherical view:

function switchToSphericalView() {
  const direction = new THREE.Vector3();
  camera.getWorldDirection(direction);
  const lookAtPoint = camera.position.clone().add(direction);
  controls.enableZoom = false;
  controls.pan = false;
  controls.target = lookAtPoint;
  controls.update();
  return;
}

This works perfectly for a Y-UP model, as seen in this live demo: Live Demo: Y-UP Model

However, when I load a Z-UP model, the spherical view does not work correctly. To address this, I calculate an outward vector from the center of the model to orient the camera correctly. Despite this attempt, the spherical view still doesn’t behave the same as with a Y-UP model.

Here’s the live demo for the Z-UP model: Live Demo: Z-UP Model

Key Steps to Reproduce: Load the model and hotspot (preloaded in both demos). Press M to move the camera to the hotspot. Press S to switch to spherical view. Rotate the camera to observe the issue (Z-UP model behaves incorrectly).

Question:

How can I modify my camera orientation logic to make the spherical view work generically for models with any orientation (Y-UP, Z-UP, or others)?

I suspect the issue is related to how the lookAt or target is being calculated relative to the model’s local axis. If you need further clarification or explanation, feel free to ask. Any suggestions, best practices, or alternative approaches would be highly appreciated!

I am building a panoramic viewer that combines a 3D model and panorama images. The viewer features hotspots within the 3D model, and when a user clicks a hotspot, the view switches from the 3D model to a 360-degree panorama view at the hotspot’s position. For reference, imagine standing on a tower and rotating in place to look around in 360 degrees.

Here’s the workflow: The user clicks a hotspot. The camera moves to the hotspot's position in the 3D model. The view switches to a spherical panorama view where the user can freely rotate the camera in 360 degrees.

I currently have a working solution for a Y-UP model, but it breaks when the model is Z-UP. I want to make the solution generic so it works with any model orientation (Y-UP, Z-UP, or others

Problem: To achieve spherical movement, I use the following logic in my code (simplified):

Get the current camera direction.
Calculate the point the camera is looking at.
Set that point as the controls' target for the spherical view.

Here’s the code for switching to the spherical view:

function switchToSphericalView() {
  const direction = new THREE.Vector3();
  camera.getWorldDirection(direction);
  const lookAtPoint = camera.position.clone().add(direction);
  controls.enableZoom = false;
  controls.pan = false;
  controls.target = lookAtPoint;
  controls.update();
  return;
}

This works perfectly for a Y-UP model, as seen in this live demo: Live Demo: Y-UP Model

However, when I load a Z-UP model, the spherical view does not work correctly. To address this, I calculate an outward vector from the center of the model to orient the camera correctly. Despite this attempt, the spherical view still doesn’t behave the same as with a Y-UP model.

Here’s the live demo for the Z-UP model: Live Demo: Z-UP Model

Key Steps to Reproduce: Load the model and hotspot (preloaded in both demos). Press M to move the camera to the hotspot. Press S to switch to spherical view. Rotate the camera to observe the issue (Z-UP model behaves incorrectly).

Question:

How can I modify my camera orientation logic to make the spherical view work generically for models with any orientation (Y-UP, Z-UP, or others)?

I suspect the issue is related to how the lookAt or target is being calculated relative to the model’s local axis. If you need further clarification or explanation, feel free to ask. Any suggestions, best practices, or alternative approaches would be highly appreciated!

Share Improve this question asked Jan 11 at 14:16 Yashwant RautYashwant Raut 391 silver badge16 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1 +50

I read source code of OrbitControls (source v0.170.0) to find how to do it and found an answer:

1.

OrbitControls already suport any camera.up vector and will work correctly with it, but only if camera.up vector was changed before you call OrbitControls constructor like:

const camera = new THREE.PerspectiveCamera(...);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer(...);

camera.up.set(0,0,1)
const controls = new OrbitControls(camera, renderer.domElement);

this will change behaviour for OrbitControls to rotate arround vector (0, 0, 1)

2.

but it don't support (just don't have method to do this) changing camera.up after OrbitControls was created so you need to update controls._quat manually and here I add method to this class to do it:

OrbitControls.prototype.upVectorChanged = function() {
    this._quat = new THREE.Quaternion().setFromUnitVectors( this.object.up, new THREE.Vector3(0,1,0) );
    this._quatInverse = this._quat.clone().invert();
}

now you can call .upVectorChanged() for any instance of OrbitControls like:

camera.up.set(0,0,1)
controls.upVectorChanged()
controls.update()

and adding this code in the end of your live demo for the Z-UP model works

How can I modify my camera orientation logic to make the spherical view work generically for models with any orientation (Y-UP, Z-UP, or others)?

Your problem is of a slightly different nature...

Whether you write a function that will contain separate logic for a model with a coordinate system (x, y or z) doesn't really matter. Because you can't check what coordinates a given model has, I'm talking about the Three.js level, I mean something like automating the checkability condition.

I assume that you or a potential user, if you give them the ability to upload a model, don't want to worry about transformations, originally exported from the software. But that's not how it works.

Whether a model has an x ​​or z coordinate system depends on how you export it from, for example, Blender. That's why Blender gives you the option to uncheck transformations in the export options. Three.js doesn't have built-in methods for checking the coordinate system, the only thing you can do is examine the model or observe how it behaves when you manipulate it, or dig into the metadata. But that doesn't seem to be what you mean...

If you'd like to try to invert the coordinates or change them from the default ones, you might want to take a look at this thread. But again, that doesn't seem to be what you mean.

转载请注明原文地址:http://anycun.com/QandA/1745708660a91123.html