翻译: 星球生成 I

本文翻译自Planet Generation - Part I

  • 译者: FreeBlues

以下为译文:

概述

我一直是一个过程内容生成的爱好者, 它允许你创建一个甚至不断改变的潜在内容无限的游戏. 它也弥补了我在艺术天赋方面的欠缺.

过程景观生成对很多游戏都很有用, 从策略游戏中的侦察模式(Skirmish mode)到单人地牢游戏(dungeon in a Roguelike), 现在我将要探索如何生成星球.

星球截图:

在过去进行平面和三维像素地形生成时, 使我熟悉了相当一些渲染生成算法, 但是在这之前我从未制造过星球, 我决定现在是时候改变这一事实了.

计划

现实世界中的星球包含了大量的信息. 地球额表面区域大约有 5.1 亿平方公里, 几乎 2/3 的地方是水, 1/3 的地方是陆地. 这些是大量的你想要生成的地形数据.

穿越陆地, 我们有河流, 湖泊和不同类型的生物群落, 描述沙漠, 丛林, 冰原以及其他更多的. 生物群落的信息能告诉你在不同的区域生活着什么类型的动物.

这也跟光照有关. 我们的光线来自太阳, 它可以被想做一种简单的直射光, 但是事实上光线射入大气层, 被称作光子的光粒子撞击地球大气颗粒, 并且反射出更多的蓝色和黄色. 这被称作大气散射.

在本文中, 我讲从制造简单的几何体开始, 作为星球的基础. 在下一篇文章中, 我将会加入更多的细节, 包括高度数据, 光线, 大气散射和细节级别(level of detail), 它将会允许戏剧性地增加星球包含的数据的总数量.

几何体

我干的第一件事是用简单的经纬度算法创建一个球体:

截图:

使用这种方法的问题是顶点会汇聚到极点, 导致顶点分布不均匀, 并且使得视觉扭曲, 特别是当你试着增加一个纹理贴图时(译者注: 就是越到两极处, 纹理贴图越小, 我们就看不到南极和北极的地形了).

因此我去寻找了一种不同的算法并且找到一些很有用的, 包括测地线和立方体映射(Geodesic and Cube Mapping).

测地线网格看起来提供了确实不错的结果, 它在给出一个很好的球体形状的同时保持了网格的均匀一致没有变形扭曲.

测地线网格能通过再分割一个 二十面体(icosahedron) 来创建, 增加额外的三角形并且推到向着球体半径的位置. 足够的镶嵌将会创建一个网格均匀没有变形的平滑的球体.

截图:

出于简单和速度的原因, 我决定从一个立方体映射算法开始. 照着我在网上找到的 Philip Nowell 写的一个公式, 我能用下面这些代码轻易地把一个立方体网格折成一个球体:

// For every vertex in the mesh
// Where vertices form 6 grids making a cube
// With bounds of [-1, -1, -1] to [1, 1, 1]
void MapCubeToSphere( Vector3& vPosition )
{
float x2 = vPosition.x * vPosition.x;
float y2 = vPosition.y * vPosition.y;
float z2 = vPosition.z * vPosition.z; vPosition.x = vPosition.x * sqrt( 1.0f - ( y2 * 0.5f ) - ( z2 * 0.5f ) + ( (y2 * z2) / 3.0f ) );
vPosition.y = vPosition.y * sqrt( 1.0f - ( z2 * 0.5f ) - ( x2 * 0.5f ) + ( (z2 * x2) / 3.0f ) );
vPosition.z = vPosition.z * sqrt( 1.0f - ( x2 * 0.5f ) - ( y2 * 0.5f ) + ( (x2 * y2) / 3.0f ) );
}

在创建立方体每一面的网格并且对每个顶点应用上面那些代码后, 立方体折成了一个球体, 如下图所示:

动态截图:

示例代码演示了创建立方体网格的一个面然后把它折成一个球体:

// Declared Variables
// width - number of vertices across the x axis
// height - number of vertices across the y axis
// radius - sphere's radius
// pVertexBuffer - vertex buffer array // Grid facing negative z
Vector3 vMinPosition( -1.0f, -1.0f, -1.0f ); for ( int y = 0; y < height; ++y )
{
for ( int x = 0; x < width; ++x )
{
Vector3 vPosition = vMinPosition;
vPosition.x += (float)x / (float)(width-1) * 2.0f; // Multiply by 2.0f to map position from -1 to +1
vPosition.y +- (float)y / (float)(height-1) * 2.0f; // Multiply by 2.0f to map position from -1 to +1 // Map the grid position into a sphere position
MapCubeToSphere( vPosition ); // The normal is just the vector from the center of the sphere.
Vector3 vNormal = vPosition.Normal(); // Extrude the sphere by the radius
vPosition *= radius; // Assign to vertex buffer
pVertexBuffer[ y * width + x ].Position = vPosition;
pVertexBuffer[ y * width + x ].Normal = vNormal;
}
}

立方体映射的优势

这里有一些我希望使用立方体映射的好处:

  • 网格是均匀的, 类似于一个二维平面网格地形, 使它容易处理;
  • 把地形当做一个网格来处理允许我们用类似 Chunked LODGeometry Clipmaps 这样的细节级别(LOD)算法渲染每一个面.
  • 允许对纹理贴图使用立方体映射, 可能会提升性能.

更多的好处在下一篇文章里.

后续

下一阶段的工作是为星球增加更多的细节, 现在它只是一个简单的球体. 在平面网格中使用很普遍的一种方法是创建一个高度图来置换顶点的 Y 坐标值.

在高度图被应用到一个球体之前, 需要做一些额外的工作, 这样图才会很好地在不同面之间包起来.

在下一篇文章中, 我会详细描述如何创建一个高度图以及一些提升细节的技巧.

下一篇文章在此 Planet Generation - Part II, 译文: 星球生成 II

参考

原文: Planet Generation - Part I

Planet Generation - Part II

Mapping a Cube to a Sphere

Rendering Massive Terrains using Chunked Level of Detail Control: DRAFT

GPU Gems 2: Chapter 2. Terrain Rendering Using GPU-Based Geometry Clipmaps

翻译: 星球生成 I的更多相关文章

  1. 翻译: 星球生成 II

    翻译: 星球生成 II 本文翻译自Planet Generation - Part II 译者: FreeBlues 以下为译文: 概述 在前一章 我解释了如何为星球创建一个几何球体. 在本文中, 我 ...

  2. 【翻译】生成 Timestamps / Watermarks

    本文翻译自flink官网:https://ci.apache.org/projects/flink/flink-docs-release-1.7/dev/event_timestamps_waterm ...

  3. 机器指令翻译成 JavaScript —— 终极目标

    上一篇,我们顺利将 6502 指令翻译成 C 代码,并演示了一个案例. 现在,我们来完成最后的目标 -- 转换成 JavaScript. 中间码输出 我们之所以选择 C,就是为了使用 LLVM.现在来 ...

  4. TensorFlow练习24: GANs-生成对抗网络 (生成明星脸)

    http://blog.topspeedsnail.com/archives/10977 从2D图片生成3D模型(3D-GAN) https://blog.csdn.net/u014365862/ar ...

  5. qt中qlineedit和qtextedit右键菜单翻译成中文

    没有linguist和lupdate等命令需要安装Linguist: 在Terminal中输入: sudo apt-get install qt4-dev-tools qt4-doc qt4-qtco ...

  6. Qt 本地化(翻译)

    Qt 本地化(翻译) 翻译流程大致是这样的:首先源代码产生 ts 文件,然后送给 Qt Linguist(Qt 语言家)这个 Qt 自带的小工具进行处理产生 qm 翻译文件,最后源代码里加载这个 qm ...

  7. 解析大型.NET ERP系统 多国语言实现

    实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...

  8. jsp机制基础

    JSP 和Servlet技术一样,JSP也是SUN公司定义的一种开发动态web资源的技术,属于JavaEE技术之一.JSP实际上就是Servlet,它们在一起又称JSP/Servlet规范. Serv ...

  9. QT国际化 一 (lupdate/linguits/lrelease)

    QT国际化(lupdate/linguits/lrelease) 本文由乌合之众瞎写http://www.cnblogs.com/oloroso/ qt国际化其实就是qt中字符串的字符集编码的设置.当 ...

随机推荐

  1. TCP/IP Illustrated Vol1 Second Edition即英文版第二版,TCP部分个人勘误

    目前已经有了英文版第二版的TCPIP详解,中文版暂时还没有,但是英文版还是有好几处错误,作者和官方竟然没有维护一个勘误表. 个人阅读过程中针对TCP部分可能有问题的地方简单勘误一下 P596:示意图中 ...

  2. Angular与PHP之间的不同的请求方式(post/get)导致的传参问题

    angularJS的$http发送POST请求,PHP无法接受数据的问题 使用jQuery进行ajax请求 $.ajax({ type: 'POST', url:'url.php', data: da ...

  3. jndi连接数据库配置过程总结

    一.我们先找到tomcat安装目录中conf目录下的context.xml更改里面的内容: <?xml version='1.0' encoding='utf-8'?> <Conte ...

  4. HBase 架构与工作原理2 - HBase 组件

    本文系转载,如有侵权,请联系我:likui0913@gmail.com 一.HBase 组件概览 Master-Slave 模式: HBase 体系结构遵循传统的 master-slave 模式,由一 ...

  5. HBase 架构与工作原理3 - HBase 读写与删除原理

    本文系转载,如有侵权,请联系我:likui0913@gmail.com 一.前言 在 HBase 中,Region 是有效性和分布的基本单位,这通常也是我们在维护时能直接操作的最小单位.比如当一个集群 ...

  6. HTTP压力测试工具wrk的安装及测试

    本次在VMware虚拟机的CentOS6.3系统中进行安装wrk压测工具,具体如下: 一.预先安装需求项 为了安装顺利,不受权限的限制,首先可以把用户切换为root用户# su + 输入root用户对 ...

  7. CGOS 8 备用交换机(割点)

    题目链接:http://cojs.tk/cogs/problem/problem.php?pid=8 题意:n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接.因电子设备容易损坏 ...

  8. typescript 不用import?

    如果你想用ts文件,而又不想import,export,怎么办呢? 感谢开发者提供的工具.    https://github.com/domchen/typescript-plus.   感想: 仅 ...

  9. 【Java线程】SwingWorker的用法

    Swing应用程序员常见的错误是误用Swing事件调度线程(Event DispatchThread,EDT).他们要么从非UI线程访问UI组件:要么不考虑事件执行顺序:要么不使用独立任务线程而在ED ...

  10. 如何调换antd中Modal对话框确认按钮和取消按钮两个按钮的位置

    今天有个工作是把所有的确认按钮放在取消按钮的左边,类似于下图这样的,公司用的时antd组件 但是antd组件的按钮时确认键放在右边的 可以采用下面的方式,将按钮调换过来: 对的,就是在modal里面的 ...