Tag: animation

Character Modeling and Animation in Maya

My latest project in game development is to create a fully animated player character designed to be easily portable into a game engine be that Unity, Unreal Engine or someone’s custom made game engine.  This is still a work in progress so it is difficult to say when it will be finished, but here is a demo showing the character in its classic T-pose as well as its completed walk animation.

For the remainder of this post I would like to give out some tips to anyone wishing to create similar works in Maya.  It may not look like it but this was the first time creating a character model and animation in Maya, which is why I would to give out some tips on how to avoid some of the same beginner mistakes that I made when working on this project.

Getting Started:

The first thing any good modeler needs to get started is some reference material of what they want their character to look like from various angles.  For bipedal characters it is generally preferred to model your character starting in the T-pose and to import image planes featuring at least the front and side profiles of your character.  This may seem like a high hurdle for those of you who lack artistic talent, but don’t panic because I myself am not artistically inclined either.  If you already have a character in mind that someone has already created plenty of reference material for you to use it may not be as difficult as you think to modify the image into a T-pose.  The following images are a front and side profile of a character that I created using only Adobe Illustrator’s pen tool and built-in rulers.  I based my model on a character that appeared in a manga that I read online called Flower Flower and used various images from that manga as reference material.

shuurei_front_profile shuurei_left_profile

You may have noticed that for the side profile I didn’t bother to draw the arm since most of the detail would be lost, not to mention it is not really  necessary to model the arm from the side view.  You may find that you need additional reference material for finer details such as the hands.  When you want to save your reference or texture images to your project folder you want to make sure you save them to your sourceImages folder instead of your images folder since the images folder is where Maya saves its rendered images when doing a batch render.  One final thing to note when importing your images into Maya is that many people prefer not to use Maya’s built-in image plane feature because they find it difficult to work with, for example one problem that I frequently had when trying to work with them was that I sometimes found that was unable to select them in the viewport even when I made sure that the layer that they were in was neither a template nor a reference.  Eventually I got so annoyed that I replaced them with polygon planes with a transparent file texture.

Modeling:

I will not cover how to do the actual modeling but I can give some suggestions as to where to start.  Here are some popular tutorial series that I used to help me model my character:

Maya LT Advanced Training: Character Modeling by Matthew Doyle (recommended)

3D Character Modeling: The Geek by Carol Ashley

One place where the the first tutorial series mentioned above is particularly useful is in described how to best model the head with good topology however it doesn’t really explain why good topology is so important.  If you want to learn more on this I suggest watching Modeling a head with proper topology on the Maya Learning Channel.  In particular I suggest looking at the third video in the series since it gives a color coded visual representation of how you may want your finished head to look.

One thing I suggest for a character of this nature is to model the body and the clothes as separate objects to start off with.  This can be helpful later if you want to be able to model the character in different outfits.  In the animation demo above the coat, sash and pants are attached to the body using a simple wrap deformer while the shoes are a part of the main model.  Keep in mind that we generally want our game characters to have a range of about 5,000-25,000 tris.  My character currently has around 27,000 tris, however I can reduce this number if I delete much of the internal geometry that will be hidden by the clothes.  Ideally the pants will be merged with the main body before getting imported into our game engine.  The coat and sash may need to dealt with differently depending our game engine since we probably want it to behave in a more realistic fashion.

Texturing:

If like me you are artistically challenged like me many of you may wish to skip making your own custom textures for your character.  I only took the time to create my own texture because I wanted to see what it would like textured and although it is plain to see that my textures could use some polishing I am quite proud of the results.  However, even if you do not wish to create your own textures you should at least take the time to make sure your UV maps are clean before proceeding to the next steps.  The reason for this is that if you decide to duplicate any part of your mesh either for use in another model or for creating blend shapes for the current model then that UV map gets copied as well and it can be a nightmare having to modify the same UV map from scratch.  For more on UV mapping see the last video in the series Maya LT Advanced Training: Character Modeling by Matthew Doyle.

For those of you who do want to try your hand at creating textures here are a few useful links that I found helpful:

Creating Textures for Characters in Autodesk Maya by Ryan Bird

How Do I Make Velvet Texture in Photoshop? by David Weedmark

Create a Linen Texture in Photoshop by Howard Pinsky

Adobe Photoshop – Basic Hair Texture Tutorial for IMVU, Second Life, The Sims & More by YouTube user TheRealMrsMVP

