Home » Community » Forums » » Loading and displaying .X files without DirectX
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Loading and displaying .X files without DirectX
Post Reply 
I have not read the article yet, but I did look at the source that comes with and this this is really neat! I always hear the question of how to use .X without DX, so this article should be of great use to those that thought it was impossible Thanks for the great article! I am looking forward to reading it now that I see it works

- Drew

 User Rating: 1933   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Absolutely the best article I've read. Great detail, exactly what I needed to understand the internals of the X file system. Great job.

Thanks again.
Jeff.

 User Rating: 1067   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Since the time I posted the article some references have evolved:

- WML math library: the site is gone with no forwarding adress. Instead you can have a look at the Ogre engine Math classes which seem to be inspired from the WML math library.

- MoonLabs: you will find the article in the resources section.

- XBDev: the site has died. I hope it will be put back one day as the tutorials were an interesting and thought provoking read.

Ghostly yours,
Red.

 User Rating: 1147   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Awesome! Thank you for that update. I am looking forward to reading the article this weekend

 User Rating: 1933   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

WML: math library can be found at http://www.geometrictools.com/
Wished there was redirection too. Always takes me a while to figure out where the site moved.

 User Rating: 1015    Report this Post to a Moderator | Link

I'm updating the links in the article. The xbdev site is obviously gone, but the page in question is cached on Archive.org

 User Rating: 2088   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Here is some additional food for thought:

I- Parsing binary X files:
this is not very hard when you read the microsoft X file description. The binary format is a tokenized representation of the text format. As such all the tokens I have described can be reused for the binary representations. The only difference is that there are a little more tokens to interpret (but the full list is given in the microsoft X file description).
Have a look at an example Mesh object.
Text Version:
Mesh Alpha { 3;
0.000000;0.000000;0.000000;,
1.000000;0.000000;0.000000;,
0.000000;1.000000;0.000000;;
1;
3;0,1,2;;
}

Binary version:
TOKEN_NAME, 4, 'M', 'e', 's', 'h',
TOKEN_NAME, 5, 'A', 'l', 'p', 'h', 'a',
TOKEN_OBRACE,
TOKEN_DWORD, 3,
TOKEN_FLOAT_LIST, 9, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
TOKEN_DWORD, 1,
TOKEN_INTEGER_LIST, 3, 0, 1, 2,
TOKEN_CBRACE

Be aware that the binary version of the vertex list may also be written as three TOKEN_FLOAT_LIST instead of a single one. It depends on the program which created the binary version.

As you can see, the algorithms used to read in text files can easily be derived to read in binary files.

II- Thoughts on code reuse:
After rereading my file, I discovered a class which was badly designed: the Framework::Mesh class.
If I want to create a Nav Mesh, this class will not be clean enough to be usable. Besides how to link the mesh navigation table to that class ?

After reflecting on this class I decided that a mesh was only composed of vertices and faces. Any other added informations were mesh properties (like materials, texture coordinates, normal vectors or mesh navigation table).

The mesh class thus becomes:
typedef enum {MESH_TEXTURECOORDS = 0, MESH_MATERIALS, MESH_NORMALS} MESH_PROPERTYTYPE;

struct Subset {
	uint16 Size;
	Face* Faces;
	};

class MeshProperty {
   protected:
      MESH_PROPERTYTYPE _Type;
   public:
      MeshProperty* IsProperty(MESH_PROPERTYTYPE pType);//returns this if the type corresponds
      virtual void UpdateIndices(void){};//used for concatenating meshes
};

class Mesh {
   public:
      Mesh(void):_nVertices(0), _Vertices(0),
      		 _nFaces(0), _Faces(0),                
                 _FirstVertex(0),          //used for mesh concatenation
                 _FirstFace(0)             //used for mesh concatenation
                 {};
      ~Mesh(void);
      Mesh* IsName(std::string &MeshName);//returns this if the name corresponds
      void UpdateIndices(void);//used when concatenating meshes
      void CreateSubsets(void);//creates subsets
      MeshProperty* GetProperty(MESH_PROPERTYTYPE pType);//returns the corresponding property
      //Vertices
      uint16 _nVertices, _FirstVertex;
      Vertex* _Vertices;
      //Faces
      uint32 _nFaces, _FirstFace;
      Face* _Faces;
      //Subset of a mesh: there is one subset for each material property used
      std::list<Subset*> _Subsets;
      //Mesh properties
      std::list<MeshProperty*> _Properties;
      std::string _Name;
};


