翻译: 星球生成 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. object-oriented first work

    前言:在星期三的第一次面向对象程序设计课,遇见我们的栋哥,初次见面,发现老师的幽默.....下课后,就给我们一道作业题目... 作业要求:Create a program that asks for ...

  2. PMS—团队展示

    点我查看作业原题 [队名] PMS(一群pm) [拟做的团队项目描述] 基于监控场景的视频摘要与人车检测跟踪系统 A system, under monitor scene, for video su ...

  3. 用jar包运行带GUI的java游戏

    这是从某论坛下载的java游戏demo,由于年代久远,所以没有记下出处.重要的是,这是一个带GUI的java程序. 链接: https://pan.baidu.com/s/1LjQ2bQPXvW-ti ...

  4. excel文件怎么使用php进行处理

    1.可以通过phpmyadmin导入csv文件 2.也可以直接使用php 处理已经将excel另存为.csv后缀的文件, 通过php专门处理csv文件的函数 如 fgetcsv() <?php ...

  5. PHP学习心得2

    对于PHP的语法结构,刚开始真的很不习惯,真搞不懂为什么每个变量之前都要加个“$”符号,每个语句写完之后都必须加上“分号”来表示此句已经结束,还有,PHP对字母的大小写是敏感的,写的时候一定要注意大小 ...

  6. Mysql 的InnoDB事务方面的 多版本并发控制如何实现 MVCC

    Mysql的MVCC不能解决幻读的问题,但是Mysql还有间隙锁功能,Mysql的间隙锁工作在Repeatable Read隔离级别下面,可以防止幻读, 参考:Mysql 间隙锁原理,以及Repeat ...

  7. Iaas

    IaaS(Infrastructure as a Service),即基础设施即服务. 消费者通过Internet 可以从完善的计算机基础设施获得服务.这类服务称为基础设施即服务.基于 Interne ...

  8. input select & input unselect

    input select & input unselect input select https://developer.mozilla.org/en-US/docs/Web/API/HTML ...

  9. avalon学习教程

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

  10. DAY4-Flask项目

    项目出现的问题: 问题处在import requests.requests库已经安装了啊; 找了半天也不知道具体错误在哪里,根据提示想是不是http.py这个模块与Python内置的同名模块冲突了?所 ...