Unity Mesh 初体验

什么是Mesh

Mesh是Unity中的一个组件,称为网格组件。通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而一个复杂的多边形,实际上是由多个三角面拼接而成。所以一个3D模型的表面是由多个彼此相连的三角面构成。三维空间中,构成这些三角面的点以及三角形的边的集合就是Mesh。如下图所示:

mesh.png

所以建模型就是就是要画一些列的三角形,而定位一个三角形就是只需要3个顶点而已。很简单哦。

比如我们要画一个五边形,如下:

demo1.png

它有五个顶点,但是在Unity中是通过把它转换成一系列的三角形来绘制的。所以我们需要想一想用几个三角形通过什么样的组合才能拼成这个五边形呢。

我们可以由(1, 2, 3), (1, 3, 4)和(1, 4, 5)三个三角形组成,

demo2.png

也可以由(2, 1, 5),(2, 4, 5) 和(2, 3, 4)三个三角形组成。

demo3.png

组成同一个形状的三角形排列方案可以有很多种,但是并不是所有的方案都能组合成我们希望的图形,比如下面这个:

demo4.png

在Unity Mesh这个类中,数组mesh.vertices就是用于存储三角形顶点坐标。当顶点数超过3个的时候,我们连接点的顺序不同,就会绘制出不同形状的图形,所以我们必须要获得我们想要的连接点的顺序。数组mesh.triangles就是用来记录连接三角形的顺序的。由于每绘制一个三角形需要知道其三个顶点的顺序,那么绘制n个三角形就需要知道3*n个点的顺序。即数组mesh.triangles的长度是3的倍数。

手写代码创建Mesh

为了简单,我们先来学习下如何用代码创建一个三角形Mesh。

public class MeshDemo : MonoBehaviour
{
        // Use this for initialization
        void Start ()
        {
            this.GetTriangle ();
        }

        // Update is called once per frame
        void Update ()
        {

        }

        public GameObject GetTriangle ()
        {
            GameObject go = new GameObject ("Triangle");
            MeshFilter filter = go.AddComponent ();

            // 构建三角形的三个顶点,并赋值给Mesh.vertices
            Mesh mesh = new Mesh ();
            filter.sharedMesh = mesh;
            mesh.vertices = new Vector3[] {
                new Vector3 (0, 0, 1),
                new Vector3 (0, 2, 0),
                new Vector3 (2, 0, 5),
            };

            // 构建三角形的顶点顺序,因为这里只有一个三角形,
            // 所以只能是(0, 1, 2)这个顺序。
            mesh.triangles = new int[3] {0, 1, 2};

            mesh.RecalculateNormals ();
            mesh.RecalculateBounds ();

            // 使用Shader构建一个材质,并设置材质的颜色。
            Material material = new Material (Shader.Find ("Diffuse"));
            material.SetColor ("_Color", Color.yellow);

            // 构建一个MeshRender并把上面创建的材质赋值给它,
            // 然后使其把上面构造的Mesh渲染到屏幕上。
            MeshRenderer renderer = go.AddComponent ();
            renderer.sharedMaterial = material;

            return go;
        }
}

代码比较简单,里面关于MeshFilter和MeshRenderer,以及Shader相关的知识,这部分我另外会单独介绍,大家可以先关注Mesh相关的部分。

下面我们再来创建一个稍微复杂一点的五边形。

public GameObject GetPentagon ()
{
    GameObject go = new GameObject ("Pentagon");
    MeshFilter filter = go.AddComponent ();

    Mesh mesh = new Mesh ();
    filter.sharedMesh = mesh;
    mesh.vertices = new Vector3[] {
        new Vector3 (0, 0, 0),
        new Vector3 (0, 2, 0),
        new Vector3 (2, 0, 0),
        new Vector3 (2, -2, 0),
        new Vector3 (1, -2, 0),
    };

    mesh.triangles = new int[9] {0, 1, 2, 0, 2, 3, 0, 3, 4};

    mesh.RecalculateNormals ();
    mesh.RecalculateBounds ();

    Material material = new Material (Shader.Find ("Diffuse"));
    material.SetColor ("_Color", Color.yellow);

    MeshRenderer renderer = go.AddComponent ();
    renderer.sharedMaterial = material;

    return go;
}

