Our Properties: Gamasutra GameCareerGuide IndieGames Indie Royale GDC IGF Game Developer Magazine GAO
My Message close
Latest News
spacer View All spacer
 
February 10, 2012
 
What drives the developers of Unity?
 
Analyst questions validity of unusual January NPD results [13]
 
Road to the IGF: Lucky Frame's Pugs Luv Beats
spacer
Latest Features
spacer View All spacer
 
February 10, 2012
 
arrow Virtual Goods - An Excerpt from Social Game Design: Monetization Methods and Mechanics
 
arrow Principles of an Indie Game Bottom Feeder [21]
 
arrow Postmortem: CyberConnect 2's Solatorobo: Red the Hunter [1]
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
February 10, 2012
 
Irrational Games
Systems Designer
 
CCP - North America
Lead Character Artist
 
CCP - North America
Sr VFX Artist
 
CCP - North America
Sr. Tech Artist
 
CCP - North America
Animation Director
 
Toys for Bob / Activision
Senior Programmer
spacer
Blogs

  Triangle Mesh Voxelization
by David Rosen on 12/02/09 07:39:00 am   Expert Blogs   Featured Blogs
3 comments Share on Twitter Share on Facebook RSS
 
 
  Posted 12/02/09 07:39:00 am
 
In my recent post on automatic skinning, one of the steps involved creating a voxel representation of the character. I couldn't find any explanations of how to do this on the Internet, so I decided to write my own!

What is a voxel?

"Voxel" is short for "volume pixel". A pixel is a single square in a 2D image, and a voxel is a single cube in a 3D lattice. Voxel models are useful in games because they aren't hollow like triangle meshes are, so we can use them for 'deep' physical simulations such as heat diffusion, fracture, and soft physics. I used voxels extensively when working with Alec Rivers to visualize his RealMatter technology, and when testing out destructible cover for an unreleashed shooter project. Here is the example model that I used for the previous post again -- the triangle surface is on the left, and the voxel model is on the right. 

So how do we make a voxel model?

A voxel model is a bounded 3D grid, so the first step is to decide its basic characteristics. How big is each block, and what are the dimensions of the grid?The size of each block depends on what you need it for -- in this case we are using it for attaching the mesh to the bones, so we only need enough resolution to make sure that important details like the mouth and fingers are not lost. Let's say each block is 1 cubic cm in size.The dimensions of the grid have to be big enough to fit the entire model, but no bigger (to avoid inefficiency). This is fairly simple -- we can just set the dimensions equal to the size of the bounding box of the surface triangles (the smallest box that encloses every point) rounded up to the nearest centimeter. Here's a picture of the voxel grid: 

 Now we have to decide which voxels are solid (intersecting the model), and which voxels are not. The method I used is a two-step process. First, we solidify a shell representing the surface, and second, we fill it in using a scanline fill algorithm. This is most clearly illustrated by looking at a single slice -- first we have just the triangle surface, next the voxel shell, and finally the filled voxel model.

 Calculating the shell is pretty straightforward. For every triangle, I check every voxel in the triangle's bounding box to see if it intersects. If it does, the voxel is made solid.Filling the shell is a little more complicated. We can see this best by looking at a single row as it's filled in. You can think of a pen scanning from left to right that goes down to the paper when it hits an outside edge and raises again when it hits an inside edge. We start out on the left with the pen up, shown here as a green square.

 There is no surface here and the pen is up, so we just move onto the next square without changing anything. 

 Here there are some intersecting surface triangles! We send a horizontal ray from left to right through the center of the voxel to see what it intersects. If the last triangle it intersects is facing to the left, then we lower the pen. Otherwise, we keep it raised. Here is a close-up of this voxel. The small white lines represent the triangle normals (which way is 'out').

 The last (and only) triangle that the pen intersects faces to the left, so we lower the pen! Here we illustrate that by changing the pen from green to red.

 Since the pen is down, it fills in empty voxels as it steps to the right.

 This process continues until we get to the next intersection. Fill, step to the right. Fill, step to the right.

 Here's a close-up of this intersection test. The rule is the same as before: If the last triangle the pen intersects is facing to the left, then we keep the pen lowered, otherwise, we raise it up. 

 In this case the last (and again, only) triangle is facing to the right, so we raise the pen.

 As it keeps moving out of the model, the pen is raised, so it fills no voxels. When we repeat this process for every row, the whole slice is filled in!

 Here is a 3D view of half of the model: first, a surface slice, next, the voxel shell, and finally, the filled voxel model.

 That's all there is to it! I hope this helps you use voxel models in your own projects. Do you have any ideas about better ways to voxelize triangle meshes, or any questions about how this works?

Follow us here!
Facebook iconModDB iconSteam iconTwitter iconYouTube icon

 
 
Comments

raigan burns
profile image
Great stuff, thanks for sharing :)

One question: is it necessary to do the triangle tests when filling in the shell? It seems like simply scanning across rows and raising/lowering the pen when you hit a new full/empty stretch would be good enough.. or even a flood-fill of some sort.

Kevin Fee
profile image
Consider the tooth in the above image. It is a "new full/empty stretch" but we don't want to toggle there because it consists of a single voxel rather than a voxel, one or more empty spaces, and another voxel. Flood fill should work, but you would need to keep in mind that you may have multiple shapes to fill, and you may have shapes within shapes that you need to make sure you don't fill.
I haven't had long to think about it, but it seems to me that the given method is the best that I can come up with. David Rosen, would you mind detailing your thoughts and alternate techniques that you may have considered or experimented with?

Christoph Kubisch
profile image
using logic op, this process can be accelerated with GPU: http://portal.acm.org/citation.cfm?doid=1375714.1375728


none
 
Comment:
 




 
UBM Techweb
Game Network
Game Developers Conference | GDC Europe | GDC Online | GDC China | Gamasutra | Game Developer Magazine | Game Advertising Online
Game Career Guide | Independent Games Festival | Indie Royale | IndieGames

Other UBM TechWeb Networks
Business Technology | Business Technology Events | Telecommunications & Communications Providers

Privacy Policy | Terms of Service | Contact Us | Copyright © UBM TechWeb, All Rights Reserved.