Search code examples
three.js3dcameralinear-algebramatrix-multiplication

How do you move a camera directly above an object in 3D space?


I am learning ThreeJS and trying to understand some fundamental concepts.

Suppose I have a camera in 3D space, looking at some target (defined in the camera.target property). The camera is located at x1, y1, z1.

I want to add a feature that when activated, moves the camera directly above the target, i.e. it should be looking down at the XY plane, as though the camera is in the sky looking STRAIGHT down.

My question is, how do I do this in ThreeJS, and also how do you think of this conceptually/mathematically?

camera-3d


Solution

  • While your question seems simple, here is a nuanced take with some tips that you might find helpful.

    Position

    Yes, the simplest answer is to assign the camera's position where the z value is the distance from the target.

    camera.position.set( 0, 0, distance )
    

    But this only works if the target is positioned at the origin. What if you target is at position ( 10, 20, 30 )?

    You can use vector math to fix this, and three has this baked in for you.

    1. Create a Vector3 with the position assigned as if the target was at the origin.
    let offset = new THREE.Vector3( 0, 0, distance )
    
    1. Add this vector to the target's position, and assign it to the camera's position.
    camera.position.addVectors( target.position, offset )
    
    1. The camera is now positioned above the target.

    Rotation

    In either case, simply repositioning you camera may not be enough to keep your target in view. After moving your camera, you will need to force it to look at the target.

    camera.lookAt( target.position )
    

    Now, lookAt is a fairly simple function, and may not result in the camera roll that you expect. You will need to figure out how best to compensate for this, by adjusting its up, quaternion, or other factors. (Compensating for this is outside the scope of this question.)

    Global vs. Local

    Another nuance is whether you want the camera to be "above" the part in a global sense, or in a local sense.

    If your camera and target exist in a global space (directly in your scene), then the directions above will suit your use-case.

    But if your target is rotated on its side within the global space (i.e. its +z axis points along the global +x axis), yet you want the camera's new orientation to be "above" the target in the sense that it is looking down the target's -z axis, then you will need to compensate for the target's rotation as well. Luckily, three also provides math functions that can accomplish this.

    camera.position.copy( offset )
    camera.position.applyMatrix4( target.matrixWorld )
    

    This first line sets the camera's position to that of the "target at the origin" position. The second line updates that vector using the target's world transformation matrix, effectively translating it into the target's space.

    Animation

    Reading between the lines, it sounds like you might want to animate this process. There are a variety of animation libraries available, and you'll need to find one that suits your needs and purpose. That said, there are also many questions about animation on Stack Overflow, and I'm sure you can find someone to answer your questions on that topic, should you hit any resistance.