Jump to content
  • Advertisement
Sign in to follow this  
synth_cat

how to load an X file

This topic is 4420 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Maybe this is not even possible, but here's what I want to do: I want to be able to load triangle xyz data from an X file float by float. I don't want to use a DX function to do this, because I'm not planning on using X-file-loading to fill my game's vertex buffer or a DirectX mesh or anything like that. I want to be able to load X files into my world modeler, filling my own struct MyTriangle array with xyz data. To explain briefly why I would want to do something so strange: The files that my worldmaker generates read as follows: int number_of_tris, block of triangle data (xyz, uv, etc.), physics geometry and other stuff.) Recently I have been using my own modelling tools to create geometry within my world editor, but they are so hard to write and hard to use that I would like to do the geometry-creation in a professional modeller and then just use my worldmaker for texturing, creation of physics geometry, and other stuff. Is this even possible? Is it legal? If so, what is the structure of an X file and where can I find out (I had trouble finding this kind of info on msdn.com)? Remember that all I care about is the straight position data. (I will be making these X files with Caligari TrueSpace6.6, if that means anything.) By the way, what is the effective difference between an ASCII X file and a ibnary X file? Thanks!

Share this post


Link to post
Share on other sites
Advertisement
What you can do is simply load the file into the standard DirectX mesh format and, using a class in somewhere in the SDK (it's called crackdecl.h/crackdecl.cpp and it's in the \Samples\C++\Direct3D\UVAtlas directory) you can extract info about the vertex declaration. Then it's as simple as locking the vertex buffer and stepping through the data. Shouldn't be too hard. I can at least start you off:

ID3DXMesh* mesh;
HRESULT hr = D3DXLoadMeshFromX("your_mesh.x", D3DXMESH_SYSTEMMEM, g_d3dDevice, NULL, NULL, NULL, NULL, &mesh);
if(FAILED(hr))
//scream and run away
void* vertBuffer;
mesh->LockVertexBuffer(D3DLOCK_READONLY, &vertBuffer);
//do stuff with vertex buffer
mesh->UnlockVertexBuffer();




And you can also do that with the index buffer so you can reassemble the faces properly. Hope that at least gets you going.

Share this post


Link to post
Share on other sites
ASCII and Binary are just different representations of the same data. ASCII can be a read and edited by us humans, binary can't (unless you're some sort of super-hardcore nerd who can read binary [lol]). In practice the difference is usually that binary encoding generates a much smaller file.

I'd also second NickGravelyn's approach. Why make your job any harder by writing your own parser?

Although, I might add a few things:

1. Use ID3DXMesh::CloneMeshFVF() with the D3DFVF_XYZ flag - this will strip out any unwanted vertex attributes. Might be safest to check that component actually exists first of course [wink]

2. Use GetNumFaces() and iterate through the index buffer, each triple of indices defines one face. Store these for the next step.

3. Lock the vertex buffer and for each triple of indices you just looked up, extract the relevant vertex from the buffer. Because of step #1 your returned pointer is just an array of D3DXVECTOR3's so its easy to just copy the XYZ position to your new structure.

Once all thats done, release the mesh and any temporary data.

Or, if you really wanna do it the hard way you'll need to get familiar with the .X file format reference section in the SDK documentation.

hth
Jack

Share this post


Link to post
Share on other sites
Thanks for the reference to that article, but I'm not sure if it will help me much, seeing as I am only going to be loading non-animated stuff.

I have a question about the function D3DXLoadMeshFromX(): Is this function "smart?" In other words, will it be able to handle any sort of .x file I throw at it? It's just that I'm not sure what sort of .x my modeller will generate.

Otherwise this seems like a really good way to go - _much_ better than a parser, especially now that I see how complicated the .x file actually is.

Share this post


Link to post
Share on other sites
Quote:
Original post by synth_cat
I have a question about the function D3DXLoadMeshFromX(): Is this function "smart?" In other words, will it be able to handle any sort of .x file I throw at it? It's just that I'm not sure what sort of .x my modeller will generate.
It should be fine - I've never had any problems with it myself, nor am I aware of other people have problems.

The .x format is extensible so you might not get ALL the information in a file (I'd expect D3DXLoadMeshFromX() to drop any data that an ID3DXMesh container can't represent). Given you only want vertex/position data you shouldn't have a problem here [smile]

hth
Jack

Share this post


Link to post
Share on other sites
Quote:
Original post by synth_cat
Just out of curiosity, how would I go about creating a .x file?
You could do it procedurally in code by using D3DXCreateMesh() or you could use your favourite modelling package. Both Wings3D and Blender are free downloads - things like Max and Maya are more popular but might require you to sell bodyparts for medical research in order to pay [lol]

For questions regarding the modelling process (and packages) you might wanna swing by the Visual Arts forum.

hth
Jack

Share this post


Link to post
Share on other sites
Sorry for not answering for so long -

Anyway, I tried out the method (for loading data from an X file into my own TRI and POINT structs), and it didn't exactly work. Let me explain: I'll start off with showing you the code:

//structs
struct TRI
{
bool alive;
int pnt_idx1;
int pnt_idx2;
int pnt_idx3;
};
struct POINT
{
float x;
float y;
float z;
};


