Unity利用代码生成空心立方体(立方体挖走一个圆柱)

2023-05-16

先看效果

还未生成mesh时挖去圆柱的立方体

 

生成mesh后挖去圆柱的立方体

放代码为敬(脚本挂在空物体上即可):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class body : MonoBehaviour
{
    //the outside radius must lager than the inside one
    [Range(0, 100)] public float innerRadius;
    [Range(1, 100)] public float outsideRadius;
    [Range(1, 100)] public float outsideRadius1;
    public int blockCounts = 80;          //how many blocks that the obj will be split into?
    public float height = 10;             //the height of the obj.
    
    private float increment;
    private float currentAngle = 0;

    private MeshFilter meshFilter;

    void Start()
    {
        meshFilter = transform.GetComponent<MeshFilter>();

        GenerateMesh();

        //show the order we generate the obj.
        StartCoroutine(SequenceTest());

    }

    private void GenerateMesh()
    {
        //declare all the array we need
        List<Vector3> vertices = new List<Vector3>();
        List<Vector2> uvs = new List<Vector2>();
        List<int> triangles = new List<int>();

        //initialize the parameters
        increment = 2 * Mathf.PI / blockCounts;
        
        //Generate the vertex we need
        vertices = GenerateVertics();
        //Fill the triangles in order
        triangles = FillTriangles(vertices.Count);

        meshFilter.mesh.vertices = vertices.ToArray();
        meshFilter.mesh.triangles = triangles.ToArray();

    }

    private List<Vector3> GenerateVertics()
    {
        //The order to Generate the vertics :   choose the left bottom as the first point, and assign the id by clockwise, inside circle generate first
        //顶点标号顺序  : 以左下角为起点,以顺时针顺序给各顶点标号,从内层圆环开始

        List<Vector3> vertices = new List<Vector3>();

        //used to load the radius we have    [Use Array to help us expand the plies]
        float[] radiuses = { innerRadius, outsideRadius };
        float[] radiuses1 = { innerRadius, outsideRadius1 };
        
        //For now this code will generate the inner circle first
        for (int i = 0; i < radiuses.Length; i++)
        {
            if (i == 0)
            {
                for (int j = 0; j < blockCounts * 4; j += 4)
                {
                    //TODO : for now ,this script will generate 4 more vertices
                    Vector3 v1 = new Vector3(radiuses[i] * Mathf.Sin(currentAngle), 0, radiuses[i] * Mathf.Cos(currentAngle));
                    Vector3 v2 = new Vector3(radiuses[i] * Mathf.Sin(currentAngle), height, radiuses[i] * Mathf.Cos(currentAngle));
                    
                    //Generate next two vertices
                    currentAngle += increment;

                    Vector3 v3 = new Vector3(radiuses[i] * Mathf.Sin(currentAngle), height, radiuses[i] * Mathf.Cos(currentAngle));
                    Vector3 v4 = new Vector3(radiuses[i] * Mathf.Sin(currentAngle), 0, radiuses[i] * Mathf.Cos(currentAngle));
                    vertices.Add(v1);
                    vertices.Add(v2);
                    vertices.Add(v3);
                    vertices.Add(v4);
                }
            }
            int c = blockCounts / 4, k0 = c/2, k1 = 0, k2 = 0, k3 = 0, k4 = 0,k5 = 0;    //c = 10,正方形一个边有10个点位
            float deltaMeshdistance = radiuses1[1] / c;     //deltaMeshdistance = 3,相邻点位的距离
            if (i == 1)
            {
                if ((0.5 * c <= k0) && (k0 < c))
                {
                    for (int j = 0; j < blockCounts * 4; j += 4)
                    {
                        if ((0.5 * c <= k0) && (k0 < c))
                        {
                            Vector3 v1 = new Vector3(k5 * deltaMeshdistance, 0, radiuses1[i] / 2);
                            Vector3 v2 = new Vector3(k5 * deltaMeshdistance, height, radiuses1[i] / 2);
                            k0++;k5++;
                            Vector3 v3 = new Vector3(k5 * deltaMeshdistance, height, radiuses1[i] / 2);
                            Vector3 v4 = new Vector3(k5 * deltaMeshdistance, 0, radiuses1[i] / 2);
                            vertices.Add(v1);
                            vertices.Add(v2);
                            vertices.Add(v3);
                            vertices.Add(v4);
                        }
                    }
                }
                if ((c <= k0) && (k0 < 2 * c))
                {
                    for (int j = 0; j < blockCounts * 4; j += 4)
                    {
                        if ((c <= k0) && (k0 < 2 * c))
                        {
                            Vector3 v1 = new Vector3(radiuses1[i] / 2, 0, radiuses1[i] / 2 - k1 * deltaMeshdistance);
                            Vector3 v2 = new Vector3(radiuses1[i] / 2, height, radiuses1[i] / 2 - k1 * deltaMeshdistance);
                            k0++; k1++;
                            Vector3 v3 = new Vector3(radiuses1[i] / 2, height, radiuses1[i] / 2 - k1 * deltaMeshdistance);
                            Vector3 v4 = new Vector3(radiuses1[i] / 2, 0, radiuses1[i] / 2 - k1 * deltaMeshdistance);
                            vertices.Add(v1);
                            vertices.Add(v2);
                            vertices.Add(v3);
                            vertices.Add(v4);
                        }
                    }
                }
                if ((2 * c <= k0) && (k0 < 3 * c))
                {
                    for (int j = 0; j < blockCounts * 4; j += 4)
                    {
                        if ((2 * c <= k0) && (k0 < 3 * c))
                        {
                            Vector3 v1 = new Vector3(radiuses1[i] / 2 - k2 * deltaMeshdistance, 0, -radiuses1[i] / 2);
                            Vector3 v2 = new Vector3(radiuses1[i] / 2 - k2 * deltaMeshdistance, height, -radiuses1[i] / 2);
                            k0++;k2++;
                            Vector3 v3 = new Vector3(radiuses1[i] / 2 - k2 * deltaMeshdistance, height, -radiuses1[i] / 2);
                            Vector3 v4 = new Vector3(radiuses1[i] / 2 - k2 * deltaMeshdistance, 0, -radiuses1[i] / 2);
                            vertices.Add(v1);
                            vertices.Add(v2);
                            vertices.Add(v3);
                            vertices.Add(v4);
                        }
                    }
                }
                if ((3 * c <= k0) && (k0 < 4 * c))
                {
                    for (int j = 0; j < blockCounts * 4; j += 4)
                    {
                        if ((3 * c <= k0) && (k0 < 4 * c))
                        {
                            Vector3 v1 = new Vector3(-radiuses1[i] / 2, 0, -radiuses1[i] / 2 + k3 * deltaMeshdistance);
                            Vector3 v2 = new Vector3(-radiuses1[i] / 2, height, -radiuses1[i] / 2 + k3 * deltaMeshdistance);
                            k0++;k3++;
                            Vector3 v3 = new Vector3(-radiuses1[i] / 2, height, -radiuses1[i] / 2 + k3 * deltaMeshdistance);
                            Vector3 v4 = new Vector3(-radiuses1[i] / 2, 0, -radiuses1[i] / 2 + k3 * deltaMeshdistance);
                            vertices.Add(v1);
                            vertices.Add(v2);
                            vertices.Add(v3);
                            vertices.Add(v4);
                        }
                    }
                }
                if ((4 * c <= k0) && (k0 < 4.5 * c))
                {
                    for (int j = 0; j < blockCounts * 4; j += 4)
                    {
                        if ((4 * c <= k0) && (k0 < 4.5 * c))
                        {
                            Vector3 v1 = new Vector3(-radiuses1[i] / 2 + k4 * deltaMeshdistance, 0, radiuses1[i] / 2);
                            Vector3 v2 = new Vector3(-radiuses1[i] / 2 + k4 * deltaMeshdistance, height, radiuses1[i] / 2);
                            k0++;k4++;
                            Vector3 v3 = new Vector3(-radiuses1[i] / 2 + k4 * deltaMeshdistance, height, radiuses1[i] / 2);
                            Vector3 v4 = new Vector3(-radiuses1[i] / 2 + k4 * deltaMeshdistance, 0, radiuses1[i] / 2);
                            vertices.Add(v1);
                            vertices.Add(v2);
                            vertices.Add(v3);
                            vertices.Add(v4);
                        }
                    }
                }
            }            
        }

        return vertices;
    }

    /// <summary>
    /// 填充三角形
    /// </summary>
    /// <param name="vertCount"></param>
    /// <returns></returns>
    private List<int> FillTriangles(int vertCount)  
    {       
        List<int> triangles = new List<int>();

        //1.fill the inner && outside surface 填充内外表面
        for (int i = 0; i < vertCount - 2; i += 2)
        {
            if (i == vertCount - 2 || i == vertCount - 1)     //connect with the origin points
            {
                triangles.AddRange(GetTriangleOrder(i, i + 1, i - (blockCounts - 2), i - (blockCounts - 3)));
            }
            else if (i < vertCount / 2)
            {
                //inner circle only needs to see the inside surface
                triangles.AddRange(GetTriangleOrder(i, i + 1, i + 2, i + 3));
            }
            else
            {
                //outside surface
                triangles.AddRange(GetTriangleOrder(i + 3, i + 2, i + 1, i));
            }
        }

        //2.fill the top && bottom surface  填充顶部和底部        
        for (int i = 0, j = vertCount / 2; i < vertCount / 2; i += 2, j += 2)   //i < 160
        {
            if (i >= vertCount / 2 - 2) //i >= 156, vertCount = 320
            {
                triangles.AddRange(GetTriangleOrder(0, vertCount / 2, j, i));   //123, 341  填充顶部
                triangles.AddRange(GetTriangleOrder(i + 1, j + 1, vertCount / 2 + 1, 1));   //填充底部
                //triangles.AddRange(GetTriangleOrder(1, 161, 318, 158));   //123, 341  填充顶部
                //triangles.AddRange(GetTriangleOrder(159, 319, 160, 0));   //填充底部                
            }
            else
            {
                triangles.AddRange(GetTriangleOrder(i + 3, j + 3, j, i));
                triangles.AddRange(GetTriangleOrder(i + 1, j + 1, j + 2, i + 2));
            }             
        }           
        return triangles;
    }

    private List<int> GetTriangleOrder(int p1, int p2, int p3, int p4)     //the input must be from the left bottom corner && sort by clockwise
    {
        //use this code to return a particular order

        List<int> output = new List<int>();

        //Add first triangle
        output.Add(p1);
        output.Add(p2);
        output.Add(p3);

        //Add the second one
        output.Add(p3);
        output.Add(p4);
        output.Add(p1);

        return output;
    }

    /// <summary>
    /// 协程,网格生成过程
    /// </summary>
    /// <returns></returns>
    IEnumerator SequenceTest()
    {
        float interval = 0.01f;
        Debug.Log(meshFilter.mesh.triangles.Length);
        for (int i = 0; i < meshFilter.mesh.triangles.Length; i += 3)
        {
            Debug.DrawLine(meshFilter.mesh.vertices[meshFilter.mesh.triangles[i]], meshFilter.mesh.vertices[meshFilter.mesh.triangles[i + 1]], Color.red, 100f);

            yield return new WaitForSeconds(interval);
            Debug.DrawLine(meshFilter.mesh.vertices[meshFilter.mesh.triangles[i + 1]], meshFilter.mesh.vertices[meshFilter.mesh.triangles[i + 2]], Color.yellow, 100f);

            yield return new WaitForSeconds(interval);
            Debug.DrawLine(meshFilter.mesh.vertices[meshFilter.mesh.triangles[i + 2]], meshFilter.mesh.vertices[meshFilter.mesh.triangles[i]], Color.blue, 100f);

            yield return new WaitForSeconds(interval);

        }
    }
}

我这里用到了协程,可以看到网格的生成过程,如果想直接看到结果,改动如下:

将第27行的
StartCoroutine(SequenceTest());
改为
SequenceTest();
再将SequenceTest()函数前的IEnumerator换为 private void
删除所有yield行的代码即可

在代码中

innerRadius为圆的半径,可以自行设定

blockCounts为切割的份数,数量越大消耗的电脑性能越多

height为高度,可以自行设定

increment为圆的角度增量

网格的生成顺序如下图红色箭头所示:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity利用代码生成空心立方体(立方体挖走一个圆柱) 的相关文章

  • FTP上传文件到服务器出现连接超时,只能创建文件夹无法创建文件问题,storeFile返回false情况

    出现连接超时情况 在排除FTP能与Linux上的服务连接成功的情况下 xff0c 在代码中加入以下代码开启ftp被动模式 ftpClient enterLocalPassiveMode 开启被动模式 ftp连接方式 主动 FTP xff1a
  • Ubuntu 20 图形界面以root身份运行应用

    Ubuntu 图形界面以 root 身份运行应用 How to launch application as root from Unity Launcher 环境 ubuntu 20 10 内核 5 8 0 26 generic 问题 pu
  • Spring的配置方式

    Spring的配置方式 开发工具与关键技术 xff1a IDEA与Java 撰写时间 xff1a 2022 3 27 传统的XML配置方式 SpringXML配置bean元素相关属性 xff1a 作为 Spring 核心机制的依赖注入 xf
  • session数据保存

    1 xff0c 点击表格中的单选框 xff0c 选择商品数据 xff0c 然后点击加入所选商品 xff0c 该商品就会添加到所选商品的列表中去 2 xff0c 关于Session并不陌生 xff0c Session是另一种记录客户状态的机制
  • Ubuntu 16.04设置开机自启动脚本

    1 创建脚本 sh文件 可以在 home user Documents scripts路径下建立名为auto run test sh的文件 xff1b auto run test sh里面写上具体要做的事 xff0c 例如我这里 xff1a
  • spring详解

    Spring 详解 什么是spring Spring是一个开源框架 xff0c 它由Rod Johnson创建 它是为了解决企业应用开发的复杂性而创建的 Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情 然而 xff
  • 谁是你生命中的贵人

    谁是你生命中的贵人 谨以此文献给我一生至爱 作者 xff1a 成晓旭 版权保留 转载请保持文章完整性 最近很奇怪的发现 xff0c 生命中的人和事 xff0c 常常不是均匀而规律地分布在人生的时间轴上 xff0c 或许很长时间都平淡无奇 x
  • Android开发之使用BroadcastReceiver实时监听电量(源码分享)

    Android系统中实时的监听手机电量以及开机启动功能都是通过BroadcastReceiver组件实现的 我们能够动态注冊这个类的一个实例通过Context registerReceiver 方法或者静态注冊 xff0c 通过 lt Re
  • 爬取豆瓣网站前top250电影名称和评分保存到本地excel中(附效果图和代码)

    import requests from lxml import etree import xlwt headers 61 39 User Agent 39 39 Mozilla 5 0 Windows NT 10 0 Win64 x64
  • IDEA项目结构介绍

    文章目录 IDEA项目结构介绍一 创建project模块二 创建Module模块三 创建Package包四 创建class类五 代码测试 IDEA项目结构介绍 project xff08 项目 工程 xff09 module xff08 模
  • Uart串口通讯协议与环形队列(裸机/RTOS)

    MCU上使用的稳定Uart通讯协议 环形队列 协议的主要内容 xff1a 接收 xff1a 字节间超时判断 环形队列接收 非阻塞式接收整帧数据 接收查错 xff1b 发送 xff1a 未应答重发 span class token punct
  • 对Excel表格数据的导出

    一 xff1a 有Excel文件模板的导出 xff08 1 xff09 判断模板文件是否存在 1 先通过Server MapPath 将相对的路径转为实际的物理路径 2 然后在通过IO流判断文件是否存在 例 xff1a System IO
  • Linux命令

    基本操作 Linux关机 重启 关机 shutdown h now 重启 shutdown r now 查看系统 CPU信息 查看系统内核信息 uname a 查看系统内核版本 cat proc version 查看当前用户环境变量 env
  • AOP概念及作用详细解释

    今天学习spring的时候接触到一个新的知识以及概念AOP 老师当时讲这个知识点的时候 xff0c 并没有讲太多关于这方面的知识 xff0c 我们所学习到的知识侧重于应用 xff0c 所以对这一块的理论知识是有一点缺少 xff0c 以至于小
  • Permission denied解决办法之一

    最近在编一个小程序 xff0c 有一步需要我删除一个文件 xff0c 但当用remove 后返回值始终是 1 用了perror后提示 Permission denied xff0c 在搜索后总是找不到解决办法 xff0c 然后我感觉是需要删
  • 数脉科技:Windows server 2016的基础设置

    是否经常不会设置Windows server 2016这款服务器而苦恼呢 xff0c 现在不用怕了数脉科技一点一点耐心的来教会大家如何学会Windows server 2016的基础设置吧 xff01 一 组策略 WIN键 43 R键 xf
  • 2020-09-11

    三招你成为短视频大神 xff01 很多小伙伴对于自媒体比较眼红 xff0c 看着抖音快手上很多靠直播 靠短视频火起来的人都挣到钱了 xff0c 所以跃跃欲试 xff0c 也想在这里面分一杯羹 但是真的那么容易吗 xff1f 直播就不用说了
  • 2020-10-15

    短视频配音选材的方法 网络短视频内容花样众多 xff0c 在快手短视频或者抖音短视频上面总是能刷到很多新奇的东西 xff0c 其中给短视频配音也是一个模块 xff0c 根据剧情来即兴发挥或者编排台词都是很重要的一部分 给短视频配音又分好多种
  • 服务器处理能力,你估算正确过吗?

    服务器处理能力 xff0c 你估算正确过吗 xff1f 作者 xff1a 成晓旭 1 引题 但凡写过技术方案的都知道 xff0c 在技术方案最终落实到工程实施部署时 xff0c 必须编制出当前解决方案需要部署的IT设备及环境 xff0c 包
  • 2020-10-20

    抖音快手短剧本写作方法 看别人拍的视频拍的新鲜有趣 xff0c 但是自己就是拍不出那种效果 xff0c 其实抖音视频前期是非常好做的 xff0c 可能发一个PPT一样的几张靓照或者是逗猫咪的小视频 xff0c 就能轻松获赞数十万 但是有个词

随机推荐

  • 2020-11-02

    如何更好的制作短视频内容 xff1f 细节决定成败 xff0c 对抖音短视频尤其重要 xff0c 抖音本来就是以内容为主的短视频平台 一个短视频能火 xff0c 一个短视频不火 xff0c 相同的主题 xff0c 不同的细节 xff0c 它
  • 2020-11-24

    如何才能撰写出好的短视频文案 首先是要调起用户的共鸣 xff0c 比如以前抖音上很火的一个视频 视频拍的很简单 xff0c 就是坐在出租车上拍摄的一些 xff0c 呼啸而过的高楼大厦和车流 xff0c 以及灰色的天空和不断向后跑的树 视频和
  • 2020-11-26

    短剧本创作小技巧 xff0c 提升完播率 相信每一个编剧在自己的短剧本拍成视频时 xff0c 都会有满足感和成就感 但有的时候 xff0c 也会辗转难眠 xff0c 而其中遇到了最大问题就是完播率太低 而影响完播率的关键所在 xff0c 就
  • 2020-11-28

    短剧本中的场景选择 一般在写短剧本的时候 xff0c 一个故事里面会有很多的故事场景 xff0c 场景写的比较好就会使短剧本在转换为段视频的时候 xff0c 制作的短视频会更加的好看 故事的场景也算得上是一个故事的主要开端 xff0c 开端
  • 基于C++11实现的阻塞队列(BlockQueue)

    思路 xff1a 生产者消费者模型 如图 xff0c 多个生产者线程和多个消费者线程共享同一固定大小的缓冲区 xff0c 它们的生产和消费符合以下规则 xff1a 生产者不会在缓冲区满的时候继续向缓冲区放入数据 xff0c 而消费者也不会在
  • 航空订票系统设计(java、数据库、通信联合项目)

    航空订票系统设计 xff08 java 数据库 通信联合项目 xff09 最近帮高中同学做的一个学校项目 xff0c 这个项目主要是用Java写的 前期主要搭建五个类 xff0c Order xff08 选择 xff09 Passenger
  • java基础之IO流中的字节流

    目录 一 xff1a 字节流写数据 二 xff1a 字节流写数据的方式 三 xff1a 字节流写数据实例 字节流写数据步骤 字节流写数据例子 字节流追加写数据 四 xff1a 字节流读取数据 五 xff1a 字节读取数据的方法 六 xff1
  • java基础之转换流

    目录 一 xff1a 解释 二 xff1a 转换流输入流 1 xff1a 构造方法 2 xff1a InputStreamReader读数据方法 3 xff1a 例子 3 xff1a 注意 三 转换流输出流 1 xff1a 构造方法 2 x
  • java基础之多线程的引入

    目录 一 xff1a 多线程概述 进程 线程 举例 二 xff1a 并行与并发 三 xff1a Java程序的运行原理 四 xff1a JVM启动的时候是单线程还是多线程呢 xff1f 一 xff1a 多线程概述 进程 正在运行的程序 xf
  • 电信运营商云计算体系架构分析

    电信运营商云计算体系架构分析 作者 xff1a 成晓旭 xff08 版权保留 欢迎转载 xff09 第三篇 xff1a 体系架构分析 电信运营商云计算发展分析之一 xff1a 战略定位分析 xff0c 可供参考 电信运营商云计算发展分析之二
  • java基础之线程安全问题(一)

    目录 一 xff1a 线程安全判断依据 二 xff1a 解决线程安全问题实现 同步代码块 1 格式 2 同步代码块的锁对象是谁 xff1f 3 xff1a 同步方法的时候 xff0c 锁对象又是谁呢 xff1f 4 xff1a 静态同步方法
  • java基础之线程安全问题(二)

    目录 一 xff1a Lock锁的使用 xff08 解决同步问题 xff09 二 xff1a 例子 三 xff1a 同步的特点 xff08 1 xff09 同步的前提 xff08 2 xff09 同步的好处 xff08 3 xff09 同步
  • redis基础知识

    目录 一 xff1a 概念 二 xff1a NoSQL分类 三 xff1a Redis数据模型 四 xff1a 键Key 一 xff1a 概念 开源的 xff08 BSD协议 xff09 xff0c 使用ANSI C 编写 xff0c 基于
  • Hive建表以及导入数据

    目录 一 xff1a 内部表和外部表 1 xff1a 外部表 2 xff1a 外部表 3 xff1a 外部表和内部表区别 二 xff1a 上传数据方式 一 xff1a 内部表和外部表 1 xff1a 外部表 内部表基础建表语句一 默认指定文
  • Hive行列互转

    目录 一 xff1a 行转列 1 xff1a lateral view 行转列 2 xff1a explode函数 3 xff1a 例子 二 xff1a 列转行 1 概念 2 xff1a 例子 一 xff1a 行转列 1 xff1a lat
  • Hive行转列的应用之计算公司累加收入

    公司代码 年度 1月 12月的收入金额 burk year tsl01 tsl02 tsl03 tsl04 tsl05 tsl06 tsl07 tsl08 tsl09 tsl10 tsl11 tsl12 853101 2010 100200
  • Hive的常用函数

    目录 1 关系运算 2 数值计算 3 条件函数 4 日期函数 5 xff1a 字符串函数 6 xff1a Hive 中的wordCount 1 关系运算 等值比较 61 61 61 lt 61 gt 不等值比较 61 lt gt 区间比较
  • IDEA配置spring环境,并简单测试

    目录 一 下载安装需要的依赖包 二 IDEA的部署 一 下载安装需要的依赖包 首先 xff0c 我们需要下载一点jar包 第一个jar包是第三方依赖的jar包 xff0c Spring的核心容器依赖commons logging的JAR包
  • Unity导出工作台(Console)数据

    首先在Unity中添加C 脚本 xff1a using System Collections using System Collections Generic using UnityEngine using UnityEditor usin
  • Unity利用代码生成空心立方体(立方体挖走一个圆柱)

    先看效果 还未生成mesh时挖去圆柱的立方体 生成mesh后挖去圆柱的立方体 放代码为敬 xff08 脚本挂在空物体上即可 xff09 xff1a using System Collections using System Collecti