Unity3D 动态创建Mesh(一)

1.Mesh、MeshFilter、MeshRenderer关系整理

在Unity3D中创建一个Cube,在Inspector可以看到其中含有MeshFilter、MeshRenderer组件。

MeshFilter含有一个Public成员 Mesh。

在Mesh中存储着三维模型的数据:vertices(顶点数据数组Vector3[])、triangles(三角形顶点索引数组,int[])、normals(法线向量数组,Vector3[])、uv(纹理坐标数组,Vector2[])。

2.使用Mesh创建一个Cube

创建一个脚本dyn3d.cs,成为Main Camera的组件,点击运行即可看到动态生成的Cube

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 public class dyn3d : MonoBehaviour {
 5
 6     // Use this for initialization
 7     void Start () {
 8
 9         CreateCube();
10     }
11
12     // Update is called once per frame
13     void Update () {
14
15     }
16
17     void CreateCube()
18     {
19
20         GameObject obj=new GameObject("cube");
21         MeshFilter mf=obj.AddComponent<MeshFilter>();
22         MeshRenderer mr=obj.AddComponent<MeshRenderer>();
23
24
25         Vector3[] vertices=new Vector3[24];
26         int[] triangles=new int[36];
27
28         //forward
29         vertices[0].Set(0.5f,-0.5f,0.5f);
30         vertices[1].Set(-0.5f,-0.5f,0.5f);
31         vertices[2].Set(0.5f,0.5f,0.5f);
32         vertices[3].Set(-0.5f,0.5f,0.5f);
33         //back
34         vertices[4].Set(vertices[2].x,vertices[2].y,-0.5f);
35         vertices[5].Set(vertices[3].x,vertices[3].y,-0.5f);
36         vertices[6].Set(vertices[0].x,vertices[0].y,-0.5f);
37         vertices[7].Set(vertices[1].x,vertices[1].y,-0.5f);
38         //up
39         vertices[8]=vertices[2];
40         vertices[9]=vertices[3];
41         vertices[10]=vertices[4];
42         vertices[11]=vertices[5];
43         //down
44         vertices[12].Set(vertices[10].x,-0.5f,vertices[10].z);
45         vertices[13].Set(vertices[11].x,-0.5f,vertices[11].z);
46         vertices[14].Set(vertices[8].x,-0.5f,vertices[8].z);
47         vertices[15].Set(vertices[9].x,-0.5f,vertices[9].z);
48         //right
49         vertices[16]=vertices[6];
50         vertices[17]=vertices[0];
51         vertices[18]=vertices[4];
52         vertices[19]=vertices[2];
53         //left
54         vertices[20].Set(-0.5f,vertices[18].y,vertices[18].z);
55         vertices[21].Set(-0.5f,vertices[19].y,vertices[19].z);
56         vertices[22].Set(-0.5f,vertices[16].y,vertices[16].z);
57         vertices[23].Set(-0.5f,vertices[17].y,vertices[17].z);
58
59         int currentCount=0;
60         for(int i=0;i<24;i=i+4)
61         {
62             triangles[currentCount++]=i;
63             triangles[currentCount++]=i+3;
64             triangles[currentCount++]=i+1;
65
66             triangles[currentCount++]=i;
67             triangles[currentCount++]=i+2;
68             triangles[currentCount++]=i+3;
69
70         }
71
72         mf.mesh.vertices=vertices;
73         mf.mesh.triangles=triangles;
74
75     }
76 }

在这里定义vertices数组存储顶点坐标信息,定义triangles数组存储三角形顶点索引。但是这个Mesh不包含normals和uv信息,所以显示出来的正方体是无纹理贴图,并且不能反应环境光照的。

3.冗余的顶点坐标

正方体6个面,每个面由2个三角形组成,所以共需要36个三角形顶点索引。但是正方体只有8个顶点,为什么需要24个顶点坐标数据呢?

答案是:Unity3D的Mesh.triangles是三角形索引数组,不仅依靠这个索引值索引三角形顶点坐标,而且索引纹理坐标,索引法线向量。即正方体的每个顶点都参与了3个平面,而这3个平面的法线向量是不同的,该顶点在渲染这3个平面的时候需要索引到不同的法线向量。而由于顶点坐标和法线向量是由同一个索引值triangles[Index]取得的,例如,根据triangles[0],triangles[14],triangles[17]在vertices中索引到的顶点都为(0.5,-0.5,0.5),但是在normals中索引到的法向量值各不相同。这就决定了在正方体中一个顶点,需要有3份存储。(如果你需要创建其它模型,需要根据实际情况决定顶点坐标的冗余度。实质上顶点坐标的冗余正是方便了法线坐标、纹理坐标的存取。)

4.三角形的渲染

准则:三角形有两面,正面可见,背面不可见。三角形的渲染顺序与三角形的正面法线呈左手螺旋定则

