Animation technique finally
I ended up taking a slightly different approach to my animation last night. It basically consists of a couple different parts.
The first part was modifying the PositionableItem class to contain a few more pieces of information:
- Target Position (publicly settable)
- Original Position (internal, set as a copy of the current position when the Target Position is set)
Then I added a step(percent) method that calculates a new position based on the current position, the original position, the target position and the percent specified.
After that, my animation logic consists of setting target positions, and then looping for a specified time. During each loop the step(percent) method is called on each object and then each object is drawn. I already had code in place to draw an image based on it’s position information, so it was pretty easy.
I loop for 250ms, sleeping for 5ms after each loop, which keeps my CPU usage low.
It works great. :)
Initial OpenGL Drawing and Animation
Before I started this little project I didn’t know any OpenGL, and really didn’t have any animation/graphics experience. Primarily I’ve been relying on Google to get me around, but there are some things I’m still struggling with and may just have to figure out on my own.
The first thing I’ve run into is how to approach drawing in a reusable way. OpenGL provides very primitive commands for drawing, and they are all oriented around drawing one frame at a time. The approach I’m settled at as of last night is to create a decorator class that will decorate my domain objects with location information, I’ve called it PositionedItem. It looks like this:
class PositionedItem
attr_accessor :x, :y, :z, :x_rotation, :y_rotation, :z_rotation
def initialize(other_obj)
@decorated_object = other_obj
@x = 0
@y = 0
@z = 0
@x_rotation = 0
@y_rotation = 0
@z_rotation = 0
end
def set_position(x, y, z, x_rotation, y_rotation, z_rotation)
@x = x
@y = y
@z = z
@x_rotation = x_rotation
@y_rotation = y_rotation
@z_rotation = z_rotation
end
def method_missing(method, *args, &block)
@decorated_object.send(method, *args, &block)
end
endThis allows me to take a pure data-class (like a “Picture” class in the code I’m currently working on) and wrap it with position information that my drawing class can use.
In my main drawing method I am currently drawing a few quads on the screen with a texture in them (from my Picture class), there is a main picture and some side pictures. At the beginning of the drawing method, I set the positions of the objects that are going to be drawn (a subset of the entire collection of objects) and then call a draw method for each picture, this method knows how to draw a single positioned item based on it’s position data.
One thing that this approach doesn’t do right now is allow for more complex, position relative items. Each drawing method call does the following steps:
- Push the current Transformation matrix
- Draw a single quad with a texture
- Pop the transformation matrix
This means that right now I can only draw quads and it’s always relative to the original location, not relative to the last quad that was drawn.
As for animation, I still don’t really have that figured out. I do have goals though:
- It has to be time-based, not frame count based
- It has to be some kind of keyframe animation, I want to define the start and end positions and calculate all of the inbetween steps
- it has to be smooth
I think my approach is going to be having animation methods for each type of animation I want to do in my drawing class. Right now I want to animate choosing the next and previous pictures, so I’m going to have a animate_select_next and an animate_select_previous method. So far, I haven’t written any code, but I think the method is going to look something like this (complete pseudocode btw):
start_time = now_time
target_time = start_time + 500ms
save_object_start_positions
define_target_positions
while( now_time < target_time)
percent_complete = (now_time - start_time) / (target_time - start_time)
objects.each do |obj|
new_position = (target_position - saved_start_position) * percent_complete
set_newposition
draw obj
end
sleep 5ms
endI might be able to keep this generic enough to use it for all my animation, and just define the target positions when I call the method.
In the meantime, I need to find good sources on how to do simple keyframe animation and drawing loop techniques in OpenGL, because I’m really just trying to figure it out on my own at this point in time.