reformat MarchingCubes, some refactoring
authormegacz <adam@megacz.com>
Sat, 28 Feb 2009 21:40:28 +0000 (13:40 -0800)
committermegacz <adam@megacz.com>
Sat, 28 Feb 2009 21:40:28 +0000 (13:40 -0800)
src/edu/berkeley/qfat/voxel/MarchingCubes.java

index f8fb4e4..cccbecf 100644 (file)
@@ -33,549 +33,9 @@ public abstract class MarchingCubes {
         public double fZ;     
     };
 
         public double fZ;     
     };
 
-    // These tables are used so that everything can be done in little
-    // loops that you can look at all at once rather than in pages and
-    // pages of unrolled code.
-    
-    // a2fVertexOffset lists the positions, relative to vertex0, of
-    // each of the 8 vertices of a cube
-    static final double a2fVertexOffset[][] = {
-        {0.0, 0.0, 0.0},{1.0, 0.0, 0.0},{1.0, 1.0, 0.0},{0.0, 1.0, 0.0},
-        {0.0, 0.0, 1.0},{1.0, 0.0, 1.0},{1.0, 1.0, 1.0},{0.0, 1.0, 1.0}
-    };
-    
-    //a2iEdgeConnection lists the index of the endpoint vertices for each of the 12 edges of the cube
-    static final int a2iEdgeConnection[][] = {
-        {0,1}, {1,2}, {2,3}, {3,0},
-        {4,5}, {5,6}, {6,7}, {7,4},
-        {0,4}, {1,5}, {2,6}, {3,7}
-    };
-
-    //a2fEdgeDirection lists the direction vector (vertex1-vertex0) for each edge in the cube
-    static final double a2fEdgeDirection[][] = {
-        {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
-        {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
-        {0.0, 0.0, 1.0},{0.0, 0.0, 1.0},{ 0.0, 0.0, 1.0},{0.0,  0.0, 1.0}
-    };
-
-    // a2iTetrahedronEdgeConnection lists the index of the endpoint
-    // vertices for each of the 6 edges of the tetrahedron
-    static final int a2iTetrahedronEdgeConnection[][] = {
-        {0,1},  {1,2},  {2,0},  {0,3},  {1,3},  {2,3}
-    };
-
-    // a2iTetrahedronEdgeConnection lists the index of verticies from a cube 
-    // that made up each of the six tetrahedrons within the cube
-    static final int a2iTetrahedronsInACube[][] = {
-        {0,5,1,6},
-        {0,1,2,6},
-        {0,2,3,6},
-        {0,3,7,6},
-        {0,7,4,6},
-        {0,4,5,6},
-    };
-
-    static final double afAmbientWhite [] = {0.25, 0.25, 0.25, 1.00}; 
-    static final double afAmbientRed   [] = {0.25, 0.00, 0.00, 1.00}; 
-    static final double afAmbientGreen [] = {0.00, 0.25, 0.00, 1.00}; 
-    static final double afAmbientBlue  [] = {0.00, 0.00, 0.25, 1.00}; 
-    static final double afDiffuseWhite [] = {0.75, 0.75, 0.75, 1.00}; 
-    static final double afDiffuseRed   [] = {0.75, 0.00, 0.00, 1.00}; 
-    static final double afDiffuseGreen [] = {0.00, 0.75, 0.00, 1.00}; 
-    static final double afDiffuseBlue  [] = {0.00, 0.00, 0.75, 1.00}; 
-    static final double afSpecularWhite[] = {1.00, 1.00, 1.00, 1.00}; 
-    static final double afSpecularRed  [] = {1.00, 0.25, 0.25, 1.00}; 
-    static final double afSpecularGreen[] = {0.25, 1.00, 0.25, 1.00}; 
-    static final double afSpecularBlue [] = {0.25, 0.25, 1.00, 1.00}; 
-
     GLvector  sSourcePoint[] = new GLvector[3];
 
     GLvector  sSourcePoint[] = new GLvector[3];
 
-    /*
-      GLenum    ePolygonMode = GL_FILL;
-      int     iDataSetSize = 16;
-      double   fStepSize = 1.0/iDataSetSize;
-      double   fTargetValue = 48.0;
-      double   fTime = 0.0;
-      boolean bSpin = true;
-      boolean bMove = true;
-      boolean bLight = true;
-
-
-      void vIdle();
-      void vDrawScene(); 
-      void vResize(GLsizei, GLsizei);
-      void vKeyboard(unsigned char cKey, int iX, int iY);
-      void vSpecial(int iKey, int iX, int iY);
-
-      GLvoid vPrintHelp();
-      GLvoid vSetTime(double fTime);
-      double fSample1(double fX, double fY, double fZ);
-      double fSample2(double fX, double fY, double fZ);
-      double fSample3(double fX, double fY, double fZ);
-      double (*fSample)(double fX, double fY, double fZ) = fSample1;
-
-      GLvoid vMarchingCubes();
-      GLvoid vMarchCube1(double fX, double fY, double fZ, double fScale);
-      GLvoid vMarchCube2(double fX, double fY, double fZ, double fScale);
-      GLvoid (*vMarchCube)(double fX, double fY, double fZ, double fScale) = vMarchCube1;
-
-      void main(int argc, char **argv) 
-      { 
-      double afPropertiesAmbient [] = {0.50, 0.50, 0.50, 1.00}; 
-      double afPropertiesDiffuse [] = {0.75, 0.75, 0.75, 1.00}; 
-      double afPropertiesSpecular[] = {1.00, 1.00, 1.00, 1.00}; 
-
-      GLsizei iWidth = 640.0; 
-      GLsizei iHeight = 480.0; 
-
-      glutInit(&argc, argv);
-      glutInitWindowPosition( 0, 0);
-      glutInitWindowSize(iWidth, iHeight);
-      glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
-      glutCreateWindow( "Marching Cubes" );
-      glutDisplayFunc( vDrawScene );
-      glutIdleFunc( vIdle );
-      glutReshapeFunc( vResize );
-      glutKeyboardFunc( vKeyboard );
-      glutSpecialFunc( vSpecial );
-
-      glClearColor( 0.0, 0.0, 0.0, 1.0 ); 
-      glClearDepth( 1.0 ); 
-
-      glEnable(GL_DEPTH_TEST); 
-      glEnable(GL_LIGHTING);
-      glPolygonMode(GL_FRONT_AND_BACK, ePolygonMode);
-
-      glLightfv( GL_LIGHT0, GL_AMBIENT,  afPropertiesAmbient); 
-      glLightfv( GL_LIGHT0, GL_DIFFUSE,  afPropertiesDiffuse); 
-      glLightfv( GL_LIGHT0, GL_SPECULAR, afPropertiesSpecular); 
-      glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0); 
-
-      glEnable( GL_LIGHT0 ); 
-
-      glMaterialfv(GL_BACK,  GL_AMBIENT,   afAmbientGreen); 
-      glMaterialfv(GL_BACK,  GL_DIFFUSE,   afDiffuseGreen); 
-      glMaterialfv(GL_FRONT, GL_AMBIENT,   afAmbientBlue); 
-      glMaterialfv(GL_FRONT, GL_DIFFUSE,   afDiffuseBlue); 
-      glMaterialfv(GL_FRONT, GL_SPECULAR,  afSpecularWhite); 
-      glMaterialf( GL_FRONT, GL_SHININESS, 25.0); 
-
-      vResize(iWidth, iHeight); 
-
-      vPrintHelp();
-      glutMainLoop(); 
-      }
-
-      GLvoid vPrintHelp()
-      {
-      printf("Marching Cubes Example by Cory Bloyd (dejaspaminacan@my-deja.com)\n\n");
-
-      printf("+/-  increase/decrease sample density\n");
-      printf("PageUp/PageDown  increase/decrease surface value\n");
-      printf("s  change sample function\n");
-      printf("c  toggle marching cubes / marching tetrahedrons\n");
-      printf("w  wireframe on/off\n");
-      printf("l  toggle lighting / color-by-normal\n");
-      printf("Home  spin scene on/off\n");
-      printf("End  source point animation on/off\n");
-      }
-
-
-      void vResize( GLsizei iWidth, GLsizei iHeight ) 
-      { 
-      double fAspect, fHalfWorldSize = (1.4142135623730950488016887242097/2); 
-
-      glViewport( 0, 0, iWidth, iHeight ); 
-      glMatrixMode (GL_PROJECTION);
-      glLoadIdentity ();
-
-      if(iWidth <= iHeight)
-      {
-      fAspect = (double)iHeight / (double)iWidth;
-      glOrtho(-fHalfWorldSize, fHalfWorldSize, -fHalfWorldSize*fAspect,
-      fHalfWorldSize*fAspect, -10*fHalfWorldSize, 10*fHalfWorldSize);
-      }
-      else
-      {
-      fAspect = (double)iWidth / (double)iHeight; 
-      glOrtho(-fHalfWorldSize*fAspect, fHalfWorldSize*fAspect, -fHalfWorldSize,
-      fHalfWorldSize, -10*fHalfWorldSize, 10*fHalfWorldSize);
-      }
-      glMatrixMode( GL_MODELVIEW );
-      }
-
-      void vKeyboard(unsigned char cKey, int iX, int iY)
-      {
-      switch(cKey)
-      {
-      case 'w' :
-      {
-      if(ePolygonMode == GL_LINE)
-      {
-      ePolygonMode = GL_FILL;
-      }
-      else
-      {
-      ePolygonMode = GL_LINE;
-      }
-      glPolygonMode(GL_FRONT_AND_BACK, ePolygonMode);
-      } break;
-      case '+' :
-      case '=' :
-      {
-      ++iDataSetSize;
-      fStepSize = 1.0/iDataSetSize;
-      } break;
-      case '-' :
-      {
-      if(iDataSetSize > 1)
-      {
-      --iDataSetSize;
-      fStepSize = 1.0/iDataSetSize;
-      }
-      } break;
-      case 'c' :
-      {
-      if(vMarchCube == vMarchCube1)
-      {
-      vMarchCube = vMarchCube2;//Use Marching Tetrahedrons
-      }
-      else
-      {
-      vMarchCube = vMarchCube1;//Use Marching Cubes
-      }
-      } break;
-      case 's' :
-      {
-      if(fSample == fSample1)
-      {
-      fSample = fSample2;
-      }
-      else if(fSample == fSample2)
-      {
-      fSample = fSample3;
-      }
-      else
-      {
-      fSample = fSample1;
-      }
-      } break;
-      case 'l' :
-      {
-      if(bLight)
-      {
-      glDisable(GL_LIGHTING);//use vertex colors
-      }
-      else
-      {
-      glEnable(GL_LIGHTING);//use lit material color
-      }
-
-      bLight = !bLight;
-      };
-      }
-      }
-
-
-      void vSpecial(int iKey, int iX, int iY)
-      {
-      switch(iKey)
-      {
-      case GLUT_KEY_PAGE_UP :
-      {
-      if(fTargetValue < 1000.0)
-      {
-      fTargetValue *= 1.1;
-      }
-      } break;
-      case GLUT_KEY_PAGE_DOWN :
-      {
-      if(fTargetValue > 1.0)
-      {
-      fTargetValue /= 1.1;
-      }
-      } break;
-      case GLUT_KEY_HOME :
-      {
-      bSpin = !bSpin;
-      } break;
-      case GLUT_KEY_END :
-      {
-      bMove = !bMove;
-      } break;
-      }
-      }
-
-      void vIdle()
-      {
-      glutPostRedisplay();
-      }
-
-      void vDrawScene() 
-      { 
-      static double fPitch = 0.0;
-      static double fYaw   = 0.0;
-      static double fTime = 0.0;
-
-      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 
-
-      glPushMatrix(); 
-
-      if(bSpin)
-      {
-      fPitch += 4.0;
-      fYaw   += 2.5;
-      }
-      if(bMove)
-      {
-      fTime  += 0.025;
-      }
-
-      vSetTime(fTime);
-
-      glTranslatef(0.0, 0.0, -1.0);  
-      glRotatef( -fPitch, 1.0, 0.0, 0.0);
-      glRotatef(     0.0, 0.0, 1.0, 0.0);
-      glRotatef(    fYaw, 0.0, 0.0, 1.0);
-
-      glPushAttrib(GL_LIGHTING_BIT);
-      glDisable(GL_LIGHTING);
-      glColor3f(1.0, 1.0, 1.0);
-      glutWireCube(1.0); 
-      glPopAttrib(); 
-
-
-      glPushMatrix(); 
-      glTranslatef(-0.5, -0.5, -0.5);
-      glBegin(GL_TRIANGLES);
-      vMarchingCubes();
-      glEnd();
-      glPopMatrix(); 
-
-
-      glPopMatrix(); 
-
-      glutSwapBuffers(); 
-      }
-
-
-
-      //vGetColor generates a color from a given position and normal of a point
-      GLvoid vGetColor(GLvector &rfColor, GLvector &rfPosition, GLvector &rfNormal)
-      {
-      double fX = rfNormal.fX;
-      double fY = rfNormal.fY;
-      double fZ = rfNormal.fZ;
-      rfColor.fX = (fX > 0.0 ? fX : 0.0) + (fY < 0.0 ? -0.5*fY : 0.0) + (fZ < 0.0 ? -0.5*fZ : 0.0);
-      rfColor.fY = (fY > 0.0 ? fY : 0.0) + (fZ < 0.0 ? -0.5*fZ : 0.0) + (fX < 0.0 ? -0.5*fX : 0.0);
-      rfColor.fZ = (fZ > 0.0 ? fZ : 0.0) + (fX < 0.0 ? -0.5*fX : 0.0) + (fY < 0.0 ? -0.5*fY : 0.0);
-      }
-
-
-
-      //Generate a sample data set.  fSample1(), fSample2() and fSample3() define three scalar fields whose
-      // values vary by the X,Y and Z coordinates and by the fTime value set by vSetTime()
-      GLvoid vSetTime(double fNewTime)
-      {
-      double fOffset;
-      int iSourceNum;
-
-      for(iSourceNum = 0; iSourceNum < 3; iSourceNum++)
-      {
-      sSourcePoint[iSourceNum].fX = 0.5;
-      sSourcePoint[iSourceNum].fY = 0.5;
-      sSourcePoint[iSourceNum].fZ = 0.5;
-      }
-
-      fTime = fNewTime;
-      fOffset = 1.0 + sinf(fTime);
-      sSourcePoint[0].fX *= fOffset;
-      sSourcePoint[1].fY *= fOffset;
-      sSourcePoint[2].fZ *= fOffset;
-      }
-
-
-      //fSample1 finds the distance of (fX, fY, fZ) from three moving points
-      double fSample1(double fX, double fY, double fZ)
-      {
-      GLdouble fResult = 0.0;
-      GLdouble fDx, fDy, fDz;
-      fDx = fX - sSourcePoint[0].fX;
-      fDy = fY - sSourcePoint[0].fY;
-      fDz = fZ - sSourcePoint[0].fZ;
-      fResult += 0.5/(fDx*fDx + fDy*fDy + fDz*fDz);
-
-      fDx = fX - sSourcePoint[1].fX;
-      fDy = fY - sSourcePoint[1].fY;
-      fDz = fZ - sSourcePoint[1].fZ;
-      fResult += 1.0/(fDx*fDx + fDy*fDy + fDz*fDz);
-
-      fDx = fX - sSourcePoint[2].fX;
-      fDy = fY - sSourcePoint[2].fY;
-      fDz = fZ - sSourcePoint[2].fZ;
-      fResult += 1.5/(fDx*fDx + fDy*fDy + fDz*fDz);
-
-      return fResult;
-      }
-
-      //fSample2 finds the distance of (fX, fY, fZ) from three moving lines
-      double fSample2(double fX, double fY, double fZ)
-      {
-      GLdouble fResult = 0.0;
-      GLdouble fDx, fDy, fDz;
-      fDx = fX - sSourcePoint[0].fX;
-      fDy = fY - sSourcePoint[0].fY;
-      fResult += 0.5/(fDx*fDx + fDy*fDy);
-
-      fDx = fX - sSourcePoint[1].fX;
-      fDz = fZ - sSourcePoint[1].fZ;
-      fResult += 0.75/(fDx*fDx + fDz*fDz);
-
-      fDy = fY - sSourcePoint[2].fY;
-      fDz = fZ - sSourcePoint[2].fZ;
-      fResult += 1.0/(fDy*fDy + fDz*fDz);
-
-      return fResult;
-      }
-
-
-      //fSample2 defines a height field by plugging the distance from the center into the sin and cos functions
-      double fSample3(double fX, double fY, double fZ)
-      {
-      double fHeight = 20.0*(fTime + sqrt((0.5-fX)*(0.5-fX) + (0.5-fY)*(0.5-fY)));
-      fHeight = 1.5 + 0.1*(sinf(fHeight) + cosf(fHeight));
-      GLdouble fResult = (fHeight - fZ)*50.0;
-
-      return fResult;
-      }
-
-
-
-
-
-
-      //vMarchTetrahedron performs the Marching Tetrahedrons algorithm on a single tetrahedron
-      GLvoid vMarchTetrahedron(GLvector *pasTetrahedronPosition, double *pafTetrahedronValue)
-      {
-      extern int aiTetrahedronEdgeFlags[16];
-      extern int a2iTetrahedronTriangles[16][7];
-
-      int iEdge, iVert0, iVert1, iEdgeFlags, iTriangle, iCorner, iVertex, iFlagIndex = 0;
-      double fOffset, fInvOffset, fValue = 0.0;
-      GLvector asEdgeVertex[6];
-      GLvector asEdgeNorm[6];
-      GLvector sColor;
-
-      //Find which vertices are inside of the surface and which are outside
-      for(iVertex = 0; iVertex < 4; iVertex++)
-      {
-      if(pafTetrahedronValue[iVertex] <= fTargetValue) 
-      iFlagIndex |= 1<<iVertex;
-      }
-
-      //Find which edges are intersected by the surface
-      iEdgeFlags = aiTetrahedronEdgeFlags[iFlagIndex];
-
-      //If the tetrahedron is entirely inside or outside of the surface, then there will be no intersections
-      if(iEdgeFlags == 0)
-      {
-      return;
-      }
-      //Find the point of intersection of the surface with each edge
-      // Then find the normal to the surface at those points
-      for(iEdge = 0; iEdge < 6; iEdge++)
-      {
-      //if there is an intersection on this edge
-      if(iEdgeFlags & (1<<iEdge))
-      {
-      iVert0 = a2iTetrahedronEdgeConnection[iEdge][0];
-      iVert1 = a2iTetrahedronEdgeConnection[iEdge][1];
-      fOffset = fGetOffset(pafTetrahedronValue[iVert0], pafTetrahedronValue[iVert1], fTargetValue);
-      fInvOffset = 1.0 - fOffset;
-
-      asEdgeVertex[iEdge].fX = fInvOffset*pasTetrahedronPosition[iVert0].fX  +  fOffset*pasTetrahedronPosition[iVert1].fX;
-      asEdgeVertex[iEdge].fY = fInvOffset*pasTetrahedronPosition[iVert0].fY  +  fOffset*pasTetrahedronPosition[iVert1].fY;
-      asEdgeVertex[iEdge].fZ = fInvOffset*pasTetrahedronPosition[iVert0].fZ  +  fOffset*pasTetrahedronPosition[iVert1].fZ;
-                        
-      vGetNormal(asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ);
-      }
-      }
-      //Draw the triangles that were found.  There can be up to 2 per tetrahedron
-      for(iTriangle = 0; iTriangle < 2; iTriangle++)
-      {
-      if(a2iTetrahedronTriangles[iFlagIndex][3*iTriangle] < 0)
-      break;
-
-      for(iCorner = 0; iCorner < 3; iCorner++)
-      {
-      iVertex = a2iTetrahedronTriangles[iFlagIndex][3*iTriangle+iCorner];
-
-      vGetColor(sColor, asEdgeVertex[iVertex], asEdgeNorm[iVertex]);
-      glColor3f(sColor.fX, sColor.fY, sColor.fZ);
-      glNormal3f(asEdgeNorm[iVertex].fX,   asEdgeNorm[iVertex].fY,   asEdgeNorm[iVertex].fZ);
-      glVertex3f(asEdgeVertex[iVertex].fX, asEdgeVertex[iVertex].fY, asEdgeVertex[iVertex].fZ);
-      }
-      }
-      }
-
-
-
-      //vMarchCube2 performs the Marching Tetrahedrons algorithm on a single cube by making six calls to vMarchTetrahedron
-      GLvoid vMarchCube2(double fX, double fY, double fZ, double fScale)
-      {
-      int iVertex, iTetrahedron, iVertexInACube;
-      GLvector asCubePosition[8];
-      double  afCubeValue[8];
-      GLvector asTetrahedronPosition[4];
-      double  afTetrahedronValue[4];
-
-      //Make a local copy of the cube's corner positions
-      for(iVertex = 0; iVertex < 8; iVertex++)
-      {
-      asCubePosition[iVertex].fX = fX + a2fVertexOffset[iVertex][0]*fScale;
-      asCubePosition[iVertex].fY = fY + a2fVertexOffset[iVertex][1]*fScale;
-      asCubePosition[iVertex].fZ = fZ + a2fVertexOffset[iVertex][2]*fScale;
-      }
-
-      //Make a local copy of the cube's corner values
-      for(iVertex = 0; iVertex < 8; iVertex++)
-      {
-      afCubeValue[iVertex] = fSample(asCubePosition[iVertex].fX,
-      asCubePosition[iVertex].fY,
-      asCubePosition[iVertex].fZ);
-      }
-
-      for(iTetrahedron = 0; iTetrahedron < 6; iTetrahedron++)
-      {
-      for(iVertex = 0; iVertex < 4; iVertex++)
-      {
-      iVertexInACube = a2iTetrahedronsInACube[iTetrahedron][iVertex];
-      asTetrahedronPosition[iVertex].fX = asCubePosition[iVertexInACube].fX;
-      asTetrahedronPosition[iVertex].fY = asCubePosition[iVertexInACube].fY;
-      asTetrahedronPosition[iVertex].fZ = asCubePosition[iVertexInACube].fZ;
-      afTetrahedronValue[iVertex] = afCubeValue[iVertexInACube];
-      }
-      vMarchTetrahedron(asTetrahedronPosition, afTetrahedronValue);
-      }
-      }
-    */        
-
-
-    // vMarchingCubes iterates over the entire dataset, calling vMarchCube on each cube
-    void vMarchingCubes(int iDataSetSize, int fStepSize)
-    {
-        int iX, iY, iZ;
-        for(iX = 0; iX < iDataSetSize; iX++)
-            for(iY = 0; iY < iDataSetSize; iY++)
-                for(iZ = 0; iZ < iDataSetSize; iZ++)
-                    {
-                        vMarchCube(iX*fStepSize, iY*fStepSize, iZ*fStepSize, fStepSize);
-                    }
-    }
-
     public abstract double fSample(double x, double y, double z);
     public abstract double fSample(double x, double y, double z);
-    public abstract double fTargetValue();
 
     //vGetNormal() finds the gradient of the scalar field at a point
     //This gradient can be used as a very accurate vertx normal for lighting calculations
 
     //vGetNormal() finds the gradient of the scalar field at a point
     //This gradient can be used as a very accurate vertx normal for lighting calculations
@@ -614,8 +74,17 @@ public abstract class MarchingCubes {
         return (fValueDesired - fValue1)/fDelta;
     }
 
         return (fValueDesired - fValue1)/fDelta;
     }
 
+    // vMarchingCubes iterates over the entire dataset, calling vMarchCube on each cube
+    void vMarchingCubes(Mesh mesh, double targetValue, int iDataSetSize, int fStepSize) {
+        int iX, iY, iZ;
+        for(iX = 0; iX < iDataSetSize; iX++)
+            for(iY = 0; iY < iDataSetSize; iY++)
+                for(iZ = 0; iZ < iDataSetSize; iZ++)
+                    vMarchCube(mesh, targetValue, iX*fStepSize, iY*fStepSize, iZ*fStepSize, fStepSize);
+    }
+
     //vMarchCube performs the Marching Cubes algorithm on a single cube
     //vMarchCube performs the Marching Cubes algorithm on a single cube
-    void vMarchCube(double fX, double fY, double fZ, double fScale) {
+    void vMarchCube(Mesh mesh, double targetValue, double fX, double fY, double fZ, double fScale) {
         int iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
         double fOffset;
         GLvector sColor;
         int iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
         double fOffset;
         GLvector sColor;
@@ -632,7 +101,7 @@ public abstract class MarchingCubes {
         //Find which vertices are inside of the surface and which are outside
         iFlagIndex = 0;
         for(iVertexTest = 0; iVertexTest < 8; iVertexTest++) {
         //Find which vertices are inside of the surface and which are outside
         iFlagIndex = 0;
         for(iVertexTest = 0; iVertexTest < 8; iVertexTest++) {
-            if(afCubeValue[iVertexTest] <= fTargetValue()) 
+            if(afCubeValue[iVertexTest] <= targetValue) 
                 iFlagIndex |= 1<<iVertexTest;
         }
         
                 iFlagIndex |= 1<<iVertexTest;
         }
         
@@ -648,7 +117,7 @@ public abstract class MarchingCubes {
             //if there is an intersection on this edge
             if ((iEdgeFlags & (1<<iEdge))!=0) {
                 fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ], 
             //if there is an intersection on this edge
             if ((iEdgeFlags & (1<<iEdge))!=0) {
                 fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ], 
-                                     afCubeValue[ a2iEdgeConnection[iEdge][1] ], fTargetValue());
+                                     afCubeValue[ a2iEdgeConnection[iEdge][1] ], targetValue);
                 
                 asEdgeVertex[iEdge].fX = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]  +  fOffset * a2fEdgeDirection[iEdge][0]) * fScale;
                 asEdgeVertex[iEdge].fY = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]  +  fOffset * a2fEdgeDirection[iEdge][1]) * fScale;
                 
                 asEdgeVertex[iEdge].fX = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]  +  fOffset * a2fEdgeDirection[iEdge][0]) * fScale;
                 asEdgeVertex[iEdge].fY = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]  +  fOffset * a2fEdgeDirection[iEdge][1]) * fScale;