这就决定了,如果我们需要渲染如下一个正方形面,那么就需要保证组成这个正方形的两个小三角形的正面法线都是指向屏幕外的。

我在程序中的顶点顺序为,三角形1: 0->3->1,三角形2: 0->2->3 。

 1 int currentCount=0;
 2 for(int i=0;i<24;i=i+4)
 3 {
 4         //三角形1
 5     triangles[currentCount++]=i;
 6     triangles[currentCount++]=i+3;
 7     triangles[currentCount++]=i+1;
 8     //三角形2
 9     triangles[currentCount++]=i;
10     triangles[currentCount++]=i+2;
11     triangles[currentCount++]=i+3;
12 }

这段代码保证了正方体的6个面,12个三角形的都正确被渲染(正面法线朝外)。

时间: 2024-08-26 19:21:16

Unity3D 动态创建Mesh(一)的相关文章

Unity3D动态创建地形网格(一)

最近一直都在搞flash3D,好像有点对不起Unity3D的朋友们了.这次简单的写一个动态创建地形网格的脚本给大家分享一下. 这次是第一部分,仅仅实现了通过高度图动态生成地形的部分.假如以后有心情和时间,再来慢慢的补充多通道刷地形材质.动态刷地形和保存高度图等的功能吧.以前我都不喜欢公开脚本源码,都是一个个部分的单独讲解然后让朋友们自己去组合起来的,但最近时间实在是不多,所以还是直接提供源码,然后在源码上面写注释,大家自行的观看吧.源码在最下面. 首先直接把脚本拖到某物体上面,运行,就会出现了上

【Unity3D】【NGUI】Atlas的动态创建

NGUI讨论群:333417608 NGUI版本:3.6.5 1.参见SZUIAtlasMakerRuntimeTest设置相应的值以上值需要提前设置好 2.没有检查是否atlas能够正确创建,自己可以改,加入返回值 3.代码都是在NGUI里面拷贝出来的,只是进行改动,没有新代码 4.适用与那种从网上下图片,之后还不想用UITexture的人,但是还是建议用UITexture如果drawcall不是问题的话 5.自己以后更新按我的方式改改就可以 6.动态创建速度较慢,建议在游戏启动的时候运行 7

【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源(当然你也可以从官网下载). ========================================== 分割线 ========================================== 写在前面 我们已经学了很多关于反射的内容,但是我们现在的反射并不能实时反射,即当反射物体移动时它们不

于Unity3D动态创建对象和创建Prefab三种方式的原型对象

u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject orignal) 需要的对象为原型. 文提供三种方式获得prefab对象. 方式一:使用脚本的public字段 直接在Project视图里找到做好的prefab,将其拖拽到指定脚本的指定public GameObject 字段. 方式二:Resource类 1.在Assets目录下的任何位置创建一个名为resources的目录.将做好的prefab放到这个目录下,p

unity3d通过代码动态创建销毁游戏对象

只能动态创建内部提供的游戏对象,代码如下: //按下C后创建 if (Input.GetKeyDown (KeyCode.C)) { GameObject s1 = GameObject.CreatePrimitive (PrimitiveType.Sphere);//创建 s1.name = "qiu";//命名 s1.GetComponent<MeshRenderer> ().material.color = Color.red;//网格渲染器 s1.transform

unity3d UGUI动态创建窗口获取窗口大小的问题

    private IEnumerator RefreshProcess(Vector2 worldPosition)     {         this.Renders();         yield return null;         yield return null;         mRootWidth = (mRoot as RectTransform).rect.width;         mrootHeigh = (mRoot as RectTransform).

Unity3D动态地形网格一

最近一直都在搞flash3D,好像有点对不起Unity3D的朋友们了.这次简单的写一个动态创建地形网格的脚本给大家分享一下.        这次是第一部分,仅仅实现了通过高度图动态生成地形的部分.假如以后有心情和时间,再来慢慢的补充多通道刷地形材质.动态刷地形和保存高度图等的功能吧.以前我都不喜欢公开脚本源码,都是一个个部分的单独讲解然后让朋友们自己去组合起来的,但最近时间实在是不多,所以还是直接提供源码,然后在源码上面写注释,大家自行的观看吧.源码在最下面.更多内容,请访问狗刨学习网http:

Unity3D 动态改变地形

直接获取TerrainData进行修改即可 using System.Collections; using UnityEngine; using UnityEditor; public class DynamicCreateTerrain : MonoBehaviour { public TerrainData terrainData; private float[,] heightsBackups; void Start() { //var terrain = CreateTerrain();

Unity3D动态对象优化代码分享

具体解释请仔细看注释里已经讲解的很细致了,这里就不多废话了 代码如下: using UnityEngine; using System.Collections; using System.Collections.Generic; /// <summary> /// 动态对象优化 /// </summary> public class DynamicOptimization : MonoBehaviour { // Use this for initialization void S