Unity中创建Mesh

匿名 (未验证) 提交于 2019-12-02 23:51:01

什么是Mesh?

Mesh是指的模型的网格,3D模型是由多边形拼接而成,而多边形实际上又是由多个三角形拼接而成的。即一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh。

原理

即动态创建一个Mesh,设置三角形和顶点数据,然后赋值给MeshFilter(增加mesh属性),通过MeshRenderer(增加材质并渲染出Mesh)绘制出来

Mesh的组成部分

1.vertices(顶点数据数组Vector3[])

2.triangles(三角形顶点索引数组,int[])

3.normals(法线向量数组,Vector3[])

4.uv(纹理坐标数组,Vector2[])

顶点坐标:顶点坐标数组存放Mesh的每个顶点的空间坐标,假设某mesh有n个顶点,则vertex的size为n

法线:法线数组存放mesh每个顶点的法线,大小与顶点坐标对应,normal[i]对应顶点vertex[i]的法线

纹理坐标:它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面. uv[i]对应vertex[i]

三角形序列:每个mesh都由多个三角面组成,而三角面的三个点就是顶点坐标里的点,三角形的数组的size = 三角形个数 * 3

创建一个立方体

1.定顶点坐标

一般我们会以立方体几何中心为坐标原点。

代码:

 1         //顶点数组  2         Vector3[] _vertices =   3         {  4             // front  5             new Vector3(-5.0f, 10.0f, -5.0f),  6             new Vector3(-5.0f, 0.0f, -5.0f),  7             new Vector3(5.0f, 0.0f, -5.0f),  8             new Vector3(5.0f, 10.0f, -5.0f),  9  10  11             // left   12             new Vector3(-5.0f, 10.0f, -5.0f), 13             new Vector3(-5.0f, 0.0f, -5.0f), 14             new Vector3(-5.0f, 0.0f, 5.0f),// 15             new Vector3(-5.0f, 10.0f, 5.0f), 16  17             // back 18             new Vector3(-5.0f, 10.0f, 5.0f), 19             new Vector3(-5.0f, 0.0f, 5.0f), 20             new Vector3(5.0f, 0.0f, 5.0f), 21             new Vector3(5.0f, 10.0f, 5.0f), 22  23  24             // right   25             new Vector3(5.0f, 10.0f, 5.0f), 26             new Vector3(5.0f, 0.0f, 5.0f), 27             new Vector3(5.0f, 0.0f, -5.0f), 28             new Vector3(5.0f, 10.0f, -5.0f), 29  30  31             // Top 32             new Vector3(-5.0f, 10.0f, 5.0f), 33             new Vector3(5.0f, 10.0f, 5.0f), 34             new Vector3(5.0f, 10.0f, -5.0f), 35             new Vector3(-5.0f, 10.0f, -5.0f), 36  37            // Bottom 38             new Vector3(-5.0f, 0.0f, 5.0f), 39             new Vector3(5.0f, 0.0f, 5.0f), 40             new Vector3(5.0f, 0.0f, -5.0f), 41             new Vector3(-5.0f, 0.0f, -5.0f), 42  43         };

这里有人会有疑问,立方体不是八个顶点吗,哪来这么多顶点,考虑一下一个面4个角,一共6个面,24个,是的,8个顶点也可以勾勒出来,但是这里考虑贴图效果,一般不共点。还有就是Unity中是左手坐标系,一定记好,因为在绘制三角面时很重要。

2.三角面索引

     //索引数组         int[] _triangles =         {           //front           2,1,0,           0,3,2,           //left           4,5,6,           4,6,7,           //back           9,11,8,           9,10,11,           //right           12,13,14,           12,14,15,           ////up           //16,17,18,           //16,18,19,           ////buttom           //21,23,22,           //21,20,23,            //不可跳跃设置索引值(否则会提示一些索引超出边界顶点   15直接20不可,要连续15-16)           17,19,18,           17,16,19,         };

这里设置的原则时外面被渲染里面剔除掉,顺时针构建(注意里外面的区别),还要注意的一个点,如上所写,比如我想生成5个面,那你的索引值也要是连续的,不可16直接蹦到20。这里立法体面的绘制顺序是(即绘制三角面的面与上面顶点顺序要一致)设置顶点的顺序