@@ -676,6 +145,51 @@ public abstract class MarchingCubes {
         }
     }
 
         }
     }
 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    // Tables //////////////////////////////////////////////////////////////////////////////
+
+    // These tables are used so that everything can be done in little
+    // loops that you can look at all at once rather than in pages and
+    // pages of unrolled code.
+    
+    // a2fVertexOffset lists the positions, relative to vertex0, of
+    // each of the 8 vertices of a cube
+    static final double a2fVertexOffset[][] = {
+        {0.0, 0.0, 0.0},{1.0, 0.0, 0.0},{1.0, 1.0, 0.0},{0.0, 1.0, 0.0},
+        {0.0, 0.0, 1.0},{1.0, 0.0, 1.0},{1.0, 1.0, 1.0},{0.0, 1.0, 1.0}
+    };
+    
+    //a2iEdgeConnection lists the index of the endpoint vertices for each of the 12 edges of the cube
+    static final int a2iEdgeConnection[][] = {
+        {0,1}, {1,2}, {2,3}, {3,0},
+        {4,5}, {5,6}, {6,7}, {7,4},
+        {0,4}, {1,5}, {2,6}, {3,7}
+    };
+
+    //a2fEdgeDirection lists the direction vector (vertex1-vertex0) for each edge in the cube
+    static final double a2fEdgeDirection[][] = {
+        {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
+        {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
+        {0.0, 0.0, 1.0},{0.0, 0.0, 1.0},{ 0.0, 0.0, 1.0},{0.0,  0.0, 1.0}
+    };
+
+    // a2iTetrahedronEdgeConnection lists the index of the endpoint
+    // vertices for each of the 6 edges of the tetrahedron
+    static final int a2iTetrahedronEdgeConnection[][] = {
+        {0,1},  {1,2},  {2,0},  {0,3},  {1,3},  {2,3}
+    };
+
+    // a2iTetrahedronEdgeConnection lists the index of verticies from a cube 
+    // that made up each of the six tetrahedrons within the cube
+    static final int a2iTetrahedronsInACube[][] = {
+        {0,5,1,6},
+        {0,1,2,6},
+        {0,2,3,6},
+        {0,3,7,6},
+        {0,7,4,6},
+        {0,4,5,6},
+    };
+
 
     // For any edge, if one vertex is inside of the surface and the
     //  other is outside of the surface then the edge intersects the
 
     // For any edge, if one vertex is inside of the surface and the
     //  other is outside of the surface then the edge intersects the
@@ -688,7 +202,8 @@ public abstract class MarchingCubes {
     //  set to 1
 
     static int aiTetrahedronEdgeFlags[] = {
     //  set to 1
 
     static int aiTetrahedronEdgeFlags[] = {
-        0x00, 0x0d, 0x13, 0x1e, 0x26, 0x2b, 0x35, 0x38, 0x38, 0x35, 0x2b, 0x26, 0x1e, 0x13, 0x0d, 0x00, 
+        0x00, 0x0d, 0x13, 0x1e, 0x26, 0x2b, 0x35, 0x38,
+        0x38, 0x35, 0x2b, 0x26, 0x1e, 0x13, 0x0d, 0x00, 
     };
 
 
     };
 
 
@@ -732,22 +247,38 @@ public abstract class MarchingCubes {
     //  the table, if edge #n is intersected, then bit #n is set to 1
 
     int aiCubeEdgeFlags[] = {
     //  the table, if edge #n is intersected, then bit #n is set to 1
 
     int aiCubeEdgeFlags[] = {
-        0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 
-        0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 
-        0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 
-        0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 
-        0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 
-        0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 
-        0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 
-        0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 
-        0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 
-        0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 
-        0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 
-        0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460, 
-        0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0, 
-        0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230, 
-        0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190, 
-        0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
+        0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+        0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 
+        0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+        0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 
+        0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+        0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 
+        0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
+        0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 
+        0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,
+        0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 
+        0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,
+        0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 
+        0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,
+        0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 
+        0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,
+        0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 
+        0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+        0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 
+        0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+        0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 
+        0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+        0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 
+        0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+        0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460, 
+        0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+        0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0, 
+        0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+        0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230, 
+        0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+        0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190, 
+        0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+        0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
     };
 
     //  For each of the possible vertex states listed in
     };
 
     //  For each of the possible vertex states listed in