0
\$\begingroup\$

I am trying to smooth a camera I create in my game, but I can't seem to find a way to actually do this correctly.

What I have :

//Calculate the "current" Forward vector
var cameraForward = 
    -Vector3.Cross(-Self.forward, target.up)
    .normalized.Cross(target.up).normalized;
//Rotate the camera on the Y axis of the current target,
// and X Axis based on delta.y and CurrentVerticalLook
cameraForward = 
    Quaternion.AngleAxis(delta.y, ViewTarget.transform.up) * 
    Quaternion.AngleAxis(CurrentVerticalLook, Self.right) * cameraForward;

var offset = cameraForward * CameraDistance;
var pos = LookAt + offset;
Self.Position = pos;
Self.transform.LookAt(ViewTarget.position)

So what I ahve tried :

I tried Lerping the Vector Position, I tried smoothing the delta.y based on the last N frames.

The Camera I need is something like this :

Rotate on the Around UP Axis of the target and Rotate on Right Axis of the Camera, Camera Up is always = to Target UP.

So this is sort of Orbital Camera, but I am having trouble finding the correct rotation/operations. The way its set right works, but the camera movement is jaggy, but I can't seem to find a way to add Slerp in there without messing everything.

Thanks!

Edit : <>

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

All you really need is an exponential filter on each of the relevant variables. Have:

// Translation parameters
Vector3 target;

// Rotation parameters
float phi;
float theta;
float radius;


// Values we want to smoothly interpolate to
Vector3 nextTarget;
float nextPhi;
float nextTheta;
float nextRadius;

// Value between 0.0 and 1.0. If 1.0, no interpolation happens.
// If 0.0, no movement happens at all. Intermediate values determine
// intermediate interpolation
float alpha;

Here's how you calculate the new camera parameters:

void UpdateCurrentTarget()
{
    target = (alpha) * nextTarget + (1.0f - alpha) * target;
    phi =    (alpha) * nextPhi    + (1.0f - alpha) * phi;
    theta =  (alpha) * nextTheta  + (1.0f - alpha) * theta;
    radius = (alpha) * nextRadius + (1.0f - alpha) * radius;
}

The camera parameters will converge to the new values smoothly. Here's how you actually compute the pose of the camera using spherical coordinates:

void UpdateCameraPose()
{
    float x = radius * sin(theta) * cos(phi) + target.x;
    float y = radius * sin(theta) * sin(phi) + target.y;
    float z = radius * cos(theta) + target.z;

    Self.transform.position = new Vector3(x, y, z);
    Self.transform.LookAt(target);
}

I prefer to do it this way because no quaternions are required.However, because they are Euler Angles, you will inevitable run into Gimbal Lock at around phi = +/- 0.5 * pi, as well as the LookAt function failing due to having the wrong up vector. You can avoid this by limiting phi so it never gets to 0.5 * pi.

\$\endgroup\$
3
  • \$\begingroup\$ My problem is actually joining all the requirements, I can and know how to smooth a "normal" camera, but I can't wrap my head around this one at all. Even when using Slerp I can't find how to do this. \$\endgroup\$
    – Morphex
    Commented Jan 15, 2015 at 20:32
  • \$\begingroup\$ Alright, then wait for someone to post the quaternion solution. \$\endgroup\$
    – mklingen
    Commented Jan 15, 2015 at 20:36
  • \$\begingroup\$ I just realized my asnwer sound a bit rude , by all means that wasnt what I wanted! I am actually trying a solution with what you posted, not sure if it works. Thank you for the feedback btw! \$\endgroup\$
    – Morphex
    Commented Jan 15, 2015 at 21:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .