
To compile the application from the source files under Linux, simply
change to the correct directory and type the following:
make
To execute the now compiled application, simply type:
./orcs
This will run the application with the default platoon
size of 3 ranks by 3 columns. If, however, you wish to specify your
own platoon size, then use either of the following:
./orcs [number]
Where [number] is an integer between 1 and 10. This will create a square
platoon, with [number] ranks and columns. Alternatively:
./orcs [ranks] [columns]
Where [ranks] and [columns] are both integers between 1 and 10. This
will create a custom sized platoon, with [ranks] ranks and [columns]
columns.
Note: Any values entered in the command line that are outside of 1 to 10
will simply default to 3.
Choose between filled or outlined polygons for the
model rendering. Defaults to filled. Examples:
Filled:
Wireframe: 
Models can be shaded with either smooth (vertex-based) or
flat (polygon-based) methods. Smooth gives a more realistic appearance than the
faceted flat shading, however the model detail is less evident in this mode.
Defaults to Flat shading. Examples:
Smooth:
Flat: 
Enabling lighting will allow the shading
engine to render appropriate highlights and shade on the model. Disabling will
simply render using flat colours. Defaults to Enabled. Examples:
Enabled:
Disabled: 
The orc model is loaded dynamically from a file during initialisation. I used a custom file format (that I've dubbed OB2), that expands on and alters the existing OBJ standard to suit the programs needs. It now supports:
The data is saved as plain text. The format is detailed in the
source code comments in the loadModel() function.
The data is loaded into a fairly complex data structure, so that all
segments can be easily accessed, moved, rotated and drawn. The main
storage components are arrays, allocated to the sizes specified by the
files. Any cross-model referencing is done with array indices, e.g. face
-> vertices, animation keyframes -> segments.
The orcoid model itself was built using Kludge3D, a straightforward
polygonal modeller for linux. I modelled each segment individually, as I
would otherwise need to implement mesh warping and a bone system, which is
more complex. I created the model using the following heirarchy:
Root
\_Torso
|_Head
| |_Eyes
| |_Jaw
| \_Teeth
|_RightUpperArm
| \_RightLowerArm
| \_RightHand
| \_Blade
|_LeftUpperArm
| \_LeftLowerArm
| \_LeftHand
| \_Shield
\_Hips
|_RightThigh
| \_RightCalf
| \_RightHindfoot
| \_RightToes
\_LeftThigh
\_LeftCalf
\_LeftHindfoot
\_LeftToes
When drawing the model, it starts with the first segment, and renders each mesh recursively for all of its children. This allows all of the offsets and rotations to be relative to the current segment, which makes positioning segments for stances/animations straightforward.
As mentioned in the last section, animations / stances are included in the OB2 model format, and hence are loaded at runtime with the rest of the mesh and stance data. Each stance is simply a list of X, Y, Z rotations, one set for each segment of the model. The animations are simply an extrapolation of that, with multiple stances being store per animation. The frames are interpolated linearly in real-time, to smooth the movement.
The orc models are effectively cloned (redrawn at new positions) to create a platoon of up to 10 x 10 orcs on the field. These are specified at the command line, or default to 10 x 10. Their positions are based on a strict row by column loop, but with added randomness to give the appearance of a dishelved beastial army, rather than the strict regemented look of disciplined human armed forces.
Not true terrain however. A "rock" model is loaded in addition to the orc model (same format), and a set number of rocks are randomly scattered, rotated, scaled and then drawn in the scene. This was a very straightforward way to make the scene more interesting, and also give a point of reference.
Each segment of each model has a specularity number assigned to it. If set to 1, then a specular highlight will be added to the rendering of that segment. This gives a nice appearance when added to armour, weapons, etc. In addition, the light sources were altered to reflect a more realistic, outdoor environment. The main light source has a yellow tinge, whilst the secondary or back light source is blue, giving a more interesting look to the scene.
A rather cheap and nasty effect, though it does improve the look of the scene. The flat ground is simply two polygons, stretched to the clipping plane. Each vertex is given a colour, and smooth shading is forced to create a gradient effect. This allowed me to create a "sunrise" effect, on the ground at least, whereby the ground appears lighter in one direction, and darker in the other. This has been aligned to suit the light sourcing as mentioned above.
The program was initially designed around the robot-arm example, as it had
some good examples of joint manipulation. I then attempted to work on some
basic animation functions, with linear interpolation, however this quickly
led to my next requirement, being a file format.
Being fairly familiar with polygonal modelling, I decided early on to
develop my own file format, one that could be easily converted from
existing formats. After fumbling around with Blender, I stumbled upon
kludge3d, a free, open-source polygonal modeller for linux. As this
supported the .OBJ model format, I decided to modify and expand upon it,
as detailed above in the Model / Mesh subsystem section.
After I had modelled all of the segments, I constructed a stance format,
and a simple function to save the current stance to disk. Thereby I could
easily create new stances, and later, new animations. Once I had the main
stances done, I went to work on the 2D "User Interface".
After messing around with the FPS display, I eventually created a simple "wrapper" for
rendering all of the 2D elements: a function that accepts a string, and x, y positions
as inputs, sets up the correct 2D matrix and renders the text with the (globally)
selected font. However it was also around this point that I noticed a
significant FPS drop, one that I don't think I successfully fixed. In any
case, I then finally moved on to animations.
I designed a simple keyframe animation model, where each frame is simply a
stance with a "time" value, that defines how many milliseconds after the
initial frame that it occurs. Now a long way into development, I finally
implemented the linear interpolation and animation functionality I
intended to write at the beginning. This took a lot longer to implement
that it should, as I spent hours trying to reason out why my animation was
running backwards, or worse, running out of control. After careful
analysis it came down to a typo in the interpolation formula that somehow
eluded me.
For the final touches, I decided to create a random rocky terrain, and
render a platoon of orcs, of variable size. These were fairly easy to
implement, as the additional orcs are merely clones, offset and redrawn
from the initial orc, and the terrain randomised versions of a single rock
model.
Given more time, here a few additions I would like to have made. These are just the more unique ideas I had, I've left out more generic additions such as texture mapping.
Early blue skinned orcs, simple stance.
Blue orcs again, charge animation.
Blue orcs paused during mid-swing.
100 red orcs on a rocky field - Wireframe.
100 red orcs on a rocky field - Smooth shaded.
Sleeping blue skinned orcs - Wireframe.
Sleeping blue skinned orcs - Flat shaded.
First known screenshot, barely an extension of the robot arm
example.
Green skinned orcs during earlier testing.
The first brighter red orcs.
Recent version, showing psuedo-lighting
effects on the ground, and a secondary light source.
Latest version, similar to above but with
increased ambient lighting.