Physics.Raycast 无法使用 Marching Cubes 生成的网格
Physics.Raycast not working with a Marching Cubes -generated mesh
What it spits out
我的 raycast 吐出了一个偏离它应该的位置的位置。我正在尝试以程序方式将对象放置在程序网格上。一段时间以来,我一直在摸不着头脑。请帮忙。
抱歉,脚本太长了。
代码的开头只是一些声明和内容。 Start 完成后,GenObjects 在 FixedUpdate 中是 运行 一次。我正在使用 marching cubes library by Scrawk and a noise library by Auburn
void GenMesh()
{
Marching marching = new MarchingCubes();
marching.Surface = 0.0f;
voxels = new float[width * height * length];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < length; z++)
{
float fx = x / (width - 1.0f);
float fy = y / (height - 1.0f);
float fz = z / (length - 1.0f);
int idx = x + y * width + z * width * height;
float surfaceHeight = noise2.GetNoise(x,z) * amplitude + offset;
float currentHeight = Mathf.Clamp(y, surfaceHeight - threshold, surfaceHeight + threshold);
float t = Mathf.Abs(currentHeight - surfaceHeight) / threshold;
voxels[idx] = Mathf.Lerp(Mathf.Clamp(noise.GetNoise(x,y,z), 0.65f, 1), -1f, t);
}
}
}
List<Vector3> verts = new List<Vector3>();
List<int> indices = new List<int>();
marching.Generate(voxels, width, height, length, verts, indices);
int maxVertsPerMesh = 30000;
int numMeshes = verts.Count / maxVertsPerMesh + 1;
for (int i = 0; i < numMeshes; i++)
{
List<Vector3> splitVerts = new List<Vector3>();
List<int> splitIndices = new List<int>();
for (int j = 0; j < maxVertsPerMesh; j++)
{
int idx = i * maxVertsPerMesh + j;
if (idx < verts.Count)
{
splitVerts.Add(verts[idx]);
splitIndices.Add(j);
}
}
if (splitVerts.Count == 0) continue;
Mesh mesh = new Mesh();
mesh.SetVertices(splitVerts);
mesh.SetTriangles(splitIndices, 0);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
MeshWelder meshWelder = new MeshWelder(mesh);
meshWelder.Weld();
GameObject go = new GameObject("Mesh");
go.layer = LayerMask.NameToLayer("Ground");
go.transform.parent = transform;
go.transform.localScale = new Vector3(100f, 100f, 100f);
go.AddComponent<MeshFilter>();
go.AddComponent<MeshRenderer>();
go.AddComponent<MeshCollider>();
go.GetComponent<Renderer>().material = m_material;
go.GetComponent<MeshFilter>().mesh = mesh;
go.GetComponent<MeshCollider>().sharedMesh = mesh;
go.GetComponent<MeshCollider>().contactOffset = 0f;
go.transform.localPosition = new Vector3(-width * 100 / 2, -height * 100 / 4, -length * 100 / 2);
meshes.Add(go);
}
}
void GenObjects(GameObject prefab, float radius, Vector2 sampleRegionSize, Vector2 origin, int seed)
{
List<Vector2> points = PoissonDiscSampling.GeneratePoints(radius, sampleRegionSize, seed);
Physics.queriesHitBackfaces = true;
foreach (Vector2 point in points)
{
RaycastHit hit;
Vector3 objPos = new Vector3(0,0,0);
bool validPosFound = false;
if (Physics.Raycast(new Vector3(point.x + origin.x, 0, point.y + origin.y), Vector3.down, out hit, height * 100, layerMask))
{
objPos = hit.point;
validPosFound = true;
} else if (Physics.Raycast(new Vector3(point.x + origin.x, 0, point.y + origin.y), Vector3.up, out hit, height * 100, layerMask))
{
objPos = hit.point;
validPosFound = true;
}
if (validPosFound)
{
GameObject newObject = Instantiate(prefab, objPos, Quaternion.Euler(0, 0, 0));
}
}
Physics.queriesHitBackfaces = false;
}
}
已修复!我的错误真的很愚蠢。我没有分配焊接网格,留下了一个肮脏的网格,上面漂浮着许多空顶点。光线投射击中了他们。
有心人的固话:
Mesh mesh = new Mesh();
Mesh mesh_temp = new Mesh();
mesh_temp.SetVertices(splitVerts);
mesh_temp.SetTriangles(splitIndices, 0);
mesh_temp.RecalculateBounds();
mesh_temp.RecalculateNormals();
MeshWelder meshWelder = new MeshWelder();
meshWelder.customMesh = new CustomMesh();
meshWelder.customMesh.vertices = splitVerts.ToArray();
meshWelder.customMesh.triangles = splitIndices.ToArray();
meshWelder.customMesh.normals = mesh_temp.normals;
meshWelder.Weld();
mesh.SetVertices(meshWelder.customMesh.vertices);
mesh.SetTriangles(meshWelder.customMesh.triangles, 0);
mesh.SetNormals(meshWelder.customMesh.normals);
mesh.RecalculateBounds();
What it spits out
我的 raycast 吐出了一个偏离它应该的位置的位置。我正在尝试以程序方式将对象放置在程序网格上。一段时间以来,我一直在摸不着头脑。请帮忙。 抱歉,脚本太长了。
代码的开头只是一些声明和内容。 Start 完成后,GenObjects 在 FixedUpdate 中是 运行 一次。我正在使用 marching cubes library by Scrawk and a noise library by Auburn
void GenMesh()
{
Marching marching = new MarchingCubes();
marching.Surface = 0.0f;
voxels = new float[width * height * length];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < length; z++)
{
float fx = x / (width - 1.0f);
float fy = y / (height - 1.0f);
float fz = z / (length - 1.0f);
int idx = x + y * width + z * width * height;
float surfaceHeight = noise2.GetNoise(x,z) * amplitude + offset;
float currentHeight = Mathf.Clamp(y, surfaceHeight - threshold, surfaceHeight + threshold);
float t = Mathf.Abs(currentHeight - surfaceHeight) / threshold;
voxels[idx] = Mathf.Lerp(Mathf.Clamp(noise.GetNoise(x,y,z), 0.65f, 1), -1f, t);
}
}
}
List<Vector3> verts = new List<Vector3>();
List<int> indices = new List<int>();
marching.Generate(voxels, width, height, length, verts, indices);
int maxVertsPerMesh = 30000;
int numMeshes = verts.Count / maxVertsPerMesh + 1;
for (int i = 0; i < numMeshes; i++)
{
List<Vector3> splitVerts = new List<Vector3>();
List<int> splitIndices = new List<int>();
for (int j = 0; j < maxVertsPerMesh; j++)
{
int idx = i * maxVertsPerMesh + j;
if (idx < verts.Count)
{
splitVerts.Add(verts[idx]);
splitIndices.Add(j);
}
}
if (splitVerts.Count == 0) continue;
Mesh mesh = new Mesh();
mesh.SetVertices(splitVerts);
mesh.SetTriangles(splitIndices, 0);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
MeshWelder meshWelder = new MeshWelder(mesh);
meshWelder.Weld();
GameObject go = new GameObject("Mesh");
go.layer = LayerMask.NameToLayer("Ground");
go.transform.parent = transform;
go.transform.localScale = new Vector3(100f, 100f, 100f);
go.AddComponent<MeshFilter>();
go.AddComponent<MeshRenderer>();
go.AddComponent<MeshCollider>();
go.GetComponent<Renderer>().material = m_material;
go.GetComponent<MeshFilter>().mesh = mesh;
go.GetComponent<MeshCollider>().sharedMesh = mesh;
go.GetComponent<MeshCollider>().contactOffset = 0f;
go.transform.localPosition = new Vector3(-width * 100 / 2, -height * 100 / 4, -length * 100 / 2);
meshes.Add(go);
}
}
void GenObjects(GameObject prefab, float radius, Vector2 sampleRegionSize, Vector2 origin, int seed)
{
List<Vector2> points = PoissonDiscSampling.GeneratePoints(radius, sampleRegionSize, seed);
Physics.queriesHitBackfaces = true;
foreach (Vector2 point in points)
{
RaycastHit hit;
Vector3 objPos = new Vector3(0,0,0);
bool validPosFound = false;
if (Physics.Raycast(new Vector3(point.x + origin.x, 0, point.y + origin.y), Vector3.down, out hit, height * 100, layerMask))
{
objPos = hit.point;
validPosFound = true;
} else if (Physics.Raycast(new Vector3(point.x + origin.x, 0, point.y + origin.y), Vector3.up, out hit, height * 100, layerMask))
{
objPos = hit.point;
validPosFound = true;
}
if (validPosFound)
{
GameObject newObject = Instantiate(prefab, objPos, Quaternion.Euler(0, 0, 0));
}
}
Physics.queriesHitBackfaces = false;
}
}
已修复!我的错误真的很愚蠢。我没有分配焊接网格,留下了一个肮脏的网格,上面漂浮着许多空顶点。光线投射击中了他们。
有心人的固话:
Mesh mesh = new Mesh();
Mesh mesh_temp = new Mesh();
mesh_temp.SetVertices(splitVerts);
mesh_temp.SetTriangles(splitIndices, 0);
mesh_temp.RecalculateBounds();
mesh_temp.RecalculateNormals();
MeshWelder meshWelder = new MeshWelder();
meshWelder.customMesh = new CustomMesh();
meshWelder.customMesh.vertices = splitVerts.ToArray();
meshWelder.customMesh.triangles = splitIndices.ToArray();
meshWelder.customMesh.normals = mesh_temp.normals;
meshWelder.Weld();
mesh.SetVertices(meshWelder.customMesh.vertices);
mesh.SetTriangles(meshWelder.customMesh.triangles, 0);
mesh.SetNormals(meshWelder.customMesh.normals);
mesh.RecalculateBounds();