运行时优化的 UV 展开
UV unwrap on Runtime optimization
我正在尝试在运行时创建 UV,我正在使用 BOX 类型的 UV(类似于 3ds max 中的 BOX UVW)并根据面部方向进行计算。
我知道创建一个运行时不是一个好的选择,但我别无选择:(它是计算后保存的,所以我做了一次。
但是 30000 个顶点我需要 40 秒...太长了
我的代码可以进行任何优化吗?
.
这是我的代码,如果你有 <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");
}
我强烈建议缓存一份 mesh.vertices
。
vertices
属性 的文档部分说明:
Returns a copy of the vertex positions or assigns a new vertex positions array.
注意 "returns a copy" -- 您在循环中访问此 属性 22 次,因此这将创建该数组的大致 22n / 3
个副本。对于具有 30,000 个顶点的网格,后台会进行超过 200,000 次不必要的复制操作。
如果您创建一个临时数组来保存顶点数据(就像您已经在 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;
}
我正在尝试在运行时创建 UV,我正在使用 BOX 类型的 UV(类似于 3ds max 中的 BOX UVW)并根据面部方向进行计算。
我知道创建一个运行时不是一个好的选择,但我别无选择:(它是计算后保存的,所以我做了一次。
但是 30000 个顶点我需要 40 秒...太长了
我的代码可以进行任何优化吗?
.
这是我的代码,如果你有 <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");
}
我强烈建议缓存一份 mesh.vertices
。
vertices
属性 的文档部分说明:
Returns a copy of the vertex positions or assigns a new vertex positions array.
注意 "returns a copy" -- 您在循环中访问此 属性 22 次,因此这将创建该数组的大致 22n / 3
个副本。对于具有 30,000 个顶点的网格,后台会进行超过 200,000 次不必要的复制操作。
如果您创建一个临时数组来保存顶点数据(就像您已经在 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;
}