//these two arrays are the heart of my modeller and need to be filled with
//data from the x file
TRI tris[MAX_TRIS];
POINT pnts[MAX_PNTS];


//here is the function that is meant to load data from an X file
void InitWorldFromX()
{
//by doing this, I set all the .alive members of tris to 0,
//so I can check later on how many tris were actually loaded into
//tris[] from the file
ZeroMemory(&tris,sizeof(tris));
ZeroMemory(&pnts,sizeof(pnts));

ID3DXMesh* mesh;
HRESULT test;
test=D3DXLoadMeshFromX("testfile.x",D3DXMESH_SYSTEMMEM,d3ddev,
0,0,0,0,&mesh);
if(FAILED(test))
{ return; //didn't work }

//now clone this mesh to a mesh with correct FVF
ID3DXMesh* clone_mesh;
mesh->CloneMeshFVF(mesh->GetOptions(),D3DFVF_XYZ,d3ddev,&clone_mesh);

num_tris=clone_mesh->GetNumFaces();
num_verts=clone_mesh->GetNumVertices();
if(num_tris>=TRIS_SIZE) return;
if(num_verts>=POINTS_SIZE) return;

/////////////////////////////////////////////////////////////////
////////////////GET XYZ DATA FROM MESH'S VERTEX BUFFER////////
/////////////////////////////////////////////////////////////////
POINT* meshvb_pnt=0;
mesh->LockVertexBuffer(D3DLOCK_READONLY,(void**)&meshvb_pnt);
if(!meshvb_pnt) return; //failed
for(int read_pnt=0; read_pnt<num_verts; read_pnt++)
{
pnts[read_pnt].p.x=meshvb_pnt[read_pnt].x;
pnts[read_pnt].p.y=meshvb_pnt[read_pnt].y;
pnts[read_pnt].p.z=meshvb_pnt[read_pnt].z;

}
mesh->UnlockVertexBuffer();

/////////////////////////////////////////////////////////////////
////////////////FILL TRI INDECES FROM MESH'S INDEX BUFFER////////
/////////////////////////////////////////////////////////////////
WORD* meshib_pnt=0;
mesh->LockIndexBuffer(D3DLOCK_READONLY,(void**)&meshib_pnt);
if(!meshib_pnt) return; //failed
for(int read_tri=0; read_tri<num_tris; read_tri++)
{
tris[read_tri].alive=1;
tris[read_tri].p[0]=(int)meshib_pnt[read_tri*3];
tris[read_tri].p[1]=(int)meshib_pnt[read_tri*3+1];
tris[read_tri].p[2]=(int)meshib_pnt[read_tri*3+2];
}
mesh->UnlockVertexBuffer();


//release the two mesh pointers
clone_mesh->Release();
mesh->Release();

return;
};





Anyway, here's the problem: When I call InitWorldFromX(), I get nothing on my screen (when tris[] and pnts[] are sent to my drawing functions, I mean.) Now I _do_ know that creating the meshes has worked because I can look through my tris[] array and check .alive values and tell that 392 tris have been filled in.

So, does anyone know what exactly the problem is? I feel sure it has something to do about the way I load xyz data from the file...

POINT* meshvb_pnt=0;
mesh->LockVertexBuffer(D3DLOCK_READONLY,(void**)&meshvb_pnt);
if(!meshvb_pnt) return; //failed
for(int read_pnt=0; read_pnt<num_verts; read_pnt++)
{
pnts[read_pnt].p.x=meshvb_pnt[read_pnt].x;
pnts[read_pnt].p.y=meshvb_pnt[read_pnt].y;
pnts[read_pnt].p.z=meshvb_pnt[read_pnt].z;

}
mesh->UnlockVertexBuffer();




...or with the way I load index data.

WORD* meshib_pnt=0;
mesh->LockIndexBuffer(D3DLOCK_READONLY,(void**)&meshib_pnt);
if(!meshib_pnt) return; //failed
for(int read_tri=0; read_tri<num_tris; read_tri++)
{
tris[read_tri].alive=1;
tris[read_tri].p[0]=(int)meshib_pnt[read_tri*3];
tris[read_tri].p[1]=(int)meshib_pnt[read_tri*3+1];
tris[read_tri].p[2]=(int)meshib_pnt[read_tri*3+2];
}
mesh->UnlockVertexBuffer();





My thanks in advance!

Share this post


Link to post
Share on other sites
Oops, my mistake! I just realized that the code in my project was this:

WORD* meshib_pnt=0;
mesh->LockIndexBuffer(D3DLOCK_READONLY,(void**)&meshib_pnt);
if(!meshib_pnt) return; //failed
for(int read_tri=0; read_tri<num_tris; read_tri++)
{
tris[read_tri].alive=1;
tris[read_tri].p[0]=(int)meshib_pnt[read_tri*3];
tris[read_tri].p[0]=(int)meshib_pnt[read_tri*3+1];
tris[read_tri].p[0]=(int)meshib_pnt[read_tri*3+2];
}
mesh->UnlockVertexBuffer();



So obviously I wouldn't have seen anything because only index 0 of each triangle got defined. I fixed this and my geometry appeared!

However, I still want to ask everyone out there if I'm going about this the correct way. Is my crude method of using a POINT* pointer to unlock the vertex buffer the safest thing to do? Will it fail on some .x files, possibly?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!