Thursday, May 1, 2008

Camera Animation, Part I

Due to the video being such high frequency, the blogger, youtube video compressors always make the video look like crap. Original can be found here:

So today I'll be giving a tutorial/sample on cut-scene animation, more specifically camera animation. This will be a 2 part tutorial, and this one will focus on linear interpolation of camera key frames.

So what are key frames? Key frames are the control points of an animation. They are the main/key points that you specifically define where the camera should be, and everything else in between is interpolated. You can also think of them as an outline of what the animation should look like. Here's a picture to help describe what I'm talking about.


Here, the green line is the path we want to follow, the orange dots are our key frames, and the red dots are the intermediate cameras that we want to generate.

So how do we create these intermediate cameras?

for (int i = 0; i < mKeyFrames.Count - 1; i++)
for (int j = 0; j < mPathSteps; j++)
//We could alternatively use the Vector3.lerp function
//but I wanted to show the math behind performing the linear interpolation

Vector3 diff = mKeyFrames[i + 1].Position - mKeyFrames[i].Position;
diff = Vector3.Multiply(diff, (float)j / (float)(mPathSteps - 1));
Vector3 center = mKeyFrames[i].Position + diff;

diff = mKeyFrames[i + 1].Look - mKeyFrames[i].Look;
diff = Vector3.Multiply(diff, (float)j / (float)(mPathSteps - 1));
Vector3 look = mKeyFrames[i].Look + diff;

diff = (mKeyFrames[i + 1].Up - mKeyFrames[i].Up);
diff = Vector3.Multiply(diff, (float)j / (float)(mPathSteps - 1));
Vector3 up = mKeyFrames[i].Up + diff;

Vector3 r = Vector3.Cross(up, look);
Vector3 u = Vector3.Cross(look, r * -1f);

Camera cam = new Camera();
cam.SetLens(mFOV, mAspect, mNearZ, mFarZ);
cam.Place(center, look, u);


Pretty self explanatory, a basic linear interpolation. XNA is handy in that we can cut out all of that code and just use Vector3.Lerp().

The included demo has a pre defined path that is shown in the video. But you can also create your own path at run-time. Here are the controls:

  • 1 - Default camera view
  • 2 - Play the camera animation
  • 3 - Rewind the camera animation
  • 4 - Pause the camera animation
  • C - Clear the current key frames
  • K - Add the current camera to the key frames list
  • B - Build the camera path from the current key frames
  • O - Save the current key frames to an XML file

When you start the demo, the predefined path is already loaded, all you have to do is hit '2', and it will play. If you want to make your own path first clear the key frames by pressing 'C', and then navigate to where you want to be along your path and press 'K' to add your key frames. Once you're happy with your path, press 'B' to build the camera animation, and then you can play it by pressing '2'. Normally, I would use winForms or a GUI such as neoforce for the controls, but this adds a lot of clutter.

So there's probably one thing that you might notice about the camera animation, and that is that it's not very smooth. Next time I will introduce cubic interpolation to smooth out the animation.


Neil Knight said...

How would use Vector3.Lerp() with this code?

Kyle Hayward said...

You would do:

diff = Vector3.Lerp( mKeyFrames[i].Position, mKeyFrames[i+1].Position, (float)j / (float)(mPathSteps - 1) );