Unity网格编程学习(二)

news/2024/11/15 10:45:13/文章来源:https://www.cnblogs.com/ekros-blog/p/18397878

目录
  • 1.创建平面
  • 2.创建立方体

1.创建平面


定义平面的长、高,以及mesh的顶点、uv、法线

public int x = 3, y = 3;
private Vector3[] vertices;
private Vector2[] uvs;
private Vector3[] normals;private void Start()
{Mesh mesh = new Mesh();MeshFilter filter = this.GetComponent<MeshFilter>();filter.mesh = mesh;vertices = new Vector3[(x + 1) * (y + 1)];uvs = new Vector2[vertices.Length];normals = new Vector3[vertices.Length];mesh.vertices = GetVertices();mesh.triangles = GetTriangles();mesh.uv = uvs;mesh.normals = normals;
}

定义获取顶点数据的方法GetVertices

private Vector3[] GetVertices()
{for (int i = 0; i < x + 1; i++){for (int j = 0; j < y + 1; j++){vertices[i * (y + 1) + j] = new Vector3(i, j, 0);uvs[i * (y + 1) + j] = new Vector2((float)i / x, (float)j / y);normals[i * (y + 1) + j] = GetNormal(i);}}return vertices;
}

因为平面的长为x,高为y,所以在长上需要x+1个顶点,在高上需要y+1个顶点,通过循环创建z轴坐标为0的顶点坐标,可以得到如图所示的绘制顺序的顶点

接下来定义获取绘制顺序的方法GetTriangle

private int[] GetTriangles()
{int[] temp = new int[x * y * 6];for (int i = 0; i < x; i++){for (int j = 0; j < y; j++){int index = i * (y + 1) + j;int tempIndex = (i * y + j) * 6;temp[tempIndex++] = index;temp[tempIndex++] = index + 1;temp[tempIndex++] = index + y + 1;temp[tempIndex++] = index + 1;temp[tempIndex++] = index + y + 2;temp[tempIndex++] = index + y + 1;}}return temp;
}

因为我们的顶点是从下至上,从左至右创建的,所以要创建如图所示的三角形,我们需要从左下角的(0,0)顶点开始向上遍历顶点,在这里我将以如图所示的方向进行三角形的绘制,因此我们只需要遍历图中标蓝的顶点便可以创建整个平面

通过观察可以发现,一号三角形的创建需要依次通过顶点0,1,4,而2号三角形的创建则需要通过顶点1,5,4

我们从y轴开始,得到第一个顶点的编号index以及数组中元素的下标tempIndex,不难发现一号三角形的绘制顺序是index,index+1,index+y+1,二号三角形的绘制顺序是index+1,index+y+2,index+y+1
通过循环遍历了所有需要遍历的顶点后,我们也已经将所有三角形的绘制顺序依次存入了数组temp中,进行绘制即可得到如图所示的平面

由于我们在GetVertices方法中就已经使用了uvs[i * (y + 1) + j] = new Vector2((float)i / x, (float)j / y);来获取uv数据,所以直接为平面添加uv贴图即可得到如图所示的效果

通过这段代码,我们将顶点的坐标标准化到(0,1)中,以此来与UV贴图进行对应
接下来定义获取法线数据的方法GetNormals

private Vector3 GetNormal(int y)
{if (y % 2 == 0){return Vector3.up;}else{return Vector3.down;}
}

我们在GetVertices方法中通过normals[i * (y + 1) + j] = GetNormal(i);语句向GetNormal方法传参,如果是奇数列则返回Vector3.up,如果是偶数列则返回Vector3.down,因此我们可以得到如下图所示的效果

在这个光源下up方向的顶点受到更多的光照,而down方向的顶点则接收到较少的光照

2.创建立方体


要创建一个基本的正方体,我们应该需要8个顶点,6个面,每个面有两个三角形,所以我们需要定义8个顶点信息并绘制12个三角形
我们先进行正方体底面的创建,我们以原点作为正方形的中心点,可以得到正方形底面的四个点的坐标为(-0.5, -0.5, -0.5),(0.5, -0.5, -0.5),(-0.5, -0.5, 0.5),(0.5, -0.5, 0.5)
绘制顶点后如图所示

接下来进行面的绘制

依次定义顶面的四个顶点的坐标后,顶点以及底面的绘制方向如图所示

