• (五)Cube


    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,所以在此不做展开。

  • 相关阅读:
    C#如何调用非托管的C++Dll
    CList 点击表头排序 (3)两种排序的第二种
    CList 点击表头排序 (2)两种排序方法中其中一种
    CList 点击表头排序 (1)SortItems函数
    CListCtrl 隔行变色
    C++去掉字符串中首尾空格和所有空格
    Dialog和FormView如何派生通用类
    STL中erase()的陷阱
    socket 笔记(一)
    prettyJson V7.1 使用
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/12253697.html
Copyright © 2020-2023  润新知