Skip to content

State of the Application 1

Tomorrow I travel to Nepal and Thailand for 7 weeks. Below are my accomplishments over the last 9 weeks and what I will try to accomplish when I get back to Sweden.

Voxel Engine
I have build a voxel engine around the concept of Sparse Octrees where each leaf store 16^3 grid of voxels. Each voxel is represented by a 16-bit  ”iso”-value and then 8-bits each for R G B and specular. This works great and by storing an array of voxels in each leaf we avoid the pressure of minimizing overhead in the node data structure.

Right now the voxel engine is split on a Server and a Client side which run on separate threads. The server side is responsible for disk read/write, voxel edits and tessellation. The client run in the same thread as the rest of the application and handles rendering and ray tracing. The main reason for this split is to avoid hick-ups in the thread that runs the graphics but have also some really nice side benefits like parallelization.

Disk storage
I have already rewritten this part of the code 3 times. Right now I use a solution based on Sqlite which gives me atomic commits. This is really a must when we handle files of several 100′s of MB. I don’t really use any of the RDBS stuff that comes with SQL, I just want to store tens of thousandths records of varying size with an unique 64-bit identifier in a single file with transactions. I tried to write this kind of system myself first and although it’s easy to get it to work, it’s very difficult to guarantee that data never gets corrupt on a crash. It is really convenient to use a 64-bit node identifier over a 32-bit since we then don’t have to reuse any identifiers.

Rendering
One of the main things I have researched the last 9 weeks is the rendering. I have come to the some what boring conclusion that Marching Cubes probably is the most efficient and artifact free solution. Voxel ray tracing looks promising at first but using ray marching directly against the voxels is waaaaay to slow and converting the voxels to a discrete SVO gives us the ugly Lego-artifact. Building a renderer based on splats is possible but a Marching Cube based solution is not much more expensive and looks a lot better. Since we use an Octree to store the nodes it should still be possible to ray trace against our marched cube triangles in real-time using GPGPU.

Right now I use vertex buffers objects and store all the indexes in CPU memory. This minimize the amount of draw calls we have to make but increase the data traffic over the PCI. This gives us about 0.7 million polys at 60 Hz. When I get back I will try to push this higher by experimenting with index buffers and glDrawMultiElements. Since I’m planing to relay only on vertex colors for texturing we want to be able to render more triangles then there are pixels on screen.

One big advantage with raster based data over vector data is down sampling. This works really well but when you do this adaptively with Marching Cubes you get pixel cracks between different resolutions. Hopefully this can be fixed by introducing “skirts” on all cubes but I haven’t tested this yet.

To calculate normals you can either use the voxel gradient or calculate it from the triangles. I have tried both and come to the conclusion that calculating it from the triangles probably is better but I’m 100% sure yet.

Widgets
I have written a widget system for UI rendering that works amazingly well. One of the core features is how I handle the XYWH coordinates for all the widgets. I basically works like this: All coordinates are relative to the widget parent. There are 2 types of coordinates, one for window area and one for client area. This coordinates can be mounted to the left or right edge. Finally we store all the coordinates on a file and allow them to be changed through the UI which allows you to try different UI layouts without ever recompiling or restarting the application.

Future:
Below is a list of what remains to be researched when I get back home:

  • Procedural texturing.
  • Automatic UV-mapping in tessellation code.
  • Prioritize tessellation front-to-back.
  • Marching Cube skirts.
  • Use odd number of voxels with redundancy per node?
  • Parallelization of tessellation.
  • Locally change voxel resolution.
  • Optimize away solid and empty spaces.
  • Parallelization of voxel edits.
  • GPGPU voxel edits.
  • Adaptive voxel edits.
  • The Level Set Method for deformation.
  • More then one voxel object per file.
  • Solidbits.

Categories: Technical.