3
\$\begingroup\$

So i have some procedurally generated mesh data and i want to reduce it down to its minimum number of verts. In case it matters this is a unity project.

Working on the basis of a simple example, lets assume a typical flat surface of points 2 by 3.

The point / vertex at [1,1] is used in many triangles.

I've generated mesh for a voxel type engine that adds verts to a list based on face visiblility and now I want to remove all the duplicates.

Can anyone come up with an efficient way of doing this because what i have is sooo bad its not even funny (and i don't even think it's logically correct) ...

private void Optimize()
{
    Vector3 v;
    Vector3 v2;
    for (int i = 0; i < Vertices.Count; i++)
    {
        v = Vertices[i];
        for (int j = i+1; j < Vertices.Count; j++)
        {
            v2 = Vertices[j];
            if (v.x == v2.x && v.y == v2.y && v.z == v2.z)
            {
                for (int ind = 0; ind < Indices.Count; ind++)
                {
                    if (Indices[ind] == j)
                    {
                        Indices[ind] = i;
                    }
                    else if (Indices[ind] > j && Indices[ind] > 0)
                        Indices[ind]--;
                }

                Vertices.RemoveAt(j);
                Uvs.RemoveAt(j);
                Normals.RemoveAt(j);
            }
        }
    }
}

EDIT: Ok i managed to get this (code sample above updated) to render an "optimised" set of verts but the UV data is all wrong now, which would make sense because i'm basically just removing any UV Vector that represents a UV coord for a removed vert and not actually considering what I need to do to "fix the tri" so to speak.

The code now seemingly does work but its quite time consuming, still looking to further optimise.

\$\endgroup\$
5
  • \$\begingroup\$ Since it's C# could you use a Dictionary's dislike of duplicates to remove duplicate vertices? \$\endgroup\$
    – Dialock
    Commented Apr 3, 2013 at 16:13
  • \$\begingroup\$ i hadn't considered that ... mainly because at the moment im simply "removing from the target data" and using a dictionary like this would basically involve me allocating another chunk of ram. My logic was something like "for each vert, grab each vert after it and if its a dupe (by location), remove the dupe, remove any other data that points to the dupe (except indices), re-point those to the original". But for some reason this isn't working quite right. \$\endgroup\$
    – War
    Commented Apr 3, 2013 at 17:35
  • \$\begingroup\$ when i say "isn't working quite right" i mean "results in 0 verts actually being rendered for some reason" \$\endgroup\$
    – War
    Commented Apr 3, 2013 at 17:38
  • \$\begingroup\$ Maybe create a vertex object that contains a position, normal, and texture coordinate. Then remove duplicates of those. \$\endgroup\$
    – Dialock
    Commented Apr 3, 2013 at 18:41
  • \$\begingroup\$ having thought about it ... you might be on to something there ... I was thinking about raw vertex info in terms of points but a vertex is more than just a point ... that may mean that my mesh is about as optimized as i can get it as the uv coordinates for each point will be different for each adjoined tri. \$\endgroup\$
    – War
    Commented Apr 3, 2013 at 22:17

2 Answers 2

3
\$\begingroup\$

Unity's Mesh class has an Optimize method which should give you what you want.

From the wiki page:

You should use it if you generate a mesh from scratch procedurally and you want to trade better runtime performance against higher load time.

\$\endgroup\$
4
  • \$\begingroup\$ I just tried that out and dumping out the raw figures, it seems to make no difference to the vertex count ... what does it actually do? since the document just says "makes it faster" basically. My idea was to reduce duplication (not have the same vert twice in the mesh) but that creates uv hell apparently \$\endgroup\$
    – War
    Commented Apr 3, 2013 at 22:14
  • 1
    \$\begingroup\$ If you don't understand how UVs, verts and faces interact you're going to have a bad time =) \$\endgroup\$ Commented Apr 4, 2013 at 6:25
  • \$\begingroup\$ well i had it all working, i started with voxels because that's about as simple as life gets in game programming, but i'm now trying to extend that a little bit to optimise what I produced. My problem is that I hadn't fully appreciated the fact that a Vert is a shared point and UV coords mean different things to different tri's attached to that point. \$\endgroup\$
    – War
    Commented Apr 4, 2013 at 15:53
  • \$\begingroup\$ I've slightly tweaked this code but taking the UV problem to 1 side this is producing the exact result i'm after. I now need to figure out how to texture my new optimised mesh and taking the UV approach i took when it was a voxel mesh likely won't work, i have something that effectively in terms of shape is not to different to an asteroid in a space game and I need to apply grass to the top and rock to the bottom. Any ideas? \$\endgroup\$
    – War
    Commented Apr 4, 2013 at 15:57
0
\$\begingroup\$

I think you will have to spend time running the optimization and there isn't much way around that. Maybe the implementation itself could be faster but still.

Try loading chunks of mesh at a time, its a common solution, or decreasing the number of optimizations that have to be done.

Another solution could be optimizing the mesh itself (the assets) rather than doing it at runtime

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .