Jump to content
  • Advertisement
Sign in to follow this  
Parduz

How to create a Mesh manually with VB6?

This topic is 4548 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

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.

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
(note: I've not had a chance to fully read the whole thread...)

Quote:
Original post by Parduz
But D3DXConcatenateMeshes is a DX9 function.
It 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]

hth
Jack

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

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!