• Unity---------Mesh理解


    Mesh顾名思义“网格”,Unity3D里面所有的模型都是由Mesh组成的,UI也不例外。

    例如下图,模型上的一个个小网格就是Mesh,这些Mesh有不同的三维顶点(Vector3),共同组成了一个3D模型。

    Unity3D中Mesh的基本单位是三角形,学习应该由浅入深,所以今天我们就从最基本最简单的等腰三角形开始画起。

    本文作者尚为初学者,如有理解不到位的地方,欢迎指正。

     

    首先我们新建一个名为TestTriangle的CSharp脚本,然后打开TestTriangle,我们开始编写代码。

    [csharp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4. /* ============================================================================== 
    5.  * 功能描述:创建三角形Mesh 
    6.  * 创 建 者:Eci 
    7.  * 创建日期:2016/09/04 
    8.  * ==============================================================================*/  
    9. [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]  
    10. public class TestTriangle : MonoBehaviour {  
    11.   
    12.   
    13.     public float sideLength = 2;  
    14.     public float angleDegree = 100;  
    15.   
    16.     private MeshFilter meshFilter;  
    17.   
    18.     [ExecuteInEditMode]  
    19.     private void Awake()  
    20.     {  
    21.   
    22.         meshFilter = GetComponent<MeshFilter>();  
    23.         meshFilter.mesh = Create (sideLength, angleDegree);  
    24.     }  
    25.   
    26.     private void Update()  
    27.     {  
    28.     }  
    29.     private Mesh Create(float sideLength, float angleDegree)  
    30.     {  
    31.         Mesh mesh = new Mesh();  
    32.         Vector3[] vertices = new Vector3[3];  
    33.   
    34.         float angle = Mathf.Deg2Rad * angleDegree;  
    35.         float halfAngle = angle / 2;  
    36.         vertices [0] = Vector3.zero;  
    37.         float cosA = Mathf.Cos (halfAngle);  
    38.         float sinA = Mathf.Sin (halfAngle);  
    39.         vertices [1] = new Vector3 (cosA * sideLength, 0, sinA * sideLength);  
    40.         vertices [2] = new Vector3 (cosA * sideLength, 0, -sinA * sideLength);  
    41.   
    42.         int[] triangles = new int[3];  
    43.         triangles [0] = 0;  
    44.         triangles [1] = 1;  
    45.         triangles [2] = 2;  
    46.   
    47.         mesh.vertices = vertices;  
    48.         mesh.triangles = triangles;  
    49.   
    50.         Vector2[] uvs = new Vector2[vertices.Length];  
    51.         for (int i = 0; i < uvs.Length; i++)  
    52.         {  
    53.             uvs[i] = Vector2.zero;  
    54.         }  
    55.         mesh.uv = uvs;  
    56.   
    57.         return mesh;  
    58.     }  
    59. }  


    RequireComponent这一行,表示我们需要MeshRenderer和MeshFilter这两个组件,当我们将TestTriangle的代码挂在GameObject上的时候,会自动添加这两个组件。而我们要移除MeshRenderer或MeshFilter的时候,编辑器就会提示不能移除。

    然后我们给出了两个公开变量,sideLength边长和angleDegree角度,因为我们这里要画的是等腰三角形,这代表的是等腰边长和等腰边长的夹角。

    ExecuteInEditMode表示会在编辑器模式下运行。

    Awake里,我们获取了MeshFilter并为它创建了Mesh。

    Create方法里面,我们看到,先后为新建的Mesh创建了vertices(定点),triangles(三角形),uv(纹理坐标)。

    vertices很简单,就是计算三角形三个顶点的坐标,因为是个二维图形,所以y坐标都为零。

    triangles里保存的是vertices的下标。

    uv暂时我们用不到,所以全部设为零。在后面文章中我们会介绍uv的用法。

    最后返回mesh。

    在编辑器里,点击运行,我们就可以看到一个紫色(因为没有材质)的三角形。

    但是只能在运行的时候才看得到这个三角形,编辑器里看不到怎么办?添加下面这段代码:

    [csharp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. void OnDrawGizmos()  
    2. {  
    3.     Gizmos.color = Color.gray;  
    4.     DrawMesh();  
    5. }  
    6.   
    7. void OnDrawGizmosSelected()  
    8. {  
    9.     Gizmos.color = Color.green;  
    10.     DrawMesh();  
    11. }  
    12.   
    13. private void DrawMesh()  
    14. {  
    15.     Mesh mesh = Create(sideLength, angleDegree);  
    16.     int[] tris = mesh.triangles;  
    17.     Gizmos.DrawLine(mesh.vertices[tris[0]], mesh.vertices[tris[1]]);  
    18.     Gizmos.DrawLine(mesh.vertices[tris[0]], mesh.vertices[tris[2]]);  
    19.     Gizmos.DrawLine(mesh.vertices[tris[1]], mesh.vertices[tris[2]]);  
    20. }  
    关于OnDrawGizmos和OnDrawGizmosSelected可以参考下面这个链接:
    http://www.ceeger.com/Script/Gizmos/Gizmos.html

    简单来讲就是在编辑器模式下,绘制辅助线框。

    这样一个简单的等腰三角形Mesh的绘制就完成了。什么?你不满意?我们稍微整理一下代码:

    [csharp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4. /* ============================================================================== 
    5.  * 功能描述:创建三角形Mesh 
    6.  * 创 建 者:Eci 
    7.  * 创建日期:2016/09/04 
    8.  * ==============================================================================*/  
    9. [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]  
    10. public class TestTriangle : MonoBehaviour {  
    11.   
    12.   
    13.     public float sideLength = 2;  
    14.     public float angleDegree = 100;  
    15.     private static readonly int ANGLE_DEGREE_PRECISION = 1000;  
    16.     private static readonly int SIDE_LENGTH_PRECISION = 1000;  
    17.   
    18.     private MeshFilter meshFilter;  
    19.   
    20.     private TriangleMeshCreator creator = new TriangleMeshCreator();  
    21.   
    22.     [ExecuteInEditMode]  
    23.     private void Awake()  
    24.     {  
    25.   
    26.         meshFilter = GetComponent<MeshFilter>();  
    27.     }  
    28.   
    29.     private void Update()  
    30.     {  
    31.         meshFilter.mesh = creator.CreateMesh(sideLength, angleDegree);  
    32.     }  
    33.   
    34.     void OnDrawGizmos()  
    35.     {  
    36.         Gizmos.color = Color.gray;  
    37.         DrawMesh();  
    38.     }  
    39.   
    40.     void OnDrawGizmosSelected()  
    41.     {  
    42.         Gizmos.color = Color.green;  
    43.         DrawMesh();  
    44.     }  
    45.   
    46.     private void DrawMesh()  
    47.     {  
    48.         Mesh mesh = creator.CreateMesh(sideLength, angleDegree);  
    49.         int[] tris = mesh.triangles;  
    50.         Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[0]]), transformToWorld(mesh.vertices[tris[1]]));  
    51.         Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[0]]), transformToWorld(mesh.vertices[tris[2]]));  
    52.         Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[1]]), transformToWorld(mesh.vertices[tris[2]]));  
    53.     }  
    54.   
    55.     private Vector3 transformToWorld(Vector3 src)  
    56.     {  
    57.         return transform.TransformPoint(src);  
    58.     }  
    59.   
    60.     private class TriangleMeshCreator  
    61.     {  
    62.         private float _sideLength;  
    63.         private float _angleDegree;  
    64.   
    65.         private Mesh _cacheMesh ;  
    66.         public Mesh CreateMesh(float sideLength, float angleDegree)  
    67.         {  
    68.             if (checkDiff(sideLength, angleDegree))  
    69.             {  
    70.                 Mesh newMesh = Create(sideLength, angleDegree);  
    71.                 if (newMesh != null)  
    72.                 {  
    73.                     _cacheMesh = newMesh;  
    74.                     this._sideLength = sideLength;  
    75.                     this._angleDegree = angleDegree;  
    76.                 }  
    77.             }  
    78.             return _cacheMesh;  
    79.         }  
    80.   
    81.         private Mesh Create(float sideLength, float angleDegree)  
    82.         {  
    83.             Mesh mesh = new Mesh();  
    84.             Vector3[] vertices = new Vector3[3];  
    85.   
    86.             float angle = Mathf.Deg2Rad * angleDegree;  
    87.             float halfAngle = angle / 2;  
    88.             vertices [0] = Vector3.zero;  
    89.             float cosA = Mathf.Cos (halfAngle);  
    90.             float sinA = Mathf.Sin (halfAngle);  
    91.             vertices [1] = new Vector3 (cosA * sideLength, 0, sinA * sideLength);  
    92.             vertices [2] = new Vector3 (cosA * sideLength, 0, -sinA * sideLength);  
    93.   
    94.             int[] triangles = new int[3];  
    95.             triangles [0] = 0;  
    96.             triangles [1] = 1;  
    97.             triangles [2] = 2;  
    98.   
    99.             mesh.vertices = vertices;  
    100.             mesh.triangles = triangles;  
    101.   
    102.             Vector2[] uvs = new Vector2[vertices.Length];  
    103.             for (int i = 0; i < uvs.Length; i++)  
    104.             {  
    105.                 uvs[i] = Vector2.zero;  
    106.             }  
    107.             mesh.uv = uvs;  
    108.   
    109.             return mesh;  
    110.         }  
    111.   
    112.         private bool checkDiff(float sideLength, float angleDegree)  
    113.         {  
    114.             return (int)((sideLength - this._sideLength) * SIDE_LENGTH_PRECISION) != 0 ||  
    115.                 (int)((angleDegree - this._angleDegree) * ANGLE_DEGREE_PRECISION) != 0;  
    116.         }  
    117.     }  
    118.   
    119.   
    120. }  

    为GameObject的MeshRenderer添加材质,我们就可以看到有颜色的三角形了。因为uv值都为0,所以是单一颜色。不过没关系,下一堂课,我们会为三角形添加不同的纹理。

    附上代码下载链接

     
     
  • 相关阅读:
    ASP.NET Web API 中 特性路由(Attribute Routing) 的重名问题
    在 ASP.NET Web API 中,使用 命名空间(namespace) 来作为路由的参数
    【转】使用create_project.py创建cocos2d项目时出错
    WCF使用net.tcp绑定时的注意事项
    WCF:如何将net.tcp协议寄宿到IIS
    关于WCF服务的调试跟踪
    Windows Store Apps 开发转载
    如何让弹出窗口和页面产生联动?
    关于C# wpf DataGrid单元格双击设置单元格内容
    在WPF的DataGrid中对行添加单击事件
  • 原文地址:https://www.cnblogs.com/w-wfy/p/7339824.html
Copyright © 2020-2023  润新知