这个中点位移算法的“粗糙常数”是什么,我该如何修改它?

时间:2016-12-08 06:06:24

标签: algorithm recursion graph terrain procedural-generation

我从"Midpoint displacement algorithm example"获取代码,将其清理干净,并将其重新用作一维线性地形生成器。以下是doMidpoint()方法的新版本:

public boolean setMidpointDisplacement(int x1, int x2) {
      // Exit recursion if points are next to eachother
      if (x2 - x1 < 2) {
          return false;
      }

      final int midX = (x1 + x2) / 2;
      final int dist = x2 - x1;
      final int distHalf = dist / 2;

      final int y1 =  map[x1];
      final int y2 = map[x2];
      final int delta = random.nextInt(dist) - distHalf;    // +/- half the distance
      final int sum = y1 + y2;
      map[midX] = (sum + delta) / 2;  // Sets the midpoint

      // Divide and repeat
      setMidpointDisplacement(x1, midX);
      setMidpointDisplacement(midX, x2);

      return true;

}

代码似乎运行良好并产生可行的地形(你可以看到how I've tested it,带有基本的GUI)

阅读"Generating Random Fractal Terrain""Mid Point Displacement Algorithm"后,我的问题是:

如何识别此代码隐式使用的“粗糙度常量”?然后,我该如何改变呢?

此外,这可能与我的主要问题直接相关,也可能没有,但我注意到代码将y值的总和加到“delta”(变化量)并将其除以2 - - 尽管这与求和的平均值相同,然后加上delta / 2。这与“粗糙度常数”有关吗?我在想我能做到

map[midX] = sum/2 + delta/K;

和K现在代表'粗糙度常数',但我不确定这是否准确,因为它似乎允许我控制平滑但不直接控制“随机数是多少每次通过“生成随机分形地形”定义的循环减少范围。

就像我之前说过的那样,我将我发现的2D MDP噪声发生器移植到一维版本中 - 但我相当确定我做到了准确,所以这不是任何问题的根源。

1 个答案:

答案 0 :(得分:1)

  

如何识别粗糙度常数&#39;这段代码隐含地使用了什么?

cited中,粗糙度是减少最大随机位移的量。当你的位移是random.nextInt(dist) = dist*random.nextDouble()时,你的dist = x2-x1和你从一个递归步骤走到另一个递归步骤,其中一半是这个dist,它跟随roughness == 1(在引用的术语中)

  

然后,我该如何改变呢?

public boolean setMidpointDisplacement(int x1, int x2, int roughness) {
  // Exit recursion if points are next to eachother
  if (x2 - x1 < 2) {
      return false;
  }

  // this is 2^-roughness as per cited
  // you can pass it precalculated as a param, using it as such here
  // is only to put it into a relation with the cited
  double factor=1.0/(1<<roughness);

  final int midX = (x1 + x2) / 2;
  final int dist = x2 - x1;
  final int distHalf = dist / 2;

  final int y1 =  map[x1];
  final int y2 = map[x2];
  // and you apply it here. A cast will be necessary though
  final int delta = factor*(random.nextInt(dist) - distHalf);    // +/- half the distance

  final int sum = y1 + y2;
  map[midX] = (sum + delta) / 2;  // Sets the midpoint

  // Divide and repeat
  setMidpointDisplacement(x1, midX, roughness);
  setMidpointDisplacement(midX, x2, roughness);

  return true;

}
  

此外,这可能与我的主要问题直接相关,也可能没有,但我注意到代码将y值的总和加到了&#34; delta&#34; (改变金额)并将其除以2

他们的方式具有通过单一划分来实现它的优势。在处理int时,累积的截断误差会因单个div而变小(更不用说稍快一点)。