创建您的Minecraft:从多维数据集生成3D关卡


部分由于Minecraft的普及,近来人们对游戏的想法越来越感兴趣,该游戏发生在一个由3D浮雕构建,并充满诸如洞穴,悬崖等元素的立方体世界中。 这样的世界是ANL库样式生成的噪声的理想应用。 本文源于对我以前实现该技术的尝试的讨论。 从那时起,库的结构发生了微小的变化。

在之前的文章中,我谈到了使用3D噪波功能实现Minecraft风格的地形。 之后,库有了一些发展,因此我决定返回此主题。 由于必须回答有关此系统的许多问题,因此我将尝试更多地讨论所涉及的概念。 为了使基本概念更清楚,我将首先生成用于Terraria和King Arthur's Gold的游戏中使用的2D地形的想法,然后将系统扩展到Minecraft等3D实例。 这将使我能够以图像为例更有效地演示概念。

该系统的开发考虑了以下抽象目标:我们应该能够将某个点或单元的坐标传递给系统,并确定该位置应放置的块类型。 我们希望系统成为一个“黑匣子”:我们给它传递一个点,返回块的类型。 当然,这仅适用于世界的最初一代。 此类游戏中的积木可以通过玩家的动作进行更改,并且尝试使用同一系统描述此类更改将很不方便。 必须以其他方式跟踪此类更改。 该系统生成原始世界,原始世界并不受玩家和其他角色的影响。

鉴于这种系统本身是复杂的实体,因此很难隐式建模,因此该技术可能不适用于对诸如草或其他生物实体之类的系统进行建模。 这同样适用于诸如下雪,结冰等系统。...本文中介绍的技术是一种隐式方法 ,即 一个可以在一个点上估计的值,并且在给定点上的值不取决于周围的值。 为了执行精确的模拟,生物系统和其他类型的系统通常需要考虑环境值。 例如:有多少阳光照射在块上? 附近有水吗? 需要回答这些问题和其他问题,以模拟生物系统以及在较小程度上其他类型的与气候相关的系统的生长和扩散。 同样,该技术也不适合对水建模。 在该系统中,没有流动,流体力学或重力知识的概念。 水是一个复杂的主题,需要进行许多复杂的计算。

因此,我们只是对泥土和石头建模。 我们需要一个函数来告诉您给定的位置:土,沙,空气,金,铁,煤等。...但是我们将从最简单的开始。 我们需要一个函数来判断块是实心的还是空心的(充满空气)。 此功能应模拟我们周围的地球。 也就是说,天空在上方,地球在下方。 因此,让我们承担圣经的任务,将天空与大地分开。 为此,我们研究了梯度函数。 将Gradient函数传递给N维空间(即任何坐标空间,无论是2D,3D还是更高的坐标空间)中的线段,并沿着该段计算梯度场。 传入坐标被投影到该线段上,并根据它们相对于线段端点的位置来计算其梯度值。 在间隔(-1.1)中为投影点分配值。 这对我们来说将是一个好的开始。 我们可以沿Y轴定义Gradient函数,在间隔的顶部,将梯度场与-1(空气)进行比较,在底部将梯度场与1(地球)进行比较。

 terraintree =
 {
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1}
 } 

(我将简要解释该条目。示例代码在Lua声明表中编写。有关格式的更多信息,请参见Lua集成一节。本质上,该格式是为读取特殊广告并将其转换为噪声模块实例树的特殊类而设计的。格式更详细,逐步C ++格式,因为它更紧凑,更干净;我认为,源代码比C ++代码更易读和压缩;大多数情况下,声明更易于阅读和理解。模块有名称,指定了源 名称或值。用于解析表声明的Lua代码包含在源代码中,以防您要直接使用这些声明。

在2D的情况下,渐变函数会接收格式为(x1,x2,y1,y2)的直线段,在3D的情况下,格式会扩展为(x1,x2,y1,y2,z1,z2)。 由(x1,y1)形成的点表示映射到0的线段的起点。由(x2,y2)形成的点是映射到1的线段的终点。也就是说,这里我们映射线段(0,1)->( 0,0)。 因此,梯度将在函数Y = 1和Y = 0的区域之间。 也就是说,该条形图以Y表示世界的尺寸。世界的任何部分都将在此条形图中。 我们可以沿X捕捉任何区域(几乎是无限的,但这里的double精度限制了我们),但是一切都很有趣,即 地球表面将在此范围内。 这种行为可以更改,但是在其中我们具有很大的灵活性。 只是不要忘了,高于或低于此范围的任何值都最无趣,因为上方的值很可能是空值,而下方的值是地面值。 (正如您很快就会看到的那样,该语句很可能是错误的。)对于本系列中的大多数图像,我将匹配2D空间中正方形(0,1)->(1,0)给出的正方形区域。 因此,一开始我们的世界看起来像这样:


到目前为止,没有什么有趣的事。 而且,该图像不能回答“给定点是实心还是空心?”的问题。 为了回答这个问题,我们需要应用Step Function (逐段定义的函数)。 除了平滑的梯度,我们还需要进行清晰的分离,其中一侧的所有位置都是空心的,而另一侧的所有位置都是实心的。 在ANL中,可以使用“ 选择”功能来实现。 Select函数接收两个传入的函数或值(在这种情况下,它们将等于“ solid”和“ hollow”(打开)),并根据控制函数的值(在这种情况下为Gradient)来选择它们。 选择模块有两个附加参数, 阈值衰减 ,它们会影响此过程。 在此阶段, 衰减是不可取的,因此我们将其设为0。threshold参数决定了Solid和Open之间的分界线将移至何处。 大于Gradient函数中该值的所有内容将变为Solid,小于阈值的所有内容将变为Open。 由于Gradient将间隔与0和1之间的值进行比较,因此将阈值设置为0.5是合乎逻辑的。 因此,我们将空间精确地分成两半。 值1将为实心位置,而值0将为空心。 也就是说,我们定义地平面的功能如下:

 terraintree =
 {
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1},
	 {name =“ ground_select”,类型=“ select”,低= 0,高= 1,阈值= 0.5,控制=“ ground_gradient”}
 }

比较与以前相同的功能区域,我们得到类似的结果:


这张图片清楚地回答了给定点是实心还是空心的问题。 我们可以使用2D空间的任何可能坐标来调用该函数,其结果将为1或0,这取决于该点相对于地球表面的位置。 但是,这种功能并不是特别有趣,它只是一条延伸到无穷大的扁平线。 为了使图像恢复原状,我们使用了一种称为“湍流”的技术。

“湍流”是将值添加到函数的传入坐标的概念的复杂名称。 想象一下,我们用坐标(0,1)调用地球的上述函数。 它位于地平面上方,因为在Y = 1时,坡度值为0,小于阈值= 0.5。 即,该点将被计算为开放。 但是,如果在调用地球功能之前,我们以某种方式改变了这一点呢? 假设我们从Y坐标中减去一个随机值,例如3。我们减去3并获得坐标(0,-2)。 如果现在我们为此点调用ground函数,则该点将被视为实体,因为Y = -2位于对应于1的渐变线段之下。突然,空心点(0,1)变为实体。 我们将在空中悬挂一块坚固的石头。 在调用ground_select函数之前,可以通过在输入点的Y坐标上添加或减去一个随机数来对函数中的任何点进行此操作。 这是ground_select函数的图像,显​​示了这一点。 在调用ground_select函数之前,将间隔(-0.25,0.25)中的值添加到每个点的Y坐标。


这比一条平线更有趣,但与地球并不十分相似,因为每个点都移动到一个完全随机的值,从而产生了混沌模式。 但是,如果我们使用连续随机函数(例如,来自ANL库的Fractal) ,那么我们将获得比其他随机模式更多的可控性。 因此,让我们将分形连接到地球平面,看看会发生什么。

 terraintree =
 {
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1},
	 {name =“ ground_shape_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 6,频率= 2},
	 {name =“ ground_scale”,type =“ scaleoffset”,scale = 0.5,offset = 0,来源=“ ground_shape_fractal”},
	 {name =“ ground_perturb”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ ground_scale”}},
	
	 {name =“ ground_select”,类型=“ select”,低= 0,高= 1,阈值= 0.5,控制=“ ground_perturb”}}
 }

这里需要注意几个方面。 首先,我们定义Fractal模块,并将其链接到ScaleOffset模块。 ScaleOffset模块将输出分形值缩放到更方便的水平。 浮雕的一部分可能在山区,并且需要更大的规模,而另一部分-比较平坦且规模较小。 稍后我们将讨论不同类型的地形,但是现在我们将使用它们进行演示。 现在,该函数的输出值如下图所示:


这比随机噪声更有趣,对吗? 至少,它看起来更像是土地,尽管部分景观看起来与众不同,而飞岛则完全陌生。 原因是输出图的每个单独点随机移动了由分形确定的不同值。 为了说明这一点,请显示执行变形的分形输出:


在上图中,所有黑点的值为-0.25,所有白点的值为0.25。 也就是说,在分形为黑色的情况下,地球功能的相应点将“向下”移动0.25。 (0.25表示屏幕的1/4。)由于一个点可以稍微移动,而其上方的另一点可以在空间上移动更大,则可能会出现岩石和飞岛的突起。 与飞岛相反,自然界中的突起很自然。 (除非我们在电影“阿凡达”中上映。)如果您的游戏需要如此奇妙的风景,那就太好了,但是如果您需要一个更逼真的模型,那么我们需要稍微调整分形函数。 幸运的是, ScaleDomain函数可以做到这一点

我们希望使该函数的行为类似于高度图函数。 想象一个2D高度图,其中地图上的每个点都代表一个点的高度,该点在向上或向下升高的网格点的网格中。 地图的白色值表示高丘陵,黑色-低谷。 我们需要类似的行为,但是要实现这一点,我们实际上需要摆脱其中一个维度。 对于高度图,我们从2D高度图创建3D高程。 同样,对于2D地形,我们需要一维高度图。 使具有相同Y坐标的分形的所有点都具有相同的值,我们可以将具有相同X坐标的所有点偏移相同的量,从而使飞行岛消失了。 为此,您可以使用ScaleDomain重置比例系数。 也就是说,在调用ground_shape_fractal函数之前,我们调用ground_scale_y将y坐标设置为0。这确保了Y值不会影响分形的输出,实际上将其转换为一维噪声函数。 为此,我们将进行以下更改:

 terraintree =
 {
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1},
	 {name =“ ground_shape_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 6,频率= 2},
	 {name =“ ground_scale”,type =“ scaleoffset”,scale = 0.5,offset = 0,来源=“ ground_shape_fractal”},
	 {name =“ ground_scale_y”,type =“ scaledomain”,来源=“ ground_scale”,scaley = 0},
	 {name =“ ground_perturb”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ ground_scale_y”},
	
	 {name =“ ground_select”,类型=“ select”,低= 0,高= 1,阈值= 0.5,控制=“ ground_perturb”}}
 }

我们将ScaleDomain函数与ground_scale链接在一起,然后将原始ground_perturb数据修改为ScaleDomain函数。 这将改变使地球移位的分形,并将其变成如下所示:


现在,如果我们看一下输出,就会得到结果:


好多了。 飞行的岛屿完全消失了,浮雕更像是山丘。 不幸的是,我们失去了突起和悬崖。 现在,整个地球都是连续且倾斜的。 如果您愿意,可以用几种方法解决此问题。

首先,您可以使用另一个TranslateDomain函数以及另一个Fractal函数。 如果在X方向上应用少量的分形湍流,我们可以使山的边缘和表面略微变形,这可能足以形成悬崖和壁架。 让我们看看它的实际作用。

 terraintree =
 {
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1},
	 {name =“ ground_shape_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 6,频率= 2},
	 {name =“ ground_scale”,type =“ scaleoffset”,scale = 0.5,offset = 0,来源=“ ground_shape_fractal”},
	 {name =“ ground_scale_y”,type =“ scaledomain”,来源=“ ground_scale”,scaley = 0},
	 {name =“ ground_perturb”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ ground_scale_y”},
	 {name =“ ground_overhang_fractal”,类型=“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 6,频率= 2},
	 {name =“ ground_overhang_scale”,类型=“ scaleoffset”,来源=“ ground_overhang_fractal”,scale = 0.2,偏移= 0},
	 {name =“ ground_overhang_perturb”,类型=“ translatedomain”,来源=“ ground_perturb”,tx =“ ground_overhang_scale”}},
	
	 {name =“ ground_select”,类型=“ select”,低= 0,高= 1,阈值= 0.5,控制=“ ground_overhang_perturb”}}
 }

