Skip to content

Instantly share code, notes, and snippets.

@yoeven
Last active January 30, 2018 15:47
Show Gist options
  • Save yoeven/224a7757480f7b7d7e09fe4c30184362 to your computer and use it in GitHub Desktop.
Save yoeven/224a7757480f7b7d7e09fe4c30184362 to your computer and use it in GitHub Desktop.
A function to remove vertices that share the same position which is calculated by the distance between the two vertices and then compared to a threshold. Code is based of this thread: https://answers.unity.com/questions/228841/dynamically-combine-verticies-that-share-the-same.html
/*
* The following code is based of this thread: https://answers.unity.com/questions/228841/dynamically-combine-verticies-that-share-the-same.html
*
* This function gets rid of shared vertices that fall within the same threshold distance.
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class AutoWeld {
public static void AutoWeldMesh(this 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[i].x < min.x) min.x = oldVertices[i].x;
if (oldVertices[i].y < min.y) min.y = oldVertices[i].y;
if (oldVertices[i].z < min.z) min.z = oldVertices[i].z;
if (oldVertices[i].x > max.x) max.x = oldVertices[i].x;
if (oldVertices[i].y > max.y) max.y = oldVertices[i].y;
if (oldVertices[i].z > max.z) max.z = oldVertices[i].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<int>[,,] buckets = new List<int>[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[i].x - min.x) / bucketStep);
int y = Mathf.FloorToInt((oldVertices[i].y - min.y) / bucketStep);
int z = Mathf.FloorToInt((oldVertices[i].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<int>(); // Make buckets lazily
for (int j = 0; j < buckets[x, y, z].Count; j++)
{
Vector3 to = newVertices[buckets[x, y, z][j]] - oldVertices[i];
if (Vector3.SqrMagnitude(to) < threshold)
{
old2new[i] = buckets[x, y, z][j];
goto skip; // Skip to next old vertex if this one is already there
}
}
// Add new vertex
newVertices[newSize] = oldVertices[i];
buckets[x, y, z].Add(newSize);
old2new[i] = 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[i] = old2new[oldTris[i]];
}
Vector3[] finalVertices = new Vector3[newSize];
for (int i = 0; i < newSize; i++)
finalVertices[i] = newVertices[i];
mesh.Clear();
mesh.vertices = finalVertices;
mesh.triangles = newTris;
mesh.RecalculateNormals();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment