【问题标题】:Diamond Square Algorithm creates diagonal cut钻石平方算法创建对角线切割
【发布时间】:2017-05-22 13:32:14
【问题描述】:

我在空闲时间正在做的事情有点问题: 我想通过 DSA 在 C++ 中创建一个高度图。但它没有按我的计划工作。 我的代码是(请忽略两个字符 cmets):

void DiamondSquareAlgorithm(int x1, int y1, int x2, int y2, float range, unsigned level)
{
    //level = size - 1 when called the first time

    if (level < 1) return;
    float a;
    float b;
    float c;
    float d;
    float e;
    for (int i = x1; i < x2; i += level)
    {
        for (int j = y1; j < y2; j += level)
        {
            //diamond
            a = startArr[i + j * (x2 - x1 + 1)]; //lo
            b = startArr[(i + level) + j * (x2 - x1 + 1)]; //ro
            c = startArr[i + (j + level) * (x2 - x1 + 1)]; //lu
            d = startArr[(i + level) + (j + level) * (x2 - x1 + 1)]; //ru
            e = startArr[(i + level / 2) + (j + level / 2) * (x2 - x1 + 1)] = (a + b + c + d) / 4;
        }
    }

    for (int i = x1; i < x2; i += level)
    {
        for (int j = y1; j < y2; j += level)
        {
            a = startArr[i + j * (x2 - x1 + 1)]; //lo
            b = startArr[(i + level) + j * (x2 - x1 + 1)]; //ro
            c = startArr[i + (j + level) * (x2 - x1 + 1)]; //lu
            d = startArr[(i + level) + (j + level) * (x2 - x1 + 1)]; //ru
            e = startArr[(i + level / 2) + (j + level / 2) * (x2 - x1 + 1)] = (a + b + c + d) / 4;

            //square
            startArr[(i + level / 2) + j * (x2 - x1 + 1)] = (a + b + e) / 3; //o
            startArr[(i + level) + (j + level / 2) * (x2 - x1 + 1)] = (b + d + e) / 3; //r
            startArr[(i + level / 2) + (j + level) * (x2 - x1 + 1)] = (d + c + e) / 3; //u
            startArr[i + (j + level / 2) * (x2 - x1 + 1)] = (a + c + e) / 3; //l
        }
    }
    DiamondSquareAlgorithm(x1, y1, x2, y2, range / 2, (level / 2));
};

结果总是这样的:

有人可以帮我找出我在代码中犯的明显严重错误吗?

【问题讨论】:

  • 我不确定是什么问题。您应该尝试添加整个代码。我不确定startArr 的大小(计算上的偏移量)和参数或输出。您可以将代码添加到:ideone.com 吗?
  • 不要理解第 11 行到第 22 行的代码块是什么。只需将值分配给 a, b, c, d, e
  • 代码末尾的分号不是问题吗? (那不应该编译)
  • 这里发生了几件事。您的算法仅在 x1y1 为零时才有效,否则索引平面数组将不正确。你也应该在level &lt;= 1 时停止递归;当level == 1 时,您将覆盖左侧和顶部单元格。你的第一个循环,正方形,是正确的,但菱形不是。钻石也需要四个源单元格,但可能在边界处除外。您的右侧和底部中点将被随后的左侧和顶部中点覆盖。

标签: c++ algorithm game-engine terrain


【解决方案1】:

我终于发现了我的代码的问题。上面的大部分内容都是正确的,除了一件小事:它不应该是 (x2 - x1 + 1)。这会将数组中的每个值进一步移动一个空格。每一步都会发生这种情况,因此出现了这条对角线;正确且有效的代码是

void DiamondSquareAlgorithm(int x1, int y1, int x2, int y2, float range, unsigned level)
{
    //level = size - 1 when called the first time
    if (level <= 1) return;
    float a;
    float b;
    float c;
    float d;
    float e;
    int width = x2 - x1;
    for (int y = x1; y < x2; y += level)
    {
        for (int x = y1; x < y2; x += level)
        {
            //diamond
            a = startArr[x + y * width]; //lo
            b = startArr[(x + level) + y * width]; //ro
            c = startArr[x + (y + level) * width]; //lu
            d = startArr[(x + level) + (y + level) * width]; //ru
            e = startArr[(x + level / 2) + (y + level / 2) * width] = Fit(((a + b + c + d) / 4) + Random(-1, 1) * range);
        }
    }
    for (int y = x1; y < x2; y += level)
    {
        for (int x = y1; x < y2; x += level)
        {
            a = startArr[x + y * width]; //lo
            b = startArr[(x + level) + y * width]; //ro
            c = startArr[x + (y + level) * width]; //lu
            d = startArr[(x + level) + (y + level) * width]; //ru
            e = startArr[(x + level / 2) + (y + level / 2) * width];

            //square
            startArr[(x + level / 2) + y * width] = Fit(((a + b + e) / 3) + Random(-0.5, 0.5) * range); //o
            startArr[(x + level) + (y + level / 2) * width] = Fit(((b + d + e) / 3) + Random(-0.5, 0.5) * range); //r
            startArr[(x + level / 2) + (y + level) * width] = Fit(((d + c + e) / 3) + Random(-0.5, 0.5) * range); //u
            startArr[x + (y + level / 2) * width] = Fit(((a + c + e) / 3) + Random(-0.5, 0.5) * range); //l
        }
    }
    DiamondSquareAlgorithm(x1, y1, x2, y2, range / 2, (level / 2));
};

float Fit(float x) 是一种采用浮点数并将其与 0 和 1 进行比较的方法,因此没有大于 1 的值,也没有小于 0 的值; float Random(float a, float b) 只是为您提供两个浮点数之间的随机浮点数。 heightfield

【讨论】:

  • 你发现了错误很好,但是这里的社区很难找到,因为你没有显示函数是如何被调用的,即参数x2和@987654326是什么@是,尽管被要求这样做。 (事后看来,对角线很明显,但仍然如此。)
猜你喜欢
  • 2016-11-08
  • 2014-03-22
  • 1970-01-01
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 2018-01-28
相关资源
最近更新 更多