结果如下:


第二种方法:您可以简单地将ground_scale_y函数的scaley参数设置为大于0 值。如果在Y中保留较小的比例尺,我们将得到变化的一部分,但是,比例尺越大,浮雕效果越强,类似于没有缩放的先前版本。


结果看起来比普通的坡山有趣得多。 但是,无论它们多么有趣,玩家仍然会厌倦以相同的方式探索浮雕,长达数公里。 另外,这样的救济将是非常不现实的。 在现实世界中,有很多可变性使地形变得更加有趣。 让我们看看如何使世界变得更加多样化。

查看前面的代码示例,您可以在其中看到一个特定的模式。 我们有一个梯度函数,该函数由赋予地球形状的函数控制,然后应用分段定义的函数并使地球变满。 也就是说,在地球塑形阶段使浮雕复杂化将更加合乎逻辑。 代替一个沿Y的分形位移和另一个沿X的位移,我们可以实现所需的复杂度(考虑到性能:每个分形都需要额外的计算成本,因此我们必须尝试保持保守。)我们可以指定地球的形式,即山脉,山麓,平坦的低地,荒地等...,并使用与低频分形链接的各种Select函数的输出来勾勒出每种类型的区域。 因此,让我们看看如何实现不同类型的地形。

为了说明这一原理,我们将救济分为三种类型:高原(平坦的坡地),山脉和低地(大多是平坦的)。 要在它们之间切换,我们使用基于选择的系统,并将它们组合成一个复杂的画布。 所以我们开始...

山麓:

有了它们,一切都很简单。 我们可以采用上面使用的方案,稍微降低山丘的振幅,甚至可以使它们具有比加性更大的减性。 降低平均身高。 我们还可以减少八度音阶数以使其平滑。

 {name =“ lowland_shape_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 2,频率= 1},
 {name =“ lowland_autocorrect”,类型=“ autocorrect”,来源=“ lowland_shape_fractal”,低= 0,高= 1},
 {name =“ lowland_scale”,类型=“ scaleoffset”,来源=“ lowland_autocorrect”,比例= 0.2,偏移= -0.25},
 {name =“ lowland_y_scale”,类型=“ scaledomain”,来源=“ lowland_scale”,scaley = 0},
 {name =“ lowland_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ lowland_y_scale”}},

高地:

他们的一切也很简单。 (实际上,这些地形类型都不难。)但是,我们使用了不同的依据来使山丘看起来像沙丘。

 {name =“ highland_shape_fractal”,type =“ fractal”,fractaltype = anl.RIDGEDMULTI,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 2,频率= 2},
 {name =“ highland_autocorrect”,类型=“ autocorrect”,来源=“ highland_shape_fractal”,低= 0,高= 1},
 {name =“ highland_scale”,类型=“ scaleoffset”,来源=“ highland_autocorrect”,比例= 0.45,偏移量= 0},
 {name =“ highland_y_scale”,type =“ scaledomain”,来源=“ highland_scale”,scaley = 0},
 {name =“ highland_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ highland_y_scale”}},

山脉:

 {name =“ mountain_shape_fractal”,type =“ fractal”,fractaltype = anl.BILLOW,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 4,频率= 1},
 {name =“ mountain_autocorrect”,类型=“ autocorrect”,来源=“ mountain_shape_fractal”,低= 0,高= 1},
 {name =“ mountain_scale”,类型=“ scaleoffset”,来源=“ mountain_autocorrect”,scale = 0.75,offset = 0.25},
 {name =“ mountain_y_scale”,type =“ scaledomain”,来源=“ mountain_scale”,scaley = 0.1},
 {name =“ mountain_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ mountain_y_scale”},

