Unity Mesh Mesh给球贴图
Posted 御雪妃舞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Mesh Mesh给球贴图相关的知识,希望对你有一定的参考价值。
之前在
Unity Mesh(三) Mesh画球
中已经说明了如何画球,现在我们在这个球的基础上贴图。
这里我们有个极坐标和直角坐标的转换,具体我也不是很明白,反正就是拿来用吧,据某位大神讲解,极坐标(球坐标)由球半径,水平角和垂直角决定,我们完全可以理解为三维坐标转换成uv坐标的方程,也就是三维坐标映射到uv坐标上,f(u,v)=[x,y,z]这样的一个映射关系,映射关系取决于函数具体怎么定义的或者这个球是怎么画的,不同的模型有不同的方法,典型的克莱因瓶一个uv完整的模型,它有自己的函数。
好了,楼主还是参考的Jasper Flick的方法,这个大神一直很崇拜。
f(u,v)=[x,y,z]
u=asin(y) / π + ½.
v=atan2(x, z) / -2π
unity自带的球贴图会在两个极点出现扭曲Twisting的现象:
包括我们之前建立的球也没有考虑到这一个点,原因是计算极点的坐标时,极点只有一个坐标,但是极点每个四分之一圆实际上是我们极点四个三角形公用了一个uv坐标,这样就会造成扭曲现象,解决方法是我们把极点的点拆分成四个相同的点,一个面一个。
这样的话,我们之前画球的点稍稍有改动,上下两个极点分别加三个点。
这样这个问题就解决了!
下面我们直接上图:
这个最后的完整代码如下:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class DrawOctahedronSphere : MonoBehaviour
public Material mat;
public int subdivisions;
public int radius;
private static Vector3[] directions =
Vector3.left,
Vector3.back,
Vector3.right,
Vector3.forward
;
void Start()
DrawSphere(subdivisions, radius);
public void DrawSphere(int subdivisions = 0, float radius = 1)
if (subdivisions > 4)
subdivisions = 4;
gameObject.GetComponent<MeshRenderer>().material = mat;
Mesh mesh = GetComponent<MeshFilter>().mesh;
mesh.Clear();
int resolution = 1 << subdivisions;
Vector3[] vertices = new Vector3[(resolution + 1) * (resolution + 1) * 4 - 3 * (resolution * 2 - 1)];
int[] triangles = new int[(1 << (subdivisions * 2 + 3)) * 3];
CreateOctahedron(vertices, triangles, resolution);
if (radius != 1f)
for (int i = 0; i < vertices.Length; i++)
vertices[i] *= radius;
Vector3[] normals = new Vector3[vertices.Length];
Normalize(vertices, normals);
Vector2[] uv = new Vector2[vertices.Length];
CreateUV(vertices, uv);
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
private static void CreateOctahedron(Vector3[] vertices, int[] triangles, int resolution)
int v = 0, vBottom = 0, t = 0;
for (int i = 0; i < 4; i++)
vertices[v++] = Vector3.down;
for (int i = 1; i <= resolution; i++)
float progress = (float)i / resolution;
Vector3 from, to;
vertices[v++] = to = Vector3.Lerp(Vector3.down, Vector3.forward, progress);
for (int d = 0; d < 4; d++)
from = to;
to = Vector3.Lerp(Vector3.down, directions[d], progress);
t = CreateLowerStrip(i, v, vBottom, t, triangles);
v = CreateVertexLine(from, to, i, v, vertices);
vBottom += i > 1 ? (i - 1) : 1;
vBottom = v - 1 - i * 4;
for (int i = resolution - 1; i >= 1; i--)
float progress = (float)i / resolution;
Vector3 from, to;
vertices[v++] = to = Vector3.Lerp(Vector3.up, Vector3.forward, progress);
for (int d = 0; d < 4; d++)
from = to;
to = Vector3.Lerp(Vector3.up, directions[d], progress);
t = CreateUpperStrip(i, v, vBottom, t, triangles);
v = CreateVertexLine(from, to, i, v, vertices);
vBottom += i + 1;
vBottom = v - 1 - i * 4;
for (int i = 0; i < 4; i++)
triangles[t++] = vBottom;
triangles[t++] = v;
triangles[t++] = ++vBottom;
vertices[v++] = Vector3.up;
private static int CreateVertexLine(Vector3 from, Vector3 to, int steps, int v, Vector3[] vertices)
for (int i = 1; i <= steps; i++)
vertices[v++] = Vector3.Lerp(from, to, (float)i / steps);
return v;
private static int CreateLowerStrip(int steps, int vTop, int vBottom, int t, int[] triangles)
for (int i = 1; i < steps; i++)
triangles[t++] = vBottom;
triangles[t++] = vTop - 1;
triangles[t++] = vTop;
triangles[t++] = vBottom++;
triangles[t++] = vTop++;
triangles[t++] = vBottom;
triangles[t++] = vBottom;
triangles[t++] = vTop - 1;
triangles[t++] = vTop;
return t;
private static int CreateUpperStrip(int steps, int vTop, int vBottom, int t, int[] triangles)
triangles[t++] = vBottom;
triangles[t++] = vTop - 1;
triangles[t++] = ++vBottom;
for (int i = 1; i <= steps; i++)
triangles[t++] = vTop - 1;
triangles[t++] = vTop;
triangles[t++] = vBottom;
triangles[t++] = vBottom;
triangles[t++] = vTop++;
triangles[t++] = ++vBottom;
return t;
private static void Normalize(Vector3[] vertices, Vector3[] normals)
for (int i = 0; i < vertices.Length; i++)
normals[i] = vertices[i] = vertices[i].normalized;
private static void CreateUV(Vector3[] vertices, Vector2[] uv)
float previousX = 1f;
for (int i = 0; i < vertices.Length; i++)
Vector3 v = vertices[i];
if (v.x == previousX)
uv[i - 1].x = 1f;
previousX = v.x;
Vector2 textureCoordinates;
textureCoordinates.x = Mathf.Atan2(v.x, v.z) / (-2f * Mathf.PI);
if (textureCoordinates.x < 0f)
textureCoordinates.x += 1f;
textureCoordinates.y = Mathf.Asin(v.y) / Mathf.PI + 0.5f;
uv[i] = textureCoordinates;
uv[vertices.Length - 4].x = uv[0].x = 0.125f;
uv[vertices.Length - 3].x = uv[1].x = 0.375f;
uv[vertices.Length - 2].x = uv[2].x = 0.625f;
uv[vertices.Length - 1].x = uv[3].x = 0.875f;
以上是关于Unity Mesh Mesh给球贴图的主要内容,如果未能解决你的问题,请参考以下文章
Unity Mesh Mesh 正八面体Octaheron贴图
Unity Mesh Mesh 立方体Cube贴图以及六个面分别贴不同的图片