zoukankan      html  css  js  c++  java
  • Unity3D之Mesh(一)绘制三角形

    前言:

    Unity自带几种简单的模型,如cube等;一般情况下,其余模型有3D建模软件生成,以合适的文件格式导入unity中;而mesh(以我目前很粗浅的了解)的一般用途就是:对现有的模型进行变形,以达到各种奇幻酷炫的表现效果。

    但是由于自己的项目需要,需要由数据(外部解释stl文件获得)按照特定情况以及要求实时地产生各种几何模型,故需要用Mesh进行建模。所以开始研究学习Mesh。


    一、引入

    3D世界中任何的面都是由三角形绘制完成的,因为任何无规则的集合图形都可以由三角形来组成。比如四边形,无论是正四边形还是无规则四边形都可以由两个三角形拼接而成。如下图,模型上的一个个小网格就是Mesh,这些Mesh有不同的三维顶点(Vector3),共同组成了一个3D模型。


    二、正文

    知识点说明:

    1.Mesh、MeshFilter、MeshRenderer关系整理

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

    MeshFilter含有一个Public成员 Mesh。

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

    2.

     Unity3D中Mesh的基本单位是三角形,故而从最基本最简单的等腰三角形开始画起。

     Mesh是Unity内的一个组件,称为网格组件。

    Mesh:是指模型的网格,建模就是建网格。细看Mesh,可以知道Mesh的主要属性内容包括顶点坐标法线纹理坐标三角形绘制序列等其他有用属性和功能。因此建网格,就是画三角形;画三角形就是定位三个点。

    Mesh Filter:内包含一个Mesh组件,可以根据MeshFilter获得模型网格的组件,也可以为MeshFilter设置Mesh内容。

    Mesh Render:是用于把网格渲染出来的组件。MeshFilter的作用就是把Mesh扔给MeshRender将模型或者说是几何体绘制显示出来。 

    它们之间的关系大概就是Unity中的对象就是GameObject,每个GameObject都可以有一个MeshFilter组件(也可以没有),该组件又有Mesh属性(这个一定有),而该属性又有顶点坐标,法线等属性。而如果GameObject里有MeshFilter,则必须要Mesh Renderer才能将此网格渲染出来,不然是看不见该网格的。


     Mesh的属性

    • 顶点坐标(vertex)
    • 法线(normal)
    • 纹理坐标(uv)
    • 三角形序列(triangle)

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

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

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

    三角形序列:每个mesh都由若干个三角形组成,而三角形的三个点就是顶点坐标里的点,三角形的数组的size = 三角形个数 * 3.     说白了:规定绘制的顺序(点连接的顺序)

    例如:某mesh有四个顶点0,1,2,3,

    V0(1, 1, 0),
    V1(-1, 1, 0),
    V2(1, -1, 0),
    V3(-1, -1, 0)

    那么它们可以组成这样的一个网格,

    tri[0] = ver[0],ver[3],ver[1],tri[1] = ver[0],ver[2],ver[3],

    注意:三角形的顶点顺序必须是顺时针,顺时针表示正面,逆时针表示背面,而unity3d在渲染时默认只渲染正面,背面是看不见的。

    那么该三角形可以表示为:

    tri  = new int[2 * 3]{0, 3, 1,   0, 2, 3};

    如何要获取第N个三角形对应的三个顶点坐标,则:v1 = tri[N*3 + 0], v2 = tri[N*3 + 1], v3 = tir[N*3 + 2]


    参照的案例(配合上述的知识点)【此事例参照他人】

    1.创建一个GameObject并添加MeshFilter以及MeshRender组件,并创建一个“CreateMesh.cs”脚本给它。

    2.获取该对象的filter组件,并创建一个mesh给它。

    3.为该mesh设置属性,这里先设置顶点,然后将三角形与顶点绑定

    using UnityEngine;
    using System.Collections;
    
    public class CreateMesh : MonoBehaviour {
    
        private MeshFilter filter;
        private Mesh mesh;
    
        // Use this for initialization
        void Start () {
            // 获取GameObject的Filter组件
            filter = GetComponent<MeshFilter>();
            // 并新建一个mesh给它
            mesh = new Mesh();
            filter.mesh = mesh;
    
            // 初始化网格
            InitMesh();
        }
        
        // Update is called once per frame
        void Update () {
        
        }
    
        /// <summary>
        /// Inits the mesh.
        /// </summary>
        void InitMesh()
        {
            mesh.name = "MyMesh";
    
            // 为网格创建顶点数组
            Vector3[] vertices = new Vector3[4]{
                new Vector3(1, 1, 0),
                new Vector3(-1, 1, 0),
                new Vector3(1, -1, 0),
                new Vector3(-1, -1, 0)
            };
    
            mesh.vertices = vertices;
    
            // 通过顶点为网格创建三角形
            int[] triangles = new int[2 * 3]{
                0, 3, 1,   0, 2, 3
            };
    
            mesh.triangles = triangles;
        }
    }
    

    效果如图:

    3.网格已经成功生成,接下来该给网格贴图了,在Inspector视图里选中Mesh Render,并拖一个材质给它,

    Mesh Render是负责渲染的,将Mesh Filter里的mesh通过自身的Materials渲染出来。

    设置完材质后,我们需要将纹理贴图与网格顶点一一对应起来,这样才能渲染出来。

    // 为mesh设置纹理贴图坐标
            Vector2[] uv = new Vector2[4]{
                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(1, 0),
                new Vector2(0, 0)
            };
    
            mesh.uv = uv;

     效果如图:

    4.mesh还有两个重要的属性,法线和颜色,这两个我不是很懂,暂时没加入,

    不过看了下自带的cube模型的mesh,每个顶点的法线好像就是设置为那个顶点所在的面的法线。

    不过肯定不是这样的,毕竟要是两个不在同一面的面共有一个顶点,那就不成立了。


    自己做的案例:(最简单粗暴地显示出一个三角形)

     1 using UnityEngine;
     2 using System.Collections;
     3 [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
     4 public class triangle_mesh : MonoBehaviour
     5 {
     6     /*
     7     creat a triangle by using Mesh 
     8      2016/11/19
     9                  ————Carl    
    10     */
    11 
    12     void Start()
    13     {
    14         MeshFilter meshfilter = new MeshFilter();
    15         meshfilter = GetComponent<MeshFilter>();
    16         Mesh mesh = new Mesh();
    17         Vector3[] vertices = new Vector3[3];
    18         vertices[0] = new Vector3(0, 0, 0);
    19         vertices[1] = new Vector3(0, 0, 1);
    20         vertices[2] = new Vector3(1, 0, 0);
    21         int[] tris = new int[3];
    22         tris[0] = 0; tris[1] = 1; tris[2] = 2;
    23         Vector2[] uvs = new Vector2[vertices.Length];
    24         for (int i = 0; i < uvs.Length; i++)
    25         {
    26             uvs[i] = Vector2.zero;
    27         }
    28 
    29         mesh.vertices = vertices;
    30         mesh.triangles = tris;
    31         mesh.uv = uvs;
    32         meshfilter.mesh = mesh;
    33     }
    34 }

    效果图:

     

    程序说明:

    1)

     

    2)

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

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

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



    总结:

    用Unity绘制三角形

    首先,creat a gameobject

    其次,挂在一个脚本,并且,添加 MeshRenderer,MeshFilter组件

    再其次:给出Mesh的: mesh.vertices = vertices;//点 mesh.triangles = tris;//索引点 mesh.uv = uvs;//纹理

    最后:meshfilter.mesh = mesh;//添加于MeshFilter组件



    【欢迎转载】

     转载请表明出处: 乐学习

  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/JLZT1223/p/6080164.html
Copyright © 2011-2022 走看看