当然,您可以更加创造性地处理此过程,但是总的来说,模式将是这样。 我们突出显示浮雕类型的特征,并为它们选择噪声函数。 对于所有这些,都适用相同的原则。 主要区别是规模。 现在,要将它们连接在一起,我们将准备其他分形,这些分形将控制“ 选择”功能。 然后,我们链接选择模块以生成整个地形。

 {name =“ terrain_type_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 3,频率= 0.5},
 {name =“ terrain_autocorrect”,类型=“ autocorrect”,来源=“ terrain_type_fractal”,低= 0,高= 1},
 {name =“ terrain_type_cache”,type =“ cache”,来源=“ terrain_autocorrect”},
 {name =“ highland_mountain_select”,类型=“ select”,low =“ highland_terrain”,high =“ mountain_terrain”,控制=“ terrain_type_cache”,阈值= 0.55,衰减= 0.15},
 {name =“ highland_lowland_select”,类型=“ select”,low =“ lowland_terrain”,high =“ highland_mountain_select”,control =“ terrain_type_cache”,阈值= 0.25,衰减= 0.15},

因此,这里我们定义了三种主要的地形类型:低地,高地和山脉。 我们使用一个分形选择其中之一,以便进行自然过渡(低地->高地->山)。 然后,我们使用另一个分形将荒地随机插入地图中。 这是完成的模块链的样子:

 terraintree =
 {
	 {name =“ lowland_shape_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 2,频率= 1},
	 {name =“ lowland_autocorrect”,类型=“ autocorrect”,来源=“ lowland_shape_fractal”,低= 0,高= 1},
	 {name =“ lowland_scale”,类型=“ scaleoffset”,来源=“ lowland_autocorrect”,比例= 0.2,偏移= -0.25},
	 {name =“ lowland_y_scale”,类型=“ scaledomain”,来源=“ lowland_scale”,scaley = 0},
	 {name =“ lowland_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ lowland_y_scale”}},
	 {name =“ ground_gradient”,type =“ gradient”,x1 = 0,x2 = 0,y1 = 0,y2 = 1},
	 {name =“ highland_shape_fractal”,type =“ fractal”,fractaltype = anl.RIDGEDMULTI,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 2,频率= 2},
	 {name =“ highland_autocorrect”,类型=“ autocorrect”,来源=“ highland_shape_fractal”,低= 0,高= 1},
	 {name =“ highland_scale”,类型=“ scaleoffset”,来源=“ highland_autocorrect”,比例= 0.45,偏移量= 0},
	 {name =“ highland_y_scale”,type =“ scaledomain”,来源=“ highland_scale”,scaley = 0},
	 {name =“ highland_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ highland_y_scale”}},

	 {name =“ mountain_shape_fractal”,type =“ fractal”,fractaltype = anl.BILLOW,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 4,频率= 1},
	 {name =“ mountain_autocorrect”,类型=“ autocorrect”,来源=“ mountain_shape_fractal”,低= 0,高= 1},
	 {name =“ mountain_scale”,类型=“ scaleoffset”,来源=“ mountain_autocorrect”,scale = 0.75,offset = 0.25},
	 {name =“ mountain_y_scale”,type =“ scaledomain”,来源=“ mountain_scale”,scaley = 0.1},
	 {name =“ mountain_terrain”,类型=“ translatedomain”,来源=“ ground_gradient”,ty =“ mountain_y_scale”},

	 {name =“ terrain_type_fractal”,type =“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 3,频率= 0.5},
	 {name =“ terrain_autocorrect”,类型=“ autocorrect”,来源=“ terrain_type_fractal”,低= 0,高= 1},
	 {name =“ terrain_type_cache”,type =“ cache”,来源=“ terrain_autocorrect”},
	 {name =“ highland_mountain_select”,类型=“ select”,low =“ highland_terrain”,high =“ mountain_terrain”,控制=“ terrain_type_cache”,阈值= 0.55,衰减= 0.15},
	 {name =“ highland_lowland_select”,类型=“ select”,low =“ lowland_terrain”,high =“ highland_mountain_select”,control =“ terrain_type_cache”,阈值= 0.25,衰减= 0.15},
	 {name =“ ground_select”,类型=“ select”,低= 0,高= 1,阈值= 0.5,控制=“ highland_lowland_select”}
 }

以下是产生的救济的一些示例:




