简体   繁体   中英

Rotate camera relative to a point

I need to rotate the camera around a player from a third person view. (Nothing fancy).

Here it is how I try it:

// Forward, right, and position define the plane - they have x,y,z components.

void rotate ( float angle, Vector interestPoint )
{
    Vector oldForward ( Forward );

    forward = forward * cos(angle) + right * sin(angle);    
    forward.Normalize();

    right = forward.CrossProduct ( up );
    right.Normalize();

    position = ( position + old_forward * position.Distance( interestPoint ) ) - (forward * position.Distance( interestPoint ) );

    this->angle += angle;
}

The problem is that if, let's say just do turn left a lot, the distance between the object and the camera increases.

For a very simple orbit camera, like most 3rd person adventure games, you will need 4 things:

  • The position of the target
  • The distance from the target
  • The azimuthal angle
  • The polar angle

(If you want your camera to be always relative to the target in orientation, you need to provide the target's orientation as well, in this case I will simply use the world orientation)

See Spherical coordinate systems for a reference.

You should map your azimuthal angle on your horizontal control (and make it loop around when you reach 2 * PI ) and your polar angle should be mapped on your vertical control (or inverted if the player selects that option and make it clamped between -PI and PI - watch out for calculations based on the world Up vector if you go parallel to it ( -PI or PI )

The distance can be fixed or driven by a spline, for this case we will assume a fixed distance.

So, to compute your position you start with WorldForward , which is a unit vector pointing in the axis that you generally consider to be your forward, for example (1,0,0) (here, if we were building a relative camera, we would use our target's forward vector) and you invert it ( * -1 ) to go "from the target" "to your camera".

(The following is untested pseudo code, but you should get the gist - also, keep note that it can be simplified, I just went for clarity)

Next step is to rotate this vector using our azimuth angle, which is the horizontal orientation component of your camera. Something like:

Vector toCamera = WorldForward * -1;
Matrix horizontalRotation = Matrix.CreateRotationZ(azimuth); // assuming Z is up
Vector horizontalRotationPosition = horizontalRotation.Transform(toCamera);

At this point, you have a camera that can rotate horizontally around your target, now to add the other axis, you simply transform again using the polar angle rotation:

Matrix verticalRotation = Matrix.CreateRotationY(polar); // assuming Y is right
Vector finalRotatedVector = verticalRotation.Transform(horizontalRotationPosition);

Now, what we have is a unit vector that points to the position where the camera should be, if you multiply it by the distance you want to keep from your target and add the position of your target, you should get your final position . Keep in mind that this unit vector, if negated, represents the forward vector of your camera.

Vector cameraPosition = targetPosition + finalRotatedVector * distanceFromTarget;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM