Разбитые текстуры с помощью Mapbox GL и THREE.js - PullRequest
0 голосов
/ 03 октября 2019

Я использовал Добавление 3D-модели Пример Mapbox GL в качестве шаблона для добавления 3D-объектов на карту Mapbox. Это работает, но иногда возникают проблемы с текстурами.

Я загружаю файл OBJ и добавляю его в сцену. Вот как выглядит модель в простой сцене THREE.js :

Silo showing concrete texture

Вот перегруженная версия кода для рендерингаэта сцена (см. gist для получения полной информации):

async function addOBJ(path, mtlPath) {
    const loader = new OBJLoader2();
    const matLoader = new MTLLoader();
    matLoader.load(mtlPath, mtlParseResult => {
        const materials = MtlObjBridge.addMaterialsFromMtlLoader(mtlParseResult);
        loader.addMaterials(materials);
        loader.load(path, group => {
            scene.add(group);
        });
    });
}

function init() {
    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.001, 1000 );
    camera.position.set(86, 100, -5);
    scene = new THREE.Scene();
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    addOBJ('silo_p2.obj', 'silo_p2.mtl');
}

Когда я пытаюсь добавить ту же модель в мою карту Mapbox, текстура выглядит странно:

Silo on Liberty Island with strange texture

Что происходит в моей сцене THREE.js + Mapbox? Похоже, что текстура превратилась в шум.

Полный источник доступен здесь , но это суть:

function getSpriteMatrix(coord, sceneCenter) {
  const rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), 90 * Math.PI / 180);
  const s = sceneCenter.meterInMercatorCoordinateUnits();
  return new THREE.Matrix4()
    .makeTranslation(coord.x - sceneCenter.x, coord.y - sceneCenter.y, coord.z - sceneCenter.z)
    .scale(new THREE.Vector3(s, -s, s))
    .multiply(rotationX);
}

class SpriteCustomLayer {
  type = 'custom';
  renderingMode = '3d';

  constructor(id) {
    this.id = id;
    this.model = loadObj('silo_p2.obj', 'silo_p2.mtl');
  }

  async onAdd(map, gl) {
    this.camera = new THREE.Camera();

    const centerLngLat = map.getCenter();
    this.center = MercatorCoordinate.fromLngLat(centerLngLat, 0);
    const {x, y, z} = this.center;
    this.cameraTransform = new THREE.Matrix4().makeTranslation(x, y, z);

    this.map = map;
    this.scene = this.makeScene();

    // use the Mapbox GL JS map canvas for three.js
    this.renderer = new THREE.WebGLRenderer({
      canvas: map.getCanvas(),
      context: gl,
      antialias: true,
    });

    // From https://threejs.org/docs/#examples/en/loaders/GLTFLoader
    this.renderer.gammaOutput = true;
    this.renderer.gammaFactor = 2.2;

    this.renderer.autoClear = false;

    this.addModel();
  }

  makeScene() {
    const scene = new THREE.Scene();
    scene.add(new THREE.AmbientLight( 0xffffff, 0.25 ));
    for (const y of [-70, 70]) {
      const directionalLight = new THREE.DirectionalLight(0xffffff);
      directionalLight.position.set(0, y, 100).normalize();
      scene.add(directionalLight);
    }
    return scene;
  }

  async addModel() {
    const model = await this.model;
    flipSides(model);

    const scene = model.clone();
    const matrix = getSpriteMatrix(
      MercatorCoordinate.fromLngLat([-74.0445, 40.6892], 0),
      this.center,
    );
    scene.applyMatrix(matrix);
    this.scene.add(scene);
  }

  render(gl, matrix) {
    this.camera.projectionMatrix = new THREE.Matrix4()
      .fromArray(matrix)
      .multiply(this.cameraTransform);
    this.renderer.state.reset();
    this.renderer.render(this.scene, this.camera);
    this.map.triggerRepaint();
  }
}

map.on('load', () => {
  const layer = new SpriteCustomLayer('statue');
  map.addLayer(layer);
});

Как мне заставить текстуру выглядетьпрямо на этом объекте в представлении Mapbox? Я использую THREE.js r109 и Mapbox GL JS v1.4.0. Из-за того, откуда берутся эти модели, использование другого формата, такого как GLTF, мне не подходит.

...