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\$

1 Answer 1

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .