private void March()
        {
            int x, y, z;

            for (int i = 0; i < metaballs.Count; i++)
            {
                z = (int)((metaballs[i].PosZ + 0.5f) * lattice.dimensionZ);
                x = (int)((metaballs[i].PosX + 0.5f) * lattice.dimensionX);
                y = (int)((metaballs[i].PosY + 0.5f) * lattice.dimensionY);

                while (z >= 0)
                {
                    LatticeCube cube = lattice.GetCube(x, y, z);
                    if (cube != null && cube.lastFrame < frameCount)
                    {
                        if (DoCube(cube))
                        {
                            RecurseCube(cube);
                            z = -1;
                        }

                        cube.lastFrame = frameCount;
                    }
                    else
                    {
                        z = -1;
                    }
                }
            }
        }
        private void GenerateEdge(LatticeCube cube, int edgeIndex, int pointIndex, int pointIndex2)
        {
            Vector3     vector;
            LatticeEdge edge = cube.edgeArray[edgeIndex];

            if (edge.lastFrame < frameCount)
            {
                vector                    = lattice.PositionOnAxis(cube.pointArray[pointIndex], cube.pointArray[pointIndex2], edge.axis);
                edge.position             = vector;
                edge.vertexIndex          = vertexPointer;
                normals[vertexPointer]    = CalculateNormal(vector);
                vertices[vertexPointer++] = vector;
                edge.lastFrame            = frameCount;
            }
        }
            public void GenerateLattice()
            {
                // calculate the amount of cubes, points and edges based on the dimensions
                int pointArrayAmount = ((dimensionX + 1) * (dimensionY + 1) * (dimensionZ + 1));

                cubeArrayAmount = dimensionX * dimensionY * dimensionZ;
                int edgeArrayAmountTotal = (cubeArrayAmount * 3) + ((2 * dimensionX * dimensionY) + (2 * dimensionX * dimensionZ) + (2 * dimensionY * dimensionZ)) +
                                           dimensionX + dimensionY + dimensionZ;
                int edgeArrayAmountNow = edgeArrayAmountTotal + ((dimensionX * dimensionY) + (dimensionX * dimensionZ) + (dimensionY * dimensionZ)) * 2;

                cubeArray  = new LatticeCube[cubeArrayAmount];
                pointArray = new LatticePoint[pointArrayAmount];
                edgeArray  = new LatticeEdge[edgeArrayAmountNow];

                // create all edges
                for (int i = 0; i < edgeArrayAmountNow; i++)
                {
                    edgeArray[i] = new LatticeEdge(-1);
                }

                // create all points
                int pointIndex = 0;

                for (float i = 0; i <= dimensionX; i++)
                {
                    for (float j = 0; j <= dimensionY; j++)
                    {
                        for (float k = 0; k <= dimensionZ; k++)
                        {
                            pointArray[pointIndex] = new LatticePoint((i / dimensionX) - 0.5f, (j / dimensionY) - 0.5f, (k / dimensionZ) - 0.5f, system);
                            pointIndex++;
                        }
                    }
                }

                // create all cubes
                for (int i = 0; i < cubeArrayAmount; i++)
                {
                    cubeArray[i] = new LatticeCube();
                }

                LatticeCube cube;
                LatticeCube cube2;
                int         cubeIndex = 0;
                int         edgeIndex = 0;

                for (int i = 0; i < dimensionX; i++)
                {
                    for (int j = 0; j < dimensionY; j++)
                    {
                        for (int k = 0; k < dimensionZ; k++)
                        {
                            cube = cubeArray[cubeIndex];

                            cubeIndex++;

                            // set the position of the cube
                            cube.posX = i;
                            cube.posY = j;
                            cube.posZ = k;

                            // set the points of the cube
                            LatticePoint[] points = cube.pointArray;
                            points[0] = GetPoint(i, j, k);
                            points[1] = GetPoint(i + 1, j, k);
                            points[2] = GetPoint(i + 1, j + 1, k);
                            points[3] = GetPoint(i, j + 1, k);
                            points[4] = GetPoint(i, j, k + 1);
                            points[5] = GetPoint(i + 1, j, k + 1);
                            points[6] = GetPoint(i + 1, j + 1, k + 1);
                            points[7] = GetPoint(i, j + 1, k + 1);

                            LatticeEdge[] edges = cube.edgeArray;

                            // set the axis of the edges
                            edges[5]       = edgeArray[edgeIndex++];
                            edges[5].axis  = 1;
                            edges[6]       = edgeArray[edgeIndex++];
                            edges[6].axis  = 0;
                            edges[10]      = edgeArray[edgeIndex++];
                            edges[10].axis = 2;

                            // checks adjacent cubes and set their edges
                            cube2 = GetCube(i + 1, j, k);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[11] = edges[10];
                                cube2.edgeArray[7]  = edges[5];
                            }

                            cube2 = GetCube(i, j + 1, k);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[4] = cube.edgeArray[6];
                                cube2.edgeArray[9] = cube.edgeArray[10];
                            }

                            cube2 = GetCube(i, j + 1, k + 1);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[0] = cube.edgeArray[6];
                            }

                            cube2 = GetCube(i + 1, j, k + 1);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[3] = cube.edgeArray[5];
                            }

                            cube2 = GetCube(i + 1, j + 1, k);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[8] = cube.edgeArray[10];
                            }

                            cube2 = GetCube(i, j, k + 1);
                            if (cube2 != null)
                            {
                                cube2.edgeArray[1] = cube.edgeArray[5];
                                cube2.edgeArray[2] = cube.edgeArray[6];
                            }

                            // set the remaining edges axis
                            if (edges[0] == null)
                            {
                                edges[0]      = edgeArray[edgeIndex++];
                                edges[0].axis = 0;
                            }

                            if (edges[1] == null)
                            {
                                edges[1]      = edgeArray[edgeIndex++];
                                edges[1].axis = 1;
                            }

                            if (edges[2] == null)
                            {
                                edges[2]      = edgeArray[edgeIndex++];
                                edges[2].axis = 0;
                            }

                            if (edges[3] == null)
                            {
                                edges[3]      = edgeArray[edgeIndex++];
                                edges[3].axis = 1;
                            }

                            if (edges[4] == null)
                            {
                                edges[4]      = edgeArray[edgeIndex++];
                                edges[4].axis = 0;
                            }

                            if (edges[7] == null)
                            {
                                edges[7]      = edgeArray[edgeIndex++];
                                edges[7].axis = 1;
                            }

                            if (edges[8] == null)
                            {
                                edges[8]      = edgeArray[edgeIndex++];
                                edges[8].axis = 2;
                            }

                            if (edges[9] == null)
                            {
                                edges[9]      = edgeArray[edgeIndex++];
                                edges[9].axis = 2;
                            }

                            if (edges[11] == null)
                            {
                                edges[11]      = edgeArray[edgeIndex++];
                                edges[11].axis = 2;
                            }
                        }
                    }
                }
            }
        private bool DoCube(LatticeCube cube)
        {
            int cubeIndex = 0;

            // check if the intensity of the point is over the treshhold
            if (cube.pointArray[0].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 1;
            }
            if (cube.pointArray[1].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 2;
            }
            if (cube.pointArray[2].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 4;
            }
            if (cube.pointArray[3].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 8;
            }
            if (cube.pointArray[4].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 16;
            }
            if (cube.pointArray[5].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 32;
            }
            if (cube.pointArray[6].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 64;
            }
            if (cube.pointArray[7].CalculateIntensity() > isoLevel)
            {
                cubeIndex |= 128;
            }

            int edgeIndex = edgeTable[cubeIndex];

            if (edgeIndex != 0)
            {
                if ((edgeIndex & 1) > 0)
                {
                    GenerateEdge(cube, 0, 0, 1);
                }

                if ((edgeIndex & 2) > 0)
                {
                    GenerateEdge(cube, 1, 1, 2);
                }

                if ((edgeIndex & 4) > 0)
                {
                    GenerateEdge(cube, 2, 2, 3);
                }

                if ((edgeIndex & 0x8) > 0)
                {
                    GenerateEdge(cube, 3, 3, 0);
                }

                if ((edgeIndex & 0x10) > 0)
                {
                    GenerateEdge(cube, 4, 4, 5);
                }

                if ((edgeIndex & 0x20) > 0)
                {
                    GenerateEdge(cube, 5, 5, 6);
                }

                if ((edgeIndex & 0x40) > 0)
                {
                    GenerateEdge(cube, 6, 6, 7);
                }

                if ((edgeIndex & 0x80) > 0)
                {
                    GenerateEdge(cube, 7, 7, 4);
                }

                if ((edgeIndex & 0x100) > 0)
                {
                    GenerateEdge(cube, 8, 0, 4);
                }

                if ((edgeIndex & 0x200) > 0)
                {
                    GenerateEdge(cube, 9, 1, 5);
                }

                if ((edgeIndex & 0x400) > 0)
                {
                    GenerateEdge(cube, 10, 2, 6);
                }

                if ((edgeIndex & 0x800) > 0)
                {
                    GenerateEdge(cube, 11, 3, 7);
                }

                int temp;
                int triangleIndex = 0;
                while (triTable[cubeIndex, triangleIndex] != -1)
                {
                    temp = cube.edgeArray[triTable[cubeIndex, triangleIndex + 2]].vertexIndex;
                    triangles[trianglePointer++] = temp;

                    temp = cube.edgeArray[triTable[cubeIndex, triangleIndex + 1]].vertexIndex;
                    triangles[trianglePointer++] = temp;

                    temp = cube.edgeArray[triTable[cubeIndex, triangleIndex]].vertexIndex;
                    triangles[trianglePointer++] = temp;

                    triangleIndex += 3;
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
        private void RecurseCube(LatticeCube cube)
        {
            int x = cube.posX;
            int y = cube.posY;
            int z = cube.posZ;

            LatticeCube adjacent;

            adjacent = lattice.GetCube(x + 1, y, z);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }

            adjacent = lattice.GetCube(x - 1, y, z);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }

            adjacent = lattice.GetCube(x, y + 1, z);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }

            adjacent = lattice.GetCube(x, y - 1, z);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }

            adjacent = lattice.GetCube(x, y, z + 1);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }

            adjacent = lattice.GetCube(x, y, z - 1);
            if (adjacent != null && adjacent.lastFrame < frameCount)
            {
                adjacent.lastFrame = frameCount;
                if (DoCube(adjacent))
                {
                    RecurseCube(adjacent);
                }
            }
        }