Skip navigation

Monthly Archives: June 2013

The description on Wikipedia is ok, but here’s more.

Marching cubes is all about filling the space with cubes, and “cutting the cubes” by triangles if the isosurface cuts through the cube.

This talk by Shewchuk is great to help understand what an isosurface is, etc.

Now, there’s all this talk about 256 possible cube configurations. What’s that about.

Well the cube has 8 vertices. Pretend being inside the isosurface means the vertex is “wet”. Assuming the cube could dip in and out of the isosurface on any of those 8 vertices, means there are 2^8=256 possible configurations for the vertices to be “wet” (inside the isosurface).

The case where the cube is “completely dry” is when no vertices are inside the isosurface. If I put one corner in the isosurface, then one vertex is “wet”. But wait! There are 8 ways that “one corner” can be wet, because there are 8 corners on a cube. So each of the 8 corners can be in one of 2 states (“wet” or “dry”), means there are 2^8 possible configurations for the corners to be wet and dry. This actually boils down to just 14 cases if you exploit symmetry (ie consider the case of “one vertex being wet” as one case, not 8 cases).

This is easier to understand if you look at a square.

So there, we have 4 vertices, so 2^4=16 cases. case 0 is “dry”. case 1 has 1 vertex wet, and there are 4 symmetric cases. Case 2 has 2 adjacent corners.. etc. Just look at the diagram.

I can’t count the number of times extremely difficult mathematese was made understandable via a quick diagram.

All academics should take COMIC DRAWING as a course in university. The reason is, to be able to express themselves via diagrams and symbols, actors and examples, rather than just relying on words and the jargon of their field.

Well, a surprising result, never use your extern variables inside a function that runs before main.

Here’s an example:

In the header:

//extern test.  the externs are giving 0's.
struct Vector4f
{
  float x,y,z,w;
  Vector4f():x(0),y(0),z(0),w(0){}
  Vector4f( float ix, float iy, float iz, float iw ) :x(ix),y(iy),z(iz),w(iw){}
} ;

extern Vector4f Red ; // This is the weird variable..

In the main.cpp file:


static map<char, Vector4f> initMapping()
{
  map<char, Vector4f> mp ;
  mp.insert( make_pair( 'r', Red ) ) ;
  
  for( auto &p : mp )
    printf( "%c: %f %f %f %f\n", p.first, p.second.x, p.second.y, p.second.z, p.second.w );
  return mp ;
}

//Vector4f Red(1,0,0,1) ; // if this is here, Red has (1,0,0,1)
map<char, Vector4f> colorMapping = initMapping() ;
Vector4f Red(1,0,0,1) ; // if Red is only given its value HERE, when the static ctor runs, Red will be (0,0,0,0)

int main(int argc, const char * argv[])
{
  for( auto &p : colorMapping )
    printf( "%c: %f %f %f %f\n", p.first, p.second.x, p.second.y, p.second.z, p.second.w );
}

So those 2 declarations of Vector4f Red (without extern qualifier) in the cpp are the issue here. If the compiler runs into the Vector4f Red(1,0,0,1) ; BEFORE running SomeStruct::initMapping(), then the mapping has the correct value for Red in it. If the compiler first runs into Vector4f Red(1,0,0,1) only __after__ running SomeStruct::initMapping(), then the value of Red inside the map would be all 0’s.