The CAR files are used in Carnivores, Carnivores 2, and Carnivores Ice Age as 3D model files for the animals and hunter, weapons, dropship, and wind indicator, and are located in the \HUNTDAT folder (in Carnivores 2 and Ice Age, the weapon CAR files are instead located in \HUNTDAT\WEAPONS). The 3DF format is a simplified version of this format.


There are several parts of the source code that handle CAR files.


Several parts in Hunt.h define the structure of CAR files. This code defines the overall structure:

typedef struct _TCharacterInfo {
  char ModelName[32];
  int AniCount,SfxCount;
  TModel* mptr;
  TAni Animation[64];
  TSFX SoundFX[64];
  int  Anifx[64];
} TCharacterInfo;

This code defines the structure of TModel:

typedef struct TagMODEL {
    int VCount, FCount, TextureSize, TextureHeight;
    TPoint3d gVertex[1024];    
    union {
     TFace    gFace  [1024];
     TFacef   gFacef [1024];
    WORD     *lpTexture, *lpTexture2, *lpTexture3;
#ifdef _d3d
    int      VLight[4][1024];
    float    VLight[4][1024];
} TModel;

Note that the actual format doesn't store TextureHeight; while this variable is used elsewhere in the source, it is never actually loaded from CAR files. In addition, TPoint3d (which defines the structure of vertices) appears above TFace/TFacef (which define the structure of faces) in this definition, even though the actual files reverse this order.

This code defines the structure of TPoint3D:

typedef struct _Point3d {
	float x; 
	float y; 
	float z;
	short owner; 
	short hide;
} TPoint3d;

This code defines the structure for TFace and TFacef:

typedef struct _Face {
   int v1, v2, v3;   
#ifdef _soft
   int   tax, tbx, tcx, tay, tby, tcy;
   float tax, tbx, tcx, tay, tby, tcy;
   WORD Flags,DMask;
   int Distant, Next, group;
   char reserv[12];  
} TFace;
typedef struct _Facef {
   int v1, v2, v3;   
   float tax, tbx, tcx, tay, tby, tcy;
   WORD Flags,DMask;
   int Distant, Next, group;
   char reserv[12];  
} TFacef;

These are nearly identical, except that TFace uses integers instead of floats for tax, tbx, tcx, tay, tby, and tcy if _soft is defined.

This code defines the structure for TAni:

typedef struct _Animation {
  char aniName[32];
  int aniKPS, FramesCount, AniTime;
  short int* aniData;
} TAni;

This code defines the structure for TSFX:

typedef struct _SoundFX {
  int  length;
  short int* lpData;


This code loads animations for animals:

//============= read animations =============//
   for (int a=0; a<chinfo.AniCount; a++) {
     ReadFile(hfile, chinfo.Animation[a].aniName, 32, &l, NULL);
     ReadFile(hfile, &chinfo.Animation[a].aniKPS, 4, &l, NULL);
     ReadFile(hfile, &chinfo.Animation[a].FramesCount, 4, &l, NULL);
     chinfo.Animation[a].AniTime = (chinfo.Animation[a].FramesCount * 1000) / chinfo.Animation[a].aniKPS;
     chinfo.Animation[a].aniData = (short int*) 
         _HeapAlloc(Heap, 0, (chinfo.mptr->VCount*chinfo.Animation[a].FramesCount*6) );
     ReadFile(hfile, chinfo.Animation[a].aniData, (chinfo.mptr->VCount*chinfo.Animation[a].FramesCount*6), &l, NULL);


// header (52 bytes)

byte(32) - ModelName, texture name (often the same as the name of the CAR file, but not always - e.g. the texture name in ALLO.CAR is "Rapt73"; the last 8 bytes are normally "msc: #", where "#" is a number)
long     - AniCount, number of animations
long     - SfxCount, number of sounds
long     - VCount, number of vertices
long     - FCount, number of faces
long     - TextureSize, texture length in bytes
// for each face (64 bytes)
long     - v1, vertex 1
long     - v2, vertex 2
long     - v3, vertex 3
long     - tax, texture vertex 1 X coordinate
long     - tbx, texture vertex 2 X coordinate
long     - tcx, texture vertex 3 X coordinate
long     - tay, texture vertex 1 Y coordinate
long     - tby, texture vertex 2 Y coordinate
long     - tcy, texture vertex 3 Y coordinate
short    - flags:
bit       - sfDoubleSide (0x0001; marks face as textured on both sides)
bit       - sfDarkBack (0x0002; marks face as having a dark back side)
bit       - sfOpacity (0x0004; marks face as transparent)
bit       - sfTransparent (0x0008; marks face as non-solid (bullets pass through harmlessly))
bit       - sfMortal (0x0010; marks face as a target zone)
bit       - sfPhong? (0x0030; marks face as Phong mapped)
bit       - sfEnvMap? (0x0050; marks face as Environment mapped)
bit       - sfNeedVC (0x0080)
bit(7)    - unknown/unused (0x0100–0x4000)
bit       - sfDark (0x8000; marks face as having a dark front side)
short    - DMask (appears to be unused in the actual code)
long     - Distant (purpose unknown; "Distant" is used in RenderSoft.cpp but doesn't seem to be loaded from files)
long     - Next (some sort of index to other faces?)
long     - group (appears to be unused in the actual code)
byte(12) - reserv (unused bytes reserved for future use)
// for each vertex (16 bytes)
float    - X coordinate
float    - Y coordinate
float    - Z coordinate
short    - owner, bone to which vertex is attached
short    - hide, whether the vertex is hidden (?)
byte(x)  - texture (16-bit TGA-style encoding in ARGB1555 format, always 256 pixels wide)
// for each animation (40 + (6 * num_vertices) bytes)
byte(32) - aniName, name of the VTL file the animation was loaded from
long     - aniKPS, time between keyframes ("KPS" therefore may stand for "keyframes per second")
long     - FramesCount, number of frames
// for each frame (6 * num_vertices bytes)
// for each vertex (6 bytes)
short    - X coordinate
short    - Y coordinate
short    - Z coordinate
// for each sound
byte(32) - name
long     - length
byte(x)  - data (16-bit mono PCM @ 22050 Hz)
long(64) - animation/sound cross-reference table

External links

Community content is available under CC-BY-SA unless otherwise noted.