三维随机分形地形生成

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

原文:http://www.gam /fractal.html

目录

说明:本页所有图像均经过优化以减小尺寸,所以与实际图像会有细微差别。

1.第一部分:生成随机分形地形

1.介绍

2.自相似

3.一维中点变换

4.高度图

5.Diamond-Square 算法

6.蓝天白云

7.其它算法

2.第二部分关于例子源码

1.安装

2.快速起步

3.使用程序

4.代码结构

5.下载源码[Visual C++工程,使用SGI实现的OpenGL](单击标题下载)

6.参考

终于找到这个SGI OpenGl地址了:

/tools/ocx/ocx_image/opengl2.exe

介绍

十年前,我参加1986 年SIGGRAPH 活动,Gavin S. P. Miller 那篇题为Definition and Rendering of Terrain Maps 的论文让我充满敬畏。该文描述了少数生成分形地形的算法,作者还介绍了一个他们认为更先进的新方法。

开始我被这些算法能够生成难以置信的风景图所震惊!(尽管这些算法被作者认为“漏洞百出”)后来,读过论文,这些算法之简单将我完全打败了。

我从此成为一个分形地形迷。

算法背后的数学可能相当复杂。然而,完全理解这些数学并不是掌握这些算法的必要条件。很好,否则我得在解释算法之前讲解所有的数,也许永远也讲不到算法。此外,关于分形数学的文字材料数以吨计,参见本文本的参考部分会有所帮助。

同样的原因,我不会深入到数学细节,也不包括对分形的广泛总览及它们可被用来做的每样东西。相反,我将描述分形地形生成背后的概念,并集中仔细讲解我个人最喜欢的”diamond-square”

算法。我将演示如何使用这个算法静态拼嵌高度数据数组,这些数据可用于几何地形数据、地形纹理数据及云纹理映射。

分形有什么用呢?假定你已经知道,那正是你读本文的原因。随机地形图对飞行模拟或制作背景纹理图(如显示一带远山)十分有用。生成地形的算法也可用于生成部分云天的纹理图。

在继续之前,申明一下:我不是游戏程序员。如果你为找到一个快速绘制地形的算法而读此文,那你来错了地方。我只描述生成地形模型的过程。着色绘制是你自己的事。

自相似

任何分形最关键的概念是自相似。当一个物体的一部分放大后看起来仍与整个物体一样,那这个物体就是自相似。

考虑一下人体的循环系统。这是自然界中自相似的好例子。从最大的动脉和静脉分支直到最小的微血管,整个过程都显现相同的分支模式。如果你不知道正在使用显微镜,将无法分辨微血管和大动脉。

现在再考虑一个简单的球。它是自相似的吗?不!大幅度放大后,它看起来不再象一个球,而象块平板。如果你不相信,看看户外。除非恰好你在太空轨道上看本文,否则将完全没法看出球是个球体。球体不是自相似的。它最用传统的欧几里德几何描述而不是分开。

地形属于自相似范畴。手掌上的碎岩锯齿状边缘与远处地平线边的山脊有相同的不规则形状。这使我们可以用分形来生成地形,不管显示时怎么放大,它看起来仍然象地面。

关自相似请注意:严格意义下,它意味着自分辨(self-identical) ,即,自身精确的缩略拷贝在逐渐放大缩小时可见。我并不知道自然界存在任何自分辨分形。但m andelbrot 集是自分辨的。我不会进一步讨论Mandelbrot 集。到参考里找进一步的信息。

一维中点变换

后边要讲的diamond-square 算法,在两维上使用一种中点变换算法。为帮助你了解个大概,我们先看一维情况。

当山脉出现在远处地平线处时,一维中点变换是绘制山脊的好算法。看看它是怎么工作的:

以一条水平地平线段开始

重复足够多次{

对场景中的每条线段做{

找到线段的中点

在Y 方向上随机移动中点一段距离

减小随机数取值范围

}

}

将随机数值域减速小多泊呢?那取决于你想要分形的陡峭程度。每次循环减少的越多,所得山脊线就越平滑。但如果减得太多,则会有明显的锯齿感。可以粗糙度存在一个常量里。后面会解释如何做。

来看个例子。我们以一条x 从-1.0 到 1.0 ,y 均为0 的线段开始。开始,我们将随机值范围设为-1.0 到 1.0 (可任意取)。这样我们在此范围里生成一个数字,并将中点移动这么多。这之后,我们就得到了:

现在第二次经过外圈循环,我们有两段,长度均原来的一半。我们的随机值也减半,即-0.5 到0.5 。我们为两个中点都生成一个这个范围内的随机点,结果为:

再次缩减范围,现在是-0.25 到0.25 。再以该范围内的数变换四个中点后,我们得到了:

有两件事你可能已经注意到了。

首先,它是递归的。实际上,它可以用一个迭代过程相当自然的实现。对于这种情况,递归或迭代都成。对于表面生成代码,使用迭代实现比递归会有一些好处。所以为保持一致,线和面相应的代码都使用迭代实现。

其次,它是个非常简单的算法,然而你能创建非常复杂的结果。这正是分形算法的美妙之处。一些简单的指令可以建立一个具有丰富细节的图像。

再跑一下题:少量简单的指令集能够生成复杂图像的事实已经成为一个新的研究领域称为分形图像压缩。其思想是保存建立图像的递归指令而不是保存图像本身。这对于自然界的分形图像是极有用的,因为指令相对图像占用的空间要少得多。 Choas (混沌)与Fractals (分形)new Frontiers of Science 有一章及一个附录涉及本主题,是一般学习分形的好读物。

回到现实。

不用太费劲,你可以读取本函数的输出到一个绘制程序而得到类似如下的东西:

这可作为窗口景色使用。相关的好东西是它是约束的,所以你可以保留一个相当的小图像并用它拼出整个场景。如果你不介意在每个方向都看见相同的山,那就这么干。

好的,在进入2D 分形表面之前,你得了解粗糙度常量。这个值决定每次循环随机数值域的减少量,也就是说,决定分形结果的粗糙程度。例子代码使用一个0.0 到 1.0 之间的浮点数并称之为 H 。因此2(-h) 是 1.0( 对于小H) 到0.5 (对大H )范围内的数。随机数范围在每次循环时乘上这个值。如果H 设为 1.0 ,则随机数范围将每次循环减半,从而得到一个非常平滑的分形。将H 设为0.0 ,则范围根本不减小,结果有明显的锯齿感。

下边是三个山脊,每个用不同的H 的值绘制:

相关文档
最新文档