Unity Mesh 生成图形(二)

一、概述

Unity 的 Mesh 是用于表示三维物体的网格数据结构。它是由一系列顶点和三角形组成的网格,用于描述物体的形状和外观。

Mesh 是由顶点、三角形和其他相关信息组成的,它用于在 Unity 中创建和渲染三维对象。顶点是网格的基本构建单元,它们定义了物体的形状,每个顶点都有三维坐标和其他可选属性,如法线、 UV 坐标和颜色。三角形则是由三个顶点组成的,它们定义了网格表面的平面,形成了物体的可见表面。

Mesh 类提供了许多方法来操作顶点和三角形,例如添加、删除、移动顶点和三角形,以及调整网格的大小和形状。这些操作可以在 Unity 编辑器中进行,也可以在代码中通过使用 Unity 的 API 来实现。

使用 Mesh 可以创建各种类型的三维对象,如静态物体、动态物体、碰撞检测对象等。在 Unity 中,Mesh 还支持各种纹理和光照技术,以便更好地渲染物体的外观和效果。
 

在上一篇文章中,我介绍了 Unity 单个面 Mesh 的绘制方法,本章继续讲解 Mesh 多个面的绘制方法,参考:

Unity Mesh 生成图形(一)-CSDN博客

二、绘制立方体

Mesh 多个面的绘制,最简单的案例就是立方体了,在上一篇文章中,我用到的是 4 个顶点来绘制一个面,那个立方体 4 个面就是 8 个顶点了,先给这 8 个顶点用球型标记出来。

在场景中加入 8 个球,并给每个球设置一个颜色

对应的顶点是:

根据上图的序号,这 8 个球对应的位置是:

第1个球:0,0,0

第2个球:0,1,0

第3个球:1,0,0

第4个球:1,1,0

第5个球:1,0,1

第6个球:1,1,1

第7个球:0,0,1

第8个球:0,1,1

所以他们对应的顶点是:

//顶点坐标
Vector3[] vertices = new Vector3[]
{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),
};

虽然有了多个面,三角形的画法不变,唯一要改变的是顶点的下标,参考下图:

我们先来画第2个面试试

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面//0, 1, 2, //2, 1, 3,//第二个面2, 3, 4,4, 3, 5,};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}

由于 Unity 只渲染正面,摄像机的视角,默认指向这个渲染平面的背面,所以是看不到的,要转一下视角,效果:

知道了原理就很容易了,现在把四个面先画出来

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面0, 1, 2,2, 1, 3,//第2个面2, 3, 4,4, 3, 5,//第3个面4, 5, 6,6, 5, 7,//第4个面6, 7, 0,0, 7, 1};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}

效果:

由于后面两个面是背面,所以没渲染出来,只要把视角转到另一边,就可以看到了

现在把顶部和底部的面加上去吧

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面0, 1, 2,2, 1, 3,//第2个面2, 3, 4,4, 3, 5,//第3个面4, 5, 6,6, 5, 7,//第4个面6, 7, 0,0, 7, 1,//顶部1, 7, 3,3, 7, 5,//底部6, 0, 4,4, 0, 2};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}

底部由于需要反过来渲染,所以方向也要反着写,效果如下:

加上 着色线框 好像看的更清楚一些

但是立方体的光影好像有点问题,用 Unity 自带的 Cube 就没有这个问题。

下面创建一个立方体来看看 Unity 中的 Cube 有什么不同

添加一个脚本 Test5,并将其拖拽到 Cube 组件上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test5 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){MeshFilter meshFilter = GetComponent<MeshFilter>();if (meshFilter != null){Mesh mesh = meshFilter.sharedMesh;Debug.Log("Vertex Count: " + mesh.vertexCount);}}
}

运行:

可以看到,默认的 Cube 有 24 个顶点,而我生成的立方体只有 8 个顶点,关于光影的问题,在后面的文章中再来解决吧。

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/588844.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 设备树: 设备树节点与属性在 dtb 文件中的存储

