UV展开运行时优化

本文关键字:优化 运行时 UV | 更新日期: 2023-09-27 18:12:27

我试图在运行时创建uv,我使用BOX类型的uv(类似于3ds max中的BOX UVW),并基于我对面部方向的计算。

我知道创建一个运行时不是一个好的选择,但我别无选择:(它是在计算后保存的,所以我做了一次。

但是我花了40秒来处理30000个顶点…太长了

是否有任何优化在我的代码,可以作出?

.

这是我的代码,如果你有<5000个顶点,可以随意使用:

public static void CreateUV(ref Mesh mesh)
{
    int i = 0;
    Vector3 p = Vector3.up;
    Vector3 u = Vector3.Cross(p, Vector3.forward);
    if (Vector3.Dot(u, u) < 0.001f)
    {
        u = Vector3.right;
    }
    else
    {
        u = Vector3.Normalize(u);
    }
    Vector3 v = Vector3.Normalize(Vector3.Cross(p, u));
    Vector2[] uvs = new Vector2[mesh.vertices.Length];
    for (i = 0; i < mesh.triangles.Length; i += 3)
    {
        Vector3 a = mesh.vertices[mesh.triangles[i]];
        Vector3 b = mesh.vertices[mesh.triangles[i + 1]];
        Vector3 c = mesh.vertices[mesh.triangles[i + 2]];
        Vector3 side1 = b - a;
        Vector3 side2 = c - a;
        Vector3 N = Vector3.Cross(side1, side2);
        N = new Vector3(Mathf.Abs(N.normalized.x), Mathf.Abs(N.normalized.y), Mathf.Abs(N.normalized.z));

        if (N.x > N.y && N.x > N.z)
        {
            uvs[mesh.triangles[i]] = new Vector2(mesh.vertices[mesh.triangles[i]].z, mesh.vertices[mesh.triangles[i]].y);
            uvs[mesh.triangles[i + 1]] = new Vector2(mesh.vertices[mesh.triangles[i + 1]].z, mesh.vertices[mesh.triangles[i + 1]].y);
            uvs[mesh.triangles[i + 2]] = new Vector2(mesh.vertices[mesh.triangles[i + 2]].z, mesh.vertices[mesh.triangles[i + 2]].y);
        }
        else if (N.y > N.x && N.y > N.z)
        {
            uvs[mesh.triangles[i]] = new Vector2(mesh.vertices[mesh.triangles[i]].x, mesh.vertices[mesh.triangles[i]].z);
            uvs[mesh.triangles[i + 1]] = new Vector2(mesh.vertices[mesh.triangles[i + 1]].x, mesh.vertices[mesh.triangles[i + 1]].z);
            uvs[mesh.triangles[i + 2]] = new Vector2(mesh.vertices[mesh.triangles[i + 2]].x, mesh.vertices[mesh.triangles[i + 2]].z);
        }
        else if (N.z > N.x && N.z > N.y)
        {
            uvs[mesh.triangles[i]] = new Vector2(mesh.vertices[mesh.triangles[i]].x, mesh.vertices[mesh.triangles[i]].y);
            uvs[mesh.triangles[i + 1]] = new Vector2(mesh.vertices[mesh.triangles[i + 1]].x, mesh.vertices[mesh.triangles[i + 1]].y);
            uvs[mesh.triangles[i + 2]] = new Vector2(mesh.vertices[mesh.triangles[i + 2]].x, mesh.vertices[mesh.triangles[i + 2]].y);
        }
    }
    mesh.uv = uvs;
    Debug.Log("Finish");
}

UV展开运行时优化

我强烈建议缓存mesh.vertices的副本。

vertices属性的文档部分声明:

返回顶点位置的副本或赋值一个新的顶点位置数组。

注意"返回一个副本"——你在循环中访问这个属性22次,所以这将创建大约22n / 3个数组副本。对于一个有3万个顶点的网格,这意味着在后台会进行超过20万次不必要的复制操作。

如果您创建一个临时数组来保存顶点数据(就像您已经在mesh.uvs中所做的那样),您应该会看到显著的性能改进。

您还可以检查mesh.triangles是否为复制操作。我预计它可能是,但文档没有指定。

这是我的代码优化感谢@rutter

public static Vector2[] CreateUV(ref Mesh mesh)
{
    int i = 0;
    Vector3 p = Vector3.up;
    Vector3 u = Vector3.Cross(p, Vector3.forward);
    if (Vector3.Dot(u, u) < 0.001f)
    {
        u = Vector3.right;
    }
    else
    {
        u = Vector3.Normalize(u);
    }
    Vector3 v = Vector3.Normalize(Vector3.Cross(p, u));
    Vector3[] vertexs = mesh.vertices;
    int[] tris = mesh.triangles;
    Vector2[] uvs = new Vector2[vertexs.Length];
    for (i = 0; i < tris.Length; i += 3)
    {
        Vector3 a = vertexs[tris[i]];
        Vector3 b = vertexs[tris[i + 1]];
        Vector3 c = vertexs[tris[i + 2]];
        Vector3 side1 = b - a;
        Vector3 side2 = c - a;
        Vector3 N = Vector3.Cross(side1, side2);
        N = new Vector3(Mathf.Abs(N.normalized.x), Mathf.Abs(N.normalized.y), Mathf.Abs(N.normalized.z));

        if (N.x > N.y && N.x > N.z)
        {
            uvs[tris[i]] = new Vector2(vertexs[tris[i]].z, vertexs[tris[i]].y);
            uvs[tris[i + 1]] = new Vector2(vertexs[tris[i + 1]].z, vertexs[tris[i + 1]].y);
            uvs[tris[i + 2]] = new Vector2(vertexs[tris[i + 2]].z, vertexs[tris[i + 2]].y);
        }
        else if (N.y > N.x && N.y > N.z)
        {
            uvs[tris[i]] = new Vector2(vertexs[tris[i]].x, vertexs[tris[i]].z);
            uvs[tris[i + 1]] = new Vector2(vertexs[tris[i + 1]].x, vertexs[tris[i + 1]].z);
            uvs[tris[i + 2]] = new Vector2(vertexs[tris[i + 2]].x, vertexs[tris[i + 2]].z);
        }
        else if (N.z > N.x && N.z > N.y)
        {
            uvs[tris[i]] = new Vector2(vertexs[tris[i]].x, vertexs[tris[i]].y);
            uvs[tris[i + 1]] = new Vector2(vertexs[tris[i + 1]].x, vertexs[tris[i + 1]].y);
            uvs[tris[i + 2]] = new Vector2(vertexs[tris[i + 2]].x, vertexs[tris[i + 2]].y);
        }
    }
    mesh.uv = uvs;
    return uvs;
}