对6个面依次进行绘制后即可得到一个基本的正方体

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

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

相关文章

如何在极狐GitLab中添加 SSH Key?

本文分享如何生成 SSH Key 并添加到极狐GitLab 中,然后用 SSH Key 进行代码拉取。 **极狐GitLab 是 GitLab 在中国的发行版,可以一键私有化部署,对于中国开发者更友好。详细安装步骤可以查看官网 https://dl.gitlab.cn/xed81vsc **。 SSH Key 对于通过 ssh 来进行极狐GitLab…

python 十进制换为二进制 高位补零

参考:https://www.cnblogs.com/zy740/p/11904185.html python 十进制转换为二进制 高位补零a = 2b = {:08b}.format(a)输出结果为八位二进制,且高位补零若为a = 2b = {:8b}.format(a)输出结果为八位二进制,但高位不补零

vue3 常用的几种组件通讯方式

vue3 常用的几种组件通讯方式,大致如下Props/Emit Pinia 事件总线(mitt) Provide/Inject 浏览器本地存储 1. Props / Emit 注释:prop属性名称 / 方法名称的格式,采用 camelCase 与 kebab-case。1.1 props (1)上游组件设置 prop 值(通过 v-bind 或 冒号) 或者 (2)下…

巧手打字通-在线打字网站,终于来啦

儿子开信息课了,要练习电脑打字了 上个学期,上小学的孩子回家跟他妈妈说:“妈妈,我要学习打字,我们学校上信息课了。” 孩子妈妈听了这诉求,就把笔记本电脑拿了出来,打开了一个word文档,把电脑推到孩子面前,来,好好练习吧,加油! 过了十分钟,我来到孩子面前,看到了…

CentOS安装MySQL8教程

官方地址: https://dev.mysql.com/downloads/mysql/ 选择版本前需先看一下服务器的 glibc 版本 ldd --version上传 将下载好的 tar 包上传到服务器上,这里演示上传到了 /usr/local/ 文件夹下 (也可以自定义位置)解压 tar -Jxvf mysql-8.0.39-linux-glibc2.17-x86_64.t…

jQuery CSS 浏览器滚动到顶部固定左侧栏

<script>$(document).ready(function() {var div = $(#leftNav_2024925); // 替换为你的 div 的 IDvar divTop = div.offset().top; // 获取 div 顶部的位置$(window).scroll(function() {var scrollTop = $(this).scrollTop(); // 获取当前滚动条的位置if (scrollTop &g…

ProComponents——ProForm,设置初始值后,点击【重置】按钮,值已清除但页面未更新

我的问题 umi+antd,使用ProComponents的QueryFilter表单进行列表筛选,首页有个进入列表的快捷跳转,会筛选列表状态(在线1/离线0)。 设置筛选状态初始值为1后,点击【重置】按钮: 1.打印初始值1已清除,但页面上未更新,仍显示筛选在线状态 2.点击2次【重置】按钮,页面才…

Rust 中的关键字以及示例

Rust 中的关键字、保留字以及对应的示例1. 常见关键字as: 用于类型转换,例如将一个值从一种类型转换为另一种类型。let x: i32 = 42; let y: u8 = x as u8;break: 用于提前退出循环。for i in 0..10 {if i == 5 {break;} }const: 定义一个常量,常量的值在编译时就确定,不会在…

跨域——应对浏览器同源策略的一种方案

理解跨域,首先需要理解同源策略 (Same origin policy)。 何为源origin

LigerUI 中的 Grid (ligerGrid) 合并单元格

在网上搜索了很都都没有正确的方法实现 合并单元格, LigerGrid 不像 EasyUI 中的 Grid 可以直接 合并单元格。 我化了点时间,解决了, 就分享给大家, 我就不做详细的注释, 只有有一定基础的都可以看懂, 菜鸟就自己去补习吧。<div id="maingrid" style="…

linux系统下各种日志文件的介绍,查看,及日志服务配置

转载于https://zhuanlan.zhihu.com/p/298335887 ,侵权删! linux系统日志文件的详细介绍 日志文件的作用 日志文件用于记录linux系统的各种运行信息的文件,相当于linux主机的日记,不同的日志文件记载了不同类型的信息,如Linux内核消息、用户登录事件、程序错误等。. 日志文件…