翻译: 星球生成 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. [转帖] go的import 语法

    package 的导入语法写 Go 代码的时经常用到 import 这个命令用来导入包,参考如下: import( "fmt" ) 然后在代码里面可以通过如下的方式调用: fmt. ...

  2. Linux下的网卡Bonding

    1. 网卡Bonding一共有0-6七种mode,具体区别请自行搜索: 2. 建议通过nmtui命令在交互模式下配置,这样不会落下重要的字段,也不用去记忆到底有哪些字段: 3. 我的实验环境是VMWa ...

  3. ubuntu16.04 关闭防火墙的方法

    开启防火墙 ufw enable 关闭防火墙 ufw disable

  4. [转帖]从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路

    从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路   http://www.52im.net/thread-1709-1-2.html     本文原作者阮一峰,作者博客:r ...

  5. 初入码田--ASP.NET MVC4 Web应用之创建一个空白的MVC应用程序

    初入码田--ASP.NET MVC4 Web应用开发之一  实现简单的登录 初入码田--ASP.NET MVC4 Web应用开发之二 实现简单的增删改查 2016-07-29 在此之前,需要一台电脑( ...

  6. p2 碰撞

    P2可以实现物体碰撞模拟,同时在碰撞过程中派发一些事件实现碰撞检测,将碰撞信息及时反馈,以添加相应的特效. P2中,当两个刚体的最小包围盒AABB发生重叠,碰撞就开始了:然后刚体的形状发生重叠,同时P ...

  7. 计算机网络【9】—— HTTP1.0和HTTP1.1的区别及常见状态码

    一.HTTP1.0与HTTP1.1的区别 1.HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理 HTTP 1.0规定浏览器与服务器只保持 ...

  8. avalon学习教程

    最近在项目中发现了个很不错的前端MVVM框架 avalon,对于基础的使用大概学习了一遍,有些深入的没应用场景还没细看. 收藏好,估计以后要用 http://www.html-js.com/artic ...

  9. css 样式 文字过长 换行处理方法

    css强制换行.强制不换行及自动换行的写法 css强制不换行 div{white-space:nowrap;} css自动换行 div{ word-wrap: break-word; word-bre ...

  10. 【大数据】Hadoop的高可用HA

    第1章 HA高可用 1.1 HA概述 1)所谓HA(high available),即高可用(7*24小时不中断服务). 2)实现高可用最关键的策略是消除单点故障(single point of fa ...