@c -*-texinfo-*-
@node Sprite3D Animation, SpriteCal3D Animation, Animation Blending Trees, Animation
@subsection Sprite3D Animation
@cindex Animation
@cindex Sprite3D
@cindex sprite actions
@cindex @code{iSprite3DState}
@cindex @code{iSprite3DFactoryState}

@emph{Written by Michael Voase,
@email{mvoase@@midcoast.com.au}.}

After you have created your sprite you are now probably wondering
what you can do to bring your creation to life? In this section
we explore the two ways in which you can introduce animation
sequences to your sprite.

For the Crystal Space developer, there are currently two options
for the production and management of sprite animation. The first
option is frame based animation, referred to as an action, and the
second is skeletal animation (which uses the external @sc{cal3d}
library).

@subsubheading Introduction

Crystal Space provides two basic mechanisms for animating sprites. The first
is frame based animation in which a mesh is defined in each frame and used
in a loop (@pxref{MeshObject Spr3D}). The second method is skeletal animation
using the @sc{cal3d} library (@pxref{MeshObject SprCal3D}).

For the purpose of this document I will describe frame based animation as an
@dfn{action}.  This name is coined from the class the implements frame
animations in the 3D sprite object @samp{iSpriteAction} and has been
traditionally referred to as an @samp{action} in the sprite loader plug in.

This document presumes that you have an operational copy of Crystal Space.
For details on obtaining and building Crystal Space please refer to the
relevant sections on obtaining (@pxref{Where to Get}) and building
(@pxref{Building}) Crystal Space.

Lastly, actions are specific to sprite 3D. There is no exactly
corresponding interface to genmesh or ball as yet, for example. So I am also
presuming you have read to sections prior to this section about sprites, if
not, then it would be a good idea to do so before delving into this section.

@subsubheading Sprite Actions

A sprite action is a series of frames which contains the position of each
vertex in a sprite for a particular time. This means for each frame, a
complete duplicate of the vertex list must be loaded into the sprite for
each frame. The positions of the vertices of course will vary, however, the
number of vertices in each frame must be equal. We will cover why later.

@subsubheading Creating a Sprite in a Map File

A sprite in a map file consists of two declaration. The first is the
declaration for its @dfn{factory} the second is a declaration of its 
@dfn{instance} in a given sector. The factory declaration is what we are
mostly interested in at the moment.

Now if you recall from Mesh Object Concepts (@pxref{MeshObject Concepts}), the
factory acts as a database of all the vertices, triangles and texels used
to define a mesh object. The primary purpose of this is to have a single
database for each mesh object. So this is where we will be defining our
sprite with its multiple actions.

The declaration starts with the @samp{meshfact} token, and looks something
like this:

@example
<meshfact name="fact">
  <plugin>crystalspace.mesh.loader.factory.sprite.3d</plugin>
  <params>
    <material>white</material>
    <frame name="first">
      <v x="0" y="0" z="0" u="0" v="0"/>
      <v x="0" y="1" z="0" u="0" v="0"/>
      <v x="1" y="0" z="0" u="0" v="0"/>
      <v x="0" y="0" z="1" u="0" v="0"/>
    </frame>
    <frame name="second">
      <v x="0" y="0" z="0" u="0" v="0"/>
      <v x="0" y="1.2" z="0" u="0" v="0"/>
      <v x="1.2" y="0" z="0" u="0" v="0"/>
      <v x="0" y="0" z="1.2" u="0" v="0"/>
    </frame>
    <frame name="third">
      <v x="0" y="0" z="0" u="0" v="0"/>
      <v x="0" y="1.4" z="0" u="0" v="0"/>
      <v x="1.4" y="0" z="0" u="0" v="0"/>
      <v x="0" y="0" z="1.4" u="0" v="0"/>
    </frame>
    <frame name="fourth">
      <v x="0" y="0" z="0" u="0" v="0"/>
      <v x="0" y="1.2" z="0" u="0" v="0"/>
      <v x="1.2" y="0" z="0" u="0" v="0"/>
      <v x="0" y="0" z="1.2" u="0" v="0"/>
    </frame>
    
    <t t1="0" t2="1" t3="2"/>
    <t t1="0" t2="3" t3="1"/>
    <t t1="0" t2="2" t3="3"/>
    <t t1="1" t2="3" t3="2"/>
    
    <action name="default">
      <f name="first" delay="200"/>
      <f name="second" delay="200"/>
      <f name="third" delay="200"/>
      <f name="fourth" delay="200"/>
    </action>
  </params>
</meshfact>
@end example

This example defines a triangular pyramid which grow larger and smaller.
To put this sprite into action, you also need to declare an instance of
the sprite in a sector. In your map file (somewhere inside a @samp{sector}
declaration), place the following mesh object declaration.

