如何产生闪电效果?


26

有生成雷电的算法吗?

我想要一种算法,该算法生成指定螺栓将在何处着陆的线段或点对象的列表。该方法将需要一个起点参数以及一个端点。螺栓应具有随机的分支,并以随机的间隔曲折弯曲。结果将是随机的闪电效果,看起来像这样


(来源:wikimedia.org

如果有人知道可以使用的算法,将不胜感激!


2
Nvidia的这篇论文应该是您所需要的,尽管它可能太广泛了。查看幻灯片7至11,它们具有一些不错的图像,应该使您对目标有所了解。如果您单击第二个链接,则会找到源代码(C ++,Direct3D)。developer.download.nvidia.com/SDK/10/direct3d/Source/Lightning/... developer.download.nvidia.com/SDK/10/direct3d/samples.html
故障

Answers:


32

您可以使用一种相当简单的算法来生成照明螺栓。

从螺栓的原点(O)和终点(E)之间的线段开始

在该线上选择一个点(大约或恰好在中间),将其称为S并将线段分为两个线段(O->SS->E)。置换S从原来的线段(沿段的正常)通过一些小的随机量之遥。这给您一个闪电般的“弯曲”。

计算折弯后,基于一个很小的随机机会,您需要添加第三条线段(通常是该O->S线段的扩展部分)。这就是您在闪电中产生“叉子”的方式。通常,您需要在此生成过程中跟踪有关螺栓强度的信息,因为您希望叉变得更暗或更模糊:

在此处输入图片说明

然后,对您拥有的所有新线段重复上述过程;您需要选择一个重复的数量以产生您喜欢的形状:

在此处输入图片说明

我的朋友的博客在这里对此技术有一个相当清晰的解释(这是我无耻地偷走照片的地方);关于增加光晕效果,它也有更多的深度。

最后,在NVIDIA的这篇论文中,也描述了相同的基本算法(还有更多详细信息)。


13

我会推荐另一种方法:快速探索随机树(RRT)。关于它的一件很酷的事情是,您可以使它转弯或向各个方向爆炸。

该算法非常基本:

// Returns a random tree containing the start and the goal.
// Grows the tree for a maximum number of iterations.
Tree RRT(Node start, Node goal, int maxIters)
{
    // Initialize a tree with a root as the start node.
    Tree t = new Tree();
    t.Root = start;


    bool reachedGoal = false;
    int iter = 0;

    // Keep growing the tree until it contains the goal and we've
    // grown for the required number of iterations.
    while (!reachedGoal || iter < maxIters)
    {
         // Get a random node somewhere near the goal
         Node random = RandomSample(goal);
         // Get the closest node in the tree to the sample.
         Node closest = t.GetClosestNode(random);
         // Create a new node between the closest node and the sample.
         Node extension = ExtendToward(closest, random);
         // If we managed to create a new node, add it to the tree.
         if (extension)
         {
             closest.AddChild(extension);

             // If we haven't yet reached the goal, and the new node
             // is very near the goal, add the goal to the tree.
             if(!reachedGoal && extension.IsNear(goal))
             {
                extension.AddChild(goal);
                reachedGoal = true;
             }
         }
         iter++;
    }
    return t;
}

通过修改RandomSampleExtendToward函数,可以得到非常不同的树。如果RandomSample仅在各处均匀采样,则树将在各个方向均匀生长。如果其偏向目标,则树将趋向于向目标生长。如果始终对目标进行采样,则树将是从起点到目标的直线。

ExtendToward也可以让您对树进行有趣的操作。一方面,如果您有障碍物(例如墙壁),则可以通过拒绝与墙壁碰撞的扩展来使树它们周围生长。

当您不将采样偏向目标时,它看起来像这样:

img
(来源:uiuc.edu

这就是墙壁的样子

RRT的一些很酷的特性完成后:

  • RRT 永远不会超越自己
  • RRT最终将以越来越小的分支覆盖整个空间
  • 从开始到实现目标的路径可能是完全随机且怪异的。

我只是使用此算法来生成闪电动画。我必须说效果很好!代码中有一个主要的错别字,例如iter不会在每个循环中递增。除此之外,这几乎已准备好按发布使用
applejacks01 '02
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.