Materials, texture coordinates and normal vectors properties are derived from the MeshProperty class.

Few modifications in the code are needed:
- Mesh::CreateSubsets,
- Model3D::ConcatenateMeshes,
- IOModelX::ProcessMeshTextureCoords, ProcessMeshNormals, ProcessMeshMaterials and ProcessMaterial,
- Object3D::Draw

This is simple to implement and as an added bonus clarifies the code. Now the Mesh class can be easily reused and augmented with new properties (navigation information, transition tables, face gravity centers, ...).

III - Performance
I have quickly timed my code after doing small improvements:
- use of OpenGL 1.1 vertex arrays.
- the sample calculates and displays three Object3D instances based on the same Model3D (tiny.x): that makes a display total of 20547 faces and 14679 vertices.

Here are the results with MinGW 3.4.2 and DevC++ 5:
- IBM S50 P4, Gfx Intel 815G, Win2K Pro: my FPS counter is blocked at the frame rate. I have not used the OpenGL extension on frame rate removal.
- Dell OptiPlex GX110 P3, Gfx Intel 810, Win NT4 sp6: 50 FPS.

That's all I wanted to say to complete the article.
Ghostly yours,
Red.

 User Rating: 1015    Report this Post to a Moderator | Link

Previous post was by me.
What is curious is that I was logged.
Ghostly yours,
Red.

 User Rating: 1147   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Loving this article, thanks a ton.

 User Rating: 1064   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I've got a question about the relation of bones and meshes.

A frame(bone) can contain other frames or meshes.

A mesh can contain a skinweights section per bone that cantains a skin offset matrix.

Doesn't this mean that every mesh can have an individual skin offset matrix for every bone and different meshes can have different skin offset matrices for the same bone?

So why is there only one skin offset matrix stored per bone?

 User Rating: 1042   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link



 User Rating: 1015    Report this Post to a Moderator | Link

nice article, but I cant port the code to linux :/
I removed the win code (timer class) and compiled the source but the program enter in loop when reading the material of the .x file.

anyone have compiled this code on linux?

 User Rating: 1015    Report this Post to a Moderator | Link

@muhkuh:
The Bone (or Frame) stores no skin offset matrices. The matrices stored within a bone only identify the position and rotation of a bone in relation to its parent.

The mesh contains the vertices and texture coordinates, and the skin offset matrices and vertices weights per bone. The aim of the skin matrices are to position the skin over the vertices of a bone, and the aim of the skin weights are to blend together the skin positions related to a vertex at the joint between bones.

This means that a mesh has an individual skin (thus a full set of skin offset matrices and skin weights).

Can different meshes reference the same set of Frames ?

In the DirectX format, a mesh block is always tied to a Frame:
- either by declaring the full mesh block within the Frame,
- or by declaring a reference to the mesh block within the Frame.

To my mind, after checking the documentation, Microsoft did not mean to have two meshes encompass the same set of Frames. It could be feasible but was not designed for. So within the X file format, the answer is no.

BUT we can extend the format to suit our needs (and extend the functionalities needed):
- either we store for the same skeletton different skins: we then keep the underlying structure but dramatically change its appearance (you can have a gorilla, a human zoo keeper and a human zoo visitor skin compatible with a single anthropoid bipedal skeletton).
- or we store special skins representing pieces of equipment: we can drape over the fully skinned body of a character a jacket skin, a trousers skin , etc...
However implementing these extensions require careful consideration to keep a compatible format with existing softwares.

I hope I answered your question.
Ghostly yours,
Red.


 User Rating: 1147   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Very helpful article!