@example
<meshobj name="test1">
  <plugin>crystalspace.mesh.loader.sprite.3d</plugin>
  <params>
    <factory>fact</factory>
    <action>default</action>
    <tween />
  </params>
  <move>
    <v x="0" y="0" z="5.0" />
  </move>
  <priority>object</priority>
  <zuse />
</meshobj>
@end example

After zipping the map file up with your sprite you should see and active
sprite five units in front of you.

@subsubheading Meaning of the Sprite

Okay, we have an example of an animation. As you can see from the example,
the sprite @emph{factory} declaration, the sprite consists of four frames
each enclosed in the @samp{frame} keyword. Each frame defines the vertices
of the pyramid in each frame. The @samp{v} token stands for @emph{vertex}.
You will also note that each frame contains a name. This is important as the
name is used to reference the frame. This applies to both map files and
the sprite 3D interface.

After the frames have been defined, a list of triangles is then declared.
Note that the @samp{t} tokens are declared after the frames. Trying
to define the triangles before the frames will result in an error and will
be flagged as such. Each @samp{t} declaration contains three indices
to the defined frame vertices. The index starts at zero and has a maximum
value equal the number of vertices minus one. During the course of animation
the triangle lists are applied to the corresponding frame and are then
sent to the graphics renderer. This is one reason why each frame must
contain the same number of vertices. Lastly, at the end of the mesh factory
declaration, there is an @samp{action} declared. 

@subsubheading Action Declaration

The declaration starts with the @samp{action} token and is then followed by
the name of the action. Setting the name is important as this is how you
will reference the action both in the map file and in the sprite interface.
Its also a good idea @emph{not} to use the same name twice, as you will prevent
the second action from being accessed. You can use the same name for an action
and a frame, as they are stored in different places. In general though,
never use the same name for two items of the same type, whether it be a mesh
object, a frame, or whatever.

After the name of the action, we enter into the body of the action where the
frame @dfn{sequences} are defined. Each frame of the sequence starts with
the @samp{F} token (standing for frame) and contains the name of the frame
and the duration that it is valid for. The frame name must be one from the 
previous list of frames and the duration is in milliseconds. The duration 
represents how long the frame will be shown for. This sprite contains only
one action. It can contain many actions. However, in all cases there must be
at least one action (usually called @emph{default}) defined for the sprite.

Lastly to implement this action, the @samp{action} keyword is used in the
mesh object declaration to tell the engine which action to use on this sprite
instance. If no action is defined in the mesh object then the engine will
use the first action defined in the factory regardless of its name.

@subsubheading Tweening and Actions.

You may have noticed that the animation looks somewhat jumpy when viewed.
This is due to the tweening flag on the sprite @dfn{instance} being set
to false. To enable tweening, set the tweening flag to true (it is normally
enabled). Tweening is a method of producing a smoother animation by
interpolating the position of the vertices between frame based on a ratio
of the time into the frame and the duration of the frame. Enabling
tweening in an animation involves an additional overhead in calculating
the interpolated vertices, however, produces a more satisfactory result.
This is also the second reason why each frame must have the same number
of vertices.

@subsubheading Interfacing with the Sprite

To begin this section, I am assuming here that you are aware of how to obtain
the various interfaces from the engine.  If not, read the documentation for
@sc{scf}, the Shared Class Facility.  @xref{SCF}.  I will be using terminology
and concepts which are explained in that section.  If you are only interested
in writing map files for the engine then you can skip ahead to the next
section.

Secondly, I am also presuming that you have loaded your sprite into the engine,
and have access to that sprite via the @samp{iEngine} interface.  That implies
that you have written a basic Crystal Space application (or are hacking up an
existing application), and can access your sprite mesh factory using calls
similar to the following:

@example
iMeshFactoryWrapper *fwrap = Engine->FindMeshFactory("name");
iMeshObjectFactory *fact = fwrap->GetMeshObjectFactory();

iMeshWrapper *mwrap = Engine->FindMeshObject("name");
iMeshObject *mesh = mwrap->GetMeshObject();
@end example

With the name being the name of your mesh factory or object, respectively.
There are four main interfaces that we will be dealing with in this section,

@itemize @bullet
@item
@code{iSpriteFrame} 
@item
@code{iSpriteAction} 
@item
@code{iSprite3DFactoryState} 
@item
@code{iSprite3DState}. 
@end itemize

The declarations for these interfaces can be found in 
@file{CS/include/imesh/sprite3d.h}. The first two interfaces can be obtained
by using the @code{FindFrame()} and @code{FindAction()} methods  in the 
@samp{iSprite3dFactoryState} interface (described later).
The third interface can be obtained by querying the @samp{iMeshObjectFactory}
interface. The @samp{iSprite3DState} interface can be obtained from the
@samp{iMeshObject} interface. The following is a summary of the methods in
each interface and what they do. An example of obtaining the state interfaces
is described below:

