-
Notifications
You must be signed in to change notification settings - Fork 0
CEM v2 Format
CEM is the model file format used in Empire Earth.
big thanks to @coderbot16 and the community for the help
by zocker-160 and @coderbot16
everything is in little endian
important: one CEM file can include multiple files + headers
CEM files start with a header, including the magic number, version, and model data as well as general model data.
Type | Name | Description | |
---|---|---|---|
u32 | magic number | Should always match 0x464D5353 or SSMF
|
|
u32 | CEM version | in this case 2
|
|
u32 | triangles / faces | How many triangles the model has in the largest LOD level | |
u32 | vertices | How many vertices the model has in each frame | |
u32 | tag points | How many tag points the model has in each frame | |
u32 | materials | How many materials the model has, must be at least 1 | |
u32 | frames | How many frames the model has, must be at least 1 | |
u32 | child models | How many children models this file has | |
u32 | lod levels | The number of levels of detail this model has, must be at least 1 | |
u32 | length of name
|
length of name + 1 (delimiter 0x00 ) |
|
string | name | The model's name | |
point3 | center | The center of the bounding box that contains every vertex in the model |
header = 52 + length of name
so if name is Scene Root
--> header = 63 bytes
Points, otherwise known as point3, represent a 3D point in space.
Type | Name | Description |
---|---|---|
f32 | x | X coordinate in space |
f32 | y | Y coordinate in space |
f32 | z | Z coordinate in space |
Vectors (vector3) have the same format.
Each level of detail contains a list of triangles, where each triangle is defined by 3 u32
s representing each vertex index. This corresponds to the concept of index buffers in computer graphics.
Organization:
- A single level of detail
- u32: number of triangles in this level of detail
- array of u32: the indices for each triangle, has a length of
triangle count * 3
- Another level of detail
- the number of LODs corresponds to the count in the header
length of one LOD level = 4 + triangle count
* 3 * 4
total length = SUM of all LOD levels
Next, the CEM file has an array of materials, with the number of materials specified in the header.
Important note! You MUST add vertex_offset to each of the indices in the corresponding triangles of each LOD level or else the parsed model will look very broken!
Type | Name | Description | |
---|---|---|---|
u32 | length of name
|
length of name + 1 (delimiter 0x00 ) |
|
string | name | The name of the material | |
u32 | texture index | The index of the texture used by this material | |
array | triangle selections | An array of (u32 offset, u32 length) pairs for each LOD level |
(1) |
u32 | vertex offset | The number to add to each triangle's vertex index | |
u32 | vertex count | The number of vertices that this material applies to | |
u32 | length of texture name
|
length + 1 (delimiter 0x00 ) |
|
string | texture name | The name of the texture used by this material |
(1) this defines which triangles get selected out of the indices array of each LOD level
the offset
+ length
of material 1 should be the same as the offset
of material 2 etc.
material = 20 + lod levels
* 8 + length of name
+ length of texture name
total length = SUM of all materials (usually 2)
After the materials the CEM file has an array of strings corresponding to each tag point, giving each tag point a name.
Type | Name | Description |
---|---|---|
u32 | length of name
|
length + 1 delimiter 0x00
|
string | name | name of tag point |
This is the most important part of the file, containing all the vertex data. CEM files use frame based animation (also known as mesh deformation animation) meaning that instead of having a system of formal bones, animations are created by simply changing the vertices and tag points that the model uses.
Type | Name | Description | |
---|---|---|---|
f32 | radius squared | Contains the maximum distance from the center point to any vertex, squared | (1) |
vertex array | vertices | The frame's vertices | |
point3 array | tag points | Positions of each tag point | |
4x4 matrix | transform | The matrix used to transform the vertices before rendering. Usually the identity matrix. | |
point3 | lower bound | Minimum values for each coordinate, forms the bounding box | |
point3 | upper bound | Maximum values for each coordinate, forms the bounding box |
(1) it seems this is being used to calculate the selection range for the object (if you set it to 0, you cannot select the model anymore by clicking on it)
Each vertex contains position, normal, and texture data.
Type | Name | Description |
---|---|---|
point3 | vertex | The position of this vertex in space |
vector3 | normal | The normal vector for this vertex, used for lighting |
point2 | texture | Contains the texture coordinate of this vertex. The material defines which texture this refers to. U (x) and V (y) are within the range 0.0 and 1.0. Note that you may need to flip the V coordinate with the expression 1.0 - v . |
4x4 matrices are used to transform vertices. (see transformation matrix ) They are in column major and in a homogeneous form. (see homogeneous coordinates )
It has to be applied to all vertices, otherwise the child models won't be in the right position or have the right rotation.
The format is an array of 16 f32
s corresponding to each element.
data type | width | s / u | range |
---|---|---|---|
s8 | 8 bits (1 byte) | signed | -128 to +127 |
s16 | 16 bits (2 bytes) | signed | -32,768 to +32,767 |
s32 | 32 bits (4 bytes) | signed | -2,147,483,648 to +2,147,483,647 |
s64 | 64 bits (8 bytes) | signed | −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
u8 | 8 bits (1 byte) | unsigned | 0 to +255 |
u16 | 16 bits (2 bytes) | unsigned | 0 to +65,535 |
u32 | 32 bits (4 bytes) | unsigned | 0 to +4,294,967,295 |
u64 | 64 bits (8 bytes) | unsigned | 0 to +18,446,744,073,709,551,615 |
point | 1,2,3 or 4 bytes | generic | |
f32 | 4 bytes IEEE 754 | signed |