前言 当前新版本的 Linux 内核 设备驱动框架&#xff0c;与设备树&#xff08;Device Tree&#xff09;结合密切&#xff0c;整体 设备树的设备驱动框架&#xff0c;比较的庞大&#xff0c;但又非常的经典。 一个个的 设备树解析函数&#xff0c;都是前人【智慧】的结晶&#…

go: go.mod file not found in current directory or any parent directory.如何解决?

这个错误表明你正在执行 go get 命令&#xff0c;但是当前目录或任何父目录中都找不到 go.mod 文件。这可能是因为你的项目还没有使用 Go Modules 进行管理。 要解决这个问题&#xff0c;有几种方法&#xff1a; go mod init <module-name> 其中 <module-name>…

华为OD机试 - 最大社交距离(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

基于 java + Springboot + vue +mysql 大学生实习管理系统(含源码)

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;实习管理系统的特点 &#x1f4d1;使用架构 &#x1f4da; 总体设计 &#x1f4da; 数据库设计 &#x1f4ac; 系统公告实体属性 &#x1f4ac; 单位成绩实体属性 &#x1f4ac; 学生实体属性 &#x1f4da; 系…

超市销售数据-python数据分析项目

Python数据分析项目-基于Python的销售数据分析项目 文章目录 Python数据分析项目-基于Python的销售数据分析项目项目介绍数据分析结果导出数据查阅 数据分析内容哪些类别比较畅销?哪些商品比较畅销?不同门店的销售额占比哪个时间段是超市的客流高封期?查看源数据类型计算本月…

10.图像高斯滤波的原理与FPGA实现思路

1.概念 高斯分布 图像滤波之高斯滤波介绍 图像处理算法|高斯滤波   高斯滤波(Gaussian filter)包含很多种&#xff0c;包括低通、高通、带通等&#xff0c;在图像上说的高斯滤波通常是指的高斯模糊(Gaussian Blur)&#xff0c;是一种高斯低通滤波。通常这个算法也可以用来模…

02 - 全加器和加法器

---- 整理自B站UP主 踌躇月光 的视频 1. 全加器 用门电路实现两个二进制数相加并求出和的组合线路&#xff0c;称为一位全加器。一位全加器可以处理低位进位&#xff0c;并输出本位加法进位。全加器比半加器多了一位进位。 1.1 实验 1&#xff1a;通过两个半加器设计全加器 1.…

【游戏漏洞】逆向基础之进制

本文给大家讲解我们日后逆向学习和实践过程中息息相关的一些重要基础 我们要讲解的是 例如 111在什么时候是正确的&#xff1f; OD&#xff0c;CE&#xff0c;IDA等工具为什么都是16进制&#xff1f; 计算机只认识0和1&#xff0c;也就2进制。 我们现实生活中常用到的是10进…

【LeetCode热题100】79. 单词搜索(回溯)

一.题目要求 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平…

Vue3+Vite Nginx部署 跨域

打包项目 webstorm打开项目之后&#xff0c;在Terminal执行打包命令 pnpm run build:prod 复制到Nginx 打包完成之后,生成的包在根目录dist&#xff0c;把dist目录拷贝到Nginx放网站目录下&#xff1a;\nginx-1.25.2\html\divided &#xff0c;dist改名了divided 修改配置…

Runes 生态一周要览 ▣ 2024.3.25-3.31|Runes 协议更新 BTC 减半在即

Runes 生态大事摘要 1、Casey 发布了 Runes 协议文档 RUNES HAVE DOCS&#xff0c;Github 代码库更新到 ord 0.17.0 版本&#xff0c;Casey 表示符文是一个“严肃”的代币协议。 2、Casey 公布了第一个硬编码的创世符文「UNCOMMONGOODS」 3、4月7日香港沙龙&#xff5c;聚焦「…

1,static 关键字.Java

目录 1.概述 2.定义格式和使用 2.1 静态变量及其访问 2.2 实例变量及其访问 2.3 静态方法及其访问 2.4 实例方法及其访问 3.小结 1.概述 static表示静态&#xff0c;是Java中的一个修饰符&#xff0c;可以修饰成员方法&#xff0c;成员变量。被static修饰后的&#xff…