【问题标题】:How to implement midpoint displacement如何实现中点位移
【发布时间】:2014-01-03 04:04:45
【问题描述】:

我正在尝试在我的游戏中实现程序生成。我想真正掌握和理解所有必要的算法,而不是简单地复制/粘贴现有​​代码。为了做到这一点,我尝试自己实现一维中点位移。我使用here 的信息来编写和指导我的代码。下面是我完成的代码,它不会抛出错误,但结果似乎不正确。

srand(time(NULL));

const int lineLength = 65;
float range = 1.0;
float displacedLine[lineLength];

for (int i = 0; i < lineLength; i++)
{
    displacedLine[i] = 0.0;
}

for (int p = 0; p < 100; p++)
{
    int segments = 1;
    for (int i = 0; i < (lineLength / pow(2, 2)); i++)
    {
        int segs = segments;
        for (int j = 0; j < segs; j++)
        {
            int x = floor(lineLength / segs);
            int start = (j * x) + 1;
            int end = start + x;
            if (i == 0)
            {
                end--;
            }
            float lo = -range;
            float hi = +range;
            float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));

            int center = ((end - start) / 2) + start;
            displacedLine[center - 1] += change;
            segments++;
        }
        range /= 2;
    }
}

我到底在哪里犯了错误,我该如何纠正?

我得到这样的结果:

但我期待这样的结果:

【问题讨论】:

  • 那么您期望得到什么结果?这些结果与您的代码产生的结果相比如何?
  • 我不完全确定如何正确地将我的点渲染成线条,所以我粗略地尝试渲染结果,但它们似乎不正确。
  • @Simon 我添加了图片来澄清我的结果。

标签: c++ algorithm procedural-generation


【解决方案1】:

答案非常简单,顺便说一句,我印象深刻的是,您设法调试了代码中所有潜在的非一错误。以下行是错误的:

displacedLine[center - 1] += change;

您正确计算了中心索引和更改量,但您错过了应将更改应用于高度中点。那就是:

displacedLine[center - 1] = (displacedLine[start] + displacedLine[end]) / 2;
displacedLine[center - 1] += change;

我相信你明白了。

【讨论】:

    【解决方案2】:

    问题似乎是您只更改每条线段的中点,而不是更改线段的其余部分与其从每一端到中点的距离成比例。以下代码似乎为您提供了更像您正在寻找的东西:

    #include <iostream>
    #include <cstdlib>
    #include <math.h>
    #include <algorithm>
    
    using namespace std;
    
    void displaceMidPt (float dline[], int len, float disp) {
        int midPt = len/2;
        float fmidPt = float(midPt);
        for (int i = 1; i <= midPt; i++) {
            float ptDisp = disp * float(i)/fmidPt;
            dline[i] += ptDisp;
            dline[len-i] += ptDisp;
        }
    }
    
    void displace (float displacedLine[], int lineLength, float range) {
        for (int p = 0; p < 100; p++) {
            int segs = pow(p, 2);
            for (int j = 0; j < segs; j++) {
                float lo = -range;
                float hi = +range;
                float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));
                int start = int(float(j)/float(segs)*float(lineLength));
                int end = int(float(j+1)/float(segs)*float(lineLength));
                displaceMidPt (displacedLine+start,end-start,change);
                }
            range /= 2;
        }
    }
    
    void plot1D (float x[], int len, int ht = 10) {
        float minX = *min_element(x,x+len);
        float maxX = *max_element(x,x+len);
        int xi[len];
        for (int i = 0; i < len; i++) {
            xi[i] = int(ht*(x[i] - minX)/(maxX - minX) + 0.5);
        }
        char s[len+1];
        s[len] = '\0';
        for (int j = ht; j >= 0; j--) {
            for (int i = 0; i < len; i++) {
                if (xi[i] == j) {
                    s[i] = '*';
                } else {
                    s[i] = ' ';
                }
            }
            cout << s << endl;
        }
    }
    
    int main () {
        srand(time(NULL));
    
        const int lineLength = 65;
        float range = 1.0;
        float displacedLine[lineLength];
    
        for (int i = 0; i < lineLength; i++) {
            displacedLine[i] = 0.0;
        }
    
        displace (displacedLine,lineLength,range);
        plot1D (displacedLine,lineLength);
        return 0;
    }
    

    以这种方式运行时,会产生以下结果:

    $ c++ -lm displace.cpp
    $ ./a
                                      *
                                  *       *
                                     * ***
                                 * *       *             *
                             * **            ****       * **
          * ***  ****  *   *                *    **         *
         * *   **    ** ***   *     *                * *
       **                                          **        *
      *                     *                         *       ***
    **                                                            ***
                                                                 *
    

    【讨论】:

      猜你喜欢
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      相关资源
      最近更新 更多