UV разворачивание при оптимизации времени выполнения

#c# #optimization #unity3d #unityscript #uv-mapping

#c# #оптимизация #unity3d #unityscript #uv-отображение

Вопрос:

Я пытаюсь создать UVs @ runtime, я использую UVs типа BOX (аналогичный BOX UVW в 3ds max) и основываю свои вычисления на ориентации лица.

Я знаю, что это не очень хороший вариант для создания среды выполнения, но у меня нет выбора: (он сохраняется после вычисления, поэтому я сделал это один раз.

НО я беру 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 amp;amp; 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 amp;amp; 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 amp;amp; 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");
}
  

Ответ №1:

Я бы настоятельно рекомендовал кэшировать копию mesh.vertices .

В документации для vertices свойства частично указано:

Возвращает копию позиций вершин или присваивает новый массив позиций вершин.

Обратите внимание, что «возвращает копию» — вы обращаетесь к этому свойству 22 раза внутри вашего цикла, так что это создаст примерно 22n / 3 копии этого массива. Для сетки с 30 000 вершинами это более 200 000 ненужных операций копирования, выполняемых в фоновом режиме.

Если вы создадите временный массив для хранения данных вершин (как вы уже делаете с mesh.uvs ), вы должны увидеть значительное улучшение производительности.

Вы также можете проверить, выполняется ли mesh.triangles операция копирования. Я предполагаю, что это может быть, но в документах не указано.

Ответ №2:

вот мой код, оптимизированный благодаря @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 amp;amp; 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 amp;amp; 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 amp;amp; 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;
}