change MarchingCubes.march() to take a VoxelData rather than a SampledField
authormegacz <adam@megacz.com>
Sun, 1 Mar 2009 03:55:08 +0000 (19:55 -0800)
committermegacz <adam@megacz.com>
Sun, 1 Mar 2009 03:55:08 +0000 (19:55 -0800)
src/edu/berkeley/qfat/Main.java
src/edu/berkeley/qfat/voxel/MarchingCubes.java

index f5a1344..56eeb83 100644 (file)
@@ -295,18 +295,25 @@ public class Main extends InteractiveMeshViewer {
     public void marchingCubes() {
         Mesh mesh = new Mesh(false);
         mesh.coalesce = true;
-        MarchingCubes.march(new SampledField() {
-                                public float getSample(Point p) {
-                                    double x = p.x;
-                                    double y = p.y;
-                                    double z = p.z;
-                                    x-=1.1;
-                                    y-=1.1;
-                                    z-=1.1;
-                                    return (float)(0.8-Math.sqrt(x*x+y*y+z*z));
-                                }
-                            },
-            0, 30, 0.1, mesh);
+        MarchingCubes.march(new VoxelData() {
+                float radius = 1.0f;
+                public float getMaxX()        { return  1.0f; }
+                public float getMinX()        { return -1.0f; }
+                public int   getNumSamplesX() { return   10; }
+                public float getMaxY()        { return  1.0f; }
+                public float getMinY()        { return -1.0f; }
+                public int   getNumSamplesY() { return   10; }
+                public float getMaxZ()        { return  1.0f; }
+                public float getMinZ()        { return -1.0f; }
+                public int   getNumSamplesZ() { return   10; }
+                public float getSample(Point p) {
+                    double x = p.x;
+                    double y = p.y;
+                    double z = p.z;
+                    return (float)(radius-Math.sqrt(x*x+y*y+z*z));
+                }
+            },
+            mesh);
         setTile(mesh);
         //fixupTile();
     }
index a365585..3112d8d 100644 (file)
@@ -35,18 +35,25 @@ public class MarchingCubes {
     };
 
     /** march iterates over the entire dataset, calling vMarchCube on each cube */
-    public static void march(SampledField sampledField, double threshold, int iDataSetSize, double fStepSize, Mesh mesh) {
-        int iX, iY, iZ;
+    public static void march(VoxelData voxels, Mesh mesh) { march(voxels, 0, mesh); }
+    public static void march(VoxelData voxels, double threshold, Mesh mesh) {
         int initialTriangles = mesh.numTriangles();
-        for(iX = 0; iX < iDataSetSize; iX++) {
+        double scaleX = (voxels.getMaxX() - voxels.getMinX()) / (double)voxels.getNumSamplesX();
+        double scaleY = (voxels.getMaxY() - voxels.getMinY()) / (double)voxels.getNumSamplesY();
+        double scaleZ = (voxels.getMaxZ() - voxels.getMinZ()) / (double)voxels.getNumSamplesZ();
+        for(int iX = 0; iX < voxels.getNumSamplesX(); iX++) {
             System.out.print("\r");
             for(int i=0; i<78; i++) System.out.print(' ');
             System.out.print("\r");
-            System.out.print(Math.ceil((iX/((double)iDataSetSize))*100) + "% marched, " +
+            System.out.print(Math.ceil((iX/((double)voxels.getNumSamplesX()))*100) + "% marched, " +
                              (mesh.numTriangles()-initialTriangles) + " triangles");
-            for(iY = 0; iY < iDataSetSize; iY++)
-                for(iZ = 0; iZ < iDataSetSize; iZ++)
-                    march(sampledField, mesh, threshold, iX*fStepSize, iY*fStepSize, iZ*fStepSize, fStepSize);
+            for(int iY = 0; iY < voxels.getNumSamplesY(); iY++)
+                for(int iZ = 0; iZ < voxels.getNumSamplesZ(); iZ++)
+                    march(voxels, mesh, threshold,
+                          iX*scaleX + voxels.getMinX(),
+                          iY*scaleY + voxels.getMinY(),
+                          iZ*scaleZ + voxels.getMinZ(),
+                          scaleX, scaleY, scaleZ);
         }
         System.out.print("\r");
         for(int i=0; i<78; i++) System.out.print(' ');
@@ -55,7 +62,9 @@ public class MarchingCubes {
     }
 
     /** performs the Marching Cubes algorithm on a single cube */
-    static void march(SampledField sampledField, Mesh mesh, double threshold, double fX, double fY, double fZ, double fScale) {
+    static void march(VoxelData voxels, Mesh mesh, double threshold,
+                      double fX, double fY, double fZ,
+                      double scaleX, double scaleY, double scaleZ) {
         int iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
         double fOffset;
         GLvector sColor;
@@ -68,9 +77,9 @@ public class MarchingCubes {
 
         // Make a local copy of the values at the cube's corners
         for(iVertex = 0; iVertex < 8; iVertex++)
-            afCubeValue[iVertex] = sampledField.getSample(new Point(fX + a2fVertexOffset[iVertex][0]*fScale,
-                                                                    fY + a2fVertexOffset[iVertex][1]*fScale,
-                                                                    fZ + a2fVertexOffset[iVertex][2]*fScale));
+            afCubeValue[iVertex] = voxels.getSample(new Point(fX + a2fVertexOffset[iVertex][0]*scaleX,
+                                                                    fY + a2fVertexOffset[iVertex][1]*scaleY,
+                                                                    fZ + a2fVertexOffset[iVertex][2]*scaleZ));
 
         // Find which vertices are inside of the surface and which are outside
         iFlagIndex = 0;
@@ -92,13 +101,13 @@ public class MarchingCubes {
             fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ], 
                                  afCubeValue[ a2iEdgeConnection[iEdge][1] ],
                                  threshold,
-                                 fScale * 0.1);
+                                 Math.min(Math.min(scaleX, scaleY), scaleZ) * 0.1);
             
-            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].fZ = fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2]  +  fOffset * a2fEdgeDirection[iEdge][2]) * fScale;
+            asEdgeVertex[iEdge].fX = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]  +  fOffset * a2fEdgeDirection[iEdge][0]) * scaleX;
+            asEdgeVertex[iEdge].fY = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]  +  fOffset * a2fEdgeDirection[iEdge][1]) * scaleY;
+            asEdgeVertex[iEdge].fZ = fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2]  +  fOffset * a2fEdgeDirection[iEdge][2]) * scaleZ;
             
