gpt4 book ai didi

java - 中点位移地形伪影

转载 作者:行者123 更新时间:2023-11-30 09:47:57 26 4
gpt4 key购买 nike

我正在尝试用 Java 实现中点位移算法。它也被称为菱形方 block 算法。我的引用是 http://www.lighthouse3d.com/opengl/terrain/index.php3?mpd .除了右边缘和下边缘外,它似乎可以正常工作。

See Midpoint Displacement Results

仔细观察,可以看到“粗糙”的边缘。谁能指出哪里出了问题?在该算法的其他在线实现中尚未观察到这种效果。

代码

private void generateWorldMPD() {               
/* The following is my first attempt at the MDP algorithm. */

// displacement boundary.
double displacementBound = Constants.DEFAULT_ROUGHNESS_CONSTANT;
double[][] A = Utilities.get2DDoubleArray(Constants.MPD_PRESET_HEIGHT, 2, 2);
int iterations =0;
while (iterations < mPDIterations) {

// create a new array large enough for the new points being added.
double [][] B = new double[A.length * 2 - 1][A[0].length * 2 - 1];

// move the points in A to B, skipping every other element as space for a new point
for (int i = 0; i < B.length; i +=2)
for (int j = 0; j < B[i].length; j+=2) {
B[i][j] = A[i / 2][j / 2];
}

//calculate the height of each new center point as the average of the four adjacent elements
//(diamond step) and add a random displacement to each
for (int i = 1; i < B.length; i+= 2)
for (int j = 1; j < B[i].length; j+=2) {
averageFromCornersAndDisplace(B, i, j, displacementBound);

}

//calculate the height of each new non-center point (square step) and add a random displacement to each
for (int i = 0; i < B.length; i ++)
for (int j = 0; j < B[i].length; j++)
if (i % 2 == 0) //on every even row, calculate for only odd columns
if (j % 2 == 0) continue;
else
averageFromAdjAndDisplace( B , i, j, displacementBound );

else //on every odd row, calculate for only even columns
if (j % 2 == 0)
averageFromAdjAndDisplace( B , i, j, displacementBound );
else
continue;

displacementBound *= Math.pow(2, -Constants.DEFAULT_ROUGHNESS_CONSTANT);

// assign B to A
A = B;

iterations++;
}
}

private void averageFromCornersAndDisplace(double[][] A, int i, int j, double displacementBoundary) {
double nw = A[ wrap(i - 1, 0, A.length - 1) ][ wrap(j - 1, 0, A[i].length - 1) ];
double ne = A[ wrap(i + 1, 0, A.length - 1) ][ wrap(j - 1, 0, A[i].length - 1) ];
double sw = A[ wrap(i - 1, 0, A.length - 1) ][ wrap(j + 1, 0, A[i].length - 1) ];
double se = A[ wrap(i + 1, 0, A.length - 1) ][ wrap(j + 1, 0, A[i].length - 1) ];
A[i][j] = (nw + ne + sw + se) / 4;
A[i][j] += randomDisplacement(displacementBoundary);
}

private void averageFromAdjAndDisplace(double[][] A, int i, int j, double displacementBoundary) {
double north = A[i][ wrap(j - 1, 0, A[i].length - 1)];
double south = A[i][ wrap(j + 1, 0, A[i].length - 1)];
double west = A[ wrap(i - 1, 0, A.length - 1) ][j];
double east = A[ wrap(i + 1, 0, A.length - 1) ][j];
A[i][j] = (north + south + east + west) / 4;
A[i][j] += randomDisplacement(displacementBoundary);
}

// This function returns a value that is wrapped around the interval if
// it exceeds the given bounds in the negative or positive direction.
private int wrap(int n, int lowerBound, int upperBound) {

int lengthOfInterval = upperBound - lowerBound;

if (n < lowerBound)
return (lowerBound - n) % lengthOfInterval;
else
return (n - upperBound) % lengthOfInterval;
}

注释

