Three.js 全局高度图未显示预期结果
Three.js global heightmap is not showing the expected result
我想使用我在网上找到的全球 4k 高度图创建一个地球模型。我找到了可以执行此操作的开源脚本。
function createGeometryFromMap() {
var depth = 512;
var width = 512;
var spacingX = 3;
var spacingZ = 3;
var heightOffset = 2;
var canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = "assets/earth.jpg";
img.onload = function () {
// draw on canvas
ctx.drawImage(img, 0, 0);
var pixel = ctx.getImageData(0, 0, width, depth);
var geom = new THREE.Geometry;
var output = [];
for (var x = 0; x < depth; x++) {
for (var z = 0; z < width; z++) {
// get pixel
// since we're grayscale, we only need one element
var yValue = pixel.data[z * 4 + (depth * x * 4)] / heightOffset;
var vertex = new THREE.Vector3(x * spacingX, yValue, z * spacingZ);
geom.vertices.push(vertex);
}
}
// we create a rectangle between four vertices, and we do
// that as two triangles.
for (var z = 0; z < depth - 1; z++) {
for (var x = 0; x < width - 1; x++) {
// we need to point to the position in the array
// a - - b
// | x |
// c - - d
var a = x + z * width;
var b = (x + 1) + (z * width);
var c = x + ((z + 1) * width);
var d = (x + 1) + ((z + 1) * width);
var face1 = new THREE.Face3(a, b, d);
var face2 = new THREE.Face3(d, c, a);
face1.color = new THREE.Color(scale(getHighPoint(geom, face1)).hex());
face2.color = new THREE.Color(scale(getHighPoint(geom, face2)).hex())
geom.faces.push(face1);
geom.faces.push(face2);
}
}
geom.computeVertexNormals(true);
geom.computeFaceNormals();
geom.computeBoundingBox();
var zMax = geom.boundingBox.max.z;
var xMax = geom.boundingBox.max.x;
var mesh = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({
vertexColors: THREE.FaceColors,
color: 0x666666,
shading: THREE.NoShading
}));
mesh.translateX(-xMax / 2);
mesh.translateZ(-zMax / 2);
scene.add(mesh);
mesh.name = 'valley';
};
}
function getHighPoint(geometry, face) {
var v1 = geometry.vertices[face.a].y;
var v2 = geometry.vertices[face.b].y;
var v3 = geometry.vertices[face.c].y;
return Math.max(v1, v2, v3);
}
当我尝试下载的 Grand Canyon 和夏威夷的演示高度图时,它们似乎还不错。但是,当我尝试将我的全局高度图实现到其中时,结果并没有显示我需要的东西。
这是大峡谷的地形:
这是我正在使用的全局高度图:
这是我得到的世界 3D 地形的结果:
很明显有些不对劲,因为那不是世界。
当您将 2D canvas 上下文告诉 .drawImage()
时,它将在 512 像素 canvas 上绘制 4000 像素的图像。 That's how it's defined in the MDN documents 如果您只使用三个 img, dx, dy
个参数。
您可以:
- 使用
dWidth, dHeight
. 的第 4 个和第 5 个参数,将地球图像绘制得更小以适合您的 512x512 像素 canvas
- 放大您的 canvas 以匹配地球图像的宽度和高度尺寸。
我想使用我在网上找到的全球 4k 高度图创建一个地球模型。我找到了可以执行此操作的开源脚本。
function createGeometryFromMap() {
var depth = 512;
var width = 512;
var spacingX = 3;
var spacingZ = 3;
var heightOffset = 2;
var canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = "assets/earth.jpg";
img.onload = function () {
// draw on canvas
ctx.drawImage(img, 0, 0);
var pixel = ctx.getImageData(0, 0, width, depth);
var geom = new THREE.Geometry;
var output = [];
for (var x = 0; x < depth; x++) {
for (var z = 0; z < width; z++) {
// get pixel
// since we're grayscale, we only need one element
var yValue = pixel.data[z * 4 + (depth * x * 4)] / heightOffset;
var vertex = new THREE.Vector3(x * spacingX, yValue, z * spacingZ);
geom.vertices.push(vertex);
}
}
// we create a rectangle between four vertices, and we do
// that as two triangles.
for (var z = 0; z < depth - 1; z++) {
for (var x = 0; x < width - 1; x++) {
// we need to point to the position in the array
// a - - b
// | x |
// c - - d
var a = x + z * width;
var b = (x + 1) + (z * width);
var c = x + ((z + 1) * width);
var d = (x + 1) + ((z + 1) * width);
var face1 = new THREE.Face3(a, b, d);
var face2 = new THREE.Face3(d, c, a);
face1.color = new THREE.Color(scale(getHighPoint(geom, face1)).hex());
face2.color = new THREE.Color(scale(getHighPoint(geom, face2)).hex())
geom.faces.push(face1);
geom.faces.push(face2);
}
}
geom.computeVertexNormals(true);
geom.computeFaceNormals();
geom.computeBoundingBox();
var zMax = geom.boundingBox.max.z;
var xMax = geom.boundingBox.max.x;
var mesh = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({
vertexColors: THREE.FaceColors,
color: 0x666666,
shading: THREE.NoShading
}));
mesh.translateX(-xMax / 2);
mesh.translateZ(-zMax / 2);
scene.add(mesh);
mesh.name = 'valley';
};
}
function getHighPoint(geometry, face) {
var v1 = geometry.vertices[face.a].y;
var v2 = geometry.vertices[face.b].y;
var v3 = geometry.vertices[face.c].y;
return Math.max(v1, v2, v3);
}
当我尝试下载的 Grand Canyon 和夏威夷的演示高度图时,它们似乎还不错。但是,当我尝试将我的全局高度图实现到其中时,结果并没有显示我需要的东西。
这是大峡谷的地形:
这是我正在使用的全局高度图:
这是我得到的世界 3D 地形的结果:
很明显有些不对劲,因为那不是世界。
当您将 2D canvas 上下文告诉 .drawImage()
时,它将在 512 像素 canvas 上绘制 4000 像素的图像。 That's how it's defined in the MDN documents 如果您只使用三个 img, dx, dy
个参数。
您可以:
- 使用
dWidth, dHeight
. 的第 4 个和第 5 个参数,将地球图像绘制得更小以适合您的 512x512 像素 canvas
- 放大您的 canvas 以匹配地球图像的宽度和高度尺寸。