用一个通用代码,实现各种锥、柱、管状体的网格创建。
非原创的同系列。虽然总觉得代码上可以再优化,但是实现的功能已经超级屌了。
真是没有不能做的,只有想不到的。
原文:
http://blog.csdn.net/qq_18408937/article/details/44181489
by 涅凡尘
具体思路:
通过Mesh网格编程实现几何体的多种变化。以立体五角星为例,大边长和小边长分别设置长度为5的数组,数组控制几何体顶层空心,顶层大小,中间层大小,底层大小,底层空心。通过循环构建上层与下层之间的网格。
效果图:
实现代码:
-
using UnityEngine;
-
using System.Collections;
-
-
public class Star3 : MonoBehaviour {
-
-
Mesh mesh;
-
-
public bool sophisticated = false; //圆滑曲面
-
public bool star = true; //星形
-
public int line = 5; //边数
-
public float[] maxsize = {0,0,5,0,0}; //外角大小
-
public float[] minSize = {0,0,1,0,0}; //内角大小
-
public float high = 1; //高度
-
public float low = -1; //低度
-
-
private Vector3[] vs; //顶点坐标
-
private int[] ts; //顶点序列
-
private Vector2[] newUVs; //UV贴图
-
private Vector3[] newNormals; //法线
-
-
// Update is called once per frame
-
void Update () {
-
//变量约束
-
line = Mathf.Clamp (line, 2, 300);
-
high = Mathf.Clamp (high, low, high);
-
low = Mathf.Clamp (low, low, high);
-
if (!star) {
-
for (int i = 0; i < 5; i++) {
-
minSize[i] = Mathf.Cos(Mathf.PI / line) * maxsize[i];
-
}
-
}
-
for (int i = 1; i < 4; i++) {
-
maxsize[i] = Mathf.Clamp (maxsize[i], 0, maxsize[i]);
-
minSize[i] = Mathf.Clamp (minSize[i], 0, maxsize[i]);
-
}
-
maxsize[0] = Mathf.Clamp (maxsize[0], 0, maxsize[1]);
-
minSize[0] = Mathf.Clamp (minSize[0], 0, minSize[1]);
-
maxsize[4] = Mathf.Clamp (maxsize[4], 0, maxsize[3]);
-
minSize[4] = Mathf.Clamp (minSize[4], 0, minSize[3]);
-
//角度计算
-
float corner = 2 * Mathf.PI / line;
-
//确定顶点数量
-
int temp = 5 * 4 * 3 * line;
-
-
vs = new Vector3[temp];
-
ts = new int[temp];
-
newUVs = new Vector2[temp];
-
newNormals = new Vector3[temp];
-
-
int count = 0;
-
float h = 0;
-
float l = 0;
-
for (int i = 0; i < 5; i++) {
-
switch (i) {
-
case 0:
-
h = high;
-
l = high;
-
break;
-
case 1:
-
h = high;
-
l = 0;
-
break;
-
case 2:
-
h = 0;
-
l = low;
-
break;
-
case 3:
-
h = low;
-
l = low;
-
break;
-
case 4:
-
h = low;
-
l = high;
-
break;
-
}
-
for (int k = 0; k < line; k++) {
-
//确定顶点坐标
-
vs[count] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
-
vs[count + 1] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k + 0.5f) * corner) * minSize[(i + 1) % 5],l);
-
vs[count + 2] = new Vector3(Mathf.Sin(k * corner) * maxsize[(i + 1) % 5],Mathf.Cos(k * corner) * maxsize[(i + 1) % 5],l);
-
-
vs[count + 3] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
-
vs[count + 4] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[i],Mathf.Cos((k + 0.5f) * corner) * minSize[i],h);
-
vs[count + 5] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k + 0.5f) * corner) * minSize[(i + 1) % 5],l);
-
-
vs[count + 6] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
-
vs[count + 7] = new Vector3(Mathf.Sin(k * corner) * maxsize[(i + 1) % 5],Mathf.Cos(k * corner) * maxsize[(i + 1) % 5],l);
-
vs[count + 8] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k - 0.5f) * corner) * minSize[(i + 1) % 5],l);
-
-
vs[count + 9] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
-
vs[count + 10] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k - 0.5f) * corner) * minSize[(i + 1) % 5],l);
-
vs[count + 11] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[i],Mathf.Cos((k - 0.5f) * corner) * minSize[i],h);
-
//确定法线
-
if (sophisticated) {
-
newNormals[count] = Vector3.Normalize(vs[count] - new Vector3(0,0,h));
-
newNormals[count + 1] = Vector3.Normalize(vs[count + 1] - new Vector3(0,0,l));
-
newNormals[count + 2] = Vector3.Normalize(vs[count + 2] - new Vector3(0,0,l));
-
newNormals[count + 3] = Vector3.Normalize(vs[count + 3] - new Vector3(0,0,h));
-
newNormals[count + 4] = Vector3.Normalize(vs[count + 4] - new Vector3(0,0,h));
-
newNormals[count + 5] = Vector3.Normalize(vs[count + 5] - new Vector3(0,0,l));
-
newNormals[count + 6] = Vector3.Normalize(vs[count + 6] - new Vector3(0,0,h));
-
newNormals[count + 7] = Vector3.Normalize(vs[count + 7] - new Vector3(0,0,l));
-
newNormals[count + 8] = Vector3.Normalize(vs[count + 8] - new Vector3(0,0,l));
-
newNormals[count + 9] = Vector3.Normalize(vs[count + 9] - new Vector3(0,0,h));
-
newNormals[count + 10] = Vector3.Normalize(vs[count + 10] - new Vector3(0,0,l));
-
newNormals[count + 11] = Vector3.Normalize(vs[count + 11] - new Vector3(0,0,h));
-
} else {
-
for (int j = 0; j < 4; j++) {
-
Vector3 newNormal = Vector3.Cross(vs[count + 3 * j + 1] - vs[count + 3 * j + 0],vs[count + 3 * j + 2] - vs[count + 3 * j + 0]);
-
for (int z = 0; z < 3; z++) {
-
newNormals[count + 3 * j + z] = Vector3.Normalize(newNormal);
-
}
-
}
-
}
-
-
count += 12;
-
}
-
}
-
//确定顶点序列
-
for (int i = 0; i < ts.Length; i++) {
-
ts[i] = i;
-
}
-
//创建网格
-
mesh = new Mesh();
-
GetComponent<MeshFilter>().mesh = mesh;
-
mesh.vertices = vs;
-
mesh.uv = newUVs;
-
mesh.triangles = ts;
-
mesh.normals = newNormals;
-
-
}
-
}
- using UnityEngine;
- using System.Collections;
- public class Star3 : MonoBehaviour {
- Mesh mesh;
- public bool sophisticated = false; //圆滑曲面
- public bool star = true; //星形
- public int line = 5; //边数
- public float[] maxsize = {0,0,5,0,0}; //外角大小
- public float[] minSize = {0,0,1,0,0}; //内角大小
- public float high = 1; //高度
- public float low = -1; //低度
- private Vector3[] vs; //顶点坐标
- private int[] ts; //顶点序列
- private Vector2[] newUVs; //UV贴图
- private Vector3[] newNormals; //法线
- // Update is called once per frame
- void Update () {
- //变量约束
- line = Mathf.Clamp (line, 2, 300);
- high = Mathf.Clamp (high, low, high);
- low = Mathf.Clamp (low, low, high);
- if (!star) {
- for (int i = 0; i < 5; i++) {
- minSize[i] = Mathf.Cos(Mathf.PI / line) * maxsize[i];
- }
- }
- for (int i = 1; i < 4; i++) {
- maxsize[i] = Mathf.Clamp (maxsize[i], 0, maxsize[i]);
- minSize[i] = Mathf.Clamp (minSize[i], 0, maxsize[i]);
- }
- maxsize[0] = Mathf.Clamp (maxsize[0], 0, maxsize[1]);
- minSize[0] = Mathf.Clamp (minSize[0], 0, minSize[1]);
- maxsize[4] = Mathf.Clamp (maxsize[4], 0, maxsize[3]);
- minSize[4] = Mathf.Clamp (minSize[4], 0, minSize[3]);
- //角度计算
- float corner = 2 * Mathf.PI / line;
- //确定顶点数量
- int temp = 5 * 4 * 3 * line;
- vs = new Vector3[temp];
- ts = new int[temp];
- newUVs = new Vector2[temp];
- newNormals = new Vector3[temp];
- int count = 0;
- float h = 0;
- float l = 0;
- for (int i = 0; i < 5; i++) {
- switch (i) {
- case 0:
- h = high;
- l = high;
- break;
- case 1:
- h = high;
- l = 0;
- break;
- case 2:
- h = 0;
- l = low;
- break;
- case 3:
- h = low;
- l = low;
- break;
- case 4:
- h = low;
- l = high;
- break;
- }
- for (int k = 0; k < line; k++) {
- //确定顶点坐标
- vs[count] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
- vs[count + 1] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k + 0.5f) * corner) * minSize[(i + 1) % 5],l);
- vs[count + 2] = new Vector3(Mathf.Sin(k * corner) * maxsize[(i + 1) % 5],Mathf.Cos(k * corner) * maxsize[(i + 1) % 5],l);
- vs[count + 3] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
- vs[count + 4] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[i],Mathf.Cos((k + 0.5f) * corner) * minSize[i],h);
- vs[count + 5] = new Vector3(Mathf.Sin((k + 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k + 0.5f) * corner) * minSize[(i + 1) % 5],l);
- vs[count + 6] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
- vs[count + 7] = new Vector3(Mathf.Sin(k * corner) * maxsize[(i + 1) % 5],Mathf.Cos(k * corner) * maxsize[(i + 1) % 5],l);
- vs[count + 8] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k - 0.5f) * corner) * minSize[(i + 1) % 5],l);
- vs[count + 9] = new Vector3(Mathf.Sin(k * corner) * maxsize[i],Mathf.Cos(k * corner) * maxsize[i],h);
- vs[count + 10] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[(i + 1) % 5],Mathf.Cos((k - 0.5f) * corner) * minSize[(i + 1) % 5],l);
- vs[count + 11] = new Vector3(Mathf.Sin((k - 0.5f) * corner) * minSize[i],Mathf.Cos((k - 0.5f) * corner) * minSize[i],h);
- //确定法线
- if (sophisticated) {
- newNormals[count] = Vector3.Normalize(vs[count] - new Vector3(0,0,h));
- newNormals[count + 1] = Vector3.Normalize(vs[count + 1] - new Vector3(0,0,l));
- newNormals[count + 2] = Vector3.Normalize(vs[count + 2] - new Vector3(0,0,l));
- newNormals[count + 3] = Vector3.Normalize(vs[count + 3] - new Vector3(0,0,h));
- newNormals[count + 4] = Vector3.Normalize(vs[count + 4] - new Vector3(0,0,h));
- newNormals[count + 5] = Vector3.Normalize(vs[count + 5] - new Vector3(0,0,l));
- newNormals[count + 6] = Vector3.Normalize(vs[count + 6] - new Vector3(0,0,h));
- newNormals[count + 7] = Vector3.Normalize(vs[count + 7] - new Vector3(0,0,l));
- newNormals[count + 8] = Vector3.Normalize(vs[count + 8] - new Vector3(0,0,l));
- newNormals[count + 9] = Vector3.Normalize(vs[count + 9] - new Vector3(0,0,h));
- newNormals[count + 10] = Vector3.Normalize(vs[count + 10] - new Vector3(0,0,l));
- newNormals[count + 11] = Vector3.Normalize(vs[count + 11] - new Vector3(0,0,h));
- } else {
- for (int j = 0; j < 4; j++) {
- Vector3 newNormal = Vector3.Cross(vs[count + 3 * j + 1] - vs[count + 3 * j + 0],vs[count + 3 * j + 2] - vs[count + 3 * j + 0]);
- for (int z = 0; z < 3; z++) {
- newNormals[count + 3 * j + z] = Vector3.Normalize(newNormal);
- }
- }
- }
- count += 12;
- }
- }
- //确定顶点序列
- for (int i = 0; i < ts.Length; i++) {
- ts[i] = i;
- }
- //创建网格
- mesh = new Mesh();
- GetComponent<MeshFilter>().mesh = mesh;
- mesh.vertices = vs;
- mesh.uv = newUVs;
- mesh.triangles = ts;
- mesh.normals = newNormals;
- }
- }
通过调节变量图中几何体均可实现。Mesh编程步骤见
Mesh网格编程(一)。
Mesh网格编程(一)。