3.UV坐标

代码:

 1      //UV数组  2         Vector2[] uvs =  3         {  4             // Front  5             new Vector2(1.0f, 0.0f),  6             new Vector2(1.0f, 1.0f),  7             new Vector2(1.0f, 0.0f),  8             new Vector2(0.0f, 0.0f),  9  10              11             // Left 12             new Vector2(1.0f, 1.0f), 13             new Vector2(0.0f, 1.0f), 14             new Vector2(0.0f, 0.0f), 15             new Vector2(1.0f, 0.0f), 16  17              18             // Back 19             new Vector2(1.0f, 0.0f), 20             new Vector2(1.0f, 1.0f), 21             new Vector2(1.0f, 0.0f), 22             new Vector2(0.0f, 0.0f), 23  24              25             // Right 26             new Vector2(1.0f, 1.0f), 27             new Vector2(0.0f, 1.0f), 28             new Vector2(0.0f, 0.0f), 29             new Vector2(1.0f, 0.0f), 30  31             //// Top 32             //new Vector2(0.0f, 0.0f), 33             //new Vector2(1.0f, 0.0f), 34             //new Vector2(1.0f, 1.0f), 35             //new Vector2(0.0f, 1.0f), 36  37  38             // Bottom 39             new Vector2(0.0f, 0.0f), 40             new Vector2(1.0f, 0.0f), 41             new Vector2(1.0f, 1.0f), 42             new Vector2(0.0f, 1.0f), 43  44         };

UV坐标从左上角开始(想象摄像机在立方体内部去判断),

开始的即(0,0),一般是在0-1之间,一些比较大的面为防止纹理被拉伸马赛克,我们会重复贴纹理,会有大于1的情况,这里的点要与顶点坐标一一对应。重复贴纹理时需要将重复帖的贴图的Wrap Mode设为Repeat(重复)。
即:
4.构建mesh
代码:
 1         Mesh mesh = new Mesh()  2         {  3             vertices = _vertices,  4             uv = uvs,  5             triangles = _triangles,  6         };  7   8         //重新计算网格的法线  9         //在修改完顶点后,通常会更新法线来反映新的变化。法线是根据共享的顶点计算出来的。 10         //导入到网格有时不共享所有的顶点。例如:一个顶点在一个纹理坐标的接缝处将会被分成两个顶点。 11         //因此这个RecalculateNormals函数将会在纹理坐标接缝处创建一个不光滑的法线。 12         //RecalculateNormals不会自动产生切线,因此bumpmap着色器在调用RecalculateNormals之后不会工作。然而你可以提取你自己的切线。 13         mesh.RecalculateNormals();

给mesh属性赋值。

