Unity高程图生成

news2024/11/25 2:40:13

大概就是根据一个灰度图,生成一个地形。

分两步来实现吧;首先,用随机数生成地形;然后,根据灰度图生成地形。

小白,没啥基础,所以只能慢慢来。

参考:

【萌新图形学】地形网格生成入门 含动画说明哦_哔哩哔哩_bilibili

【萌新图形学】地形生成下篇——随机大地形与真实地形_哔哩哔哩_bilibili

首先,得有一些基本概念的:

一些基本概念

演示

我是个小白,所以,刚开始,来点直观的吧

新建了一个空物体gameobject,手动添加了3样东西给它:

  1. MeshFilter组件

  1. MeshRender组件

  1. 考虑到没有材质球会成粉色,所以新建了个默认的材质球给它。

前两个组件是主要的,下面的动图就简单的演示了这两个组件的作用。

顺便提一下,这里有个线框模式显示的开关。

大概有了个朦胧的认识。现在,开始文档里的正式介绍。

Mesh

Unity - Scripting API: Mesh (unity3d.com)

《inherits from Object》

里面按一定规则存着模型的数据,比如顶点什么的。【就是顶点着色器里的那个顶点】

看定义可能比较朦胧,看这个示例代码,就很清楚它是什么了:

MeshFilter

Unity - Manual: Mesh Filter component (unity3d.com)

这个组件,也很简单呐;里面就一个Mesh。。

具体可以这么用:

Unity - Scripting API: MeshFilter.mesh (unity3d.com)

从代码里可以看到,这个组件里的Mesh,就是上面的那个Mesh类

MeshRender

Unity - Manual: Mesh Renderer component (unity3d.com)

材质球,UnityShader,就是拖给这个组件的。再结合它的名字猜一下——它负责把网格画出来

小结

  • MeshFilter组件和Mesh类是一对

  • 负责提供数据

  • 如顶点在模型坐标系下的坐标

  • MeshRender组件和材质球,shader是一对

  • 定义了如何使用数据

  • 比如在片元着色器里把quad给discard成ball,point sprite就是这么来的

后面就是按着视频来了。

1*1的平面

这个是视频里的代码。

结合上面介绍的基本概念,大概知道它在干什么吧。

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

public class Terrian : MonoBehaviour
{
    public float width = 0.1f;

    MeshRenderer meshRenderer;
    MeshFilter meshFilter;

    // 用来存放顶点数据
    List<Vector3> verts;
    List<int> indices;

    private void Awake()
    {
    }

    private void Start()
    {
        verts = new List<Vector3>();
        indices = new List<int>();

        meshRenderer = GetComponent<MeshRenderer>();
        meshFilter = GetComponent<MeshFilter>();

        Generate();
    }

    public void Generate()
    {
        ClearMeshData();

        // 把数据填写好
        AddMeshData();

        // 把数据传递给Mesh,生成真正的网格
        Mesh mesh = new Mesh();
        mesh.vertices = verts.ToArray();
        //mesh.uv = uvs.ToArray();
        mesh.triangles = indices.ToArray();

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        meshFilter.mesh = mesh;
    }

    void ClearMeshData()
    {
        verts.Clear();
        indices.Clear();
    }

    void AddMeshData()
    {
        verts.Add(new Vector3(0, 0, 0));
        verts.Add(new Vector3(0, 0, 1));
        verts.Add(new Vector3(1, 0, 1));
        verts.Add(new Vector3(1, 0, 0));

        indices.Add(0);  indices.Add(1);  indices.Add(2);
        indices.Add(0);  indices.Add(2);  indices.Add(3);
    }
    
}

在上面的那个演示的基础上,把它拖给空物体,就可以了。

更大规模的平面

灌数据到Mesh的原理

主要就俩数组,一个是顶点,一个是索引。

视频里这个图挺好的。

顶点数据

索引数据

稍微复杂一点,因为顶点是单独的,这个是相互关联的。

很形象的图,涉及到二维逻辑地址和一维物理地址的换算。

从特殊到一般:

最终应用

试一试

修改前:

void AddMeshData()
{
    verts.Add(new Vector3(0, 0, 0));
    verts.Add(new Vector3(0, 0, 1));
    verts.Add(new Vector3(1, 0, 1));
    verts.Add(new Vector3(1, 0, 0));

    indices.Add(0);  indices.Add(1);  indices.Add(2);
    indices.Add(0);  indices.Add(2);  indices.Add(3);
}

修改后

void AddMeshData()
{
    int N = 10;
    //01填充顶点数据
    for (int z = 0; z < N; ++z)//按先x后z的顶点排列顺序,所以最外层的循环是z不是x
    {
        for(int x = 0; x < N; ++x)
        {
            Vector3 temp = new Vector3(x, 0, z);
            verts.Add(temp);
        }
    }
    //02填充索引数据
    for(int z = 0; z < N - 1; ++z)
    {
        for(int x = 0; x < N - 1; ++x)
        {
            int index_lb = z * N + x;//index of the left bottom vertex. lb = left bottom
            int index_lt = (z + 1) * N + x;
            int index_rt = (z + 1) * N + x + 1;
            int index_rb = z * N + x + 1;

            indices.Add(index_lb);indices.Add(index_lt);indices.Add(index_rt);
            indices.Add(index_rt);indices.Add(index_rb);indices.Add(index_lb);
        }
    }
}

结果,符合预期;在原点那里放了个cube,作参照。

从平面到地形

这个不难,加一行

void AddMeshData()
{
int N = 10;
//01填充顶点数据
for (int z = 0; z < N; ++z)//按先x后z的顶点排列顺序,所以先循环的是z
{
    for(int x = 0; x < N; ++x)
    {
        float height = Random.Range(0.1f, 1.0f);//随机加个高度
        Vector3 temp = new Vector3(x, height, z);
        verts.Add(temp);
    }
}
//02填充索引数据
for(int z = 0; z < N - 1; ++z)
{
    for(int x = 0; x < N - 1; ++x)
    {
        int index_lb = z * N + x;//index of the left bottom vertex. lb = left bottom
        int index_lt = (z + 1) * N + x;
        int index_rt = (z + 1) * N + x + 1;
        int index_rb = z * N + x + 1;

        indices.Add(index_lb);indices.Add(index_lt);indices.Add(index_rt);
        indices.Add(index_rt);indices.Add(index_rb);indices.Add(index_lb);
    }
}


}

结果,有高度起伏了。

这个是10*10规模的,更大的规模也是一样的。计算机擅长重复。

源自灰度图的地形

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于stm32电梯管理系统设计

基于stm32电梯管理系统设计这里记录一下以前自己做的嵌入式课程设计&#xff0c;报告中的图片和文字太多了&#xff0c;全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156&#xff0c;也可在微信公众号 *高级嵌入式软件* 里回复 *电梯* 查看完整版文章摘要关键…

Oracle Apex 21.2 安装过程

什么是 Oracle APEX&#xff1f; Oracle APEX 是广受欢迎的企业级低代码应用平台。借助该平台&#xff0c;您可以构建功能先进的可扩展安全企业应用&#xff0c;并在任何位置&#xff08;云或内部部署&#xff09;部署这些应用。 使用 APEX&#xff0c;开发人员可快速开发并部…

域组策略自动更新实验报告

域组策略自动更新实验报告 域组策略自动更新实验报告 作者: 高兴源 1要求、我公司为了完善员工的安全性和系统正常漏洞的维护&#xff0c;所以采用域组策略自动更新的方法来提高账户安全性&#xff0c;减少了用户的错误。 1.实验环境如下1台2008r2一台创建域&#xff0c;一台wi…

【云原生】k8s中Pod进阶资源限制与探针

一、Pod 进阶 1、资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;调度器就使用该信息来决定将 Pod 调度到哪个节点上。当还…

嵌入式 STM32 步进电机驱动,干货满满,建议收藏

目录 步进电机 1、步进电机驱动原理 2、步进电机驱动 3、步进电机应用 1、第一步&#xff1a;初始化IO口 2、设置行进方式 四、源码 步进电机 步进电机被广泛应用于ATM机、喷绘机、刻字机、写真机、喷涂设备、医疗仪器及设备、计算机外设及海量存储设备、精密仪器、工业…

_improve-3

createElement过程 React.createElement()&#xff1a; 根据指定的第一个参数创建一个React元素 React.createElement(type,[props],[...children] )第一个参数是必填&#xff0c;传入的是似HTML标签名称&#xff0c;eg: ul, li第二个参数是选填&#xff0c;表示的是属性&#…

String、StringBuffer和StringBuilder的详解

目录 一、String讲解 1.String&#xff08;String字符串常量&#xff09; 2.String 拼接方式与性能的影响 二、StringBuffer 和 StringBuilder 讲解 1.StringBuffer 和 StringBuilder 使用场景:(StringBuffer、StringBuilder字符串变量) 2.StringBuffer的使用 3.StringB…

shell脚本常用命令

shell概述 shell是一个命令行解释器&#xff0c;它接收应用程序/用户命令&#xff0c;然后调用操作系统内核。 shell还是一个功能强大的编程语言&#xff0c;易编写、易调试、灵活性强。 shell解析器 查看系统自带的所有shell解析器 cat /etc/shells查看系统默认的shell解析…

超算中心、并行计算

现在超算中心已经迅速发展 合肥&#xff1a; 合肥先进中心 合肥曙光超算中心平台 合肥安徽大学超算中心 合肥中科大超算中心 合肥中科院超算中心 合肥大一点的公司都会有自己的集群&#xff0c; 超算中心又称为集群&#xff0c;一般集群是小型服务器组成&#xff0c;超…

EasyRecovery16免费的电脑的数据恢复工具

常见的数据恢复有两种方式&#xff0c;第一种方式是找别人恢复&#xff0c;按照市场价来说&#xff0c;数据恢复的价格每次在100-500之间&#xff0c;但这种方式容易使自己设备上的隐私资料泄露出去&#xff0c;不安全。 另一种方式则是自己学会数据恢复的方法&#xff0c;有问…

逻辑回归

逻辑回归 在分类问题中&#xff0c;要预测的变量y为离散值&#xff08;y0~1&#xff09;&#xff0c;逻辑回归模型的输出变量范围始终在 0 和 1 之间。 训练集为 {(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))}\{(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})\} {…

地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?

指针是C语言中的一个重要概念&#xff0c;也是C语言的一个重要特色&#xff1b;使用指针&#xff0c;可以使程序简洁、紧凑、高效。不掌握指针&#xff0c;就没有掌握C语言的精华。 目录 一、定义 1.1地址 1.2指针 1.3指针变量 1.4指针和指针变量的区别 二、使用指针变量…

C#关于HWindowControl实现一些便捷功能——(缩放与拖动图像)

C#关于HWindowControl实现一些便捷功能——&#xff08;缩放与拖动图像&#xff09;一、关于Hwindow窗体显示的part二、以鼠标为中心的缩放三、以鼠标拖动移动图片一、关于Hwindow窗体显示的part 首先 HWindowControl 控件的尺寸是固定的&#xff0c;当我们在这个固定的尺寸中…

C++类和对象:构造函数和析构函数

目录 一. 类的六个默认成员函数 二. 构造函数 2.1 什么是构造函数 2.2 编译器自动生成的默认构造函数 2.3 构造函数的特性总结 三. 析构函数 3.1 什么是析构函数 3.2 编译器自动生成的析构函数 3.3 析构函数的特性总结 一. 类的六个默认成员函数 对于任意一个C类&…

零基础如何入门网络安全(黑客)

我经常会看到这一类的问题&#xff1a; 学习XXX知识没效果&#xff1b;学习XXX技能没方向&#xff1b;学习XXX没办法入门&#xff1b; 给大家一个忠告&#xff0c;如果你完全没有基础的话&#xff0c;前期最好不要盲目去找资料学习&#xff0c;因为大部分人把资料收集好之后&a…

三天吃透Java虚拟机面试八股文

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

趣味数学题存疑待证1

原文出自&#xff1a;球面上随机 N 个点在同一个半球上的概率 要求任意N个点&#xff0c;全在同一个半球上的概率&#xff0c;我们需要构造使得分母为有限的样本集合&#xff0c;分子则为有N个点在同一半球的情况集 首先对任意N个点取其对称点使得可划分点为2N&#xff0c;在…

【数据库】第七章 数据库设计

第七章数据库设计 数据库设计概述 数据库设计的基本步骤 需求分析概念结构设计逻辑结构设计物理结构设计数据库实施数据库运行和维护 需求分析 收集需求&#xff0c;理解需求 收集各个角色的需求 概念数据库设计 建立概念模型 &#xff0c;E-R图/IDEF1x图 消除冲突&…

【JDK8新特性之日期时间API-案例实操】

一.JDK8新特性之日期时间API-案例实操 之前我们学习了Stream流、Lambda表达式以及方法引用等相关的内容&#xff0c;如果想学习的同学可以看一下之前的文章&#xff0c;接下来我们一起学习一下关于JDK8中新日期时间API的使用。 二.JDK中原始日期时间存在的问题 设计不合理&…

VC++随鼠标移动显示坐标和坐标映射模式学习

VC6&#xff0c;新建一个单文档工程&#xff1b; 把这两个加到视类头文件&#xff1b; CPoint m_ptOut; //用来保存鼠标坐标 CString strPosition; //用来保存输出的内容 视类CPP的构造函数中初始化&#xff0c; m_ptOut.x 0; m_ptOut.y 0; 用类向导为视类…