neat, well-explained and to the point. certainly saved me a lot of headaches.

Thank you.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I have been reading lots of articles on this subject, and want to make sure i am understanding this correctly. Take a look at the simple armature below:



My goal is to figure out the values of 2 types matrices in the resultant .X file: 1 is the FrameTransformMatrix and the other is the OffsetMatrix (found in SkinWeights template)

From the picture, the .X file as I understand it should look like the following:

Frame Scene_Root {
   // set to identity
   FrameTransformMatrix {
      1.000000,0.000000,0.000000,0.000000,
      0.000000,1.000000,0.000000,0.000000,
      0.000000,0.000000,1.000000,0.000000,
      0.000000,0.000000,0.000000,1.000000;;
   }
   Frame Root {
      // also identity because the root is at the origin
      FrameTransformMatrix {
         1.000000,0.000000,0.000000,0.000000,
         0.000000,1.000000,0.000000,0.000000,
         0.000000,0.000000,1.000000,0.000000,
         0.000000,0.000000,0.000000,1.000000;;
      }
      Frame Child1 {
         // translate child1 1 unit in the positive Y direction
         FrameTransformMatrix {
            1.000000,0.000000,0.000000,0.000000,
            0.000000,1.000000,0.000000,0.000000,
            0.000000,0.000000,1.000000,0.000000,
            0.000000,1.000000,0.000000,1.000000;;
         }
         Frame Child2 {
            // translate child 1 unit in positive Y (relative to Child1)
            // this would actually be a 2 unit translation relative to Root
            // rotate 45 degrees about Z-axis
            FrameTransformMatrix {
               cos(45),sin(45),0.000000,0.000000,
               -sin(45),cos(45),0.000000,0.000000,
               0.000000,0.000000,1.000000,0.000000,
               0.000000,1.000000,0.000000,1.000000;;
            }
         } // end of Child2
      } // end of Child1
   } // end of Bone
   
   // Frame for mesh here
   // Frame MyMesh { etc...

   SkinWeights {
      "Root";
      // vertices and weights here
      
      // offset matrix here at end
         1.000000,0.000000,0.000000,0.000000,
         0.000000,1.000000,0.000000,0.000000,
         0.000000,0.000000,1.000000,0.000000,
         0.000000,0.000000,0.000000,1.000000;;
   }
   SkinWeights {
      "Child1";

       // vertices and weights here

       // offset matrix for child1 (inverse combined matrix?)
            1.000000,0.000000,0.000000,0.000000,
            0.000000,1.000000,0.000000,0.000000,
            0.000000,0.000000,1.000000,0.000000,
            0.000000,-1.000000,0.000000,1.000000;;
   }
   SkinWeights {
      "Child2";

       // vertices and weights here

       // offset matrix for child1 (inverse combined matrix?)
               -cos(45),-sin(45),0.000000,0.000000,
               sin(45),-cos(45),0.000000,0.000000,
               0.000000,0.000000,1.000000,0.000000,
               0.000000,-2.000000,0.000000,1.000000;;
   }

} // end of Scene_Root


Is this correct?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I'm still reading through the article, trying to incorporate it into my own (learning experience) 3D engine. I just wanted to say that I found the introduction very helpful for helping me decide how to implement certain things. Most 3D engines are a little unwieldly for a beginner to navigate.

Quote:

We could use the Model Object and add a Draw method. But doing this will cause some problems down the road


and

Quote:

There are many 3D-model file formats. We would need to implement a load method for each existing file format plus a function to get the correct loading function from the file extension. This would transform our code into some ungainly spaghetti.


Were very helpful because that was the direction I was headed.

 User Rating: 1226   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The greate article! It's very helpful for me and I have some question. please answer me.

class Object3D uses the FIRST mesh of the class Model3D,(member function "SetupModel") but Model3D may have the other meshes in the list "_Meshes". "_Meshes" also have the concatenation of all meshes in it's LAST NODE.
Where other meshes-include concatenation are USED?

Thanks.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The link for the source is dead. How do I get the source of the article?

 User Rating: 998   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: