How to create a Mesh manually with VB6?
Hi to all from a newbie. I'm italian, so pls excuse my poor english.
I've read everything i've found on the web about D3DXCreateMeshFVF and D3DXCreateMesh.... but i really can't do something good.
I'm asking for a source sample about creating a mesh manually with VB6 and DX8.1.
I need to see how to create submeshes ('cause i need different textures) and how to make that textures coordinates.
If an example is useful to understand what i'm doing, then suppose to build an house of lego bricks. Actually i'm using each different type of lego brick as a single mesh (loading .x files at the startup). The rendering of a "house" built with 1000 briks is really slow.
So i'm trying to make an unique mesh of the house, being the brick vertex in "snapped" positions, to leave out the invisible parts of the bricks.
Thanks in advance for the help.
A D3DX Mesh has a concept of "attribute buffer", with which you can define subsets per mesh face. Each DWORD (or Long in VB6) in this buffer represents one triangle's subset id. D3DXCreateMesh* functions allocate this buffer for you automatically, so you only have to fill it with the subset indices. To access the attribute buffer data, the mesh interface has methods "LockAttributeBuffer" and "UnlockAttributeBuffer".
When you're finished with filling the attribute buffer, be sure to call the Optimize method with the flag D3DXMESHOPT_ATTRSORT on the mesh, so that the device can render all triangles of any subset with one call instead of one call per triangle.
As for the texture coordinates - they behave exactly the same whether you use the Mesh interface or raw vertex buffers.
As for the bricks - why don't you model the brick pattern as a bump-mapped texture in the first place? It doesn't help to just "snap" individual bricks in order to remove extraneous faces; you'd need a bit more complicated algorithm to remove the triangles between the bricks, such as Boolean union or similar, and this would probably be overkill for what you're trying to do.
When you're finished with filling the attribute buffer, be sure to call the Optimize method with the flag D3DXMESHOPT_ATTRSORT on the mesh, so that the device can render all triangles of any subset with one call instead of one call per triangle.
As for the texture coordinates - they behave exactly the same whether you use the Mesh interface or raw vertex buffers.
As for the bricks - why don't you model the brick pattern as a bump-mapped texture in the first place? It doesn't help to just "snap" individual bricks in order to remove extraneous faces; you'd need a bit more complicated algorithm to remove the triangles between the bricks, such as Boolean union or similar, and this would probably be overkill for what you're trying to do.
Quote:Original post by Nik02
A D3DX Mesh has a concept of "attribute buffer", with which you can define subsets per mesh face. Each DWORD (or Long in VB6) in this buffer represents one triangle's subset id. D3DXCreateMesh* functions allocate this buffer for you automatically, so you only have to fill it with the subset indices. To access the attribute buffer data, the mesh interface has methods "LockAttributeBuffer" and "UnlockAttributeBuffer".
When you're finished with filling the attribute buffer, be sure to call the Optimize method with the flag D3DXMESHOPT_ATTRSORT on the mesh, so that the device can render all triangles of any subset with one call instead of one call per triangle.
As for the texture coordinates - they behave exactly the same whether you use the Mesh interface or raw vertex buffers.
As for the bricks - why don't you model the brick pattern as a bump-mapped texture in the first place? It doesn't help to just "snap" individual bricks in order to remove extraneous faces; you'd need a bit more complicated algorithm to remove the triangles between the bricks, such as Boolean union or similar, and this would probably be overkill for what you're trying to do.
I'm sorry, Nik, but i'm really a newbie, so this does not help me so much.
Suppose i have an hex shaped brick (where the "button" on the top is another hex, just a bit little than the base).
Also the Button have a texture, while the base have another.
What should i do to create that mesh?
I can sound lazy, but i'm not: i've a nearly finished app, and i can't just figure out this final step....
<edit>
This show my actual rendering, and i need to make the terrain as as unique mesh.
http://heroscapehq.com/modules/coppermine/albums/userpics/11449/normal_maptest.jpg
It already helps a lot if you can get all the tiles to a single mesh. You can do this by using the D3DXConcatenateMeshes function (although it doesn't calculate new subset indices to the concatenated faces). You can define the subsets before the operation, though, so you'll have the necessary info on the mesh later. Think of subsets as "material indices" - every unique material+texture combination in the scene should have an unique index before the concatenation.
The actual polygon count rarely is an issue, rather the number of drawing calls is most often the bottleneck of a graphics engine. Hence, I don't recommend culling "hidden" polygons away unless it is absolutely necessary. Instead, I would cull away those whole tiles that are completely hidden from the player - before the concatenation.
Do ask for more info if needed [smile]
The actual polygon count rarely is an issue, rather the number of drawing calls is most often the bottleneck of a graphics engine. Hence, I don't recommend culling "hidden" polygons away unless it is absolutely necessary. Instead, I would cull away those whole tiles that are completely hidden from the player - before the concatenation.
Do ask for more info if needed [smile]
(note: I've not had a chance to fully read the whole thread...)
hth
Jack
Quote:Original post by ParduzIt shouldn't be too hard to emulate this function yourself. Create a destination mesh of the correct format - if they're the same then great, otherwise check out the union method that the docs mention. Then just lock the destination IB & VB buffers and then each of the source meshes and simply concatenate/append the data to whatever you've already written. The only tricky part will be making sure that the attribute table and ranges remain correct - it shouldn't be hard to do, just one of those things that (in my experience) is easy to trip up on [smile]
But D3DXConcatenateMeshes is a DX9 function.
hth
Jack
NOTE: I hope i will be not misunderstood, 'cause my english is not so good. So if the following phrases seems "ungrateful" or something bad, then you know that's not true. [End Note]
There's something that i don't undestand: while i apreciate all your explanation, there's don't move my knowledge a bit. I've read each sigle page i've found about that, i've found some C++ sample to look at, but i'm still in the same position.
The reason i'm asking for code is 'cause i'm stucked with theory. I've tryied a lot of things, obtaining in the better case my app hangs, in the worst a PC reboot. It's evidence to me that i can't do more far than where i am with only "suggestion". Seeing your efforts to lead me in the right way is frustrating, 'cause i'm not able to apreciate these efforts.
So, PLEASE, give me a bit of code to work with, i will study it and being not a "human language" but a programmin language i'm sure that then i will understand you all.
If there's a rule that says "do your code yourself, we're not working for you" then just tell me, i will stop asking until i will able to understand that theory.
Again, thanks for you efforts: i'm so sad that i can't actually understand what you're saying.
There's something that i don't undestand: while i apreciate all your explanation, there's don't move my knowledge a bit. I've read each sigle page i've found about that, i've found some C++ sample to look at, but i'm still in the same position.
The reason i'm asking for code is 'cause i'm stucked with theory. I've tryied a lot of things, obtaining in the better case my app hangs, in the worst a PC reboot. It's evidence to me that i can't do more far than where i am with only "suggestion". Seeing your efforts to lead me in the right way is frustrating, 'cause i'm not able to apreciate these efforts.
So, PLEASE, give me a bit of code to work with, i will study it and being not a "human language" but a programmin language i'm sure that then i will understand you all.
If there's a rule that says "do your code yourself, we're not working for you" then just tell me, i will stop asking until i will able to understand that theory.
Again, thanks for you efforts: i'm so sad that i can't actually understand what you're saying.
This code is in VC++, but the same DirectX functions I used should be available in VB. I think the faces might be the wrong way around though.
EDIT: Vaves, LOL. I meant to type faces.
[Edited by - CodeReaver on April 6, 2006 10:10:42 AM]
bool InitMesh() { void *vertices = NULL; void *indices = NULL; TESTVERTEX box0[] = { {-0.5f, 0.5f, -0.5f, 0xFFFF0000}, // Top Left Front { 0.5f, 0.5f, -0.5f, 0xFFFF0000}, // Top Right Front {-0.5f, -0.5f, -0.5f, 0xFFFF0000}, // Bottom Left Front { 0.5f, -0.5f, -0.5f, 0xFFFF0000}, // Bottom Right Front {-0.5f, 0.5f, 0.5f, 0xFFFF0000}, // Top Left Back { 0.5f, 0.5f, 0.5f, 0xFFFF0000}, // Top Right Back {-0.5f, -0.5f, 0.5f, 0xFFFF0000}, // Bottom Left Back { 0.5f, -0.5f, 0.5f, 0xFFFF0000}, // Bottom Right Back }; TESTVERTEX box1[] = { {-0.5f, 0.5f, -0.5f, 0xFF00FF00}, // Top Left Front { 0.5f, 0.5f, -0.5f, 0xFF00FF00}, // Top Right Front {-0.5f, -0.5f, -0.5f, 0xFF00FF00}, // Bottom Left Front { 0.5f, -0.5f, -0.5f, 0xFF00FF00}, // Bottom Right Front {-0.5f, 0.5f, 0.5f, 0xFF00FF00}, // Top Left Back { 0.5f, 0.5f, 0.5f, 0xFF00FF00}, // Top Right Back {-0.5f, -0.5f, 0.5f, 0xFF00FF00}, // Bottom Left Back { 0.5f, -0.5f, 0.5f, 0xFF00FF00}, // Bottom Right Back }; short topLeftFront = 0, // Top Left Front topRightFront = 1, // Top Right Front bottomLeftFront = 2, // Bottom Left Front bottomRightFront = 3, // Bottom Right Front topLeftBack = 4, // Top Left Back topRightBack = 5, // Top Right Back bottomLeftBack = 6, // Bottom Left Back bottomRightBack = 7; // Bottom Right Back WORD faces[] = { // Left faces topLeftFront, topLeftBack, bottomLeftBack, // 0 bottomLeftBack, bottomLeftFront, topLeftFront, // 1 // Front faces topLeftFront, bottomLeftFront, bottomRightFront, // 2 bottomRightFront, topRightFront, topLeftFront, // 3 // Right faces topRightBack, topRightFront, bottomRightFront, // 4 bottomRightFront, bottomRightBack, topRightBack, // 5 // Back faces bottomLeftBack, topLeftBack, topRightBack, // 6 topRightBack, bottomRightBack, bottomLeftBack, // 7 // Top faces topRightFront, topRightBack, topLeftBack, // 8 topLeftBack, topLeftFront, topRightFront, // 9 // Bottom faces bottomLeftFront, bottomLeftBack, bottomRightBack, // 10 bottomRightBack, bottomRightFront, bottomLeftFront // 11 }; if(FAILED( D3DXCreateMeshFVF( 12, // Number of faces (Polygons) 8, // Number of vertices. 0, // Adjacency (To do with neighbouring faces, but not needed here) D3DFVF_TESTVERTEX, // = D3DFVF_XYZ | D3DFVF_DIFFUSE g_pD3DDevice, // The device &g_pD3DXMesh0 // The mesh ) )) return false; if(FAILED( D3DXCreateMeshFVF( 12, // Number of faces (Polygons) 8, // Number of vertices. 0, // Adjacency (To do with neighbouring faces, but not needed here) D3DFVF_TESTVERTEX, // = D3DFVF_XYZ | D3DFVF_DIFFUSE g_pD3DDevice, // The device &g_pD3DXMesh1 // The mesh ) )) return false; if(FAILED(g_pD3DXMesh0->LockVertexBuffer(0,(void**)&vertices))) return false; memcpy(vertices, box0, sizeof(box0)); g_pD3DXMesh0->UnlockVertexBuffer(); if(FAILED(g_pD3DXMesh1->LockVertexBuffer(0,(void**)&vertices))) return false; memcpy(vertices, box1, sizeof(box1)); g_pD3DXMesh1->UnlockVertexBuffer(); if(FAILED(g_pD3DXMesh0->LockIndexBuffer(0,(void**)&indices))) return false; memcpy(indices, faces, sizeof(faces)); g_pD3DXMesh0->UnlockIndexBuffer(); if(FAILED(g_pD3DXMesh1->LockIndexBuffer(0,(void**)&indices))) return false; memcpy(indices, faces, sizeof(faces)); g_pD3DXMesh1->UnlockIndexBuffer(); LPD3DXFRAME frame = new D3DXFRAME[2]; ZeroMemory(frame, sizeof(D3DXFRAME[2])); frame[0].pMeshContainer = new D3DXMESHCONTAINER; frame[1].pMeshContainer = new D3DXMESHCONTAINER; ZeroMemory(frame[0].pMeshContainer, sizeof(D3DXMESHCONTAINER)); ZeroMemory(frame[1].pMeshContainer, sizeof(D3DXMESHCONTAINER)); frame[0].pMeshContainer->MeshData.pMesh = g_pD3DXMesh0; frame[1].pMeshContainer->MeshData.pMesh = g_pD3DXMesh1; frame[0].pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH; frame[1].pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH; frame[0].pMeshContainer->Name = "RedCube__"; frame[1].pMeshContainer->Name = "GreenCube"; frame[0].Name = frame[0].pMeshContainer->Name; frame[1].Name = frame[1].pMeshContainer->Name; D3DXMATRIX transMatrix; D3DXMatrixIdentity(&transMatrix); frame[0].TransformationMatrix = transMatrix; transMatrix._11 = 0.5; transMatrix._22 = 0.5; transMatrix._33 = 0.5; transMatrix._41 += 0.25f; frame[1].TransformationMatrix = transMatrix; frame[0].pFrameFirstChild = &frame[1]; // Can also use D3DXF_FILEFORMAT_TEXT or D3DXF_FILEFORMAT_COMPRESSED or D3DXF_FILEFORMAT_BINARY D3DXSaveMeshToX("glasscube.x", g_pD3DXMesh0, NULL, NULL, NULL, 0, D3DXF_FILEFORMAT_BINARY); D3DXSaveMeshHierarchyToFile("frames.x", D3DXF_FILEFORMAT_TEXT, frame, NULL, NULL); return true;}
EDIT: Vaves, LOL. I meant to type faces.
[Edited by - CodeReaver on April 6, 2006 10:10:42 AM]
I drew a small diagram illustrating the concatenation of multiple meshes into one:
The operation really just copies the meshes into the bigger buffer in order, that's all. To access the buffers, call the LockVertexBuffer, LockIndexBuffer and LockAttributeBuffer of the mesh interface. When you have the pointers, you can use DXCopyMemory to transfer the data around.
Do call the optimize method after this operation, so that the subsets (that the attribute buffer defines) get organized in more efficient manner.
It's my principle not to give source code easily - instead, I would like you to truly understand the operation. Once you do, writing the code is quite trivial.
The operation really just copies the meshes into the bigger buffer in order, that's all. To access the buffers, call the LockVertexBuffer, LockIndexBuffer and LockAttributeBuffer of the mesh interface. When you have the pointers, you can use DXCopyMemory to transfer the data around.
Do call the optimize method after this operation, so that the subsets (that the attribute buffer defines) get organized in more efficient manner.
It's my principle not to give source code easily - instead, I would like you to truly understand the operation. Once you do, writing the code is quite trivial.
Nik02, this is by far the most understandable help to understand mesh (being me a non english speaking).
I've almost done anything...but i'm stucked in the attribute buffer.
The VB version of the LockAttributeBuffer function returns a long, which in C is a pointer, but i can't use in any way in VB.
What i've to do to modify the attribute buffer?
I've almost done anything...but i'm stucked in the attribute buffer.
The VB version of the LockAttributeBuffer function returns a long, which in C is a pointer, but i can't use in any way in VB.
What i've to do to modify the attribute buffer?
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement