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 update
    void Start()
    {
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        if (meshFilter != null)
        {
            Mesh mesh = meshFilter.sharedMesh;
            Debug.Log("Vertex Count: " + mesh.vertexCount);
        }
    }
}

运行:

可以看到,默认的 Cube 有 24 个顶点,而我生成的立方体只有 8 个顶点,两个构建方式应该不一样。

其实解决光影的问题也很简单,改下材质的类型,也是可以解决光影问题的

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>();
        //创建无光影材质
        Material material = new Material(Shader.Find("Unlit/Color"));
        //设置材质颜色为白色
        material.color = Color.white; 
        meshRenderer.material = 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;
    }
}

效果:

结束

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

end

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Xen Server 8 Install

Xen Sevrer 前言 XenServer&#xff08;以前称为 Citrix Hypervisor&#xff09;是业界领先的平台&#xff0c;实现了经济高效的桌面、服务器和云虚拟化基础结构。XenServer 支持任意规模或类型的组织整合计算资源&#xff0c;以及将计算资源转换为虚拟工作负载&#xff0c;从…

YOLOv7原创独家改进: 小目标 | CAMixing:卷积-注意融合模块和多尺度提取能力 | 2024年4月最新成果

💡💡💡本文独家改进:CAMixingBlock更好的提取全局上下文信息和局部特征,包括两个部分:卷积-注意融合模块和多尺度前馈网络; 💡💡💡红外小目标实现涨点,只有几个像素的小目标识别率提升明显 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特…

Java NIO Selector选择器源码分析

文章目录 前言Selector类结构Selector抽象类AbstractSelectorSelectorImplWindowsSelectorImpl三种SelectionKey集合 前言 Java NIO&#xff08;New I/O&#xff09;的Selector选择器是一个用于多路复用&#xff08;Multiplexing&#xff09;的I/O操作的关键组件。它允许一个单…

JVM基础篇

初识JVM Java虚拟机的组成 字节码文件 i与1 javap ideajclasslib arthas(线上运行的)

无问芯穹 MaaS AI 平台公测免费试用笔记:二

上一篇笔记中&#xff0c;聊过了无问芯穹的 MaaS 服务中的“虚拟机”产品。本篇文章来聊聊最近宣传中提到的大手笔免费百亿 Token 用量的“大模型服务平台” 吧。 分享下这个支持异构芯片推理的国产 “Replicate”、模型市场服务使用的经验和小技巧。 写在前面 本篇文章根据…

openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint

文章目录 openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint254.1 功能描述254.2 语法格式254.3 参数说明254.4 示例 openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint 254.1 功能描述 指明子链接块的名称。…

HarmonyOS NEXT应用开发之@Provide装饰器和\@Consume装饰器:与后代组件双向同步

Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provide装饰的变…

JVM入门到精通一篇就够了

JVM入门到精通一篇就够了 一、JVM运行时数据区域1.程序计数器2.虚拟机栈2.1 局部变量表2.2 关于局部变量表的一些思考2.3 操作数栈2.4 动态连接(Dynamic Linking)2.5 返回地址(Return Address) 3. 本地方法栈(Native Stack)4. 虚拟机堆(Heap)4.1 新生代4.2 老年代4.3 新生代对象…

来个自定义的电子木鱼吧

<!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width, initial-scale1"><title>自定义木鱼</title> </head> <body style"background-…

基于DWT(离散小波变换)的图像加密水印算法,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

软件赋能新型工业化,数智培育新质生产力——第二届软件创新发展大会蓄势待发

我国正在加快培育新质生产力&#xff0c;赋能新型工业化&#xff0c;软件作为新质生产力的基石与引擎&#xff0c;发展机遇空前。武汉是中国软件产业的重要一极&#xff0c;以其独特的地理优势和坚实的产业基础&#xff0c;正逐渐成为国内外瞩目的软件产业集聚发展高地。 武汉发…

shell 批量创建用户

代码 rootlocalhost:~ 2024-04-03 15:45:03# cat create_user.sh ######################################################################### # File Name: create_user.sh # Author: eight # Mail: 18847097110163.com # Created Time: Wed 03 Apr 2024 03:…

stm32 HAL中断GPIO——2——代码部分

1HAL中中断结构 在stm32f1XX_it.c中可以看到生成的中断函数 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); 选中函数CtrlF 可调用出搜索框 搜索范围为整个项目 再点击Find Next 检索 可以找到可以找到如下函数 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) {/* EXTI li…

linux 回收站机制(笔记)

Linux下回收站机制https://mp.weixin.qq.com/s/H5Y8VRcaOhFZFXzR8yQ7yg 功能 &#xff1a;设立回收站&#xff0c;并且可定时清空回收站。 一、建议将alias rm 改成别的。 比如alias rmm &#xff0c;同时修改rm -rf ~/.trash/* 改成 rmm -rf ~/.trash/* 不然影响rm 的正常使…

高压放大器高压放大测试器的操作方式讲解

HA-30K 是一台非常实用的高电压讯号放大器&#xff0c;它具有最小的体积、最轻的重量及最简易的操作&#xff0c;非常高的电压输出(30kVp-p)等优点。 本机连续输出电压量最大值达到 30kVp-p&#xff0c;还有输出过压保护&#xff0c;当输出电压≥36kVp-p 时&#xff0c;放大器…

如何在比特币上验证ZK Proofs

1. 引言 前序博客有&#xff1a; 基于BitVM的乐观 BTC bridgeBitVM&#xff1a;Bitcoin的链下合约Bitcoin Bridge&#xff1a;治愈还是诅咒&#xff1f;BitVM2&#xff1a;比特币上的无需许可验证以比特币脚本来实现SNARK VerifierClementine&#xff1a;Citrea的基于BitVM的…

kettle介绍-Step之If field value is null

If field value is null介绍 替换NULL值步骤可以将输入流中所有字段的空值进行替换&#xff0c;也可以指定一种类型下的空值进行替换&#xff0c;还可以指定一个字段下的空值进行替换 三种替换NULL模式 所有字段空值全部替换选定字段替换指定值根据数据类型替换指定值

商家转账到零钱开通不了解决方案

商家转账到零钱是什么&#xff1f; 【商家转账到零钱】可以说是【企业付款到零钱】的升级版&#xff0c;商家转账到零钱可以为商户提供同时向多个用户微信零钱转账的能力&#xff0c;支持分销返佣、佣金报酬、企业报销、企业补贴、服务款项、采购货款等自动向用户转账的场景。…

算法学习——LeetCode力扣图论篇2(1020. 飞地的数量、130. 被围绕的区域、827. 最大人工岛)

算法学习——LeetCode力扣图论篇2 1020. 飞地的数量 1020. 飞地的数量 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相…

WorkPlus智能AI助理:定制化部署,拓展企业协作新境界

近年来&#xff0c;随着人工智能技术不断发展&#xff0c;智能助理在企业管理中发挥着日益重要的作用。其中&#xff0c;WorkPlus智能AI助理作为一款支持私有化部署的新一代智能助理软件&#xff0c;为企业内部协作场景带来了全新的可能性。通过结合企业自身的行业知识和应用场…