首页 > 编程语言 >Unity网格编程学习(二)

Unity网格编程学习(二)

时间:2024-09-05 15:03:10浏览次数:12  
标签:index Vector3 int 编程 0.5 网格 ++ Unity 顶点

目录

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个面依次进行绘制后即可得到一个基本的正方体

标签:index,Vector3,int,编程,0.5,网格,++,Unity,顶点
From: https://www.cnblogs.com/ekros-blog/p/18397878

相关文章

  • 软件测试学习笔记丨Linux-Bash编程语法
    本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/32091一、Bash编程基础1.1变量1.1.1语法Variable_name=value1.1.2变量定义的规则变量名区分大小写,a和A为两个不同的变量;变量名可以使用大小写字母混编的形式进行编写;变量名与值之间的=两侧都不能有空格;在读取或打印变量......
  • Shell编程:文本处理器(cut、split、paste、eval 命令)
    文章目录文本处理器2cut命令-快速裁剪语法格式常用选项示例split命令-文件拆分语法格式常用选项示例paste命令-文件合并语法格式常用选项示例eval命令-变量扫描器工作原理示例文本处理器2本章讲解grep、sort、uniq、tr、cut、split、paste命令等。这......
  • Shell编程:文本处理器(grep、sort、uniq、tr 命令)
    文章目录文本处理器1grep命令-搜索文本语法格式常用选项示例sort命令-行排序语法格式常用选项示例uniq命令-快捷去重语法格式常用选项示例tr命令-字符替换删除语法格式常用选项参数示例文本处理器1本章讲解grep、sort、uniq、tr、cut、split、paste命......
  • C++和Python混合编程——C++调用Python入门
    大纲代码结构初始化Python解释器获取GIL为什么需要GIL?GIL的影响导入Python模块并执行代码释放GIL终止Python解释器完整代码编译执行结果项目地址在《C++和Python混合编程——Python调用C++入门》一文中,我们熟悉了Python调用C++编译的动态库的方法。但是作......
  • Java接口使用指南:开启高效编程之门
    在Java编程世界中,接口是实现模块间通信的一种核心机制。它们定义了一组方法规范,允许不同的类或系统按照统一的方式进行交互。随着互联网服务的兴起,API(应用程序编程接口)成为了Java开发者必须掌握的技能之一。本文将为您详细介绍如何在Java中使用API接口,以及如何通过它们提升开发效......
  • 12 Python面向对象编程:运算符重载
    本篇是Python系列教程第12篇,更多内容敬请访问我的Python合集在理解运算符重载之前我们已经知道了什么是方法重载,方法重载就是子类继承父类并且定义了一个和父类一样的方法。知道了什么是重载,也知道了什么是运算符(加减乘除等),那么运算符重载也很好理解了,其实就是在......
  • 13 Python面向对象编程:装饰器
    本篇是Python系列教程第13篇,更多内容敬请访问我的Python合集Python装饰器是一种强大的工具,用于修改或增强函数或方法的行为,而无需更改其源代码。装饰器本质上是一个接收函数作为参数的函数,并返回一个新的函数。装饰器的用途包括日志记录、性能测试、事务处理、缓......
  • 12 Python面向对象编程:运算符重载
    本篇是Python系列教程第12篇,更多内容敬请访问我的Python合集在理解运算符重载之前我们已经知道了什么是方法重载,方法重载就是子类继承父类并且定义了一个和父类一样的方法。知道了什么是重载,也知道了什么是运算符(加减乘除等),那么运算符重载也很好理解了,其实就是在类里面......
  • 13 Python面向对象编程:装饰器
    本篇是Python系列教程第13篇,更多内容敬请访问我的Python合集Python装饰器是一种强大的工具,用于修改或增强函数或方法的行为,而无需更改其源代码。装饰器本质上是一个接收函数作为参数的函数,并返回一个新的函数。装饰器的用途包括日志记录、性能测试、事务处理、缓存、权......
  • 《C++中的反射机制:开启高级编程之门》
    一、引言在现代编程中,反射机制是一种强大的工具,它允许程序在运行时检查和操作对象的结构和行为。虽然C++语言本身并没有内置的反射机制,但通过一些技巧和技术,我们可以在C++中实现类似的功能。本文将深入探讨如何在C++中实现反射机制,以及它在实际编程中的应用。二、什么......