Numberkruncher I modified your code to use uniform spatial partitioning. Now it should be like 100 times faster on large meshes. Hope this can help someone.
public static void AutoWeld (Mesh mesh, float threshold, float bucketStep) {
Vector3[] oldVertices = mesh.vertices;
Vector3[] newVertices = new Vector3[oldVertices.Length];
int[] old2new = new int[oldVertices.Length];
int newSize = 0;
// Find AABB
Vector3 min = new Vector3 (float.MaxValue, float.MaxValue, float.MaxValue);
Vector3 max = new Vector3 (float.MinValue, float.MinValue, float.MinValue);
for (int i = 0; i < oldVertices.Length; i++) {
if (oldVertices_.x < min.x) min.x = oldVertices*.x;*_
if (oldVertices_.y < min.y) min.y = oldVertices*.y;
if (oldVertices.z < min.z) min.z = oldVertices.z;
if (oldVertices.x > max.x) max.x = oldVertices.x;
if (oldVertices.y > max.y) max.y = oldVertices.y;
if (oldVertices.z > max.z) max.z = oldVertices.z;
}*_
// Make cubic buckets, each with dimensions “bucketStep”
int bucketSizeX = Mathf.FloorToInt ((max.x - min.x) / bucketStep) + 1;
int bucketSizeY = Mathf.FloorToInt ((max.y - min.y) / bucketStep) + 1;
int bucketSizeZ = Mathf.FloorToInt ((max.z - min.z) / bucketStep) + 1;
List[,] buckets = new List[bucketSizeX, bucketSizeY, bucketSizeZ];
// Make new vertices
for (int i = 0; i < oldVertices.Length; i++) {
// Determine which bucket it belongs to
int x = Mathf.FloorToInt ((oldVertices*.x - min.x) / bucketStep);*
int y = Mathf.FloorToInt ((oldVertices*.y - min.y) / bucketStep);*
int z = Mathf.FloorToInt ((oldVertices*.z - min.z) / bucketStep);*
// Check to see if it’s already been added
if (buckets[x, y, z] == null)
buckets[x, y, z] = new List (); // Make buckets lazily
for (int j = 0; j < buckets[x, y, z].Count; j++) {
Vector3 to = newVertices[buckets[x, y, z][j]] - oldVertices*;*
if (Vector3.SqrMagnitude (to) < threshold) {
old2new = buckets[x, y, z][j];
goto skip; // Skip to next old vertex if this one is already there
}
}
// Add new vertex
newVertices[newSize] = oldVertices*;*
buckets[x, y, z].Add (newSize);
old2new = newSize;
newSize++;
skip:;
}
// Make new triangles
int[] oldTris = mesh.triangles;
int[] newTris = new int[oldTris.Length];
for (int i = 0; i < oldTris.Length; i++) {
newTris = old2new[oldTris*];*
}
Vector3[] finalVertices = new Vector3[newSize];
for (int i = 0; i < newSize; i++)
finalVertices = newVertices*;*
mesh.Clear();
mesh.vertices = finalVertices;
mesh.triangles = newTris;
mesh.RecalculateNormals ();
mesh.Optimize ();
}
this is really useful. thanks! i plugged it into my experimental marching cubes engine. any idea how i can stop it removing verts on the edge of chunks?
– magic9cubecome to think of it.. i really need a solution that matches the normals up across the separate meshes where vertices are shared. this will only work across a single mesh i guess.
– magic9cubeboxiness you code works really well. Would be great if you could provide code with possibility to update uv's as well.
– Grimwardwhat should be the values for threshold and bucketstep?
– bhansalideepika@numberkruncher Thanks so much for this! I'm actively trying to use this function but I am not exactly certain how threshold and bucketStep work together. For example, if I've both = .03 I can reduce a 12k vertice mesh to 1.7k vertices. If I change bucketStep to .04, the result is 1.4k vertices. And again if I change bucketStep to .01, the result is 1.7k. So you can see my confusion as changing the value in both directions doesn't seem to make sense. I want to adjust these values to keep more vertices depending on the size of my models. Please respond and advise. Thanks!
– jvhgamer