pdeschenes's picture

Managing vertices/faces in C#

Hello everybody,

I'm currently building a CAD-like application using OpenTK and need to manage large meshes (~1,000,000 triangles). I did some test with VBOs and the performance is great for rendering (could be better but, it's not my problem right now).

I'm using a List to manage the vertices. Each time, I need to rebuild the entire mesh and need to do it in real-time. I did the following test to simulate the construction of 1,000,000 vertices 30x (aka 30 FPS)

for (int j=0; j<30; j++) {
for (int i=0; i<1000000; i++)
vertices.Add(new Vector3(0, 0, 0));

It takes 1.4 sec to complete (should be a way under 1s since I still need to render it) and this sample doesn't even make any matrix transformation. So I'm really far from my objective.

Maybe I approach the problem the wrong way but, I was wondering what you guys would do in a similar situation (large dynamic meshes to render in real-time).

- Patrick


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Inertia's picture

Do not .Clear() the arraylist, allocate it once (before the for-j-loop) and overwrite the vectors. Even better, since you know the length of the array create a Vector3[] instead of an Arraylist.

As your code is right now you are instantiating 30 mil vector3 structs in a dynamic array. Just copying them into a fixed-size array should be somewhat faster.

the Fiddler's picture

Inertia's advice is sound. Alternatively, use a List<> constructor that takes the list size as a parameter (to avoid relocations while the list grows) and treat the list as a plain array (i.e. no Clear() or Add()).

In general, you'll have to minimize data transfers both on system memory and over the bus to video memory.

Things you can try:

  • Use Vector3h instead of Vector3. This change alone will cut data transfers in half.
  • Instead of storing data in managed memory, use GL.MapBuffer to allocate an unmanaged block of memory and write to that directly (using unsafe code will give you a nice speed boost here).
  • Try different VBO modes, StreamDraw might be better suited to this style of rendering.
the Fiddler's picture

One more thing: you can fill the buffer returned by GL.MapBuffer from a secondary thread. This way, the rendering won't have to stall while new data is being uploaded.

If this still isn't enough, you'll have to implement a more radical approach. For example, if the mesh is a regular grid with changes only in one direction (i.e. it is a heightmap), you can compress it heavily by storing it as a 1024x1024 texture. You can then use displacement mapping to render it entirely on the GPU.