It is recommended that your first complete Tutorial 16 - The key in frames before you commence with this tutorial.
Now that your engine has the capability to capture keyframes of your scenes, the next step is to move smoothly between these frames. This is achieved by using a technique better known as interpolation.
When we study the above illustrations, you'll notice that we are working with two keyframes that contain a bone structure with three joints (red, green and blue vertices). Interpolation is the intermediate step between rendering the two keyframes. Instead of rendering frame one and directly thereafter frame two, we render an intermediate scene before rendering frame two. This intermediate step results in a more fluent animation flow between the two keyframes.
The red line in the image below represents the timetrack of our animation. When we render a scene with an interpolation value of 0, then frame one is rendered. When we render our scene with an interpolation value of 1, then frame two is rendered. Using any real value in between 0 and 1 results in an interpolated scene being rendered, based on the given value. E.g. rendering with an interpolation value of 0.5 will render an interpolated scene halfway between frame one and two.
In a similar fashion to how we interpolate rotations of joints, we can interpolate the rotation, position or scale of any model in our scene.
Dim model As R3Model ' temporary model object Dim cube As R3Model ' temporary cube model Dim i As Integer Dim light As R3LightSource ' light source Dim cam As R3Camera ' camera used in our scene me.Maximize ' maximize the window me.MouseCursor = REALbasic.System.Cursors.StandardPointer ' set mouse cursor ' instantiate the Scene object Scene = new R3Scene Scene.BackgroundColor.SetValue(1, 1, 1) ' white background ' load textures used in scene Scene.Texture.Append new R3Texture(imgFinger) Scene.Texture.Append new R3Texture(imgPrint) Scene.Texture.Append new R3Texture(imgCube1) Scene.Texture.Append new R3Texture(imgCube2) ' add front light source light = new R3LightSource light.Position.SetValue(1, 0, 3) Scene.LightSource.Append light ' add camera cam = new R3Camera cam.DollyOut 30 ' move back so that we can get the model in our view Scene.Camera.Append cam Scene.ActiveCamera = 0 ' set the index of the active camera ' instantiate a new hand model model = R3_Tut00016Hand ' add the model to our scene Scene.AppendModel model ' add cubes for i = 0 to 2 cube = R3_Tut00016Cube Scene.AppendModel cube next i ' starting status of all fingers are erected FingerErected.Append true ' pinky FingerErected.Append true ' index finger FingerErected.Append true ' middle finger FingerErected.Append true ' ring finger FingerErected.Append true ' thumb ' disable animation timers Timer1.Enabled = false Timer2.Enabled = false FingerIndex = -1 ' no finger selected OpenGLSurface1.Render ' refresh OpenGL surface17. Add the following code to the Action event of Timer2:
' do we have enough frames to interpolate with? if Keyframe.Ubound > 0 then ' yes, so set up the scene with interpolation between keyframes Scene.SetKeyframe Keyframe(KeyframeIndex), Keyframe(KeyframeIndex + 1), Interpolation OpenGLSurface1.Render ' refresh the OpenGL surface Interpolation = Interpolation + 0.1 ' go to the next interpolated frame if Interpolation >= 1 then KeyframeIndex = KeyframeIndex + 1 Interpolation = 0.1 if KeyframeIndex > (Keyframe.Ubound - 1) then KeyframeIndex = 0 end if end if end if18. Add the following code to the Action event of cmdPlay:
' are we busy playing the keyframes? if Playing then ' yes, so stop playing the keyframes Timer2.Enabled = false cmdPlay.Caption = "Play" ' change caption of play button ' enable controls cmdSaveKeyframe.Enabled = true lstKeyframes.Enabled = true Playing = false ' indicate that we are not busy playing the keyframes else ' no, so start playing the keyframes ' first disable controls while playing keyframes cmdSaveKeyframe.Enabled = false lstKeyframes.Enabled = false cmdPlay.Caption = "Stop" ' change caption of play button KeyframeIndex = 0 Interpolation = 0 Timer2.Enabled = true Playing = true ' indicate that we are busy playing the keyframes end if19. Save and run the project.
In the previous tutorial we changed the scene by passing a R3SceneKeyframe object to the R3Scene.SetKeyframe method. This instantly changed the scene to the given keyframe.
The new R3Scene class used in this tutorial has a second SetKeyframe method, with the difference being that a start keyframe, end keyframe and interpolation value is passed in as parameters. This method will automatically interpolate the scene, using the given keyframes and interpolation value.
On line 6 of the Timer2.Action event you can see how we use this new method to generate an interpolated scene from two keyframes. On line 10 we increase our interpolation value by 0.1 until it reaches 1. When the interpolation value reaches 1, we make the current end keyframe the new start keyframe and we make the next keyframe in our array the new end keyframe. The interpolation value is also reset to 0.1.
The Timer2.Action basically loops through all the captured keyframes, and goes back to the first keyframe as soon as we reach the end of the keyframe array.
A new SetKeyframe method is also added to our R3Model class to assist with the interpolation of individual models.
The R3Joint class got a new method named Interpolate that serves the same purposes as the SetKeyframe methods of the R3Scene and R3Model classes.
Study the logic of the Timer2.Action event until you feel comfortable with how the new interpolation methods can be used to create a smooth animation effect between different keyframes.