So, well I've been trying to find out the reason of the following bug in my marching cubes implementation, but I can't figure it out.
Now this is a two state implementation of MC (just two exact isovalues 0 or 1) and the isovalue of the cells at the blue triangles are 0 means that they don't have to be triangulated. But they are for some reason. Therefore they got a fallback texture. But it's been a long time since I'm trying to figure this out, so if you have any idea please share it with me. Here is the code of my MC implementation.
public class MarchingCubes
{
private Region region;
private Chunk chunk;
private Mesh mesh = new Mesh ();
private List<Vector3> vertices = new List<Vector3> ();
private List<int> triangles = new List<int> ();
private List<Vector2> uvs = new List<Vector2> ();
private ValPair[] pairs = new ValPair[8];
private Debugger debugger;
private int chunkSize = 16;
private float isolevel = 1f;
public MarchingCubes (Debugger debugger)
{
this.debugger = debugger;
}
private float CornerValue (Vector3i pos)
{
int x = pos.x;
int y = pos.y;
int z = pos.z;
if (y < 0 || y >= 128)
return 0f;
if (x >= 0 && x < chunkSize && z >= 0 && z < chunkSize) {
return chunk.GetValue (x, y, z);
} else {
Chunk neighbor = null;
int ix = chunk.X (), iz = chunk.Z ();
if (x < 0) {
ix--;
if (ix == -1)
return 0f;
x = 16;
}
if (z < 0) {
iz--;
if (iz == -1)
return 0f;
z = 16;
}
if (x >= chunkSize) {
ix++;
if (ix == region.regionSize)
return 0f;
x = 0;
}
if (z >= chunkSize) {
iz++;
if (iz == region.regionSize)
return 0f;
z = 0;
}
neighbor = region.GetChunk (ix, iz);
return neighbor.GetValue (x, y, z);
}
}
struct ValPair
{
public Vector3 position;
public float intsect;
}
public Mesh Render (Region region, Chunk chunk)
{
this.region = region;
this.chunk = chunk;
vertices.Clear ();
triangles.Clear ();
uvs.Clear ();
Cell cell;
Block block;
for (int x = 0; x < chunkSize; x++) {
for (int z = 0; z < chunkSize; z++) {
for (int y = 0; y <= chunk.GetRow(x, z).GetHeight(); y++) {
cell = chunk.GetRow (x, z).GetCell (y);
block = cell.GetBlock ();
int cubeIndex = 0;
for (int i = 0; i < 8; i++) {
pairs [i].intsect = CornerValue (new Vector3i (x, y, z) + offset [i]);
if (pairs [i].intsect < isolevel)
cubeIndex += 1 << i;
}
if (cubeIndex == 0 || cubeIndex == 255)
continue;
for (int i = 0; i < 8; i++) {
pairs [i].position = (new Vector3i (x, y, z) + offset [i]).ToVector3 ();
}
Vector3[] vertlist = new Vector3[12];
if ((edgeTable [cubeIndex] & 1) == 1)
vertlist [0] = VertexInterp (pairs [0], pairs [1]);
if ((edgeTable [cubeIndex] & 2) == 2)
vertlist [1] = VertexInterp (pairs [1], pairs [2]);
if ((edgeTable [cubeIndex] & 4) == 4)
vertlist [2] = VertexInterp (pairs [2], pairs [3]);
if ((edgeTable [cubeIndex] & 8) == 8)
vertlist [3] = VertexInterp (pairs [3], pairs [0]);
if ((edgeTable [cubeIndex] & 16) == 16)
vertlist [4] = VertexInterp (pairs [4], pairs [5]);
if ((edgeTable [cubeIndex] & 32) == 32)
vertlist [5] = VertexInterp (pairs [5], pairs [6]);
if ((edgeTable [cubeIndex] & 64) == 64)
vertlist [6] = VertexInterp (pairs [6], pairs [7]);
if ((edgeTable [cubeIndex] & 128) == 128)
vertlist [7] = VertexInterp (pairs [7], pairs [4]);
if ((edgeTable [cubeIndex] & 256) == 256)
vertlist [8] = VertexInterp (pairs [0], pairs [4]);
if ((edgeTable [cubeIndex] & 512) == 512)
vertlist [9] = VertexInterp (pairs [1], pairs [5]);
if ((edgeTable [cubeIndex] & 1024) == 1024)
vertlist [10] = VertexInterp (pairs [2], pairs [6]);
if ((edgeTable [cubeIndex] & 2048) == 2048)
vertlist [11] = VertexInterp (pairs [3], pairs [7]);
for (int i = 0; triTable [cubeIndex, i] != -1; i += 3) {
int index = vertices.Count;
vertices.Add (vertlist [triTable [cubeIndex, i]]);
vertices.Add (vertlist [triTable [cubeIndex, i + 1]]);
vertices.Add (vertlist [triTable [cubeIndex, i + 2]]);
float tec = (0.25f);
Vector2 uvBase;
if (debugger.useDebugUVs) {
uvBase = debugger.debugUV;
} else {
if (block != null) {
uvBase = block.UV;
} else {
uvBase = debugger.debugUV;
}
uvs.Add (uvBase);
uvs.Add (uvBase + new Vector2 (0, tec));
uvs.Add (uvBase + new Vector2 (tec, tec));
triangles.Add (index + 0);
triangles.Add (index + 1);
triangles.Add (index + 2);
}
}
}
}
}
mesh.Clear ();
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.uv = uvs.ToArray ();
mesh.RecalculateNormals ();
mesh.RecalculateBounds ();
return mesh;
}
bool IsBitSet (int b, int pos)
{
return ((b & pos) == pos);
}
Vector3 VertexInterp (ValPair pair1, ValPair pair2)
{
float mu;
Vector3 p = new Vector3 ();
if (Mathf.Abs (isolevel - pair1.intsect) < 0.00001)
return pair1.position;
if (Mathf.Abs (isolevel - pair2.intsect) < 0.00001)
return pair2.position;
if (Mathf.Abs (pair1.intsect - pair2.intsect) < 0.00001)
return pair1.position;
mu = (isolevel - pair1.intsect) / (pair2.intsect - pair1.intsect);
p.x = (float)(pair1.position.x + mu * (pair2.position.x - pair1.position.x));
p.y = (float)(pair1.position.y + mu * (pair2.position.y - pair1.position.y));
p.z = (float)(pair1.position.z + mu * (pair2.position.z - pair1.position.z));
return p;
}
public Mesh ToMesh (Mesh mesh)
{
if (mesh == null)
mesh = new Mesh ();
mesh.Clear ();
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.uv = uvs.ToArray ();
mesh.RecalculateNormals ();
mesh.RecalculateBounds ();
return mesh;
}
Any other rotated versions of the specific case are seeable.