Author Topic: G3Dv3 File format spec  (Read 11132 times)

martiño

  • Behemoth
  • *******
  • Posts: 1,095
    • View Profile
G3Dv3 File format spec
« on: 18 May 2004, 21:07:47 »
WARNING: this spec is for G3Dv3 Glest now uses G3Dv4, please take a look to model_header.h and model.h/cpp to know about G3Dv4. I will probabbly update this spec soon for G3Dv4.

Many people is asking us for plugins/converters for non-3dsmax platforms. We don't have the time to spend in this task, so that's we decided to publish the G3D spec. That way anyone can make its own plugins/converters. If anyone needs further explainations use this board, or mail us to: theproject 'at' glest 'dot' org

This is a spec for G3D (Glest 3D) file format, this spec will be included in future versions of the Glest Editor Pack.

G3D (Glest 3D) version 3 file format specificacion. v0.1.

1. DATA TYPES
================

G3D files use the following data types:

uint8: 8 bit unsigned int
uint32: 32 bit unsigned int
float32: 32 bit float

2. MODEL HEADER
===============

Every g3d file starts by a model header:

struct ModelHeader{
   uint8 id[3];
   uint8 version;
   uint32 meshCount;
};

id: identifier, must be be "g3d"
version: g3d file version, must be 3 (not '3')
meshCount: the number of meshes in the model

3. MESHES
===============

After the model header they come the meshes, each mesh has it's own header:

struct MeshHeader{
   uint32 vertexFrameCount;
   uint32 normalFrameCount;
   uint32 texCoordFrameCount;
   uint32 colorFrameCount;
   uint32 pointCount;
   uint32 indexCount;
   uint32 properties;
   uint8 texName[64];
};

vertexFrameCount: number of vertex frames in the mesh
normalFrameCount: number of normal frames in the mesh, this value has to be 0, 1, or the same as vertexFrameCount
texCoordFrameCount: number of texture coordinate frames in the mesh, this value has to be 0, 1, or the same as vertexFrameCount
colorFrameCount: number of color frames in the mesh, this value has to be 1, or the same as vertexFrameCount
pointCount: number of vertices per frame
indexCount: number of indices in the mesh
properties: additional properties of the mesh:

enum MeshProperty{
   mpNoTexture= 1,
   mpTwoSided= 2,
   mpCustomTexture= 4
};

mpNotexture: this mesh has not a texture
mpTwoSided: this mesh is two sided
mpCustomTexture: replace alpha in the texture by a custom texture (user for faction colors)


texName: texture file (in tga format), path is relative to this file path

After each mesh is comes the mesh data:

vertices: vertexFrameCount * pointCount * 3, float32 values representing the x, y, z vertex coords for all frames
normals: normalFrameCount * pointCount * 3, float32 values representing the x, y, z normal coords for all frames
texture coords: texCoordFrameCount * pointCount * 2, float32 values representing the s, t tex coords for all frames
colors: colorFrameCount * 4, float32 valuesrepresenting the r, g, b, a coords for all frames
indices: indexCount, uint32 values representing the indices


4. EXAMPLES
===============

Here is the C++ code for saving a G3D file:

//save a model to a g3d file
void Model::saveG3d(const string &path){
   
   FILE *f= fopen(path.c_str(), "wb");
   if(f==NULL){
      throw runtime_error("Can't open file for writting: "+path);
   }

   ModelHeader modelHeader;
   modelHeader.id[0]= 'G';
   modelHeader.id[1]= '3';
   modelHeader.id[2]= 'D';
   modelHeader.version= 3;
   modelHeader.meshCount= meshCount;

   string dir= cutLastFile(path);

   fwrite(&modelHeader, sizeof(ModelHeader), 1, f);
   for(int i=0; i<meshCount; ++i){
      meshes.save(dir, f);
   }

   fclose(f);
}

void Mesh::save(const string &dir, FILE *f){
   MeshHeader meshHeader;
   meshHeader.vertexFrameCount= vertexFrameCount;
   meshHeader.normalFrameCount= normalFrameCount;
   meshHeader.texCoordFrameCount= texCoordFrameCount;
   meshHeader.colorFrameCount= colorFrameCount;
   meshHeader.pointCount= pointCount;
   meshHeader.indexCount= indexCount;
   meshHeader.properties= 0;

   if(twoSided) meshHeader.properties|= mpTwoSided;
   if(customTexture) meshHeader.properties|= mpCustomTexture;

   if(texture==NULL){
      meshHeader.properties|= mpNoTexture;
      meshHeader.texName[0]= '\0';
   }
   else{
      strcpy(reinterpret_cast<char*>(meshHeader.texName), texName.c_str());
      texture->getPixmap()->saveTga(dir+"/"+texName);
   }
   
   fwrite(&meshHeader, sizeof(MeshHeader), 1, f);
   fwrite(vertices, sizeof(Vec3f)*vertexFrameCount*pointCount, 1, f);
   fwrite(normals, sizeof(Vec3f)*normalFrameCount*pointCount, 1, f);
   fwrite(texCoords, sizeof(Vec2f)*texCoordFrameCount*pointCount, 1, f);
   fwrite(colors, sizeof(Vec4f)*colorFrameCount, 1, f);
   fwrite(indices, sizeof(uint32)*indexCount, 1, f);
}
« Last Edit: 9 June 2005, 18:44:19 by martiño »

StrikerShot21

  • Guest
(No subject)
« Reply #1 on: 25 May 2004, 21:07:50 »
It would be a good idea to NOT make a G3D importer. That way no one could steal your models that you used in your game. ;)
« Last Edit: 1 January 1970, 00:00:00 by StrikerShot21 »

enveloop

  • Guest
(No subject)
« Reply #2 on: 22 April 2005, 00:41:39 »
Only the code is opensource under GPL, the data isn´t.
« Last Edit: 1 January 1970, 00:00:00 by enveloop »

martiño

  • Behemoth
  • *******
  • Posts: 1,095
    • View Profile
(No subject)
« Reply #3 on: 26 May 2005, 18:59:13 »
We have to think about the license for the data. In the case of the models the problem you may have is that they are in G3D format, so you will not able to modify them, apart from that I dont think that tucho will care if you modify textures or any other stuff.
« Last Edit: 1 January 1970, 00:00:00 by martiño »

StrikerShot21

  • Guest
(No subject)
« Reply #4 on: 30 May 2005, 04:42:46 »
What I meant was I made a bunch of models for my game and I would hate to have some idiot use a G3D importer to steal my models and mis-use them.
« Last Edit: 1 January 1970, 00:00:00 by StrikerShot21 »

sackofcatfood

  • Guest
(No subject)
« Reply #5 on: 30 May 2005, 08:01:00 »
It's your job to enforce your own copyrights... I don't think development of new model making plugins should be hampered just to make extracting models more difficult.

How much sense does it make to open source a project and then try to obscure the way the sourcecode works?
« Last Edit: 1 January 1970, 00:00:00 by sackofcatfood »

StrikerShot21

  • Guest
(No subject)
« Reply #6 on: 30 May 2005, 16:14:25 »
All I'm sayign is having a G3D importer is a bd idea. G3D exporting is fine with me. I just don't think giving people the oppertunity to steal the models used in game is a wise idea. How would you feel if you worked on hard on making a mod for this game and I stole all of the models you used?
« Last Edit: 1 January 1970, 00:00:00 by StrikerShot21 »

martiño

  • Behemoth
  • *******
  • Posts: 1,095
    • View Profile
(No subject)
« Reply #7 on: 30 May 2005, 17:55:38 »
I'm not going to make any G3D importer, and I doubt that such thing will ever exist.
« Last Edit: 1 January 1970, 00:00:00 by martiño »

enveloop

  • Guest
(No subject)
« Reply #8 on: 30 May 2005, 23:19:20 »
If only for the sake of priorities, that would be the last one on the list.
« Last Edit: 1 January 1970, 00:00:00 by enveloop »

martiño

  • Behemoth
  • *******
  • Posts: 1,095
    • View Profile
(No subject)
« Reply #9 on: 30 May 2005, 23:33:08 »
The importer isn't even on the list of priorities, it's simply useless.
« Last Edit: 1 January 1970, 00:00:00 by martiño »

StrikerShot21

  • Guest
(No subject)
« Reply #10 on: 31 May 2005, 22:14:07 »
Good, now I don't have to worry about model stealing.
« Last Edit: 1 January 1970, 00:00:00 by StrikerShot21 »

seltsamuel

  • Guest
(No subject)
« Reply #11 on: 9 June 2005, 11:27:10 »
Ups thats me above  :O
I wrote so long that my session must have expired
« Last Edit: 1 January 1970, 00:00:00 by seltsamuel »

MatzeB

  • Guest
Re: Did i get it right ? and some Question for Blender Im/Ex
« Reply #12 on: 9 June 2005, 14:47:11 »
I didn't look at the format myself yet, but I can guess a bit from martinios description above :)

Model Header is easy no Question.

Some Definitions to Clarify

As a Mesh u call a static Model ?
So Meshcount is the Number of Animationsteps -1 ?
[/quote]
A model is composed from multiple meshs. A mesh has 1 texture and a set of triangles (so usually you will have as many meshs as textures probably...).
The meshs itself seem to be keyframe animated. vertexFrameCount seems to be the number of frames that the animation has. normal-, texCoord-, colorFrameCount are probably there so that you can say to either not specify them, specify them once for all frames or specify values for each frame separately.

Quote
The Vertex is a single Point of which consists the Model ?
When u mean Vertexframe u mean a FACE ?
The Face in your Format is a Triangle or a Rectangle of Vertex
depending on the Value of Pointcount ?
Rectangles and Triangles cannot be mixed.
The Number of Vertexframes is the complete number of ALL Faces ? visible or not colored or not textured or not ?
A vertex is a point in the 3d model. The number of vertices is defined in the pointCount variable and is constant for all animation frames. If you have the list of vertices, you can construct triangles out of them. The indexCount variable seems to count the number of indices into the vertex list, so a mesh should be constructed out of indexCount/3 triangles...