-            vGetNormal(sampledField, asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ);
+            vGetNormal(voxels, asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ);
         }
 
         // Draw the triangles that were found.  There can be up to five per cube
@@ -132,16 +141,16 @@ public class MarchingCubes {
      *  This gradient can be used as a very accurate vertx normal for
      *  lighting calculations
      */
-    static void vGetNormal(SampledField sampledField, GLvector rfNormal, double fX, double fY, double fZ) {
+    static void vGetNormal(VoxelData voxels, GLvector rfNormal, double fX, double fY, double fZ) {
         rfNormal.fX =
-            sampledField.getSample(new Point(fX-0.01, fY, fZ)) -
-            sampledField.getSample(new Point(fX+0.01, fY, fZ));
+            voxels.getSample(new Point(fX-0.01, fY, fZ)) -
+            voxels.getSample(new Point(fX+0.01, fY, fZ));
         rfNormal.fY =
-            sampledField.getSample(new Point(fX, fY-0.01, fZ)) -
-            sampledField.getSample(new Point(fX, fY+0.01, fZ));
+            voxels.getSample(new Point(fX, fY-0.01, fZ)) -
+            voxels.getSample(new Point(fX, fY+0.01, fZ));
         rfNormal.fZ =
-            sampledField.getSample(new Point(fX, fY, fZ-0.01)) -
-            sampledField.getSample(new Point(fX, fY, fZ+0.01));
+            voxels.getSample(new Point(fX, fY, fZ-0.01)) -
+            voxels.getSample(new Point(fX, fY, fZ+0.01));
         vNormalizeVector(rfNormal, rfNormal);
     }