UnigineScript
The Language
Core Library
Engine Library
Node-Related Classes
GUI-Related Classes
Plugins Library
High-Level Systems
Samples
Usage Examples
C++ API
API Reference
Integration Samples
Usage Examples
C++ Plugins
Migration
Migrating to UNIGINE 2.0
C++ API Migration
Migrating from UNIGINE 2.0 to UNIGINE 2.1

Mesh File Formats

Unigine supports the following mesh file formats for common and skinned meshes:

  • *.mesh, which is used for static geometry
  • *.smesh, which is used for animated characters
  • *.sanim, which contains animation for *.smesh files

It is also possible to convert meshes of external formats to Unigine-supported mesh formats by using the MeshImport tool.

Here are some general notes that are valid for any mesh format.

  • All data is in the little-endian notation.
  • float is a 32-bit IEEE754 floating-point type. It has a range of 3.4 e-38 to 3.4 e+38.
  • int is a signed 32-bit two's complement integer. It has a range of –2,147,483,648 to 2,147,483,647.
  • unsigned short is an unsigned 16-bit integer. It has a range of 0 to 65,535.
  • char is a signed 8-bit two's complement integer. It has a range of -128 to 127.
  • unsigned char is a 8-bit unsigned integer. It has a range of 0 to 255.
  • string must be null terminated. The string size should include this terminating null character.
  • All formats allow multiple surfaces.

Compression of Normals

Compression of normalized floating-point normals into unsigned short format is performed in the following way:

Source code (UnigineScript)
x = (unsigned short)(clamp((int)((normal.x * 0.5f + 0.5f) * 65535.0f),0,65535));
y = (unsigned short)(clamp((int)((normal.y * 0.5f + 0.5f) * 65535.0f),0,65535));
z = (unsigned short)(clamp((int)((normal.z * 0.5f + 0.5f) * 65535.0f),0,65535));
Here:
  • normal is a normalized float normal.
  • x, y and z are unsigned short compressed normals.

Mesh

This is a universal file format for static geometry.

MESH File Format

  1. File format identifier (int "mi08" ('m' | ('i' << 8) | ('0' << 16) | ('8' << 24)))
  2. Bounding volume of the whole mesh:
    • Mesh bounding box minimum (float[3])
    • Mesh bounding box maximum (float[3])
    • Mesh bounding sphere center (float[3])
    • Mesh bounding sphere radius (float)
  3. Number of surfaces (int)
  4. Header information for each of mesh surfaces:
    • Name of the surface. It is a null-terminated string that contains:
      1. The number of characters in the string including the null character (int). 1024 characters is the maximum.
      2. Surface name of the specified length (char[length])
    • Bounding box minimum for the current surface (float[3])
    • Bounding box maximum for the current surface (float[3])
    • Bounding sphere center for the current surface (float[3])
    • Bounding sphere radius for the current surface (float)
  5. Surface data for each of mesh surfaces:
    • Number of vertices in a surface (int)
    • For each vertex:
      1. Vertex position along X, Y and Z axes (float[3])
      2. Three-component normal (unsigned short[3])
    • Vertex texture coordinates:
      1. Number of texture coordinates 0, i.e. the number of texture coordinates in the 1st UV set (int)
      2. For each of texture coordinates 0:
        • UV texture coordinates 0 (float[2])
      3. Number of texture coordinates 1, i.e. the number of texture coordinates in the 2nd UV set (int)
      4. For each of texture coordinates 1:
        • UV texture coordinates 1 (float[2])
    • Number of triangles in a surface (int)
    • For each triangle, three vertex indices are stored:
      • If the number of vertices is lower than 65536 (unsigned short indices[3])
      • If the number of vertices is greater or equal 65536 (int indices[3])

Skinned Mesh

Skinned meshes are used for animated characters or machinery. Bone-based animation provides optimal performance, because it is very memory-efficient.

There are two types of skinned meshes:

  • Containing both mesh data (vertices and their weights) and animation (bones and their transformations). This variant of storing mesh together with animation data in one file is less flexible and more memory consuming. Use it only for small animation sequences.
  • Containing only mesh data, i.e. the bind pose. This approach is useful, if you prefer to put additional animation out to separate files.

