首页 > 解决方案 > 像素数据长度与缓冲区几何顶点长度不匹配 - Three.js

问题描述

我正在使用 Mapbox RGB 图块获取高程数据并更新 Three.js 中的平面缓冲区几何图形。然后我打算使用他们的卫星纹理来完成 3D 地形瓦片网格的生成。之后,我将创建一个动态加载网格系统。

现在我的问题是我得到的图像像素数据多于顶点。这意味着我无法将像素数据映射到高度的顶点 Z 值。我做了一个快速插件并检查我是否可以得到一个固定的高度和宽度段,它可以工作,但它没有。

对于上下文,图像块的分辨率为 512x512。像素数据长度为520849,缓冲区几何的 Float32Array 长度为519168

下面是我的粗略代码,用于创建要通过发送 ThreeJSON 的 REST API 提供的数据集。

import * as THREE from "three";
import fs from "fs";
import Canvas from "canvas";
import path from "path";

const __dirname = path.resolve(path.dirname(""));

async function getPixels(imagePath) {
  try {
    const data = await fs.promises.readFile(
      __dirname + imagePath,
      function (err, data) {
        if (err) throw err;
        const img = new Canvas.Image(); // Create a new Image
        img.src = data;

        // Initialize a new Canvas with the same dimensions
        // as the image, and get a 2D drawing context for it.
        const canvas = new Canvas(img.width, img.height);
        const ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);

        const imgData = context.getImageData(0, 0, img.width, img.height);
        return imgData;
      }
    );
    return data;
  } catch (err) {
    console.error(err);
  }
}

function rgbToHeight(r, g, b) {
  return -10000 + (r * 256 * 256 + g * 256 + b) * 0.1;
}

export const tileToMesh = async (rgbTilePath, textureTilePath) => {
  try {
    const pixels = await getPixels(rgbTilePath);
    const planeSize = parseInt(Math.sqrt(pixels.length / 4));

    const geometry = new THREE.default.PlaneGeometry(
      planeSize,
      planeSize,
      415,415
    //   planeSize - 1,
    //   planeSize - 1
    );

    for (let i = 0; i < pixels.length; i += 4) {
      const r = pixels[i + 0];
      const g = pixels[i + 1];
      const b = pixels[i + 2];
      const height = rgbToHeight(r, g, b);

      if (!geometry.vertices[i / 4]) {
        console.error(`No vertices at index ${i / 4} found.`);
        break;
      }
      geometry.vertices[i / 4].z = height;
    }

    geometry.verticesNeedUpdate = true;

    const texture = new THREE.TextureLoader().load(textureTilePath);
    const material = new THREE.MeshBasicMaterial({
      map: texture,
      side: DoubleSide,
      wireframe: true,
    });
    const mesh = new THREE.Mesh(geometry, material);

    return mesh;
  } catch (err) {
    console.error(err);
  }
};

标签: three.jsmapboxbuffer-geometry

解决方案


推荐阅读