0
\$\begingroup\$

so I'm trying to write a marching cubes class for my game, at the moment I have it close (I think). Right now I'm focusing on vertexes and indices. So I'm getting triangles to appear where I want them to but not how I want them to. Here's some screen shots. Front View

Bottom View

And here's the source I'm using to create the mesh.

public class MeshGenerator {

private static int[][] vertexOffset = new int[][] { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 },
        { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } };
private static float target = 0.5f;

public static Voxel[][][] generateVoxels(int size) {
    Voxel[][][] voxels = new Voxel[size][size][size];

    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            for (int k = 0; k < size; k++) {
                voxels[i][j][k] = new Voxel(VoxelMaterial.Grass);
            }
        }
    }

    return voxels;
}

public static MeshData generateMeshMarchingCubes(Voxel[][][] voxels) {

    List<Vector3f> verts = new ArrayList<Vector3f>();
    List<Float> normals = new ArrayList<Float>();
    List<Integer> indices = new ArrayList<Integer>();
    List<Float> textureCoords = new ArrayList<Float>();

    for (int x = 0; x < voxels.length; x++) {
        for (int y = 0; y < voxels.length; y++) {
            for (int z = 0; z < voxels.length; z++) {

                if (voxels[x][y][z].getMaterial() == VoxelMaterial.Air) {
                    continue;
                }

                float[] cube = new float[8];

                if (checkIfExpose(voxels, x, y, z, cube) == false) {
                    continue;
                }

                MarchCube(new Vector3f(x, y, z), cube, verts, indices);

                normals.add(0f);
                normals.add(1f);
                normals.add(0f);

                textureCoords.add(0f);
                textureCoords.add(1f);
            }
        }
    }

    MeshData data = new MeshData();
    data.setIndices(UniversalFunctions.intListToArray(indices));
    data.setVertsFromVector3f(verts);
    data.setNormals(UniversalFunctions.floatListToArray(normals));
    data.setTextureCoords(UniversalFunctions.floatListToArray(textureCoords));

    return data;
}


private static boolean checkIfExpose(Voxel[][][] voxels, int x, int y, int z, float[] cube) {

    Voxel[] surroundingVoxels = getSurroundingVoxels(voxels, x, y, z);
    boolean bool = false;

    for (int i = 0; i < surroundingVoxels.length; i++) {
        if (surroundingVoxels[i].getMaterial() == VoxelMaterial.Air) {
            cube[i] = 0;
            bool = true;
        } else {
            cube[i] = 1;
        }
    }

    return bool;
}

private static Voxel[] getSurroundingVoxels(Voxel[][][] voxels, int x, int y, int z) {

    int maxLength = voxels.length;
    List<Voxel> voxelList = new ArrayList<Voxel>();

    if(y - 1 > 0 && y - 1 < maxLength) {
        voxelList.add(voxels[x][y - 1][z]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    if(x - 1 > 0 && x - 1 < maxLength) {
        voxelList.add(voxels[x - 1][y][z]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    if(z - 1 > 0 && z - 1 < maxLength) {
        voxelList.add(voxels[x][y][z - 1]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    if(z + 1 > 0 && z + 1 < maxLength) {
        voxelList.add(voxels[x][y][z + 1]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    if(x + 1 > 0 && x + 1 < maxLength) {
        voxelList.add(voxels[x + 1][y][z]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    if(y + 1 > 0 && y + 1 < maxLength) {
        voxelList.add(voxels[x][y + 1][z]);
    } else {
        voxelList.add(new Voxel(VoxelMaterial.Air));
    }

    return voxelList.toArray(new Voxel[voxelList.size()]);
}

// MarchCube performs the Marching Cubes algorithm on a single cube
private static void MarchCube(Vector3f pos, float[] cube, List<Vector3f> vertList, List<Integer> indexList) {
    int i, j, vert, idx;
    int flagIndex = 0;
    float offset = 0.0f;

    Vector3f[] edgeVertex = new Vector3f[12];

    for(int inter = 0; inter < 12; inter++) {
        edgeVertex[inter]  =  new Vector3f();
    }

    // Find which vertices are inside of the surface and which are outside
    for (i = 0; i < 8; i++) {
        if (cube[i] <= target) {
            flagIndex |= 1 << i;
        }
    }

    // Find which edges are intersected by the surface
    int edgeFlags = MarchingCubesCases.cubeEdgeFlags[flagIndex];

    // If the cube is entirely inside or outside of the surface, then there will be
    // no intersections
    if (edgeFlags == 0)
        return;

    // Find the point of intersection of the surface with each edge
    for (i = 0; i < 12; i++) {

        // if there is an intersection on this edge
        if ((edgeFlags & (1 << i)) != 0) {
            offset = GetOffset(cube[MarchingCubesCases.edgeConnection[i][0]],
                    cube[MarchingCubesCases.edgeConnection[i][1]]);


            edgeVertex[i].x = pos.x + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][0]
                    + offset * MarchingCubesCases.edgeDirection[i][0]);
            edgeVertex[i].y = pos.y + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][1]
                    + offset * MarchingCubesCases.edgeDirection[i][1]);
            edgeVertex[i].z = pos.z + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][2]
                    + offset * MarchingCubesCases.edgeDirection[i][2]);

        }
    }

    // Save the triangles that were found. There can be up to five per cube
    for (i = 0; i < 5; i++) {

        if (MarchingCubesCases.triangleConnectionTable[flagIndex][3 * i] < 0) {
            break;
        }

        idx = vertList.size();

        for (j = 0; j < 3; j++) {
            vert = MarchingCubesCases.triangleConnectionTable[flagIndex][3 * i + j];
            indexList.add(idx + MarchingCubesCases.windingOrder[j]);
            vertList.add(edgeVertex[vert]);
        }

    }
}

// GetOffset finds the approximate point of intersection of the surface
// between two points with the values v1 and v2
private static float GetOffset(float v1, float v2) {
    float delta = v2 - v1;
    return (delta == 0.0f) ? 0.5f : (target - v1) / delta;
}

I've checked the other look up tables multiple times and they seem good, so tbh I'm lost, I'm not sure where I'm going wrong so any help would be amazing.

Edit : I'm using the generateVoxels to create the voxels in the generateMeshMarchingCubes. The MeshData class is just a holder for the indices, certs, normals, etc for the mesh.

\$\endgroup\$
0
\$\begingroup\$

So to be honest I never really solved this problem.... In java, I translated it to c# and it was working fine, so I have no idea what went wrong, I think my java let me down, but after translating it to c# and using the unity engine it was working fine

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.