Three.js camera on path

yes, cameraTargetlook does already lookAt(lookTarget.position) so it’s rotation is already defined in the updateCamera loop, you can easily do this though by changine the position of lookTarget left and right, does that make sense?

@Lighty i mean so it looks at the translated position of lookTarget

my task is to turn the object itself, from the fact that I change the camera a little, this will not affect the rotation of the object itself.

I mean that my object - the model is loaded like this.

solved the problem by turning the model itself in a blender, but it’s still interesting if there is a solution to this.

i made something like this once, camera movement along a path and the object’s somewhat turning: the math is in the “useFrame” bits, that’s the frameloop.


@Lighty yes there’s actually a simple way after some reading using rotateOnAxis after lookAt… i’ve updated the pen here…

safe x

Thank you!!!

1 Like

@Lighty pleasure.

I just saw this on the weekly summary.

You can’t rotate the camera on the Z-axis. But you can rotate the world around the camera. This allows you use an “in cockpit” view.

Here are a couple of examples:
Flight Display
Flight Simulation

As the last example illustrates, three.js can handle some pretty complex modeling at 60fps. So you are not limited to a wireframe world.

@phil_crowther, not sure what you mean by

i didn’t know that, can you explain a bit more what you mean?

would this not allow you to do so…?

var z_axis = new THREE.Vector3( 0, 0, 1 );

camera.up.applyQuaternion(quaternion.setFromAxisAngle(z_axis, angle));

1 Like

What I meant was that you can you can’t currently rotate a scene on the Z-axis using the camera. There is no camera.rotation.z.

The kind of scene I had in mind begins with a standard skybox, created as follows:
envMap = new THREE.CubeTextureLoader()
.load([“px.jpg”, “nx.jpg”, “py.jpg”, “ny.jpg”, “pz.jpg”, “nz.jpg”]);
scene.background = envMap;

You then populate this 3D space with objects.

You can use the camera to look at the scene you have created by changing the camera position and rotation. You can rotate the camera on the x-axis to look up or down (camera.rotation.x). And you can rotate the camera on the y-axis to look left or right (camera.rotation.y). But you can’t rotate the camera on the z-axis so that the horizon is banked. There is no camera.rotation.z. The horizon is always level. (You can go upside down 180 degrees, but the horizon will still be level.)

In your example, it looks like you want to create something like a roller coaster simulation where the coaster is banking a lot. If you were to eventually put that coaster track in a standard skybox environment and were to attach a camera to your vehicle, you would be able to follow the movement of the vehicle up and down and left and right. But you would not be able to get the camera to bank with the vehicle. The camera (and horizon) would always remain level - as if on a gimbal.

At present, it appears that you are not having this problem because (I believe) you are effectively rotating the world (the track) around the camera. If you want to add a skybox (which I assume you will), you will have to use something like the custom version that I created which rotates around you. If you want to use a directional light source (like the sun), you will need to move the light around you. And if you create external objects (like a ground map or terrain), you will have to move and rotate those objects around you.

My two demo programs should provide you with an example of how those things can be done. Feel free to extract what you want from them. Everything is in subroutines, so that should be relatively easy.


then why if i do

camera.rotation.z = 0.5; 

does the camera rotate on z?

maybe i’m not getting something but i’ve made an example here…

1 Like

and an example with env map…

camera.rotation.z = 0;

camera.rotation.z = 0.5;

am i missing something you mean?

1 Like

Very interesting!

I tried inserting camera.rotation.z into one of my programs and it still didn’t work - until I removed the command: camera.lookAt(scene.position).

That is a very handy command that I have been using forever and that you can use to make the camera look at the center of the scene or at an object. Apparently that command overrides camera.rotation.z. So my previous advice may only apply if you want to use that particular command.

If will see if I can avoid that limitation by putting the object in the center of the scene and switching to camera.lookAt(object).

EDIT: I tried camera.lookAt(0,0,0) and it also prevented Z-rotation. So it looks like I will have to find/create an alternative function which serves the same purpose.


1 Like

@phil_crowther Ahh yes I get you now, would a way round that be to attach a child to the camera that looks at the scene position and set the camera x and y rotation to the rotation of said child so you still have explicit control over camera.rotation.z?

Let me take a look at your example and see what happens if I add a Skybox. I don’t want to lead you (or me) down the wrong path.

One other factor that will come into play is whether you want to look left or right as you are moving along. This will affect the amount of camera.rotation.z. For example, if you are moving straight and bank your vehicle while looking right or left, there will be no z rotation, only x rotation (up/down).

My program handles that. But I am curious if the method that you are using will turn out to be better and faster.

1 Like

Okay, I added a simple Skybox to the scene. It looks pretty neat.

However, it appears that there is no camera z rotation. (It’s kind of hard to tell because the program does all the banking when looking up or down, not at the horizon.)

I am guessing that the reason is that the program includes a variation of the “dreaded” “lookAt” command which cancels out any camera z rotation. Or it could be that you are using OrbitControls which - in the examples I have seen - do not provide for camera z rotation.

So this particular example looks okay without camera z rotation - because of the path you are following. However, if you if you want camera z rotation, it appears that you have to either:

  1. Use the method I described in my first message; or
  2. Find a substitute for the “lookAt” command.

This looks like an interesting project, so I encourage you to keep working on it.


As I took one last look at the string, I realized that this is not your project - that, like me, you were merely trying to help. So I would be interested in hearing whether you agree with my conclusions.

As I was considering whether to revise what I have done, I realized that even if I figure out how to rotate the camera on the z-axis, I am going to have to find a way to prevent it from rotating my object, e.g. the cockpit. That’s one nice thing about the method I developed - the cockpit does not move. Only the external objects move. So I don’t have to undo any rotation.

1 Like


Yes I agree and i do see the conundrum now i realise you meant…


in conjunction with


i keep thinking there must be a simple way round the issue, i made an example this morning to get your feedback, thoughts and likely find the holes in an approach like this…

i’ve set up 2 cameras, one is a ghost used to lookAt(mesh); and the main has camera.rotation.x and y to update to the ghost camera’s x and y rotation, this means we can rotate the z axis as we want on the main camera which would be the z axis copied from a banking fuselage in the case mentioned…

let me know what you think i’m probably being really silly and missing something quite important as you seem to have been through this and found a viable and solid solution.


1 Like

I actually didn’t realize (or had forgotten) that lookAt was preventing camera.rotate.z from working. So this has been helpful.

And I do have some situations where my solution does not work. For example, I have some aircraft that have reflective surfaces. My solution does not handle reflections - which I believe requires multiple cameras.

So I am definitely interested in a solution, like the one you are suggesting, that would allow me to use the default Skybox. I will take a look at it since it seems to do a good job of “looking at” the object.

1 Like

yeah it might need a bit of fixing up and figuring out with long term logic…

i guess the ghost camera would lookAt(things) and translate xyz transforms and rotation x and y axis to the main camera?

for example have the main camera.position set to the ghost camera.position.x y and z and the main camera.rotation x and y set to that of the ghost camera?

then if you put conventional orbit controls in the scene, you can assign them to the ghost camera so that main camera follows suit an it’s camera.rotation.z is always free to assign to?

if you also needed the camera to then follow a moving target you would simply have the ghost cameras position follow the target meaning the main camera would in turn follow the ghost camera?

does it make sense or can you see bugs in this approach?

1 Like