The number of vertices and triangle is staying constant for the whole animation. The thing that is animated are the positions of the vertices. And eventually the normals, texture Coordinates and texture colors (if their count was not 0 or 1).

Quote
Normalframes are FACES pointing to the Viewer so that he can see the Surface (they are Visible textured or colored) ?
In which case they have to be 0 or 1 or number of vertices ?
0 = no normals 1 = all faces use this value or 1 value for each of the Vertexframes (Faces) ???

The same is right for texure Coord ?

The same is right for ColorFrame ??
Why is there no 0 ? maybe is ther no color but only texture ?

indexCount: number of indices in the mesh ??
What means an indice ? i could not figure it out im too stupid :O
Please explain me that thing.
normals are the normal vector and are specified per triangle face. Sometimes it makes sense to adjust them a bit to make lighting more smooth (that's why they're explicitely saved here and not just calculated while loading). See above for meaning of 0,1,frames

index is an index into the vertex list. See above.

Quote
The Properties are no problem but

mpTwoSided: this mesh is two sided
means it that all FACES are rendered from both sides ? (2 sided normals)
Yes the properties seem to be affect a whole mesh including all animation frames.

Hope this helps you get an im/exporter running. Unfortunately I don't have time to run such projects myself.

Greetings,
       Matze
« Last Edit: 19 June 2016, 06:20:07 by filux »

MatzeB

  • Guest
Re: Did i get it right ? and some Question for Blender Im/Ex
« Reply #13 on: 9 June 2005, 15:00:44 »
Quote from: Anonymous
No problem to understand but did u ever thought about using PNG ?
I tested to convert the TGA´s to PNG there is mostly more than 50% saved space without loss maybe u should consider using PNG for TGA and BMP grafix. The lib is easy to get/use and has a nice license www.libpng.org
and its a free graphics standard.

About that, png have the disadvantage that you have to learn and link in an extra library while tga can be loaded with a few hundret lines of code (also in my experience windows coders don't use as much external libraries as linux coders... maybe because they had more bad experiences with that on windows :)

The more important point is probably that loading pngs takes considerably longer than loading tga images. If you want to have fast loading times in your game, then you should use simple formats like bmp or tga.
« Last Edit: 19 June 2016, 06:19:54 by filux »

martiño

  • Behemoth
  • *******
  • Posts: 1,095
    • View Profile
(No subject)
« Reply #14 on: 9 June 2005, 18:41:52 »
Matze has already answered most of your questions, however i will try to explain a bit more in depth how the G3D format works.

Current G3D forma version is "v4", many of the concepts in previous versions like "normalFrameCount" or "colorFrameCount" have disappeared, they are in model_header.h just for backwards compatibility.

G3Dv4 comes from "Glest: Duelfield", a project that is now dead, but we made some work on it and improved the model format since v3, thats we are using it now for Glest.


Basic model structure:

A model is composed by several meshes, each mesh has properties, textures and several frames. In G3Dv4 only vertex positions and normals are stored for every frame, materials and texture coordinates are only stored once per mesh (in G3Dv3 they could be stored for every frame, and normalFrameCount and texCoordFrameCount indicated how many frames were stored, but this stuff is no used any more).

And now a brief explaination on the G3Dv4 data in model_header.h:

Code: [Select]
struct FileHeader{
uint8 id[3];
uint8 version;
};

This header is shared among all versions, id must be "G3D" and version must be 4 (in binary, not the character 4).

//version 4
Code: [Select]
struct ModelHeader{
uint16 meshCount;
uint8 type;
};

enum ModelType{
mtMorphMesh
};



meshCount: the number of meshes in this model
type: the type of file, by now only mtMorphMesh is supported, and its value is 0


Code: [Select]
enum MeshPropertyFlag{
mpfTwoSided= 0,
mpfCustomColor= 1,
};


Properties for a mesh, mpfTwoSided means that all the triangles are renderer by both sides, if this property is not se only "counter clockwise" faces are rendered. mpfCustomColor means that the alpha in the current texture is replaced by a custom color, usually de color of the player team (used to distinguish your units from the enemy ones).



Quote
enum MeshTexture{
   mtDiffuse,
   mtSpecular,
   mtNormal,
   mtReflection,
   mtColorMask,

   meshTextureCount
};

Quote
const uint32 meshNameSize= 64;
const uint32 mapPathSize= 64;

struct MeshHeader{
   uint8 name[meshNameSize];
   uint32 frameCount;
   uint32 vertexCount;
   uint32 indexCount;
   float32 diffuseColor[3];
   float32 specularColor[3];
   float32 specularPower;
   float32 opacity;
   uint32 properties;
   uint32 textures;
};



name: name of the mesh
fameCount: number of key frames in this mesh
vertexCount: number of vertices in each key frame
indexCount: number of indices
diffuseColor: RGB value for the color of this mesh
specularColor: not used currently
specularPower: not used by now
opacity: opacity of this mesh
properties: property flags
textures: textures in this mesh, usually this value is 1, indicating a single diffuse texture
« Last Edit: 1 January 1970, 00:00:00 by martiño »

 

anything