Orbit controls zooming limits

I am using Orbit controls and they have a weird limit. Zooming depends on the radius of the spherical coordinates of the camera relative to the orbiting axis, and, of course, you have a limit when zooming in because the radius can only get so little, but the problem is if you zoom close to the orbiting axis, then rotate the camera and look down (or up) you can’t zoom into that direction because of the radius… So, my question is, how can I achieve that behavior (zooming up or down when radius is at its limit) using Orbit controls.

No code? No explanatory pictures or video?

I don’t think adding code makes sense since it’s more a conceptual question about zooming in OrbitControls. But to be honest, I’m not quite sure I understand it. In context of perspective cameras, the amount of dollying is limited by the properties controls.minDistance and controls.maxDistance.

Orbiting does not have influence on how far you can dolly in/out. Besides, the camera always focuses the target vector defined via controls.target. I don’t understand what you mean with “can’t zoom into that direction because of the radius”. Can you please explain this sentence in more detail?

Crossposting:

You’re going to have to post some code or some screen shots to explain this. Please note that there are two concepts that can be considered “zooming” one is “dollying” and actual zoom. Dollying means that you are moving the camera forwards and backwards, zooming means that you are changing the field of view. I’m not entirely sure but i think you’re dollying when you use orbit camera, hence the limit, you can only get so close to a subject. With zooming, youd reduce the field of view, so you could “zoom” even further once you’re at the limit.

To clarify things:

OrbitControls implemented “zooming” for perspective camerad by dollying. When using an orthographic camera, “zooming” is implemented by changing the zoom level of the camera since dollying doesn’t have any visual effect in this case.

There is a possibility that naming of things in the OrbitControls example is misleading.

To zoom

OrbitControls - to dolly
Real world camera - adjust the lens to make the Field Of View narrower or wider

To dolly

OrbitControls - to zoom
Real world camera - usually someone moves the camera, or an actual “dolly” is used:

What’s really interesting is that internally, the OrbitControls class uses the term “dolly” to correctly describe the code and math that handles the dollying.

It’s the high level interface that suddenly changes the terminology and uses “zoom”.

Although it does get mapped in the “dolly” function, into dollying:

If you look at the variable zoomSpeed as dollySpeed this would feel more like Maya or 3d studio max.

As with anything in three.js examples, OrbitControls is just an example, and you can hack it to fit your needs. If you want to implement zooming on top of dollying, it would probably make sense to rename all the zoom variables into dolly.

Hello! Thanks for answering so thoroughly! Let me share a video I recorded with my problem so I can explain myself a bit better, here’s the youtube link

Text on the video:

I can’t keep on moving the camera on the lookingAt direction,
because the mousewheel event depends on the spherical.radius
Now that’s so close to 0 it won’t allow me to dolly in anymore,
this is what I meant when I wrote “can’t zoom in in any direction”.

Oh ok, you might need to adjust your center for the effect that you want. You won’t be able to “zoom into” the building (aka dolly into it) if you are already the closest you can be to the center. You could zoom in and see just the roof on your screen (and not the ground and stuff). At my work we modified the controls to handle pan a bit differently, by offseting the camera related to the center, not moving the center with it if that makes sense.

When you start panning up (towards the sky) you bring the center with you, so when you try to dolly in, you’re already as close as you can be to this point in the sky. You won’t get what you need out of the box in either way.

Exactly! That was sort of my question, how to keep on dollying in in the world space regardless of how close you are to the center (the controls.target). I agree that I gotta modify the controls, thou I don’t think changing the panning process would help me because: I want to always orbit around an axis that’s in front of the camera, otherwise is rather awkward, and if I reach the center the spherical radius should be able to grow in the other direction, I could change the line

spherical.radius *= scale;

to

const newRadius = spherical.radius + scale;
spherical.radius = Math.abs(newRadius);

scale would then be positive or negative depending on the user’s scroll and this would also maintain a constant dolly speed. Now, if newRadius < 0, I would have to change the polar and the azimuthal angle to their inverse. For example, if I’m dollying from the Y axis down to the center, both phi and teta = 90, but if I reach the center and keep going their new value would be -90 so I’m looking up to the center instead of down to it, and if newRadius= 0, they both equal 0 too of course.

I’m just thinking out loud here, I’ll try some tests and post results, and if anyone knows how to accomplish what I intent, please let me know :slight_smile: Thanks for the help!

You definitely need something more complex than OrbitControls but it can be built on top of it. You could have a raycaster for example, shooting from the center of the camera and always use that as your orbit controls center.

If it for example adjusts to the roof, you could add a distance check, once you dolly too close to the roof, take the next hit target (floor) and use that.

Don’t worry about the question being confusing, i’m glad that didn’t demoralize you. I think it’s not the way you asked but the nomenclature in this example file.

1 Like

This is not true.Dollying with an orthographic camera can have visual effect if you clip geometry.

1 Like

oh thanks!! I solved it adding a couple of lines :smiley: (in the this.update function)

To get the vector where the camera is looking at

 var cameraWorldDir = new THREE.Vector3();

Kept this

spherical.radius *= scale;

get that lookingAt vector

scope.object.getWorldDirection(cameraWorldDir);

Magic:

if (spherical.radius <= 2) {
    scope.target.add(cameraWorldDir.multiplyScalar(0.4));
}

So, if I ever get close enough to the center, I just move the target (orbiting center) along the lookAt vector, aka I push it back.

Thank you for bearing with me and for the help!

3 Likes

You’re welcome, glad to have helped!

1 Like