翻译: 星球生成 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. 在win7 64位操作系统下 arduino驱动安装问题的解决

    主要参考以下两个博客: 操作教程:http://blog.csdn.net/u013926582/article/details/24442583 文件下载:http://www.arduino.cn ...

  2. Thinking in Java & 内部类

    静态内部类可以直接创建对象new B.C(); 如果内部类不是静态的,那就得这样 B b = new B(); B.C c = b.new C(); //要想直接创建内部类的对象,不能按照想象的方式, ...

  3. java9初探

    最近研究了一下java9的新特性,也看完了<Modularity Programming in Java 9>,有一些收获写博客记录一下. 1.java9初探

  4. exFAT移动硬盘写保护怎么去掉

    cmd命令提示符下运行chkdsk命令: 比如在E盘,则输入的命令如下: E:(冒号不可少,输入后回车) CHKDSK /F /X  (回车) 等命令执行完了,即可去掉exFAT移动硬盘写的保护.

  5. 性能分析_linux服务器CPU_中断

    中断 1.  指标范围 1.1  Interrupt rate 应该与cpu利用率结合分析,如果cpu利用率在合理范围内,大量的中断也是可以接受的.一个巨大的中断值,同时伴随着缓慢的系统性能表现,指示 ...

  6. ini_set

    1.ini_set函数是设置选项中的值,在执行函数后生效,脚本结束的时候,这个设置也失效.ini_set 用于更改配置文件的配制,次更改仅用于此脚本的执行.不是所有的选项都能被改函数设置的. 2.in ...

  7. linux 负载均衡配置 keepalive lvs 使用nginx转发 CentOS7 搭建LVS+keepalived负载均衡

    最近希望能够配置一下负载均衡,在虚拟机上面,但是网上找了很多资料很零散,对于不了解的人,很多不够详细,最近终于做好了,把具体的步骤写下来,方便各位网友查阅学习 这个实验需要安装nginx如果没有安装过 ...

  8. [BinaryTree] AVL树、红黑树、B/B+树和Trie树的比较

    转自:AVL树.红黑树.B/B+树和Trie树的比较 AVL树 最早的平衡二叉树之一.AVL是一种高度平衡的二叉树,所以通常的结果是,维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应 ...

  9. 用python和unittest编写app自动化测试用例

    import unittest import webdriver import time class Test(unittest.TestCase): @classmethod def setUpCl ...

  10. ajax异步请求loading

    1.找到一张loading图片 2.添加样式 <style> .loadingWrap{ position:fixed; top:; left:; width:100%; height:1 ...