提问人:Statey 提问时间:6/26/2017 最后编辑:HarrYStatey 更新时间:8/1/2023 访问量:3852
行进立方体在网格中生成孔
Marching Cubes generating holes in mesh
问:
我正在Unity中开发Marching Cubes实现。我的代码基于 Paul Bourke 的代码,实际上进行了大量修改,但无论如何,我正在检查某个位置的块是否为 null,如果它是空的,则在其上放置调试纹理。
这是我的MC脚本。
public class MarchingCubes
{
private World world;
private Chunk chunk;
private List<Vector3> vertices = new List<Vector3> ();
private List<Vector3> normals = new List<Vector3> ();
private Vector3[] ns;
private List<int> triangles = new List<int> ();
private List<Vector2> uvs = new List<Vector2> ();
private Vector3[] positions = new Vector3[8];
private float[] corners = new float[8];
private Vector3i size = new Vector3i (16, 128, 16);
Vector3[] vertlist = new Vector3[12];
private float isolevel = 1f;
private float Corner (Vector3i pos)
{
int x = pos.x;
int y = pos.y;
int z = pos.z;
if (x < size.x && z < size.z) {
return chunk.GetValue (x, y, z);
} else {
int ix = chunk.X, iz = chunk.Z;
int rx = chunk.region.x, rz = chunk.region.z;
if (x >= size.x) {
ix++;
x = 0;
}
if (z >= size.z) {
iz++;
z = 0;
}
return chunk.region.GetChunk (ix, iz).GetValue (x, y, z);
}
}
Block block;
public Mesh MarchChunk (World world, Chunk chunk, Mesh mesh)
{
this.world = world;
this.chunk = chunk;
vertices.Clear ();
triangles.Clear ();
uvs.Clear ();
for (int x = 0; x < size.x; x++) {
for (int y = 1; y < size.y - 2; y++) {
for (int z = 0; z < size.z; z++) {
block = chunk.GetBlock (x, y, z);
int cubeIndex = 0;
for (int i = 0; i < corners.Length; i++) {
corners [i] = Corner (new Vector3i (x, y, z) + offset [i]);
positions [i] = (new Vector3i (x, y, z) + offset [i]).ToVector3 ();
if (corners [i] < isolevel)
cubeIndex |= (1 << i);
}
if (eTable [cubeIndex] == 0)
continue;
for (int i = 0; i < vertlist.Length; i++) {
if ((eTable [cubeIndex] & 1 << i) == 1 << i)
vertlist [i] = LinearInt (positions [eCons [i, 0]], positions [eCons [i, 1]], corners [eCons [i, 0]], corners [eCons [i, 1]]);
}
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.125f);
Vector2 uvBase = block != null ? block.UV : new Vector2 ();
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);
}
}
}
}
if (mesh == null)
mesh = new Mesh ();
mesh.Clear ();
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.uv = uvs.ToArray ();
mesh.RecalculateNormals ();
return mesh;
}
bool IsBitSet (int b, int pos)
{
return ((b & pos) == pos);
}
Vector3 LinearInt (Vector3 p1, Vector3 p2, float v1, float v2)
{
Vector3 p;
p.x = p1.x + (isolevel - v1) * (p2.x - p1.x) / (v2 - v1);
p.y = p1.y + (isolevel - v1) * (p2.y - p1.y) / (v2 - v1);
p.z = p1.z + (isolevel - v1) * (p2.z - p1.z) / (v2 - v1);
return p;
}
private static int[,] eCons = new int[12, 2] {
{ 0, 1 },
{ 1, 2 },
{ 2, 3 },
{ 3, 0 },
{ 4, 5 },
{ 5, 6 },
{ 6, 7 },
{ 7, 4 },
{ 0, 4 },
{ 1, 5 },
{ 2, 6 },
{ 3, 7 }
};
private static Vector3i[] offset = new Vector3i[8] {
new Vector3i (0, 0, 1),
new Vector3i (1, 0, 1),
new Vector3i (1, 0, 0),
new Vector3i (0, 0, 0),
new Vector3i (0, 1, 1),
new Vector3i (1, 1, 1),
new Vector3i (1, 1, 0),
new Vector3i (0, 1, 0)
};
}
我没有把这些表放在示例中,因为它们与 Bourke 代码中的表相同。
编辑: 我发现蓝色三角形处的单元格值为 0,因此不必对它们进行三角测量,但它们下方的单元格值为 1,因此会创建一个顶部三角形来完成网格。
答: 暂无答案
评论
cubeIndex
if (grid.val[6] < isolevel) cubeindex |= 128; if (grid.val[7] < isolevel) cubeindex |= 64;