您可能会注意到获得了相当高的可变性。 在某些地方,高耸的断山出现,在另一些地方,则有光滑的倾斜平原。 现在,我们需要添加洞穴,以便我们能够探索地下世界的奇观。

对于洞穴,我使用应用于ground_select的乘法系统。 也就是说,我创建了一个输出1或0的函数,然后将它们乘以ground_select的输出。 因此,函数的任何点都变为空心,其洞穴函数的值为0。也就是说,在要获取该洞穴的地方,该洞穴的函数应返回0,而当该洞穴不应为该函数时,函数应返回1。洞穴,我想基于1-octave Ridged Multifractal建立一个洞穴系统。

 {name =“ cave_shape”,type =“ fractal”,fractaltype = anl.RIDGEDMULTI,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 1,频率= 2},

结果是这样的:


如果我们将Select函数作为分段定义函数应用(如我们对地球坡度所做的那样),则将其实现为使得选择阈值的下部为1(无洞穴),上部为0(有洞穴),结果将类似于以下内容:

 {name =“ cave_shape”,type =“ fractal”,fractaltype = anl.RIDGEDMULTI,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 1,频率= 2},
 {name =“ cave_select”,type =“ select”,低= 1,高= 0,控制=“ cave_shape”,阈值= 0.8,衰减= 0},

结果:


当然,它看起来非常平滑,因此请添加一些分形噪声以使该区域变形。

 {name =“ cave_shape”,type =“ fractal”,fractaltype = anl.RIDGEDMULTI,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 1,频率= 2},
 {name =“ cave_select”,type =“ select”,低= 1,高= 0,控制=“ cave_shape”,阈值= 0.8,衰减= 0},
 {name =“ cave_perturb_fractal”,类型=“ fractal”,fractaltype = anl.FBM,基本类型= anl.GRADIENT,interptype = anl.QUINTIC,八度= 6,频率= 3},
 {name =“ cave_perturb_scale”,类型=“ scaleoffset”,来源=“ cave_perturb_fractal”,scale = 0.25,offset = 0},
{name="cave_perturb", type="translatedomain", source="cave_select", tx="cave_perturb_scale"},

:


. , , :


threshold cave_select , . , — , . highland_lowland_select , , , , . , , . , . , highland_lowland_select cave_shape , . — Cache . , , , . , ( highland_lowland_select ) . . , :

{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},

Cache, ground_select , , . , :

