翻译: 星球生成 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. php 把数字转化为大写中文

    PHP 数字转大写中文 PHP入门小菜鸟一枚.下午要求写一个把数字转成大写中文的脚本,百度了一波,几十个博客和网站都是用的那四个代码,第一个运行不了,第二个有问题,不合要求,第三个第四个太长,懒得看, ...

  2. jieba库的应用

    #!/usr/bin/python# -*- coding:utf-8 -*- import imp,sys imp.reload(sys)from matplotlib.font_manager i ...

  3. 优化Linux下的内核TCP参数以提高系统性能

    内核的优化跟服务器的优化一样,应本着稳定安全的原则.下面以64位的Centos5.5下的Squid服务器为例来说明,待客户端与服务器端建立 TCP/IP连接后就会关闭SOCKET,服务器端连接的端口状 ...

  4. rpm安装和二进制安装

    rpm包安装 Tomcat RPM安装(先安装JDK + 再安装Tomcat) 1:升级系统自带的JDK(也可以使用oracle的JDK) yum install -y java-1.8.0-open ...

  5. 6/4 sprint2 看板和燃尽图的更新

  6. php单例模式 (转

    假设我们需要写一个类用来操作数据库,并同时满足以下要求: ①SqlHelper类只能有一个实例(不能多)②SqlHelper类必须能够自行创建这个实例③必须自行向整个系统提供这个实例,换句话说:多个对 ...

  7. [转帖]windows 2008 Server R2 /Win7启用TLS 1.2

    来自新浪博客的 一个文章 自己很早之前曾经看过 iis的加密工具 但是当时没有认识到TLS1.2协议的问题 这里 晚上学习了一下.  http://blog.sina.com.cn/s/blog_16 ...

  8. 我项目中使用userData的实例 UserData.js

    关于userData的介绍,请参见http://hi.baidu.com/kaisep/blog/item/1da9a3312d2da5a15edf0e87.htmlhttp://hi.baidu.c ...

  9. 深入理解JAVA虚拟机阅读笔记4——虚拟机类加载机制

    虚拟机把描述类的Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 在Java语言中,类型的加载.连接和初始化过程都是 ...

  10. UVA11248_Frequency Hopping

    给一个有向网络,求其1,n两点的最大流量是否不小于C,如果小于,是否可以通过修改一条边的容量使得最大流量不小于C? 首先对于给定的网络,我们可以先跑一遍最大流,然后先看流量是否大于C. 然后保存跑完第 ...