private void generateWorldMPD() {               
/* The following is my first attempt at the MDP algorithm. */

// displacement boundary.
double displacementBound = Constants.DEFAULT_ROUGHNESS_CONSTANT;
double[][] A = Utilities.get2DDoubleArray(Constants.MPD_PRESET_HEIGHT, 2, 2);
int iterations =0;

这部分定义了一个变量 displacementBound,一个初始化为默认值的 double 二维数组,以及另一个名为 iterations 的变量。

while (iterations < mPDIterations) {

// create a new array large enough for the new points being added.
double [][] B = new double[A.length * 2 - 1][A[0].length * 2 - 1];

// move the points in A to B, skipping every other element as space for a new point
for (int i = 0; i < B.length; i +=2)
for (int j = 0; j < B[i].length; j+=2) {
B[i][j] = A[i / 2][j / 2];
}

这部分是声明循环的地方。它将运行 mPDIterations 循环。创建了一个临时数组 B 来保存 A 的更新版本,使 B 大于 A 以保存新版本数据点。之后有两个 for 循环,一个嵌套在另一个循环中,将 A 的当前值放入临时 B,注意每隔一行和每一列保留空白的。看看这个例子:

// The '*'s represent a cell in an array that is populated with a value.
// The '_'s represent a cell in an array that is empty.

// This is 'A'.
* *
* *

// This is 'B'. At the moment, completely empty.
_ _ _
_ _ _
_ _ _

// The elements of 'A' are tranferred to 'B'.
// Blank cells are inserted in every other row, and every other column.
* _ *
_ _ _
* _ *

现在是下一段代码:

        //calculate the height of each new center point as the average of the four adjacent elements  
//(diamond step) and add a random displacement to each
for (int i = 1; i < B.length; i+= 2)
for (int j = 1; j < B[i].length; j+=2) {
averageFromCornersAndDisplace(B, i, j, displacementBound);

}

在此部分中,中心 处的每个点指的是在南<的每个主要方向上都有一个空的相邻单元格的单元格/strong>、西 的值是四个相邻 点的平均值和随机位移值 添加到它。这称为菱形步骤。阐明什么是“中心”:

// The big "O" indicates the 'center' in this 2D array.
* _ *
_ O _
* _ *

下一个代码部分:

//calculate the height of each new non-center point (square step) and add a random displacement to each
for (int i = 0; i < B.length; i ++)
for (int j = 0; j < B[i].length; j++)
if (i % 2 == 0) //on every even row, calculate for only odd columns
if (j % 2 == 0) continue;
else
averageFromAdjAndDisplace( B , i, j, displacementBound );

else //on every odd row, calculate for only even columns
if (j % 2 == 0)
averageFromAdjAndDisplace( B , i, j, displacementBound );
else
continue;

这部分与上一段代码类似。它为每个非中心点和空点分配一个新值;该值是主要方向西中相邻元素的平均值,添加了另一个随机位移值。这称为方步。上面的代码确保只有非中心点和空点被赋予新值;这些要点等同于侧要点,如下所述:

// The big 'O's indicate the 'side points' in this 2D array.
* O *
O * O
* O *

结束 while 循环的部分如下:

        displacementBound *= Math.pow(2, -Constants.DEFAULT_ROUGHNESS_CONSTANT);

// assign B to A
A = B;

iterations++;
} // end of while loop

根据上述文章中给出的信息,变量 displacementBound 在上面的部分中被减少,其中包括 while 循环的结束。 A 的内容通过在开始另一次循环迭代或终止循环之前将 B 的更新内容分配给 A 来更新。A p>

最后,辅助方法 averageFromCornersAndDisplace()averageFromSidesAndDisplace()wrap() 已包含在内,但对它们的额外解释是不必要。 randomDisplacement() 方法根本没有包含在内。供您引用,它返回一个随机 float x,以给定数 b 为界:

// The method returns a double x, where -b <= x < b
double randomDisplacement(double b);

最佳答案

我刚刚看到你的帖子弹出,我想你已经整理好了。不管怎样,如果你想做这样的包装,有一个巧妙的技巧可以解决负面模组在 C/Java 中不能正常工作的事实。您所做的只是将模数的一些倍数(注意不要溢出)加回数字以确保它是非负数。然后你可以像往常一样修改而不会破坏。这是一个例子:

private int wrap(int n, int lowerBound, int upperBound) {
int lengthOfInterval = upperBound - lowerBound;
return lowerBound + ((n - lowerBound + lengthOfInterval) % lengthOfInterval);
}

关于java - 中点位移地形伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6471503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com