文章目录
- 1.概述
- 2.基础版Cube
-
- 2.1 基类
- 2.2 Cube代码
- 3.完善版Cube
-
- 3.1 基础版Cube的问题
- 3.2 完善版Cube顶点
- 3.3 三角形数组
- 3.4 法线数组
- 3.5 完整代码
- 4.结语
1.概述
Unity自带cube模型,但是此文实现,分基础版和完善版。基础版不进行顶点法线计算,完善版会进行法线计算,结果会跟自带cube比较接近。
2.基础版Cube
2.1 基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class CreateMeshBase : MonoBehaviour
{
MeshFilter meshFilter;protected Mesh mesh;protected virtual Vector3[] Vertices {
get; }protected virtual int[] Triangles {
get; }protected virtual Vector3[] Normals {
get; }protected virtual Vector2[] Uvs {
get; }protected virtual string MeshName {
get; }protected virtual void Start(){
GetMeshFilter();}protected virtual void Reset(){
GetMeshFilter();}protected virtual void OnValidate(){
GetMeshFilter();}void GetMeshFilter(){
if (meshFilter == null){
meshFilter = GetComponent<MeshFilter>();mesh = new Mesh(); }mesh.triangles = null;mesh.uv = null;mesh.vertices = null;mesh.name = MeshName;mesh.vertices = Vertices;mesh.triangles = Triangles;mesh.uv = Uvs;meshFilter.mesh = mesh;}private void OnDrawGizmos(){
if (Vertices == null) return;Gizmos.color = Color.red;Gizmos.DrawSphere(Vector3.zero, 0.5f);Gizmos.color = Color.blue;for (int i = 0; i < Vertices.Length; i++){
Gizmos.DrawSphere(Vertices[i], 0.3f);}}
}
2.2 Cube代码
代码即为定义八个顶点,然后依次设置三角形即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CreateCube : CreateMeshBase
{
public float halfLength = 5;protected override string MeshName{
get{
return "Cube Mesh";}}protected override Vector3[] Vertices{
get{
Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);return vertices;}}protected override int[] Triangles{
get{
int[] triangles = new int[36]{
0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};return triangles;}}
}
3.完善版Cube
3.1 基础版Cube的问题
基础版Cube由于三个面公用一个顶点,导致此顶点处的法线和切线无法定义,所以需要分离顶点。这样顶点位置存在三个相互重合的点,每个点只跟自己对应的平面产生关系。
3.2 完善版Cube顶点
新Cube生成方法实在基础版基础上生成的,但是定点数由8个变成36个,即根据基础版的三角形数组生成。如下所示
protected override Vector3[] Vertices{
get{
Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);int[] triangles = new int[36]{
0,3,1,3,2,1,4,5,6,4,6,7,1,2,6,1,6,5,0,4,3,4,7,3,0,1,4,1,5,4,3,6,2,3,7,6};cubeVertices = new Vector3[36];for (int i = 0; i < cubeVertices.Length; i++){
cubeVertices[i] = vertices[triangles[i]];}return cubeVertices;}}
3.3 三角形数组
根据3.2生成的新的顶点数组,此时三角形数组值即为其索引,如下所示:
protected override int[] Triangles{
get{
/*int[] triangles = new int[36]{0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};*/int[] triangles = new int[36];for (int i = 0; i < triangles.Length; i++){
triangles[i] = i;}return triangles;}}
3.4 法线数组
基础版cube看起来与unity自带的相比比较奇怪,这是因为没有设置顶点的法向。由于基础版公用顶点,所以法线无法定义,所以新版本法线则比较容易。如下所示:
protected override Vector3[] Normals{
get{
Vector3[] normals = new Vector3[36];for (int i = 0; i < normals.Length - 2; i+=3){
Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);for (int j = 0; j < 3; j++){
normals[i + j] = normal;}}return normals;}}
3.5 完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CreateNewCube : CreateMeshBase
{
public float halfLength = 5;private Vector3[] cubeVertices = new Vector3[36];protected override string MeshName{
get{
return "Cube Mesh";}}protected override Vector3[] Vertices{
get{
Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);int[] triangles = new int[36]{
0,3,1,3,2,1,4,5,6,4,6,7,1,2,6,1,6,5,0,4,3,4,7,3,0,1,4,1,5,4,3,6,2,3,7,6};cubeVertices = new Vector3[36];for (int i = 0; i < cubeVertices.Length; i++){
cubeVertices[i] = vertices[triangles[i]];}return cubeVertices;}}protected override int[] Triangles{
get{
/*int[] triangles = new int[36]{0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};*/int[] triangles = new int[36];for (int i = 0; i < triangles.Length; i++){
triangles[i] = i;}return triangles;}}protected override Vector3[] Normals{
get{
Vector3[] normals = new Vector3[36];for (int i = 0; i < normals.Length - 2; i+=3){
Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);for (int j = 0; j < 3; j++){
normals[i + j] = normal;}}return normals;}}//override
}
4.结语
即使完善版cube也未进行uv定义以及切线定义。切线一般均为Vector4类型,值为相应切向或者(-1,0,0,-1)。至于uv问题不考虑是因为比较负责,涉及每个面都相同还是不同的uv,对于cube贴图问题一般使用自带或者cube贴图shader来实现,所以在此不做展开,如果需要可以参考如下。