Control for turning camera? (fixed axis and pivot point)

Hi, I’m searching for a control that allows me to spin the camera around like standing on a tower and having a 360 degree view while you (the camera) is turning around. The camera pivot point is fixed.

Following features need to be fulfilled:

  • mouse and touch controls on mobile devices (like OrbitControls)
  • damping activated
  • fixed to y-axis
  • no zoom needed

Is it possible to configure one of the existing cameras to make this happen? I want to avoid building a new custom control if possible.

Thanks in advance!
Best, Jan

Bildschirmfoto 2022-05-02 um 10.58.37

How about introducing two cameras like this:

1st camera is controlled via OrbitControls as-is.
2nd camera uses 1st camera’s position as target and 1st camera’s taget as position.

Then render what the 2nd camera sees.

P.S.: locking to y-axis can be achieved via max/minPolarAngle = Math.PI / 2.

Hi, thanks for the super quick response! While I was trying out your proposal I came up with a sandbox like that: MapControls Events (forked) - CodeSandbox

This is just a super simple OrbitControl with the default canvas camera and it spins around very nicely.
But honestly I have no idea why it does that. Shouldn’t this control always “orbit” around something?

To my knowledge, a camera controlled through OrbitControls can orbit around the controls.target (a 3D point), based on a mouse click&drag action. Without your mouse input, nothing happens or moves. Give me a little time and I will present a JSFiddle which demonstrates my point.

To be continued …

1 Like

Have you seen my CodeSandbox above? This does exactly what I wanted it to do :slight_smile: You can simply spin around by dragging the mouse.

I was just confused because most other OrbitControl examples do something like that: Orbit Controls Demo

Anyways, the way it works on the Sandbox is perfect for me!

Thanks for alerting me, but since I had already started the implementation, (which turned out to be a little more involved than I had expected) I didn’t want to throw it away.

I saw your code sandbox, but couldn’t detect a “spin around”. For me it appeared as a mere “pan”.

Anyway, here is my interpretation of your initial request:

Initially you see a 3rd-person view from an external, fixed-position camera.

I’m showing both orbiting and pivoting cameras by means of a CameraHelper, whose representation on screen scales with the far plane of the camera frustum. That’s why I had to restrict the far reach of each camera, so their respective CameraHelpers wouldn’t visually intersect.

The orbiting camera is shown close to the ground, while I elevated the pivoting camera by a small amount. See how they’re always facing each other when you click&drag.

By activating ONE of the three statements in the render() function, you get to see what each of the cameras sees.

/************ Activate ONLY ONE of the following:  ************/
		
//	renderer.render( scene, orbitCamera );
//	renderer.render( scene, pivotCamera );
	renderer.render( scene, observerCamera );

Better off writing a function that rotates camera based on direction of mouse movement instead of using OrbitControls.

But, if you’d like to use OrbitControls, here is a demo: Ray_Muti.html (7.3 KB)

To activate keyboard commands make the mouse is over the canvas and has focus.

  • Press 1 key to switch to 360 mode.
  • Press 0 key to revert.

These are the thread starter’s requirements:

Following features need to be fulfilled:

mouse and touch controls on mobile devices (like OrbitControls)
damping activated
fixed to y-axis
no zoom needed

And OrbitControls has all of that right out of the box.

Thanks for your offer, but I supplied my own demo in the JSFiddle already. :stuck_out_tongue:

Wow, this feedback is overwhelming! Thanks for those detailed examples!!! I need to closely study them!

Seems we have 3 completely different approaches that are doing more or less the same thing. I also added a gridHelper to my demo, maybe that makes it even clearer that it is nicely spinning around with close to zero code effort: OrbitControl spinning 360 view - CodeSandbox

As Christophs answer was first, maybe you could put all 3 possible ways (link to your fiddle, my sandbox and the html file) into a single reply, so I can set the “Solution” flag that future visitors see all solutions at once.

Thanks guys for your support!!!

I have to correct myself. My solution is not correct. It spins around a center point and because the outer boxes are away far enough it looks like the camera is spinning around.

But the camera is orbitting around the center what is not the desired solution.

1 Like

camera.rotation.y = ???

As long as you are not using “LookAt” (which overrides everything), you should be able to freely rotate the camera in any direction you like - along the x, y and/or z axes.

I have written several posts on the subject of moving and rotating your camera.

Using OrbitControls and setting the target position to be 1 cm in front of the camera, limiting polar rotation to the angle you need, should do the trick.
I’m using this for years, lastly I combined OrbitControls (rotate & panning) + TrackballControls (zoom) to have damping also on zoom (not available with OrbitControls).

1 Like

That’s an incredibly cool and effortless variant and I’d be willing to pass you the solution credit if I knew how to do that!

Setting target position is simple: controls.target.set(x,y,z)

And to get target position knowing the camera (just remove typing for simple js):

const calculateTarget = (camera: PerspectiveCamera, distance = 0.01): Vector3 =>
  (new Vector3()).addVectors(
    camera.getWorldPosition(new Vector3()),
    camera.getWorldDirection(new Vector3()).multiplyScalar(distance)
  );

Hey all,

I played around with OrbitControls for a while now and it just seems to be overkill for just spinning a camera around.

My second approach was now to simply place a camera in the center and use the @use-gesture library (https://use-gesture.netlify.app) to add the incoming delta.x movements (from mouse or touch) to the rotation property of the camera. With some simple adjustments this works very well but looks extremely static, because (of course) there is no damping.

Next step was to calculate the damping all by hand and I just didn’t manage to get it really smooth like all those libraries make it.

Now I thought it would be better to add the “react-spring” library (https://react-spring.io/) and let this tool handle the rotation calculations including the damping factor… but even though this should work somehow I don’t get it to work with THREE :frowning:

Here is a very reduced demo of the scene: Camera Rotation with useDrag and useSpring - CodeSandbox

Currently nothing happens there because “spring” seems to output not the rotation prop that the camera would need and I have no idea how to get it working.

Any ideas on that?

OK, I already thought there is only a simple piece missing. It was as simple as wrapping the “PerspectiveCamera” into “animated” from “react-spring”… The rest should only be fine-tuning.

I just updated the sandbox: Camera Rotation with useDrag and useSpring - CodeSandbox

And all this with only a few lines of code :slight_smile:

Thanks guys for your fantastic feedback!!!