5.增加MeshFilter组件,网格过滤。以及增加MeshRenderer组件添加材质实现渲染。OK!!!到这基本已经绘制完了,Mesh已经出来了。

  1 using System.Collections;   2 using System.Collections.Generic;   3 using UnityEngine;   4    5 public class ShaderBase : MonoBehaviour   6 {   7    8     void Start()   9     {  10         GameObject gameObject = new GameObject("Cube");  11         gameObject.transform.position = Vector3.zero;  12    13         //顶点数组  14         Vector3[] _vertices =   15         {  16             // front  17             new Vector3(-5.0f, 10.0f, -5.0f),  18             new Vector3(-5.0f, 0.0f, -5.0f),  19             new Vector3(5.0f, 0.0f, -5.0f),  20             new Vector3(5.0f, 10.0f, -5.0f),  21   22   23             // left    24             new Vector3(-5.0f, 10.0f, -5.0f),  25             new Vector3(-5.0f, 0.0f, -5.0f),  26             new Vector3(-5.0f, 0.0f, 5.0f),//  27             new Vector3(-5.0f, 10.0f, 5.0f),  28   29             // back  30             new Vector3(-5.0f, 10.0f, 5.0f),  31             new Vector3(-5.0f, 0.0f, 5.0f),  32             new Vector3(5.0f, 0.0f, 5.0f),  33             new Vector3(5.0f, 10.0f, 5.0f),  34   35   36             // right    37             new Vector3(5.0f, 10.0f, 5.0f),  38             new Vector3(5.0f, 0.0f, 5.0f),  39             new Vector3(5.0f, 0.0f, -5.0f),  40             new Vector3(5.0f, 10.0f, -5.0f),  41   42   43             // Top  44             new Vector3(-5.0f, 10.0f, 5.0f),  45             new Vector3(5.0f, 10.0f, 5.0f),  46             new Vector3(5.0f, 10.0f, -5.0f),  47             new Vector3(-5.0f, 10.0f, -5.0f),  48   49            // Bottom  50             new Vector3(-5.0f, 0.0f, 5.0f),  51             new Vector3(5.0f, 0.0f, 5.0f),  52             new Vector3(5.0f, 0.0f, -5.0f),  53             new Vector3(-5.0f, 0.0f, -5.0f),  54   55         };  56         //索引数组  57         int[] _triangles =  58         {  59           //front  60           2,1,0,  61           0,3,2,  62           //left  63           4,5,6,  64           4,6,7,  65           //back  66           9,11,8,  67           9,10,11,  68           //right  69           12,13,14,  70           12,14,15,  71           ////up  72           //16,17,18,  73           //16,18,19,  74           ////buttom  75           //21,23,22,  76           //21,20,23,  77   78           //不可跳跃设置索引值(否则会提示一些索引超出边界顶点   15直接20不可,要连续15-16)  79           17,19,18,  80           17,16,19,  81         };  82   83         //UV数组  84         Vector2[] uvs =  85         {  86             // Front  87             new Vector2(1.0f, 0.0f),  88             new Vector2(1.0f, 1.0f),  89             new Vector2(1.0f, 0.0f),  90             new Vector2(0.0f, 0.0f),  91   92               93             // Left  94             new Vector2(1.0f, 1.0f),  95             new Vector2(0.0f, 1.0f),  96             new Vector2(0.0f, 0.0f),  97             new Vector2(1.0f, 0.0f),  98   99              100             // Back 101             new Vector2(1.0f, 0.0f), 102             new Vector2(1.0f, 1.0f), 103             new Vector2(1.0f, 0.0f), 104             new Vector2(0.0f, 0.0f), 105  106              107             // Right 108             new Vector2(1.0f, 1.0f), 109             new Vector2(0.0f, 1.0f), 110             new Vector2(0.0f, 0.0f), 111             new Vector2(1.0f, 0.0f), 112  113             //// Top 114             //new Vector2(0.0f, 0.0f), 115             //new Vector2(1.0f, 0.0f), 116             //new Vector2(1.0f, 1.0f), 117             //new Vector2(0.0f, 1.0f), 118  119  120             // Bottom 121             new Vector2(0.0f, 0.0f), 122             new Vector2(1.0f, 0.0f), 123             new Vector2(1.0f, 1.0f), 124             new Vector2(0.0f, 1.0f), 125  126         }; 127  128         Mesh mesh = new Mesh() 129         { 130             vertices = _vertices, 131             uv = uvs, 132             triangles = _triangles, 133         }; 134  135         //重新计算网格的法线 136         //在修改完顶点后,通常会更新法线来反映新的变化。法线是根据共享的顶点计算出来的。 137         //导入到网格有时不共享所有的顶点。例如:一个顶点在一个纹理坐标的接缝处将会被分成两个顶点。 138         //因此这个RecalculateNormals函数将会在纹理坐标接缝处创建一个不光滑的法线。 139         //RecalculateNormals不会自动产生切线,因此bumpmap着色器在调用RecalculateNormals之后不会工作。然而你可以提取你自己的切线。 140         mesh.RecalculateNormals(); 141         gameObject.AddComponent<MeshFilter>().mesh=mesh; 142         //Material/New Material 1 143         gameObject.AddComponent<MeshRenderer>().material = Resources.Load<Material>("Material/New Material"); 144  145     } 146  147 }


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!