行进立方体未创建预期的网格
Posted
技术标签:
【中文标题】行进立方体未创建预期的网格【英文标题】:Marching cubes not creating expected meshes 【发布时间】:2020-10-10 19:38:44 【问题描述】:我一直在尝试使用 c# 实现统一的行进立方体,但是正在创建的网格都具有 90 度的旋转。
在这个例子中,我试图创建一个立方体。
这是我当前的代码,如果有人能找出问题所在,那将非常感谢。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class train : MonoBehaviour
//setup e.g varables and lists
//----------------------------------------------------------------------------------------------------
//size of the chunk
public int size = 10;
//binary stuff
public List<int> binary = new List<int>();
int bitewisenum = 0;
//posithions
public static Vector3 xyz = new Vector3();
public Vector3 list_edges = new Vector3();
//how much air the cut off point bettween air and solid 0.45 - 0.55 works best
public float dencity = 0.4f;
//mesh
public Vector3[] vertices;
public List<Vector3> vertices_list = new List<Vector3>();
public List<Vector3> vertices_list_store = new List<Vector3>();
public List<Vector3> inverlist = new List<Vector3>();
//we can convert it back to an array later
public List<int> tri = new List<int>();
Mesh mesh;
private int[] num;
private float airsolid_test;
public float cutoff; // 11 works best
//perlin noise
//---------------------------------------------------------------------------------------------------
public static float Perlin3D(float x, float y, float z, float cut)
//float AB = Mathf.PerlinNoise(x, y);
//float BC = Mathf.PerlinNoise(y, z);
//float AC = Mathf.PerlinNoise(x, z);
//
//
//float BA = Mathf.PerlinNoise(y, x);
//float CB = Mathf.PerlinNoise(z, y);
//float CA = Mathf.PerlinNoise(z, x);
//
////get the avarge
//float ABC = AB + BC + AC + BA + CB + CA;
//float per = ABC / 6f;
//if (y > cut)
//
// per = Mathf.Pow(per * (y / 8.5f), 2.718f) + 0.3f;
//
//testing
float per;
if (x >= cut)
per = 0f;
else if (y >= cut)
per = 0f;
else if (z <= 0)
per = 0f;
else if (x <= 0)
per = 0f;
else if (z >= cut)
per = 0f;
else if (y <= 0)
per = 0f;
else
per = 10f;
//testing ends
return per;
//----------------------------------------------------------------------------------------
private void Start()
//set up binary
binary.Add(1);
binary.Add(2);
binary.Add(4);
binary.Add(8);
binary.Add(16);
binary.Add(32);
binary.Add(64);
binary.Add(128);
//setup mesh
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
tri.Clear();
//testing --------------------------------------
airsolid_test = dencity;
//0.1 is because of the perlin noise
for (float x = 0.1f; x < 16; x++)
for (int y = 0; y < 15; y++)
for (int z = 0; z < 15; z++)
//airsolid_test = dencity;
//if (y >= cutoff)
////mountans
// airsolid_test += 0.0f;//0.2f
//
//else
////caves
// airsolid_test -= 0.005f;//0.005
//
xyz.x = x;
xyz.y = y;
xyz.z = z;
createshape(x, y, z);
upmesh();
//xyz.x = x;
// xyz.y = y;
// xyz.z = z;
// createshape(x, y, z);
//upmesh();
//upmesh stands for update mesh
void upmesh()
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = tri.ToArray();
mesh.RecalculateNormals();
//-------------------------------------------------------------------------------------
// this is the main function and you give it an xyz cordanit and it sets the mesh's triangles and veticeys
void createshape(float x, float y, float z)
//list for the binary
List<int> bite = new List<int>();
bite.Clear();
bitewisenum = 0;
//this is getting the binay representation for each point on the cube if the point is > the density value store it as a 1 else as a 0
// so we end up with a binary number like 10011101
//position 7
if (Perlin3D(x + 1, y, z + 1, cutoff) > airsolid_test)
bite.Add(1);
//these store the value for intertopilation later but im not using it yet
float Pose_7 = Perlin3D(x + 1, y, z + 1,cutoff);
else
bite.Add(0);
//position 6
if (Perlin3D(x + 1, y + 1, z + 1, cutoff) > airsolid_test)
bite.Add(1);
float Pose_6 = Perlin3D(x + 1, y + 1, z + 1, cutoff);
else
bite.Add(0);
//position 5
if (Perlin3D(x, y + 1, z + 1, cutoff) > airsolid_test)
bite.Add(1);
float Pose_5 = Perlin3D(x, y + 1, z + 1, cutoff);
else
bite.Add(0);
//position 4
if (Perlin3D(x, y, z + 1, cutoff) > airsolid_test)
bite.Add(1);
float Pose_4 = Perlin3D(x, y, z + 1, cutoff);
else
bite.Add(0);
//position 3
if (Perlin3D(x + 1, y, z, cutoff) > airsolid_test)
bite.Add(1);
float Pose_3 = Perlin3D(x + 1, y, z, cutoff);
else
bite.Add(0);
//position 2
if (Perlin3D(x + 1, y + 1, z, cutoff) > airsolid_test)
bite.Add(1);
float Pose_2 = Perlin3D(x + 1, y + 1, z, cutoff);
else
bite.Add(0);
//position 1
if (Perlin3D(x, y + 1, z, cutoff) > airsolid_test)
bite.Add(1);
float Pose_1 = Perlin3D(x, y + 1, z, cutoff);
else
bite.Add(0);
//position 0
if (Perlin3D(x, y, z, cutoff) > airsolid_test)
bite.Add(1);
float Pose_0 = Perlin3D(x, y, z, cutoff);
else
bite.Add(0);
//convert binary in to decimal because i dont know an easy way to do this but
//loop throught all items in the binary list and change them
for (int i = 0; i <= 7; i++)
if (bite[i] == 1)
bitewisenum += binary[i];
//print(bitewisenum);
//check if its not all air or inside an object
//this means that we check if its 0 or 255
//now we need to make the mesh and show it
if (bitewisenum != 0 && bitewisenum != 255)
//Debug.Log("made a mesh");
//store the int array for easyer use
int[] trian = table.TriangleTable[bitewisenum];
/*
* at this point the int array describes edges not postions
* and we need to change that so what we do is loop through ever item in the list and
* parce it through a function(table.transform_to_postion) this returns a Vector 3
* which we then add to a list
*/
vertices_list.Clear();
for (int num = 0; num < trian.Length; num++)
//get the actule postions
//we give the function a edge index as an int which represents a edge index and it gives you the actule postion back as a vector 3
list_edges = transform_to_postion(trian[num]);
//add them to the list
vertices_list.Add(list_edges);
vertices_list_store.Add(list_edges);
//end of the for loop
// set vetaceys
vertices = vertices_list_store.ToArray();
//
//setting the triangles based off how many items there are on the verticeys list
if (vertices_list.Count / 3 == 1)
for (int i = 1; i < 4; i++)
tri.Add(tri.Count);
else if (vertices_list.Count / 3 == 2)
for (int i = 1; i < 7; i++)
tri.Add(tri.Count);
else if (vertices_list.Count / 3 == 3)
for (int i = 1; i < 10; i++)
tri.Add(tri.Count);
else if (vertices_list.Count / 3 == 4)
for (int i = 1; i < 13; i++)
tri.Add(tri.Count);
else if (vertices_list.Count / 3 == 5)
for (int i = 1; i < 16; i++)
tri.Add(tri.Count);
/*
Debug.Log("the legnth of verticys: "+vertices.Length);
Debug.Log("the legnth of tri: "+tri.Length);
Debug.Log("tri legnth " + tri.Length);
end of the if loop
*/
//end of the function
public static Vector3 transform_to_postion(int number_edge)
Vector3 xyz_of_edge = new Vector3();
//check which one it is and then set the xyz
if (number_edge == 0)
xyz_of_edge.x = xyz.x + 0.5f;
xyz_of_edge.y = xyz.y;
xyz_of_edge.z = xyz.z + 1f;
else if (number_edge == 1)
xyz_of_edge.x = xyz.x + 1f;
xyz_of_edge.y = xyz.y;
xyz_of_edge.z = xyz.z + 0.5f;
else if (number_edge == 2)
xyz_of_edge.x = xyz.x + 0.5f;
xyz_of_edge.y = xyz.y;
xyz_of_edge.z = xyz.z;
else if (number_edge == 3)
xyz_of_edge.x = xyz.x;
xyz_of_edge.y = xyz.y;
xyz_of_edge.z = xyz.z + 0.5f;
else if (number_edge == 4)
xyz_of_edge.x = xyz.x + 0.5f;
xyz_of_edge.y = xyz.y + 1f;
xyz_of_edge.z = xyz.z + 1f;
else if (number_edge == 5)
xyz_of_edge.x = xyz.x + 1f;
xyz_of_edge.y = xyz.y + 1f;
xyz_of_edge.z = xyz.z + 0.5f;
else if (number_edge == 6)
xyz_of_edge.x = xyz.x + 0.5f;
xyz_of_edge.y = xyz.y + 1f;
xyz_of_edge.z = xyz.z;
else if (number_edge == 7)
xyz_of_edge.x = xyz.x;
xyz_of_edge.y = xyz.y + 1;
xyz_of_edge.z = xyz.z + 0.5f;
else if (number_edge == 8)
xyz_of_edge.x = xyz.x;
xyz_of_edge.y = xyz.y + 0.5f;
xyz_of_edge.z = xyz.z + 1f;
else if (number_edge == 9)
xyz_of_edge.x = xyz.x + 1f;
xyz_of_edge.y = xyz.y + 0.5f;
xyz_of_edge.z = xyz.z + 1f;
else if (number_edge == 10)
xyz_of_edge.x = xyz.x + 1f;
xyz_of_edge.y = xyz.y + 0.5f;
xyz_of_edge.z = xyz.z;
else if (number_edge == 11)
xyz_of_edge.x = xyz.x;
xyz_of_edge.y = xyz.y + 0.5f;
xyz_of_edge.z = xyz.z;
//Debug.Log("edge index " + number_edge);
//Debug.Log("edges "+xyz_of_edge);
//Debug.Log(xyz_of_edge);
return xyz_of_edge;
【问题讨论】:
从您的屏幕截图中猜测,您的 Z 轴和 Y 轴已调换(交换)。 我尝试交换 Z 轴和 Y 轴,但这只是在不同的轴上导致了同样的问题。 【参考方案1】:我发现问题在于我标记立方体点的方式。我把三角测量表弄错了,这导致了方向错误。 为了解决这个问题,我所做的只是在我的代码中重新定义了指向实际值的点。
【讨论】:
以上是关于行进立方体未创建预期的网格的主要内容,如果未能解决你的问题,请参考以下文章