@example
csRef<iSprite3dFactoryState> fstat =
  scfQueryInterface<iSprite3dFactoryState> (fact);
csRef<iSprite3DState> stat =
  scfQueryInterface<iSprite3DState> (mesh);
@end example

The @samp{mesh} and @samp{fact} variables are the ones mentioned earlier in
this chapter.  The following is summary of the methods and interface that are
useful to the sprite animator during production.  This summary does not fully
document the @samp{iSprite3DState} or @samp{iSprite3DFactoryState} interfaces
since they are adequately documented elsewhere.  Only methods which are
relevant to frame animation are treated here.

@subsubheading @code{iSpriteFrame}

@noindent
Current version: 0.0.2

@table @code
@item void SetName(char const*)
Set the name of this frame.
@item char const* GetName()
Return the name of this frame
@item int GetAnmIndex()
Returns the index of the first vertex used in this frame.  The vertex list is
stored in the sprite factory.
@item int GetTexIndex()
Returns the index to the first texel used in this frame.  The texel list is
stored in the sprite factory.
@end table

@subsubheading @code{iSpriteAction}

@noindent
Current version: 0.0.1

@table @code
@item void SetName(char const*)
Set the name of this action.
@item char const* GetName() const
Return the name of this action.
@item int GetFrameCount()
Get the total number of frames in this animation.
@item iSpriteFrame* GetFrame(int)
Returns frame specified by input argument.
@item iSpriteFrame* GetNextFrame()
Returns the next frame in the sequence.
@item int GetFrameDelay(int)
Returns the duration of frame specified by input argument.
@item void AddFrame(iSpriteFrame* frame, int time)
Adds the frame given by @samp{frame} to this action
and set the duration to @samp{time} milliseconds. This method is used
by the loader to add frames to an action. If you want to ``roll your own'',
you will be using this interface to create your own actions. The frame
must already be present in the frame list held by the sprite factory
that this action came from.
@end table

@subsubheading @code{iSprite3DFactoryState}

@noindent
Current version: 0.0.2

@table @code
@item void AddVertices(int number)
Adds @samp{number} vertices to @strong{all} frames
in this sprite factory. The all is emphasized so that you are aware
that the actual number of vertices created is @samp{number} multiplied
by the number of frames. This is done to satisfy the requirement that
all frames must be of an equal size.
@item iSpriteFrame* AddFrame()
Creates a new frame on the sprite frame list and
returns a pointer to the newly created frame. The loader uses
this method to load frames into a sprite. For each new frame
added, an additional bank of vertices and texels is created for
the new frame. Once you have this frame, you will then be using
the @samp{iSpriteFrame} interface to operate on the frame.
@item iSpriteFrame* FindFrame(const char* title)
Finds the frame named @samp{title} in this sprite
factory and returns a pointer the frame.
@item int GetFrameCount()
Returns the number of frames in this sprite factory.
@item iSpriteFrame* GetFrame(int index) const
Returns a pointer to frame @samp{index}. This
frame is part of the list of frames stored in this sprite factory.
@item iSpriteAction* AddAction()
Create a new action and return a pointer to the action.
Once you have obtained the action, you will then be using the 
@samp{iSpriteAction} interface to modify this action.
@item iSpriteAction* FindAction(const char* title) const
Returns a pointer to the action named @samp{title}.
@item iSpriteAction* GetFirstAction() const
Returns a pointer to the first action in this sprite factory.
@item int GetActionCount() const
Returns the number of actions stored in this sprite factory.
@item iSpriteAction* GetAction(int index) const
Returns a pointer to action number @samp{index}
@item void EnableTweening(bool flag)
Enables or disables tweening on this sprite factory
depending on @samp{flag}. 
@item bool IsTweeningEnabled()
Returns the current setting for tweening on this sprite factory.
@end table

@subsubheading @code{iSprite3DState}

@noindent
Current version: 0.0.4

@table @code
@item void SetFrame(int index)
Sets this sprite to frame number @samp{index} in the
action current applied to this sprite.
@item int GetCurFrame() const
Returns the index number of the current frame in the
current action applied to this sprite.
@item int GetFrameCount() const
Returns the number of frames in the current action
applied to this sprite.
@item bool SetAction(const char *title)
Set the current action of this sprite to the action
named @samp{title}. Returns a flag indicating if the operation was
successful or not.
@item iSpriteAction* GetCurAction() const
Returns a pointer to the current action applied to this sprite.
@item EnableTweening(bool flag)
Description: Enables or disables tweening on this sprite according
to @samp{flag}.
@item bool IsTweeningEnabled() const
Returns a flag indicating if tweening is enabled for this sprite.
@end table
