- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 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/
我是一名优秀的程序员,十分优秀!