下面是我的Value Noise实现,我正在使用它来生成地形。当地形的长度(Y尺寸)长于其宽度(X尺寸)时,它会产生奇怪的瑕疵,但不会产生。
我一直盯着这几个小时。知道是什么导致了这个吗?
(来自demo的屏幕截图。您可以在浏览器控制台中查看代码并立即通过将THREE.Terrain.Value = ValueNoise; rebuild();
放在下面的代码后立即查看结果。)
1:1宽高比:
1:1.1宽高比:
/**
* Generate a heightmap using white noise.
*
* @param {Vector3[]} g The terrain vertices.
* @param {Object} options Settings
* @param {Number} scale The resolution of the resulting heightmap.
* @param {Number} segments The width of the target heightmap.
* @param {Number} range The altitude of the noise.
* @param {Number[]} data The target heightmap.
*/
function WhiteNoise(g, options, scale, segments, range, data) {
if (scale > segments) return;
var i = 0,
j = 0,
xl = segments,
yl = segments,
inc = Math.floor(segments / scale),
k;
// Walk over the target. For a target of size W and a resolution of N,
// set every W/N points (in both directions).
for (i = 0; i <= xl; i += inc) {
for (j = 0; j <= yl; j += inc) {
k = j * xl + i;
data[k] = Math.random() * range;
/* c b *
* l t */
var t = data[k],
l = data[ j * xl + (i-inc)] || t, // left
b = data[(j-inc) * xl + i ] || t, // bottom
c = data[(j-inc) * xl + (i-inc)] || t; // corner
// Interpolate between adjacent points to set the height of
// higher-resolution target data.
for (var lastX = i-inc, x = lastX; x < i; x++) {
for (var lastY = j-inc, y = lastY; y < j; y++) {
if (x === lastX && y === lastY) continue;
var px = ((x-lastX) / inc),
py = ((y-lastY) / inc),
r1 = px * b + (1-px) * c,
r2 = px * t + (1-px) * l;
data[y * xl + x] = py * r2 + (1-py) * r1;
}
}
}
}
// Assign the temporary data back to the actual terrain heightmap.
// Accumulate additively across multiple calls to WhiteNoise.
for (i = 0, xl = options.xSegments + 1; i < xl; i++) {
for (j = 0, yl = options.ySegments + 1; j < yl; j++) {
k = j * xl + i;
g[k].z += data[k] || 0;
}
}
}
/**
* Generate random terrain using value noise.
*
* The basic approach of value noise is to generate white noise at a
* smaller octave than the target and then interpolate to get a higher-
* resolution result. This is then repeated at different resolutions.
*
* @param {Vector3[]} g The terrain vertices.
* @param {Object} options Settings
*/
ValueNoise = function(g, options) {
// Set the segment length to the smallest power of 2 that is greater
// than the number of vertices in either dimension of the plane
var segments = Math.max(options.xSegments, options.ySegments) + 1, n;
for (n = 1; Math.pow(2, n) < segments; n++) {}
segments = Math.pow(2, n);
// Store the array of white noise outside of the WhiteNoise function to
// avoid allocating a bunch of unnecessary arrays; we can just
// overwrite old data each time WhiteNoise() is called.
var data = new Array(segments*(segments+1));
// Layer white noise at different resolutions.
var range = options.maxHeight - options.minHeight;
for (var i = 2; i < 7; i++) {
WhiteNoise(g, options, Math.pow(2, i), segments, range * Math.pow(2, 2.4-i*1.2), data);
}
// Clamp and stretch the results
THREE.Terrain.Clamp(g, {
maxHeight: options.maxHeight,
minHeight: options.minHeight,
stretch: true,
});
};
答案 0 :(得分:2)
当你指定临时data
字段的高度变化时,你真的有两个不同的索引,因为你有两个不同的地图大小:原始地图和临时地图膨胀到下一个2的幂。所以:
for (i = 0, xl = options.xSegments + 1; i < xl; i++) {
for (j = 0, yl = options.ySegments + 1; j < yl; j++) {
var kg = j * xl + i;
var kd = j * segments + i;
g[kg] += data[kd];
}
}
我还认为您的data
索引中可能存在一个错误的错误。 data
的大小应为(segments + 1) * (segments + 1)
,因为您需要两个维度中的外部单元格,而xl
和yl
应为segments + 1
。