My raycast spits out a position way off from what it's supposed to be. I'm trying to place objects procedurally on a procedural mesh. I've been scratching my head at this for a while. Please help. Sorry for the long script.
The start of the code is just some declares and stuff. GenObjects is run once in FixedUpdate after Start has finished. I'm using a 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;
}
}
Fixed! My mistake was really stupid. I wasn't assigning the welded mesh, leaving a filthy mesh with lots of empty verts floating about. The raycast was hitting them.
The fixed lines for anyone who cares:
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();