Question by
GameDeveloperAf · May 10, 2021 at 09:34 PM ·
verticesnormalsmeshfilterduplicateuvs
How to weld mesh vertices in the runtime
I took a look at this post https://answers.unity.com/questions/1382854/welding-vertices-at-runtime.html to weld vertices.
Answer of user @imaxus is right but there is a problem with lights and normals. Answer of @Bunny83 does not work. Why? Can someone explain why?
I used the user imaxus's code. But there is a issue with lighting and normals. How to fix?
public static Mesh WeldVertices(Mesh aMesh, float aMaxDelta = 0.01f) {
var verts = aMesh.vertices;
var normals = aMesh.normals;
var uvs = aMesh.uv;
Dictionary<Vector3, int> duplicateHashTable = new Dictionary<Vector3, int>();
List<int> newVerts = new List<int>();
int[] map = new int[verts.Length];
//create mapping and find duplicates, dictionaries are like hashtables, mean fast
for (int i = 0; i < verts.Length; i++) {
if (!duplicateHashTable.ContainsKey(verts[i])) {
duplicateHashTable.Add(verts[i], newVerts.Count);
map[i] = newVerts.Count;
newVerts.Add(i);
}
else {
map[i] = duplicateHashTable[verts[i]];
}
}
// create new vertices
var verts2 = new Vector3[newVerts.Count];
var normals2 = new Vector3[newVerts.Count];
var uvs2 = new Vector2[newVerts.Count];
for (int i = 0; i < newVerts.Count; i++) {
int a = newVerts[i];
verts2[i] = verts[a];
normals2[i] = normals[a];
uvs2[i] = uvs[a];
}
// map the triangle to the new vertices
var tris = aMesh.triangles;
for (int i = 0; i < tris.Length; i++) {
tris[i] = map[tris[i]];
}
aMesh.triangles = tris;
aMesh.vertices = verts2;
aMesh.normals = normals2;
aMesh.uv = uvs2;
aMesh.RecalculateBounds();
aMesh.RecalculateNormals();
return aMesh;
}
Then I took a look at Bunny83's code, but it did not work nd even it did not give and error. How to fix this? HELP PLEASE
public static void WeldVertices(Mesh aMesh, float aMaxDelta = 0.001f)
{
var verts = aMesh.vertices;
var normals = aMesh.normals;
var uvs = aMesh.uv;
List<int> newVerts = new List<int>();
int[] map = new int[verts.Length];
// create mapping and filter duplicates.
for(int i = 0; i < verts.Length; i++)
{
var p = verts[i];
var n = normals[i];
var uv = uvs[i];
bool duplicate = false;
for(int i2 = 0; i2 < newVerts.Count; i2++)
{
int a = newVerts[i2];
if (
(verts[a] - p).sqrMagnitude <= aMaxDelta && // compare position
Vector3.Angle(normals[a], n) <= aMaxDelta && // compare normal
(uvs[a] - uv).sqrMagnitude <= aMaxDelta // compare first uv coordinate
)
{
map[i] = i2;
duplicate = true;
break;
}
}
if (!duplicate)
{
map[i] = newVerts.Count;
newVerts.Add(i);
}
}
// create new vertices
var verts2 = new Vector3[newVerts.Count];
var normals2 = new Vector3[newVerts.Count];
var uvs2 = new Vector2[newVerts.Count];
for(int i = 0; i < newVerts.Count; i++)
{
int a = newVerts[i];
verts2[i] = verts[a];
normals2[i] = normals[a];
uvs2[i] = uvs[a];
}
// map the triangle to the new vertices
var tris = aMesh.triangles;
for(int i = 0; i < tris.Length; i++)
{
tris[i] = map[tris[i]];
}
aMesh.vertices = verts2;
aMesh.normals = normals2;
aMesh.uv = uvs2;
aMesh.triangles = tris;
}
@Bunny83 can you help me why with your code does not work?
Comment