我创建了一个类似于您在3D环境中所追求的系统。我有一个视频短片,说明它的简单机械在这里和博客文章在这里。
这是我在不可见的墙壁(高速播放)后面的压力力学制成的一点gif:
让我解释所涉及的数据,以了解系统的某些功能。在当前系统中,每块水包含2字节的内容:
//Data2 Data
//______________________________ _____________________________________
//|0 |0 |000 |000 | |0 |0 |000 |000 |
//|Extra|FlowOut|Active|Largest| |HasSource|IsSource|Direction|Height|
//------------------------------ -------------------------------------
Height
是立方体中的水量,类似于您的压力,但是我的系统只有8个水位。
Direction
是流动的方向。在决定下一个水流向何处时,它更有可能沿当前方向继续流动。在需要时,它还可用于快速向后追溯流回到其源多维数据集。
IsSource
指示此多维数据集是否为源多维数据集,这意味着它永远不会耗尽水。用于河流,泉水等的源。例如,上方gif左侧的多维数据集是源多维数据集。
HasSource
指示此多维数据集是否已连接到源多维数据集。连接到水源时,多维数据集将尝试在寻找其他“更饱满”的非水源多维数据集之前,先从水源中获取更多的水。
Largest
告诉此多维数据集及其源多维数据集之间最大的流量是多少。这意味着,如果水流过一个狭窄的缝隙,它将限制该立方体的流量。
Active
是一个柜台。当此多维数据集有活动流经过,到达或从中流出时,活动流将递增。否则,活动值将随机减少。一旦激活达到零(意味着不激活),该立方体中的水量将开始减少。这种行为就像蒸发或浸入地下。(如果有流量,就应该退潮!)
FlowOut
指示此多维数据集是否已连接到位于世界边缘的多维数据集。一旦建立了通往世界边缘的道路,水往往会优先选择该道路。
Extra
是将来使用的额外费用。
既然我们已经知道了数据,那么让我们看一下该算法的高级概述。该系统的基本思想是优先考虑流出和流出。正如我在视频中解释的那样,我从头开始工作。每层水在y轴上一次处理一次。每个级别的多维数据集都是随机处理的,每个多维数据集将在每次迭代中尝试从其源中抽取水。
流动立方体按照其流动方向返回,从水源中拉出水,直到它们到达水源立方体或没有母体的流动立方体。将流动方向存储在每个多维数据集中,使遵循到源的路径就像遍历链表一样容易。
该算法的伪代码如下:
for i = 0 to topOfWorld //from the bottom to the top
while flowouts[i].hasitems() //while this layer has flow outs
flowout = removeRandom(flowouts[i]) //select one randomly
srcpath = getPathToParent(flowout) //get the path to its parent
//set cubes as active and update their "largest" value
//also removes flow from the source for this flow cycle
srcpath.setActiveAndFlux()
//now we deal with regular flow
for i = 0 to topOfWorld //from the bottom to the top
while activeflows[i].hasitems() //while this layer has water
flowcube = removeRandom(activeflows[i]) //select one randomly
//if the current cube is already full, try to distribute to immediate neighbors
flowamt = 0
if flowcube.isfull
flowamt = flowcube.settleToSurrounding
else
srcpath = getPathToParent(flowcube) //get the path to its parent
flowamt = srcpath.setActiveAndFlux()
flowcube.addflow(flowamt)
//if we didn't end up moving any flow this iteration, reduce the activity
//if activity is 0 already, use a small random chance of removing flow
if flowamt == 0
flowcube.reduceActive()
refillSourceCubes()
扩展流的基本规则,其中(按优先级排序):
- 如果下面的立方体水少,则向下流
- 如果相邻的同一个立方体的水较少,则横向流动。
- 如果上方的多维数据集的水较少,并且源多维数据集高于上方的多维数据集,则向上流动。
我知道,那是很高的水平。但它很难进入更详细的没有得到的方式进入细节。
该系统运行良好。我可以很容易地装满水坑,水溢出继续向外延伸。如上图所示,我可以填满U形隧道。但是,正如我所说,系统不完整,我还没有解决所有问题。我已经很长时间没有在流量系统上工作了(我认为alpha不需要它,所以我将其搁置)。但是,当我将其置于以下位置时,我正在处理的问题是:
水池。当得到一大堆水时,从儿童到父母的指针就像是一团乱麻,无论选择了哪个随机立方体都可以向任何方向流动。就像用愚蠢的绳子填充浴缸一样。当您想排干木盆时,您是否应该沿着傻弦的路径回到其根源?还是应该随便拿什么?因此,在多维数据集位于一个大池中的情况下,它们可能应该只是忽略其父流,而从其上方的任何内容中拉取。为此,我想出了一些基本的工作代码,但是从来没有一个我满意的优雅解决方案。
多父母。一个子流很容易由多个父流提供。但是孩子有一个指向单亲的指针是不允许的。可以通过使用足够的位以允许每个可能的父方向使用一个位来解决此问题。如果有多个双亲,可能会更改算法以随机选择一条路径。但是,我从来没有绕过它来测试和查看可能会出现的其他问题。