How to handle meshes with _many_ triangles

Started by
7 comments, last by genne 16 years, 10 months ago
In my program the meshes are computed using marching cubes over a 3-dimensional set of bits composed by a stack of images. Now, if I run the algorithm on, say 16 images, all of them being of size 1024x1024, I get a lot of data and often very complex meshes with a lot of polygons. So, in these cases, DirectX (Actually DirectX Managed, but not sure if it matters) often gives me an exception "out of memory" (probably on the graphics card) when trying to create these meshes, which of course isn't the wanted result. Is there a workaround for this? Perhaps a way to force the mesh into using the internal memory instead of the graphic cards memory for these meshes? Rendering speed is not a matter here, so for all I care the solution could be very slow. Thanks in advance for any comments!
Advertisement
This reply makes assumptions on your goal as I don't know what you mean by "marching cubes".

1024x1024x16 = 16,777,216 unique points of data.
If you are storing just position information per vertex (3 floats) then that's
50,331,648 bytes of data on your graphics card (approximately 50MB), if you have color info, that's another 50+MB, texture is another 33 (UV coordinates, two floats). So, you can easily calculate your vertex storage requirements to see if you are exceeding your graphics card memory.

I am making assumptions here but if you are storing, position, texture, normal per vertex then your mesh is already around 150MB. How much memory does your graphics card use?

Another place you may run out of memory is texture memory. You are using 1024x1024x16, can your graphics card handle this much texture memory in a single pass?

If speed is not an issue, you could do all of your vertex processing on the CPU, then when you get the array of all vertexes for your mesh you could then possibly split that into chunks small enough to send off the the GPU.

Hope this helps, it sounds like you are asking way too much from your GPU.

Webby

Quote:Original post by WebsiteWill
This reply makes assumptions on your goal as I don't know what you mean by "marching cubes".


A well known (in the sense that people are aware of the existence) algorithm in "deeper" graphics coding (that is e.g. ray tracing, medicine applications, just for fun coding, etc.):

;)

Quote:[lazy_quote]rest of post[/lazy_quote]


Ack. Solution to this bloated data mass is to write your own (probably software) renderer with yer own primitive declarations.
oh, and not to forget. The other "workaround" is simply to reduce the size, given WebsiteWills calculus, maximize your dimensions so that SizeOfYourData<=SizeOfYourVidMem (or enable "outsourcing" to main RAM (I am a bit rusty on direct3d, so I can't tell how to do, if possible).

Remember that the more dimensions an array consists of, the more sensitive it gets on size-increasing. While a 2d-bitmap just gets four times bigger when doubling the size of each axis ( (4*4) / (2*2) = 4 ), cubic arrays already get 8 times bigger ( (4*4*4) / (2*2*2) = 8 ).
Quote:Original post by WebsiteWill
1024x1024x16 = 16,777,216 unique points of data.
If you are storing just position information per vertex (3 floats) then that's
50,331,648 bytes of data on your graphics card (approximately 50MB), if you have color info, that's another 50+MB, texture is another 33 (UV coordinates, two floats). So, you can easily calculate your vertex storage requirements to see if you are exceeding your graphics card memory.

One way to save memory here is to pack the data. While the coordinates might take 12 bytes, the normal can be packed into 3 (assume you don't need high accuracy), with another byte used for indexing into a colour table, for example.
The easiest thing to do here is just to send down multiple batches to the video card. If you're rendering millions of vertices the extra overhead of the draw calls won't matter so much. So find a reasonable number of triangles that you can draw, then create vertex/index buffers of that size and keep re-filling it (with LOCK_DISCARD0) between draw calls. You probably could get away with having just the one index buffer if your triangles don't reuse vertices.
Thanks everyone for your comments!

I'm using position and normal for each vertex, so I guess that gives me around 100 MB, which for me is too much.

Though, I liked the idea of splitting the meshes into smaller ones and sending them of to the GPU. I tried using Mesh.Split(...) for this (once again DirectX Managed), but that gave me the same error (E_OUTOFMEMORY), so I guess somehow this method makes use of the GPU? Is there a simple way of splitting a mesh without the use of GPU-memory? (I am reusing vertices)
Search the forum for quad and octtrees.

A quadtree would probably be suitable for you here. This would subdivide your mesh recursively 4 chunks at a time. Each leaf node holds a small fraction of the overall mesh (size of mesh depends on the number of times you subdivide it). So you could process your entire mesh into one large index for vertices and another for faces then subdivide it once to end up with 4 chunks or subdivide twice to end up with 16 chunks, then 64, etc, etc until you reach a chunk size you can live with.

You can pick your number of subdivisions first or you can come up with an alternate scheme like (while chunk.facecount > 100000 subdivide chunk).

For each face you have to figure out what chunk to place it in. Come up with an algo here that works best for you. Myself, I just figure that if ANY vertice of the face is in the current node then I store ALL 3 verts for the face in the current node. There are MANY ways to do this. Myself I just do the above and remove the face from the all-inclusive list of unprocessed faces. When I am out of unprocessed faces then I know all faces and vertices are in their proper nodes (that's the general idea).

When this is done you will have X nodes that you can send to the graphics card by a simple recursive render procedure.

The render functon would look something like this. Call it on the root node.
render()
{
IF I am a leaf
set graphics card to my vertex and index buffers and render
ELSE
child1.render()
child2.render()
child3.render()
child4.render()
END
}

Now, no matter how many times you subdivide your mesh, you can render it appropriately. It's not exactly this cut and dry as there are other pieces of logic you have to fill in and you have to decide how and where to store your vertex and index buffers but this should get you off to a good start.

Webby

Thanks WebsiteWill, but I think that's a bit too complex solution for me. I was looking for a more simpler way to split them up.

Actually, I succeeded using Mesh.Split by constructing the Mesh with the MeshFlags.SoftwareProcessing flag. Now, my problem seems to be that I render too many meshes (more than 23000). When calling Device.Present() I get a DriverInternalErrorException, and then the device is more or less useless.

Anyone know why I get this exception? Is there a limit for how many meshes you may render?

Thanks again for any comments!

This topic is closed to new replies.

Advertisement