# MakeAModelFrom-code **Repository Path**: asiworld/MakeAModelFrom-code ## Basic Information - **Project Name**: MakeAModelFrom-code - **Description**: No description available - **Primary Language**: C# - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2020-02-25 - **Last Updated**: 2022-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 代码制作模型的教程 > git地址:https://gitee.com/asiworld/MakeAModelFrom-code > > csdn博客地址:https://blog.csdn.net/JianShengShuaiest > > bilibili地址:https://space.bilibili.com/15766978 ## 简介 大家好 我是谢斯,今天给大家做一个关于,<代码制作模型的教程> 如何通过代码来制作一个我们想要的模型 通常我们所见到的模型,是maya或者3dmax制作并导出的fbx文件,而对于一些特殊的客户要求,这种模型无法满足条件 解决这类多变的形状的模型,如通过变化一些参数使得模型变化,这时使用maya/3dmax的模型就很难解决问题,我们需要通过写代码的方式来制作一个我们需要的模型. ## 下面对基础知识进行讲解 首先引入的是三个类型 **Mesh** **网格**:模型的网格,建模就是建网格。 **Mesh Filter** **网格过滤器:** 内包含一个Mesh组件,可以根据MeshFilter获得模型网格的组件,也可以为MeshFilter设置Mesh内容。 **Mesh Renderer** **网格渲染器:** 是用于把网格渲染出来的组件。MeshFilter的作用就是把Mesh扔给MeshRender将模型或者说是几何体绘制显示出来。 ![说明2](README.assets/说明2.png) 上面的基础讲解可以看出主要的信息都在Mesh中,我们要制作模型也就是要自己做一个mesh然后放到Mesh Filter中就可以了. 下面我们再细致的了解一下mesh ## Mesh的属性: **顶点坐标(vertex****)**顶点坐标数组存放Mesh的每个顶点的空间坐标,假设某mesh有n个顶点,则顶点坐标的的size为n **法线(normal****)**法线数组存放mesh每个顶点的法线,大小与顶点坐标对应,normal[i]对应顶点vertex[i]的法线 **纹理坐标(uv****)**它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面. uv[i]对应vertex[i] **三角形序列(triangle****)**每个mesh都由若干个三角形组成,而三角形的三个点就是顶点坐标里的点,三角形的数组的size=三角形个数* 3,三角形的顶点顺序必须是顺时针,顺时针表示正面,逆时针表示背面,而unity3d在渲染时默认只渲染正面,背面是看不见的。(也就是左手定责) 上面讲的都很理论下面我就用更白的话和更具体的实例来让大家明白. ## 画板 首先让我们来了解一下模型的本质,模型实际上就是点组成的.两个点连接起来就是一条线,而三个点互相连接就是一个面了,根据这三个点的连接顺序,我们就能得到一个方向,这个就是渲染的方向,也就是我们常说的unity的面,而unity的面是单面,而不是双面的,渲染的面的方向是有规则的,就是左手定则(我们看起来是顺时针 表示正面,逆时针 表示背面,正面是可以看到的,而背面是不可以被看到的,所以对于unity中的模型,其最基本的就是点,可以说对于模型来说所有的信息都记录在点上. ## 通过代码制作模型的一个demo 在SCRIPT6中的代码可以当做是一个模板 private Vector3 Faxian(Vector3 a, Vector3 b, Vector3 c, int index = 0) private void AddCorss(ref Dictionary _dic_v3Normal, List _list_v3Vertices, int a, int b, int c) protected void DrawModel(ref List _list_nTriangles, ref Dictionary _dic_v3Normal, List _list_v3Vertices, int a, int b, int c, int d) 这三个是一起的 但是只使用DrawModel就可以,其他的函数是辅助这个函数的 ![说明](README.assets/说明.png) ## 工程简介 ### 场景1 下面我分6步来来给大家逐步深入的学习 我们先来设置三个点A(r) B(g) C(b) 然后把三个点按照A->C->B>A的顺序连接起来 根据连接的方向,我们可以得到这是一个逆时针,那么现在我们看到的这个面就是反面,在unity中以现在的视角是看不到面的 但是我们按照A->B->C->A的顺序来连接起来,通过左手定责,它就是一个朝向我们的面了,在unity中就可以看得到. 并且我们加入一个任意模型以这个模型做基础来修改他的点线面来制作 从图中可以很清晰的看出来,摄像机的那个面是顺时针方向,所以可以看到面,而scene视图中是正好相反的,所以看不到面 以上我已经介绍了简单的制作一个面的概念,下面我们来扩展成体的概念 ![说明3](README.assets/说明3.png) ### 二场景 体就是多个面,多个三角形,多个角度,我们用一个简单的一个带90度折角的模型来展示一下如图 其中ABC 和ACD面垂直,现在我们通过代码来实现这个制作 现在我们发现这个面已经有了,但是没有菱角,没有立体感 ![说明4](README.assets/说明4.png) ### 三场景: 这就要引入我们的新的概念,法线概念,有了法线才有立体感,法线就是这个面的朝向的方向,而这些信息并不记录在线和面上,我上面说过,模型的信息都以点为基础记录.所以法线的信息也记录在点上. 而这样就会出现矛盾,上面的两个面 四个点,而A点和C点在两个面上,一个点只可以有一个法线呀,所有这里我们要做的是一个面上的点我们要互相独立.也就是说我们做两个面的时候需要使用6个点 这样就可以达到每个点都有自己的法线方向.A点和C两个点就需要有两套分别对应的是两个面,直接上代码,看代码就马上理解 这样我们就因为添加了六个点的法线方向而让这两个面有了棱角,有了立体的感觉 ![说明5](README.assets/说明5.png) ### 四场景: 当然还有一个概念是UV的概念,UV是一个vector2数组,对于比较复杂的图形我们的UV没法很好的设置,原因是设置UV的对应值非常复杂,所以我在这里就简单的介绍一下,实用性并不高,但说不定要用的, 首先UV为什么是vector2呢,是因为对应的是一张1*1贴图,我们随便引入一个贴图 我们看到,加上贴图后,正常的cube是已经有的了 为什么我们代码生成的模型的没有贴图,因为我们UV点都是空的或者说都是原点,现在我么把这个UV加进去 同样UV点和vertices是一一对应的. ,然后把上面的模型ACD面的不加UV,只把A的这个加UV 这样我们的这个面就加入了贴图,原因就是有了UV ![说明6](README.assets/说明6.png) ### 五场景: 下面我们把ACD面也加入UV,为了让大家方便学习,换一些值, 看了上面的两个例子,这里简单的总结一下,就是UV的点和vertices 也是一一对应的,对应的vector2的值是(0,0)到(1,1)的一张贴图的对应点,然后贴图就可以展到我们通过代码绘制的面上了. ![说明7](README.assets/说明7.png) ### 六场景: 最后我们制作一个圆柱体,不需要贴图的,但是要有法线的,为了让大家理解制作的过程,我会在代码中加入延时和演示的功能, 这个例子我只演示一遍,我不给大家做代码的分析,里面是没有难点的,至少我认为对于正常的高中生水平来说应该也是可以理解的,只要多看几次代码就可以理解透了. ![说明8](README.assets/说明8.png) ## 结束 以上就是所有的教学内容, 以上所有的代码已经发到github上的,地址在视频下方是有的,有兴趣的话可以下载.