|
||||||||||||||||||
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 |
|
![]() Drew_Benton GDNet+ Member since: 7/29/2004 From: Katy, TX, United States |
||||
|
|
||||
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 |
||||
|
||||
![]() webjeff Member since: 1/2/2004 From: Roselle, IL, United States |
||||
|
|
||||
| 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. |
||||
|
||||
![]() Red Ghost Member since: 4/18/2002 From: Paris, France |
||||
|
|
||||
| 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. |
||||
|
||||
![]() Drew_Benton GDNet+ Member since: 7/29/2004 From: Katy, TX, United States |
||||
|
|
||||
Awesome! Thank you for that update. I am looking forward to reading the article this weekend ![]() |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| 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. |
||||
|
||||
![]() Myopic Rhino Staff Member since: The dawn of time
From: Temecula, CA, United States |
||||
|
|
||||
| I'm updating the links in the article. The xbdev site is obviously gone, but the page in question is cached on Archive.org |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| 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. |
||||
|
||||
![]() Red Ghost Member since: 4/18/2002 From: Paris, France |
||||
|
|
||||
| Previous post was by me. What is curious is that I was logged. Ghostly yours, Red. |
||||
|
||||
![]() Chris81 Member since: 5/13/2005 From: Canton, OH, United States |
||||
|
|
||||
| Loving this article, thanks a ton. |
||||
|
||||
![]() muhkuh Member since: 4/5/2004 From: Berlin, Germany |
||||
|
|
||||
| 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? |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| 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? |
||||
|
||||
![]() Red Ghost Member since: 4/18/2002 From: Paris, France |
||||
|
|
||||
| @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. |
||||
|
||||
![]() Rebuto Member since: 8/1/2005 From: speer, WY, United States |
||||
|
|
||||
| Very helpful article! neat, well-explained and to the point. certainly saved me a lot of headaches. Thank you. |
||||
|
||||
![]() pbergeron Member since: 2/25/2006 From: Prairieville, LA, United States |
||||
|
|
||||
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? |
||||
|
||||
![]() Numsgil Member since: 7/18/2002 From: San Francisco, CA, United States |
||||
|
|
||||
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: and Quote: Were very helpful because that was the direction I was headed. |
||||
|
||||
![]() kkang93 Member since: 4/3/2007 |
||||
|
|
||||
| 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. |
||||
|
||||
![]() Silverclaw Member since: 4/25/2006 From: Setubal, Portugal |
||||
|
|
||||
| The link for the source is dead. How do I get the source of the article? |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|