# How to get the min/max vertex's pos of a mesh in object space?

Hello,

I am trying to get the min/max vertex’s pos of a mesh. The mesh is very big. Therefore, iterating on mesh.vertices is very slow. I also tried to use meshRenderer.bounds. However, it gave me wrong result if the mesh’s pivot is not located in the center of bounds.

Is there any fast way to do this?

Searching for a max x/y/z vertex shouldn’t be too slow, even for fairly large meshes. Can you show your current solution? How long does your current solution take?

What exactly are you referring to by the “mesh’s pivot”?

1 Like

Before any of this I would make sure that this is actually going to be a problem. Use the Unity Profiler, are you creating any unexpected allocations on a per-frame basis? Then instead of making things faster, first I would try to spread the calculation up over multiple frames, simplify the mesh itself, or cache the bounds calculation at the start of the game/loading-event. If this isn’t possible however…

I might try using the C# job system (which produces naturally more optimized code) and then parallelizing the algorithm. You could find the min/max of a small segment of the vertices for each job, then compare them all up at the end (divide and conquer).

If that doesn’t speed things up enough then you might want to keep separate data structures just storing vertices that you can manage yourself and do clever things. If your mesh doesn’t rotate much frame-frame, you could store 3 versions of the vertices, each list would be sorted by a different axis (x,y,z) which could really speed things up. You could generate a convex hull from your mesh and only ever test those points for the bounds operations. If you’re not rotating the mesh, but moving individual verts, you could recalculate using only those changed values.

It’s hard to go into more detail without more context.

1 Like

can you show how you iterate them?

check that you are not doing this:

1 Like

This sounds like a contradiction in itself. Why should the mesh pivot / origin be in the center of the bounds? If it were the mesh needs to be perfectly symetrical around the pivot. Any mesh that isn’t won’t have the bounds center and the pivot aligned. You specifically said the min / max vertex, not some arbitrary AABB centered around the pivot. What if the pivot is for example at the bottom of the mesh? If the bounds are centered on the pivot it means it has to be twice as large as it needs to be. So it does not represent the min / max of your vertices.

Also note you should not use Renderer.bounds as it gives you the AABB of your object in worldspace. Use Mesh.bounds. It gives you the AABB of the mesh in local space. Though keep in mind that Unity calculates the AABB for your mesh only for imported meshes. If you create you mesh manually / procedural at runtime, you have to set the mesh bounds yourself. Either by calculating the min / max vertex positions manually and assign the bounds to mesh.bounds, or just by calling Mesh.RecalculateBounds.

Though as I said, the pivot of the mesh is kinda irrelevant for the AABB of the object. It can even lie outside the bounds all together, depending on how the mesh was created.

``````    public static float GetMeshRenderBounds(Mesh mesh)
{
float bounds = float.MinValue;
int count = mesh.vertexCount;
List<Vector3> vertices = new List<Vector3>();
mesh.GetVertices(vertices);
for (int i = 0; i < vertices.Count; i++)
{
EditorUtility.DisplayProgressBar("Get detail renderbounds", "Get detail renderBounds for " + mesh.name, i/(float)(count));
Vector3 pos = vertices[i];
bounds = Mathf.Max(bounds, pos.x, pos.y, pos.z, -pos.x, -pos.y, -pos.z);
}
EditorUtility.ClearProgressBar();
return bounds;
}
``````

This is my implementation. It is pretty simple. It will cost nearly 10+ sec for a mesh with 64000 vertices.

I see. Thank you very much.

Actually, I am trying to get the min/max vertex object space pos in a scene by my editor tool. Due to static batch, the run time min/max will be different from min/max in editor. Therefore, I group my renderers by materials and use bounds.encapsulate(all renderer.bounds of one type of material) , and use bounds.extent to estimate the min/max vertex pos. I don’t know how Unity generate pivot of the combined mesh after static batch.

In most of cases, the estimate is good enough. But there are some corner cases make things wrong.

i’d test:

• cache vertices.count
• don’t display progress bar inside the loop (or at least not every step)
• replace Mathf.Max with your own code

versus

``````        float bounds = float.MinValue;
...
for (int i = 0; i < vertices.Count; i++)
{
bounds = Mathf.Max(bounds, pos.x, pos.y, pos.z, -pos.x, -pos.y, -pos.z);
}
``````

If you aim for positions you need to store the positions. You only store the maximum value encountered no matter what axis. So you probably need 6 different vectors to store the minimum and maximum in each of the 3 axis. What you do here does not make much sense.

I would also suspect the progress bar to take too long. Editor is not really suited for “real time” use. Debug.Log in a loop can also kill your performance. Just comment out EditorUtility.DisplayProgressBar and see how long it takes. 65k vertices should be no issue. You can stop the time with Systems.Diagnostics.Stopwatch and display how long it has taken afterwards.

Well the thing that’s probably 99% of your performance here is your “DisplayProgressBar” call. For every vertex you create two new strings in this part:

"Get detail renderBounds for " + mesh.name

First of all reading the name of an Mesh object reads that name from native code. That means the name has to be copied into a managed string everytime you read that property. Next you concat those two strings which will create a new string. So you allocate probably several megabytes of garbage just for those strings. Updating the progressbar that often is also a complete waste of time. So do it only every now and then. I would recommend something like

So when we want about 100 updates, we simply do this before the loop.

``````int mod = vertices.Count / 100;
string message = "Get detail renderBounds for " + mesh.name;
``````

“mod” is the number of vertices we want to process before we update our progress bar. That means inside the for loop we just do

``````if (i % mod == 0)
{
EditorUtility.DisplayProgressBar("Get detail renderbounds", message, i/(float)(count));
}
``````

Though as exiguous saidm your for loop doesn’t really make much sense. If you want to find the min / max values in each axis you have to do something like that:

``````Vector3 min = Vector3.one * float.PositiveInfinity;
Vector3 max = Vector3.one * float.NegativeInfinity;
for(int i = 0; i < vertices.Count; i++)
{
var v = vertices[i];
if (v.x < min.x) min.x = v.x;
if (v.y < min.y) min.y = v.y;
if (v.z < min.z) min.z = v.z;
if (v.x > max.x) max.x = v.x;
if (v.y > max.y) max.y = v.y;
if (v.z > max.z) max.z = v.z;
}
``````

Note that iterating through 64k vertices is lightning fast and certainly does not take 10 seconds. You more likely can do that over a thousand times per frame.

You really need to profile your code to be sure what’s making it slow, but like people have said before, doing any EditorUtility immediate mode stuff is probably taking 99% of the time.

I would avoid if-statements in favour of Mathf.max or Mathf.min in a tight loop.
Yeah 64k verts shouldn’t be a problem for any modern cpu.
If you really want to optimize though I would separate the 3 axis’ into three Unity JOBS, you can even sort the vertices each frame by axis and do lightening fast bounds calculation that way.

The Mathf.Max implementation looks like this:

``````return a > b ? a : b;
``````

Which as far as I know would compile into the same thing that Bunny83’s if statements would.

Jobs are a good suggestion if you really need to process massive numbers of vertices as fast as possible. It should be trivial (textbook-example levels of trivial) to jobify.