Realistic Eye Texture Painting by Krishnamurti Martins Costa

Rigging:

When it comes time to rig your model be sure to create a new scene file and then just import your model into that file.  That way if you ever need to make changes to your model you will not break the functionality of your rig.  I highly recommend following this tutorial on character rigging:  Creating a Character Rig by the Maya Learning Channel.

There are a couple that the above tutorial does does not mention that you should keep in mind.  The first is how to properly use to pull vector constraints.  If you follow the tutorial exactly you may never run into the problem that I had, but in case you do here is how you can fix it.  When you create your pull vector constraint on your IK arm/leg you may find that the model has twisted slightly and no longer matches your FK arm/leg.  This can cause some unsightly snapping when switching between IK and FK.  The reason for this is that the object that drives the constraint is not on a plane with the joints that the IK handle controls.  To get around this problem we could just recreate our joint structure from scratch making sure that there is no unexpected bend in the joints.  Alternatively, we can create a triangular plane and snap its corners to the joints controlled by the IK handle, scale the plane out and make its surface live.  then we can  snap the object diving the pull vector constraint to that plane.  Then when you make your pull vector your IK and FK arm/leg should match.

Another thing to keep in mind is that you will need to have additional joint structures for the head and the jaw.  While jaw motion may arguably be handled using blend shapes, you must at least have a couple of head joints so that when you skin your rig you have something to paint your head weights to.  If you try to paint your head weights to your neckEnd_result_JNT then when you rotate your head control you will have your model’s eyes popping out of their head due to the spline neck’s rotation.

Although I said that jaw motion could be handled using blend shapes, I prefer the method of using joints.  Jaw motion is controlled by a control curve set that is set within a bounding bound grouped together with a bunch of other controls for manipulating facial expressions.  I also created a joint structure for my characters tongue which is based closely on the  joint structure for the spine.  I gave the tongue a dual set of controls so that the animator would have the choice of how they want to be able to manipulate the tongue.  The blend mode is controlled by an attribute on the IK head control.  In auto mode the animator can use a set of controls grouped with the facial expressions to control the position, length and width of the tongue.  In manual mode the animator  can directly manipulate the position and rotation of the tongueEnd_bind_JNT which in turn affects the squash and stretch of the tongue.

facial_ctrls manual_tongue_ctrl

Blend Shapes:

While joints are useful for animating a change between several poses, blend shapes allow us to change the mesh of our model by blending the positions or our mesh’s vertices between one set of positions and another.  This is particularly useful for blending between facial expressions.

When using blend shapes it is important to understand that every vertex in the mesh has an index or number associated with it.  When using blend shapes maya interpolates between the positions of vertices with matching indices according to the blend weight.  So in order for a model and its blend shape to deform properly the indices of their vertices need to line up.   If we duplicate a mesh the vertices of the two meshes should match up appropriately.  However, if we modify the topology of the duplicate and then create our blend shape then we are likely to result in what many refer to as the spiky-ball-of-death.  So it is incredibly important to maintain the same topology between our original mesh and its respective blend shapes.

However, often it is inconvenient to have to duplicate an entire mesh for each blend shape, especially if all we want to blend is the head.  One way we can accomplish this is by separating the part of the mesh that we want to blend from the original mesh and creating our blend shapes from duplicates of this mesh.  (I personally like to export this duplicated mesh into a separate file and create my blend shapes there since as Maya scene files grow larger and larger they use up a lot of memory and can slow your system down considerably.)  When we want to recombine our separated head to the body mesh simply make sure that you select the mesh that you wish to attach a blend shape to before you select the main body.  This ensure that the indices of the vertices that are being blended stay the same.  Then when you go to create your blend shape node simply make sure that the option Check Topology is turned off.

Another problem that might crop up when creating blend shapes is the possibility that you may wish to mirror a blend shape.  Unfortunately, Maya does not provide any built-in tools that make this easy to accomplish.  But fear not, because there is an open source MEL script that can help you accomplish this with little to no effort.  It and a video tutorial on how to use it can be found at http://www.animationmethods.com/scripts.

Finally if it turns out that you absolutely need to make changes to your topology there is a way to do it without having to recreate all your blend shapes from scratch.  There is a tool called Bake Topology to Targets which (possibly) can give you the results you need.  The YouTube video Maya BlendShape Tips and Tricks by Steven Roselle shows how this can be done.

Animation:

Before starting to create our animations it is a good idea to study up on how to use the Maya Trax Editor.  The YouTube video Maya Trax Editor Tutorial – by Matty Mac gives a pretty good explanation of how it works.  The basic premise is that first we need to create a character set of all the controls that we are going to need within the file that contains our rig.  Then starting in a new file we create a reference to our character rig file.  Making sure our character set is not selected we key in our animation to the time slider.  Next we select our character set, add it to the Trax Editor and then go to Create->Animation Clip->Options and make sure to select the TimeSlider as the source.  Then it is a simple task to export the animation clip to your clips folder.

For more advanced animation you can also check out the YouTube video on Animation Layers titled CGI 3D Tutorial HD: “Using Animation Layers in Maya” – by 3dmotive.

Additional References:

Facial Rigging Tutorial by Adam Bailey

Tips and Tricks: Blendshape Heads by Jennifer Conley

Sprite Animation in Java

In this posting I will be describing the process by which we can program a simple sprite-based animation.  A sprite is simply a two-dimensional graphical image that is integrated into a larger scene.  They are a popular tool for populating scenes in video games as they are easily manipulated separately from the rest of the scene.  To animate it we need a series of image frames for each individual sprite.  These are often stored collectively in a single image called a spritesheet.  When we draw our sprite we only draw one frame at a time.  Then as time passes we just switch between our frames to give the illusion that our sprite is moving.  I will be writing the sample code for this example in Java, but it should not be too hard to adapt it to other languages.

The first thing we want to do is define a structure to store each frame of our animation.  The purpose of this is to put some separation between the constant definitions that are shared between animations of a single type and the constantly updating data of the individual animation objects.  In it we will store three things:  the image associated with this frame, the number of the frame indicating where in the list of frames it belongs, and the duration of time that the animation should spend on this one frame.

// AnimationFrame.java
import java.awt.image.BufferedImage;
public class AnimationFrame {
    public final BufferedImage image;
    public final int frameNumber;
    public final int duration;

    public AnimationFrame(BufferedImage image, int frameNumber, int duration) {
        this.image = image;
        this.frameNumber = frameNumber;
        this.duration = duration;
    }
}

Next we can create our Animation class.  In it we store a list frames in the order that they should be played, the name of the current animation, the index of the current frame, the amount of time that needs to elapse before we switch to the next frame and a boolean variable to indicate whether or not the animation is currently playing.  Optionally we can also include a boolean variable to allow the animation to loop back the the beginning once the final  frame has been shown.

Most of the work done by the Animation object is done within our update method which is meant to be called every frame before we draw our Sprite to the screen.  It takes as a parameter the amount of time that has elapsed since our last update.  We subtract this time from our timeToNext value and if the result is negative we know that it is time to switch to the next frame.  then we increment our timeToNext variable by the duration of the next frame.  The rest is just a matter of providing methods that allow the client to start, stop and pause the animation.  If you are a fan of the Observer Pattern you can even include a custom listener class object whose functions are called when certain state changes are made within the Animation class.  We could make such an interface in just a few lines like so:

// AnimationListener.java
public interface AnimationListener {
    public void onComplete(); // gets called when animation reaches end (unless looping)
    public void onStart();    // gets called when the animation's start method is called
    public void onPlay();     // gets called when the animation's play method is called
    public void onPause();    // gets called when the animation's pause method is called
    public void onStop();     // gets called when the animation's stop method is called
}

One final note to make is that if you wish your program to be multithreaded, it may be a good idea to define any function calls that alter your animation’s state using the synchronized keyword.

// AnimationClip.java
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

public class AnimationClip {
    private final List<AnimationFrame> frames;
    private final List<AnimationListener> listeners;
    private String name;
    private int timeToNextFrame;
    private int currentFrame;
    private boolean playing;
    private final boolean loop;

    /**
     * Class constructor
     * @param name name of the clip
     * @param frames ordered list of frames
     * @param loop boolean value determining whether the clip should repeat itself
     */
    public AnimationClip(String name, ArrayList<AnimationFrame> frames, boolean loop) {
        this.frames = frames;
        this.name = name;
        this.loop = loop;
        listeners = new ArrayList<>();
        playing = false;
        currentFrame = 0;
        timeToNextFrame = (frames.size() > 0)? frames.get(currentFrame).duration : 0;
    }

    /**
     * Gets the name of the clip
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * Gets whether the clip is playing
     * @return true if clip is currently playing
     */
    public boolean isPlaying() {
        return playing;
    }

    /**
     * Gets the current frame of the animation
     * @return the frame image or null if there are no frames
     */
    public synchronized BufferedImage getFrame() {
        return (frames.size() > 0)? frames.get(currentFrame).image : null;
    }

    /**
     * Starts the clip from the beginning
     */
    public synchronized void start() {
        playing = true;
        currentFrame = 0;
        timeToNextFrame = (frames.size() > 0)? frames.get(currentFrame).duration : 0;
        for (AnimationListener listener : listeners) listener.onStart();
    }

    /**
     * Starts the clip from the current frame
     */
    public synchronized void play() {
        playing = true;
        for (AnimationListener listener : listeners) listener.onPlay();
    }

    /**
     * Pauses the clip
     */
    public synchronized void pause() {
        playing = false;
        for (AnimationListener listener : listeners) listener.onPause();
    }

    /**
     * Stops the clip and sets the current frame back to the beginning
     */
    public synchronized void stop() {
        playing = false;
        currentFrame = 0;
        timeToNextFrame = (frames.size() > 0)? frames.get(currentFrame).duration : 0;
        for (AnimationListener listener : listeners) listener.onStop();
    }

    /**
     * Updates the animation based on the amount of time that has elapsed.
     * Note: Will only update if the animation is currently playing
     * @param elapsed
     */
    public synchronized void update(long elapsed) {
        if (!playing) return;
        timeToNextFrame -= elapsed;
        if (timeToNextFrame < 0) {
            int numFrames = frames.size();
            ++currentFrame;
            if (currentFrame >= numFrames) {
                if (loop) currentFrame = 0;
                else {
                    // end of the animation, stop it
                    currentFrame = numFrames - 1;
                    timeToNextFrame = 0;
                    playing = false;
                    for (AnimationListener listener : listeners)
                        listener.onComplete();
                    return;
                }
            }
            AnimationFrame current = frames.get(currentFrame);
            timeToNextFrame += current.duration;
        }
    }

    /**
     * Adds a listener to the list of listeners
     * @param listener the listener to add
     */
    public void addAnimationListener(AnimationListener listener) {
        listeners.add(listener);
    }
}

What is Cripple Mr. Onion?

Cripple Mr. Onion was originally a gambling card game played by the characters in the fictional universe of the Discworld novels written by Terry Pratchett. Since no official rules have been set by the author himself, many Roundworld (our world) denizens have taken it upon themselves to create a set of rules for the game. One popular version was designed by Andrew C. Millard with help by Prof. Terry Tao and was even mentioned in the book Turtle Recall, which is a kind of Discworld encyclopedia written by Terry Pratchett himself. The book gives a vague description of the rules with the understanding that people playing the game are free to modify or ignore the rules as set. What follows is the unique interpretation I envisioned and I hope you will all enjoy playing it as much as I enjoyed creating it.

CMO Screen CaptureMany versions of the game envisioned it with eight suits of cards much like combining two sets of regular playing cards but with the suits all different. The book Turtle Recall describes the deck as a regular set of playing cards combined with the complete Caroc deck (Discworld tarot deck). In my version there are a total of 78 playing cards divided up into six suits of thirteen cards each. The first four suits, turtles, elephants, staves and octograms are exactly like a regular set of 52 playing cards but with their suits renamed. The remaining two suits follow the same numbering scheme as the remaining four but have unique names for each card. The suits themselves are called the Lesser Arcana and the Greater Arcana and together they form the Caroc deck.

The game itself bears striking resemblance to both Poker and Blackjack. Like Poker there are various hand ranks that become exceedingly rare the higher their rank goes. Cards have number values just like in Blackjack and the rank of one’s hand is determined by how well you group the cards in your hand to sum to 21. However, what truly separates Cripple Mr. Onion from its Roundworld counterparts are the various optional rules that can be included. These are otherwise known as the “Modifiers.” A player may choose to use as many or as few modifiers as they wish with the exception of the Crippling Rule which is always active (hence the name Cripple Mr. Onion).

The user interface is built using Java’s swing library. The main application runs on the swing library’s Event Dispatch Thread (EDT). Meanwhile, the main game loop runs on the Engine Core thread and determines which animations need to be played and what the board should look like at various stages of the game. Whenever the core thread needs to start an animation, request input from the user or change the appearance of the board it calls a static method of the Application class to get an event object which it forwards to the EDT. This allows the core thread to make thread safe changes to the GUI.

The Application object loads all the necessary game resources and initializes the various swing components, some of which include a menu bar and glass pane as well as the content panes for various dialogs. The Application provides static methods for starting these dialogs with the appropriate modality and parent window. The menu bar provides the user with a list of game options and help tools which call these methods. The Table object represents the game view and acts as the content pane for the main window. It provides various public methods for changing the appearance of the board and for enabling and disabling certain components. The Animation Pane is the glass pane of the main window and is where all the animations are drawn.

Rendering animations using Swing components can be tricky since drawing only occurs when a paint event is dispatched by the EDT, a method known as passive rendering. The Animation objects in this game use threads that repeatedly update before calling the repaint method on the component to which they are attached. Then whenever a paint event is dispatched the given component’s paint method merely calls on the paint method of its attached Animation object.

// Animation.java

import java.awt.Component;
import java.awt.Graphics;
import java.util.ArrayList;

/**
 *
 * @author GK Potts
 */
public abstract class Animation implements Runnable {
    private final int SLEEP_DELAY = 25;

    protected ArrayList<AnimationListener> listeners;
    private Component context;
    private Thread currentThread;
    private long startTime;
    private long oldTime;
    private long currentTime;
    private boolean playing;
    private boolean running;

    public Animation() {
        listeners = new ArrayList<>();
        playing = false;
        running = false;
    }

    public abstract void paint(Graphics g);

    public abstract void update(long elapsed);

    ...

    @Override
    public void run() {
        long elapsed, sleep;
        running = true;
        currentThread = Thread.currentThread();
        startTime = System.currentTimeMillis();
        oldTime = startTime;
        for (AnimationListener listener : listeners) listener.onStart();
        while (running) {
            currentTime = System.currentTimeMillis();
            elapsed = currentTime - oldTime;
            if (playing) {
                update(elapsed);
                context.repaint();
            }

            oldTime = currentTime;
            sleep = SLEEP_DELAY - elapsed;
            if (sleep < 0) sleep = 2;

            try { Thread.sleep(sleep); }
            catch (InterruptedException e) { return; }
        }
    }
}

When an animation event occurs, an Animation object is constructed using position data collected from the Table. The Animation is then fitted with its own personal listener object whose methods are called whenever the animation is started, paused, stopped or reaches its end.   The only one of these methods that is truly important is the OnComplete method because it notifies the core thread when the animation is finished.   The Animation object is then attached to the Animation Pane and finally started on a new thread. Note that the animation thread does not need to be invoked on the EDT since it does not make any direct changes to the GUI. It merely calls the repaint method of the component to which it is attached. Repaint merely schedules a paint event to be executed later, thus making our Animations thread safe. If we ran our animation thread on the EDT our GUI would freeze until the animation thread ended.

In addition to having Animations for moving objects, this game also supports sprite based animations. Each time a card flips over or a modifier effect is activated, a sprite based Animation Clip object determines which frame to use based on the total elapsed time. This Animation Clip object is based almost entirely on the sprite based animation class that I wrote for use in the game engine I built for my previous game Captain Polly’s Booty. To see my blog posting on sprite animation click here.

The various Animation subclasses each utilize an Animation Data object which stores the position, rotation, and image data for each of the cards and provides helper methods for stepping forward the position, rotation and animation. Then using Hash Maps the animation objects map the Card objects to the Animation Data objects allowing the animation to simply cycle through the list of cards to update their positions and paint them. This way the order of the list determines what order to draw the cards in. Additional these data objects also store a rotated version of the image so that the program does not need to call the image rotation function, which is rather time consuming, within the paint method.

To prevent the clipping of images as a result of rotation each image is resized to a square whose sides are equal to the diameter of the circle that completely encloses the image. The images are then rotated about their center and position data is altered to take into account the change in size.

Player hands are evaluated through the use of two Objects: the Grouping, and the Hand Evaluator. Grouping merely looks at a set of cards and determines if it forms a valid card grouping and stores its overall ranking. Hand Evaluator looks at a player’s entire hand and attempts to create the best possible Grouping from the cards available. Hand Evaluator is also useful for evaluating possible hands by being able to generate modified copies of itself. These copies can then be compared to the original to see which one is a better hand.