{name="cave_shape", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape", source_1="cave_attenuate_bias"},
{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},

Bias . , . cave_shape_attenuate , Combiner anl::MULT . cave_shape . cave_perturb . :


, . ( , , . — , - , (0,1).) , , , , . , .

terraintree=
 {
	{name="ground_gradient", type="gradient", x1=0, x2=0, y1=0, y2=1},
	
	{name="lowland_shape_fractal", type="fractal", fractaltype=anl.BILLOW, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=2, frequency=0.25},
	{name="lowland_autocorrect", type="autocorrect", source="lowland_shape_fractal", low=0, high=1},
	{name="lowland_scale", type="scaleoffset", source="lowland_autocorrect", scale=0.125, offset=-0.45},
	{name="lowland_y_scale", type="scaledomain", source="lowland_scale", scaley=0},
	{name="lowland_terrain", type="translatedomain", source="ground_gradient", ty="lowland_y_scale"},
	
	{name="highland_shape_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=4, frequency=2},
	{name="highland_autocorrect", type="autocorrect", source="highland_shape_fractal", low=-1, high=1},
	{name="highland_scale", type="scaleoffset", source="highland_autocorrect", scale=0.25, offset=0},
	{name="highland_y_scale", type="scaledomain", source="highland_scale", scaley=0},
	{name="highland_terrain", type="translatedomain", source="ground_gradient", ty="highland_y_scale"},

	{name="mountain_shape_fractal", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=8, frequency=1},
	{name="mountain_autocorrect", type="autocorrect", source="mountain_shape_fractal", low=-1, high=1},
	{name="mountain_scale", type="scaleoffset", source="mountain_autocorrect", scale=0.45, offset=0.15},
	{name="mountain_y_scale", type="scaledomain", source="mountain_scale", scaley=0.25},
	{name="mountain_terrain", type="translatedomain", source="ground_gradient", ty="mountain_y_scale"},

	{name="terrain_type_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=3, frequency=0.125},
	{name="terrain_autocorrect", type="autocorrect", source="terrain_type_fractal", low=0, high=1},
	{name="terrain_type_y_scale", type="scaledomain", source="terrain_autocorrect", scaley=0},
	{name="terrain_type_cache", type="cache", source="terrain_type_y_scale"},
	{name="highland_mountain_select", type="select", low="highland_terrain", high="mountain_terrain", control="terrain_type_cache", threshold=0.55, falloff=0.2},
	{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
	{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
	{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},
	
	{name="cave_shape", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
	{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape", source_1="cave_attenuate_bias"},
	{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
	{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
	{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
	{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},
	
	{name="ground_cave_multiply", type="combiner", operation=anl.MULT, source_0="cave_select", source_1="ground_select"}
 }

, :




. , . . , . ? ? , , , . , . .

, . threshold cave_select cave_attenuate_bias , cave_attenuate_bias , , . , Y, X ( , X). , cave_shape_attenuate , , (, ), . select terrain_type_fractal , , . , , , , , , . , .


. . , , , . , . , . ScaleOffset , . 2D , 3D , .

3D


, Terraria King Arthur's Gold , , Minecraft Infiniminer ? ? , . 3D-. 3D-, 3D- , Y , 2D-. - , , . , Ridged Multifractal 2D- , 3D , , . 3D , 1- Ridged Multifractal, seed. Select 1 0, . , , , , .

terraintree3d=
 {
	{name="ground_gradient", type="gradient", x1=0, x2=0, y1=0, y2=1},
	
	{name="lowland_shape_fractal", type="fractal", fractaltype=anl.BILLOW, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=2, frequency=0.25},
	{name="lowland_autocorrect", type="autocorrect", source="lowland_shape_fractal", low=0, high=1},
	{name="lowland_scale", type="scaleoffset", source="lowland_autocorrect", scale=0.125, offset=-0.45},
	{name="lowland_y_scale", type="scaledomain", source="lowland_scale", scaley=0},
	{name="lowland_terrain", type="translatedomain", source="ground_gradient", ty="lowland_y_scale"},
	
	{name="highland_shape_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=4, frequency=2},
	{name="highland_autocorrect", type="autocorrect", source="highland_shape_fractal", low=-1, high=1},
	{name="highland_scale", type="scaleoffset", source="highland_autocorrect", scale=0.25, offset=0},
	{name="highland_y_scale", type="scaledomain", source="highland_scale", scaley=0},
	{name="highland_terrain", type="translatedomain", source="ground_gradient", ty="highland_y_scale"},

	{name="mountain_shape_fractal", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=8, frequency=1},
	{name="mountain_autocorrect", type="autocorrect", source="mountain_shape_fractal", low=-1, high=1},
	{name="mountain_scale", type="scaleoffset", source="mountain_autocorrect", scale=0.45, offset=0.15},
	{name="mountain_y_scale", type="scaledomain", source="mountain_scale", scaley=0.25},
	{name="mountain_terrain", type="translatedomain", source="ground_gradient", ty="mountain_y_scale"},

	{name="terrain_type_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=3, frequency=0.125},
	{name="terrain_autocorrect", type="autocorrect", source="terrain_type_fractal", low=0, high=1},
	{name="terrain_type_y_scale", type="scaledomain", source="terrain_autocorrect", scaley=0},
	{name="terrain_type_cache", type="cache", source="terrain_type_y_scale"},
	{name="highland_mountain_select", type="select", low="highland_terrain", high="mountain_terrain", control="terrain_type_cache", threshold=0.55, falloff=0.2},
	{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
	{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
	{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},
	
	{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
	{name="cave_shape1", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_shape2", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape1", source_1="cave_attenuate_bias", source_2="cave_shape2"},             
	{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
	{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
	{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
	{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},
	
	{name="ground_cave_multiply", type="combiner", operation=anl.MULT, source_0="cave_select", source_1="ground_select"}
 }

:



, . , , , , .… , , .

Source: https://habr.com/ru/post/zh-CN472574/


All Articles