Notice
  • Zero frame is a bind pose frame.
  • A single-frame SMESH file is the skinned mesh bind pose.

SMESH File Format

  1. File format identifier (int "ms08" ('m' | ('s' << 8) | ('0' << 16) | ('8' << 24)))
  2. Number of bones (int)
  3. Header information for each bone:
    • Name of the bone. It is a null-terminated string that contains:
      1. The number of characters in the string including the null character (int). 1024 characters is the maximum.
      2. Bone name of the specified length (char[length]).
    • Parent of the bone (int). If case of the root bone without a parent, -1 is used.
  4. Number of frames in bone-based animation (int)
  5. Transformation data for each bone in each frame:
    • Bone position along along X, Y, Z axes; W component stores the bone scale in all directions (float[4])
    • Bone rotation quaternion (float[4])
  6. Number of surfaces in the skinned mesh (int)
  7. Header information for each of skinned mesh surfaces:
    • Name of the surface. It is a null-terminated string that contains:
      1. The number of characters in the string including the null character (int). 1024 characters is the maximum.
      2. Surface name of the specified length (char[length])
  8. Surface data for each of skinned mesh surfaces:
    • Number of vertices in a surface (int)
    • For each vertex:
      1. Vertex position along X, Y, Z axes (float[3])
      2. Three-component normal (unsigned short[3])
      3. Number of vertex weights (unsigned char)
      4. For each vertex weight:
        • A bone to which the vertex is attached (unsigned short)
        • Vertex weight (unsigned char). 255 is the maximum.
    • Vertex texture coordinates:
      1. Number of texture coordinates 0, i.e. the number of texture coordinates in the 1st UV set (int)
      2. For each of texture coordinates 0:
        • UV texture coordinates 0 (float[2])
      3. Number of texture coordinates 1, i.e. the number of texture coordinates in the 2nd UV set (int)
      4. For each of texture coordinates 1:
        • UV texture coordinates 1 (float[2])
    • Number of triangles in a surface (int)
    • For each triangle, three vertex indices are stored:
      • If the number of vertices is lower than 65536 (unsigned short indices[3])
      • If the number of vertices is greater than or equal to 65536 (int indices[3])

Skinned Mesh Animation

Skinned mesh animation format contains only animation for SMESH files. They are useless without a "base" skinned mesh in its bind pose that contains vertices and their weights.
SANIM files store animation data more efficiently than one SMESH file that contains both a mesh and bones transformations. That is the reason why SANIM files are ideal for long animations.

If you need to load such a file in a script, treat it like a SMESH animation file.

SANIM File Format

  1. File format identifier (int "as08" ('a' | ('s' << 8) | ('0' << 16) | ('8' << 24)))
  2. Number of bones in skinned animation (int)
  3. Header information for each bone:
    • Name of the bone. It is a null-terminated string that contains:
      1. The number of characters in the string including the null character (int). 1024 characters is the maximum.
      2. Bone name of the specified length (char[length])
    • Parent of the bone (int)
  4. Bounding box within which animation takes place:
    • Bounding box minimum along X, Y and Z axes; and the minimum bone scale in the W component (float[4])
    • Bounding box size and the bone scale spread in the W component (float[4]). This size = xyz_max - xyz_min.
  5. Number of skinned animation frames (int)
  6. Transformation data for each bone in each frame:
    • Sets a flag (unsigned char), each 8 bits of which determine if the current frame should store (or read) new translation, scale or rotation components for the bone. If these components have not changed since the previous frame, new data is not stored. Instead, data from the previous frame is used, which maximizes the efficiency of memory usage.
    • If the data is flagged as changed, for each component of the bone:
      1. Translation of the bone along X (unsigned short)
      2. Translation of the bone along Y (unsigned short)
      3. Translation of the bone along Z (unsigned short)
      4. Scale of the bone in all directions in W component (unsigned short)
      5. X component of the rotation quaternion for the bone (unsigned short)
      6. Y component of the rotation quaternion for the bone (unsigned short)
      7. Z component of the rotation quaternion for the bone (unsigned short)
      8. W component of the rotation quaternion for the bone (unsigned short)
      These position and rotation values are specified inside of the calculated bounding box: as a coordinate between its minimum and its maximum (a value in range from 0 to 65535).
Last update: 2017-07-03