Comments and answers for "Dynamically combine verticies that share the same space"
http://answers.unity.com/questions/228841/dynamically-combine-verticies-that-share-the-same.html
The latest comments and answers for the question "Dynamically combine verticies that share the same space"Comment by Hazkin on Hazkin's answer
http://answers.unity.com/comments/1474101/view.html
Thanks a lot! Really useful!Tue, 27 Feb 2018 10:50:28 GMTHazkinComment by rageingnonsense on rageingnonsense's answer
http://answers.unity.com/comments/1398879/view.html
I think there may be a flaw with this where a vertex that lays on the boundary of a bucket may not have its duplicate found if the duplicate is within threshold, but in an adjacent bucket.Fri, 25 Aug 2017 19:38:35 GMTrageingnonsenseComment by rageingnonsense on rageingnonsense's comment
http://answers.unity.com/comments/1398868/view.html
Ok, so imagine you have a model of a skyscraper, with 1000 vertices. In order to find the duplicates, you have to test each vertex against each other vertex. In a worst case scenario, you will have to do a distance check 1000x1000, which is 1000000 times!
Now what this code does (pretty sure) is that it takes your skyscraper model, and divides it into smaller, more manageable chunks. "bucketStep" (which is an awful name for the parameter) loosely translates how many subdivisions it will make for searching. This makes it faster because most vertices will not be anywhere near the one you are testing, so it reduced the number of vertices you need to search to ones that are closer.
So let's say you use bucketStep 1. It will divide your vertices, based on their position, into 6 "buckets", or groups (because it add 1 to whatever number you pass for bucket). If your model was centered on Vector3.zero, then you could think of these buckets as being +x, -x, +y, -y, +z, -z. So, you have a vertex in your mesh that is (1, 10, -20), it will be added to the (+x, +y, -z) bucket. then, when it searches to see if there are any vertices that are duplicates, it will only search this bucket, which happens to have 1/6th the number of vertices (it really depends on the model actually, but I am simplifying here).
The higher you set bucketStep, the faster, theoretically, it should work.Fri, 25 Aug 2017 19:00:28 GMTrageingnonsenseComment by jvhgamer on jvhgamer's comment
http://answers.unity.com/comments/1374875/view.html
@numberkruncher @boxiness What does threshold do in your version? Boxiness what does bucketStep do in your version? I really want to understand these functions but I'm not sure if these cubic buckets have any effect on the quality of the mesh, or if it is just the threshold. I've been experimenting with the values back and forth to find a repeatable pattern. I've had success but no luck in fully understanding what is going on. I'm still lost.Thu, 06 Jul 2017 14:05:28 GMTjvhgamerComment by numberkruncher on numberkruncher's comment
http://answers.unity.com/comments/1374461/view.html
@jvhgamer no idea since I didn't write that version of the answer ;)Wed, 05 Jul 2017 18:32:06 GMTnumberkruncherComment by jvhgamer on jvhgamer's answer
http://answers.unity.com/comments/1374460/view.html
@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!Wed, 05 Jul 2017 17:54:39 GMTjvhgamerComment by jvhgamer on jvhgamer's answer
http://answers.unity.com/comments/1371775/view.html
@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!Thu, 29 Jun 2017 17:32:25 GMTjvhgamerComment by bhansalideepika on bhansalideepika's answer
http://answers.unity.com/comments/845067/view.html
what should be the values for threshold and bucketstep?Tue, 02 Dec 2014 06:52:16 GMTbhansalideepikaComment by Grimward on Grimward's answer
http://answers.unity.com/comments/833258/view.html
boxiness you code works really well. Would be great if you could provide code with possibility to update uv's as well.Sun, 16 Nov 2014 21:42:40 GMTGrimwardComment by magic9cube on magic9cube's answer
http://answers.unity.com/comments/740896/view.html
come 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.Fri, 04 Jul 2014 14:28:20 GMTmagic9cubeComment by magic9cube on magic9cube's answer
http://answers.unity.com/comments/740888/view.html
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?
[1]: /storage/temp/28677-tear.jpgFri, 04 Jul 2014 14:12:54 GMTmagic9cubeAnswer by kilik128
http://answers.unity.com/answers/667535/view.html
is Uv destroy for my try
but vertex workingWed, 19 Mar 2014 01:39:45 GMTkilik128Answer by boxiness
http://answers.unity.com/answers/666626/view.html
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[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 ();
mesh.Optimize ();
}Tue, 18 Mar 2014 02:25:52 GMTboxinessComment by Orion on Orion's answer
http://answers.unity.com/comments/663172/view.html
I have tried implementing this, but it turned out as unacceptably slow. In the end I used a kd-tree to store and search the vertices, which, in my case, was 50x faster (that's not an exaggeration).Thu, 13 Mar 2014 17:56:31 GMTOrionComment by frogsbo on frogsbo's answer
http://answers.unity.com/comments/657540/view.html
Thank you, I am vaguely familiar with all this because I write procedural mash, I have found that using procedural volumetric texture shaders is a very nice workaround because it looks very original, and rewriting UVs is difficult, I wrote a box projection script, but it struggles with shared vertices, so much work!
Here is a JavaScript version without UVs
function AutoWeld( mesh:Mesh, threshold:float) {
var verts : Vector3[]= mesh.vertices;
var tris:int[] = mesh.triangles;
// Build new vertex buffer and remove "duplicate" verticies
// that are within the given threshold.
var newVerts : List.<Vector3> = new List.<Vector3>();
var newUVs : List.<Vector2> = new List.<Vector2>();
for (var i=0;i<verts.Length;i++) {
for (var j=0;j<verts.Length;j++) {
if (verts[i] == verts[j] && i != j ){
newVerts.Add(verts[i]);
}
}
}
// Rebuild triangles using new verticies
Debug.Log("Is mouse_position null? " + (newVerts.Count ));
for ( i=0;i<tris.Length;i++) {
for ( j=0;j<newVerts.Count;j++) {
if (newVerts[j] == verts[ tris[i] ]) {
tris[i] = j;
break;
}
}
}
//print ("tis different" + newVerts.Count + "--" + tris.Length);
// Update mesh!
//mesh.Clear();
mesh.vertices =newVerts.ToArray();
mesh.triangles = tris;
// mesh.uv = newUVs.ToArray();
mesh.RecalculateNormals();
}
@script RequireComponent (MeshFilter);Fri, 07 Mar 2014 03:39:51 GMTfrogsboComment by numberkruncher on numberkruncher's answer
http://answers.unity.com/comments/486779/view.html
You may just need to clear the mesh, I have updated my answer accordingly :)Thu, 04 Jul 2013 16:50:00 GMTnumberkruncherComment by numberkruncher on numberkruncher's answer
http://answers.unity.com/comments/486776/view.html
I am not sure why this was not working for you, but according to the Unity documentation the order in my answer is still correct: http://docs.unity3d.com/Documentation/ScriptReference/Mesh.htmlThu, 04 Jul 2013 16:47:49 GMTnumberkruncherComment by Lexoka on Lexoka's answer
http://answers.unity.com/comments/486753/view.html
That was useful to me, thanks (I don't need the UV coordinates anyway).
However, mesh.vertices = newVerts.ToArray(); generates an error because Unity apparently checks the number of vertices in mesh.vertices against the number of vertices referenced in mesh.triangles.
I suspect this check was not performed in previous versions of Unity, which is why the script used to work, but doesn't anymore.
Anyway, the fix was simple, you just have to do mesh.triangles = tris; before mesh.vertices = newVerts.ToArray(); instead of after.Thu, 04 Jul 2013 16:05:30 GMTLexokaComment by aldonaletto on aldonaletto's answer
http://answers.unity.com/comments/401281/view.html
You could simply set vertices within some limit to the same value, like this:
for (int i = 0; i < vertices.Length; i++){
Vector3 curVert = vertices[i]; // get vertex [i]
// compare it to the next vertices:
for (int j = i+1; j < vertices.Length; j++){
// if any one inside limit distance...
if (Vector3.Distance(curVert, vertices[j]) < 0.0001f){
vertices[j] = curVert; // make it equal to vertex [i]
}
}
}
This approach would simply eliminate possible precision errors, without modifying the vertices count. Maybe the same should be applied to the UV pairs, since UV seams are very visible.Mon, 18 Feb 2013 03:20:42 GMTaldonalettoComment by numberkruncher on numberkruncher's answer
http://answers.unity.com/comments/400949/view.html
Thank you for clarifying that for me. My intention was not to reduce the number of vertices for improved performance, but rather to remove certain visual artefacts that occur on some joins. In Blender the process of welding solves the problem. My scene is procedurally generated at design time.Sun, 17 Feb 2013 17:10:25 GMTnumberkruncherAnswer by aldonaletto
http://answers.unity.com/answers/230762/view.html
You must not share equal vertices when their uv or normals are different, what usually happens at the edges of different faces, or to "close" a curved surface. Consider the Unity cube: it has 24 vertices (4 per face) instead of just 8, because the normals (and uv, I guess) are different at the edges.<br>
In order to do a safer vertex reduction, you should also compare uv and normals of equal vertices. To further complicate matters, there may exist other less popular properties associated to each vertex, like uv2, tangents and colors, which should be compared too for a 100% safe vertex reduction (take a look at the [Mesh doc][1] for a complete list).<br>
NOTE: I would also replace the first *foreach* by a regular *for (int k=0;...;...)* - I have not found any .NET doc ensuring that the *foreach* sequence also starts at 0.
[1]: http://unity3d.com/support/documentation/ScriptReference/Mesh.htmlFri, 23 Mar 2012 00:37:35 GMTaldonalettoAnswer by numberkruncher
http://answers.unity.com/answers/230713/view.html
I think the answer is that this is not feasible. I have worked out how to write this logic and have points 1/3/4 working great. Here is the code that I wrote for step 2.
Whilst this does in fact weld the verticies together, it screws up the UV coordinates because it seems that there can only be one UV coordinate pair for each vertex. This has had the effect of (properly mapped->mirrored->stretched->mirrored->properly mapped->...)
If anybody knows how to solve this problem then that would be fantastic. Still, here is the welding code that I wrote should it be of any use to anybody:
private void AutoWeld(Mesh mesh, float threshold) {
Vector3[] verts = mesh.vertices;
// Build new vertex buffer and remove "duplicate" verticies
// that are within the given threshold.
List<Vector3> newVerts = new List<Vector3>();
List<Vector2> newUVs = new List<Vector2>();
int k = 0;
foreach (Vector3 vert in verts) {
// Has vertex already been added to newVerts list?
foreach (Vector3 newVert in newVerts)
if (Vector3.Distance(newVert, vert) <= threshold)
goto skipToNext;
// Accept new vertex!
newVerts.Add(vert);
newUVs.Add(mesh.uv[k]);
skipToNext:;
++k;
}
// Rebuild triangles using new verticies
int[] tris = mesh.triangles;
for (int i = 0; i < tris.Length; ++i) {
// Find new vertex point from buffer
for (int j = 0; j < newVerts.Count; ++j) {
if (Vector3.Distance(newVerts[j], verts[ tris[i] ]) <= threshold) {
tris[i] = j;
break;
}
}
}
// Update mesh!
mesh.Clear();
mesh.vertices = newVerts.ToArray();
mesh.triangles = tris;
mesh.uv = newUVs.ToArray();
mesh.RecalculateBounds();
}Thu, 22 Mar 2012 21:44:51 GMTnumberkruncher