代码也很简单,不再废话。大家可以自己动手试试看,改变mest.triangles中三角形的顺序,看看会产生什么不同的结果。

Mesh是Unity内的一个组件,称为网格组件。3D网格是Unity中最重要的图形元素。在Unity中存在多种组件用于渲染标准网格或者蒙皮网格、拖尾或者3D线条。

在Unity-》Component-》Mesh组件内,有Mesh Filter,Text Mesh, Mesh Render三个子项。在圣典中可以看到,有四项内容:

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

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

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

梳理一下内容,大概就是Unity中的对象就是GameObject,每个GameObject都可以有一个MeshFilter组件(也可以没有),该组件又有Mesh属性(这个一定有),而该属性又有个Ver贴上,也就是一个Vector3数组,储存着顶点信息。

网格(Mesh)对象拥有顶点及其相关数据(法线和UV坐标)和三角形属性的属性。顶点可以任何顺序提供,但是法线和UV数组必须有序,这样索引均与顶点对应(即法线数组的元素0提供顶点0的法线,等等)。顶点为Vector3,代表对象局部空间的点。法线为标准化的Vector3,再一次在本地坐标中代表方向。UV指定为Vector2,但由于Vector2类型没有成为U和V的字段,因此也就相应的将其转换为了X和Y。

三角形指定为在顶点数组中充当索引的整数三元组。数组不使用特殊类类表示三角形,而只是一个简单的整数指数列表。每一个三角形都是以三个为一组,因此,前三个元素定义为第一个三角形,后面三个元素定义为第二个三角形,并依此类推。

三角形的一个重要细节就是拐角处顶点的顺序。尽管从哪个拐角开始并不重要,但顶点应予以排序,这样当俯视三角形的可见外表面时,各个拐角会按顺时针转动。

此处也应该知道了UV坐标表示的是什么。

抓取百度百科的信息:

“UV”这里是指u,v纹理贴图坐标的简称(它和空间模型的X, Y, Z轴是类似的). 它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面.

扯到UV坐标,想起来有人问的材质,贴图和纹理有什么区别。其实,除了看到Textures文件夹内都是图形,和Materials文件夹内都是材质球外,我也不知道这三者有什么区别。对了,材质球可以根据光照、贴图、纹理进行生成,然后扔给GameObject的Render组件里的Material属性。

知乎上的回答如下:

整个 CG 领域中这三个概念都是差不多的,在一般的实践中,大致上的层级关系是:
材质 Material包含贴图 Map,贴图包含纹理 Texture。

纹理是最基本的数据输入单位,游戏领域基本上都用的是位图。此外还有程序化生成的纹理 Procedural Texture。

贴图的英语 Map 其实包含了另一层含义就是“映射”。其功能就是把纹理通过 UV 坐标映射到3D 物体表面。贴图包含了除了纹理以外其他很多信息,比方说 UV 坐标、贴图输入输出控制等等。

材质是一个数据集,主要功能就是给渲染器提供数据和光照算法。贴图就是其中数据的一部分,根据用途不同,贴图也会被分成不同的类型,比方说 Diffuse Map,Specular Map,Normal Map 和 Gloss Map 等等。另外一个重要部分就是光照模型 Shader ,用以实现不同的渲染效果。

对了,如果导入的模型的网格具有蒙皮信息,Unity会自动创建一个Skinned Mesh Renderer.

注意:在使用Mesh Filter的时候必须同时提供一个Mesh Renderer组件,因为需要将其渲染出来,否则你不见他。

Text Mesh :文件过滤器,用于显示3D文字的。

Mesh Renderer :网格渲染器。用于渲染网格显示游戏对象。

Mesh Renderer的Materials可以放置多张贴图,用于显示在游戏对象的外表。

时间: 2024-08-24 10:08:06

Unity Mesh 初体验的相关文章

Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单总结一下成功安装方法: 1,Vmware Player 12.1.1-3770994(Virtual Box 老版本Win10上启动不了,新版本5.1不再支持Mac OS) 2,执行命令关闭Hyper-v服务重启:bcdedit /set hypervisorlaunchtype off (不然无法

iOS AR技术初体验,使用EasyAR示例程序的小白指南

QQ前两天的传递火炬,是我第一次直接接触到AR.(虽然之前听同事说过,因为他喜欢玩游戏,PS.3DS等等都玩过,这个技术最开始就是从这里出现的).所以感觉很有趣,就想自己也试着搞一下玩玩...下面是我的初体验. 首先搜索了一下网上有哪些支持的SDK,比较好的几个:Metaio被苹果收购.Vuforia被高通(Qualcomm)卖给PTC后,相对较好的有ARToolKit.Wikitude等.不过国内也有不错的.本着能不看英文就不看英文的想法,我选择了一个国内的引擎:EasyAR. 既然选择了,就

erlang 初体验

最近测试了一下 erlang的坑... 如不出意外.... 大家第一眼看到这语法... 心里第一句一定是"我擦.这TM都是啥!!!!!" 没有变量!!! 没有结构体!!! 没有循环!!! 好吧,至少我是这样想的. 找了半天..连个if也不知道怎么写.. 这记录一些基本常识.. -module(module_name)  %%定义模块 括号内的要和文件名相同. -export([fun1/1 fun2/2]) %%这里是导出2个函数对外使用  函数名/参数名. 一个简单的函数定义如下 f

linux初体验

第一次听到linux这个'词语'是在一次偶然的朋友聊天中朋友提到的,之前压根没听到过'这个东西',所以我可以说是个linux的新新手,菜鸟都不算. 截至到目前,我已经开始linux系统运维学习有差不多10天时间了.在没接触linux之前,我对它的认识仅仅是:它是个计算机系统.决定学习linux系统运维之前,自我以为运维应该是对系统的一些日常维护之类的,不会很难的东西,我更希望运维是个不难的东西,我个人很笨,对难的东西可能接受的很慢,所以我愿意认为运维是很简单的,这样我就可以轻轻松松的掌握运维相关

【Spark深入学习 -15】Spark Streaming前奏-Kafka初体验

----本节内容------- 1.Kafka基础概念 1.1 出世背景 1.2 基本原理 1.2.1.前置知识 1.2.2.架构和原理 1.2.3.基本概念 1.2.4.kafka特点 2.Kafka初体验 2.1 环境准备 2.2 Kafka小试牛刀 2.2.1单个broker初体验 2.2.2 多个broker初体验 2.3 Kafka分布式集群构建 2.3.1 Kafka分布式集群构建 2.3.2 Kafka主题创建 2.3.3 生产者生产数据 2.3.4消费者消费数据 2.3.5消息的

Java8初体验(二)Stream语法详解

原文链接:http://ifeve.com/stream/ 1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel aggregate operations. 我们来解读一下上面的那句话: Stream是元素的集合,这点让Stream看起来用些类似Iterator: 可以支持顺序和并行的对原Stream进行汇聚的操作: 大家可以把Stream当成一个高级版本的

hibernate--CRUD初体验

hibernate的crud操作初体验. 看具体实例 package com.fuwh.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.annotations.GenericGenerator; @Entity publ

Oracle SQL篇(一)null值之初体验

    从我第一次正式的写sql语句到现在,已经超过10年的时间了.我写报表,做统计分析和财务对账,我一点点的接触oracle数据库,并尝试深入了解.这条路,一走就是10年,从充满热情,到开始厌倦,我不知道我还能坚持多久,未来的路,谁知道呢? 也许是该抓紧时间,做一点什么了,我不知道该开始写些什么,我从来没有在网上写东西的习惯.     先从简单的开始吧,那当然就是SQL,这是我SQL系列的第一篇,希望我能够坚持. 在Oracle数据库中,如果一个表中的列没有值的话,我们可以说是空值,比如IT员

AngularJS路由系列(3)-- UI-Router初体验

本系列探寻AngularJS的路由机制,在WebStorm下开发. AngularJS路由系列包括: 1.AngularJS路由系列(1)--基本路由配置2.AngularJS路由系列(2)--刷新.查看路由,路由事件和URL格式,获取路由参数,路由的Resolve3.AngularJS路由系列(3)-- UI-Router初体验4.AngularJS路由系列(4)-- UI-Router的$state服务.路由事件.获取路由参数5.AngularJS路由系列(5)-- UI-Router的路由