6. The Sprite models

(Thanks to Raphaël Quinet who wrote most of this section)

General description of Sprites

The sprites are used in Quake to represent objects that could not be rendered properly using polygons (because of a shape with too many small details) or that were not worth the trouble of using polygons (they render faster than Alias models or BSP based models).

The sprites are essentially designed for stuff like explosions, fire, magical effect, or the like. They can also be used for simple objects that have a vertical axis of rotation, like torches or barrels.

The format of the sprites is rather simple. Basically, this is a list of 2D pictures (flat bitmaps) organized in lumps.

Some frames are grouped in animation sequences, that start with the first picture in the animation and automatically proceed to the next, at the time values indicated in the beginning of the sequence.

6.2 The Format of .SPR files

The sprite files (.SPR) begin with a header, which is immediately followed by the list of frames. There are no pointers to the individual pictures, which means that the engine probably reads and parses the whole file once and for all, because the only way to access a given picture is to read all previous frames and know their width and height.

6.2.1 Sprite file header

Here is the format of the .SPR file header:

typedef struct
{ char name[4];                // "IDSP"
  long ver1;                   // Version = 1
  long type;                   // See below
  float radius;                // Bounding Radius
  long maxwidth;               // Width of the largest frame
  long maxheight;              // Height of the largest frame
  long nframes;                // Number of frames
  float beamlength;            // 
  long synchtype;              // 0=synchron 1=random
} spr_t;

The size of this header is 0x24 bytes.

Type of sprites:

6.2.2 Sprite frames

There are two types of frames. Most of them contain a single picture, but some of them (in s_torch.spr and shots.spr) contain multiple pictures associated with floating point values.

The first kind of frames are marked with a leading (long) zero, followed by the picture data:

  long group;                 // Always 0 for single-picture frames
  picture pic;                 // Picture data, see below

The second kind of frames are marked with a leading 0x1 or 0x10000000, followed by the number of pictures, a list of floating point values, and a list of pictures:

  long group;                  // not zero (0x1 or 0x10000000)
  long npics;                  // Number of pictures
  float times[npics];          // 0.0, 0.2, 0.3, ...
  picture pic[npics];          // Pictures

The times are offsets that describe when the corresponding picture shall be displayed, relative to an animation frame that repeats regularly. 0.0 means start of the animation frame, and 1.0 is the end. So if you have npics pictures, and want a regular sequence of pictures, you will start from 0.0 and regularly increase the dates by 1/npics.

By the way... the above is just a wild guess. But what the heck can it be, if it's not time stamps?

6.2.3 Pictures

The format of each individual picture is given below. It contains the X and Y offsets, the width and height of the picture, followed by the list of pixels. The reference to the Quake palette is implicit and the value 0xFF denotes a transparent pixel.

typedef struct
{ long ofsx;                   // horizontal offset, in 3D space
  long ofsy;                   // vertical offset, in 3D space
  long width;                  // width of the picture
  long height;                 // height of the picture
  char Pixels[width*height];   // array of pixels (flat bitmap)
} picture;