рендеринг нескольких 3D-моделей gltf в одном слое на карте с использованием mapbox gl и трех js

Я использовал добавление gltf 3D. Модель на карте с использованием mapbox gl и three.js из ссылки

но добавление одной трехмерной модели gltf в один отдельный слой и добавление их на карту работает нормально, но есть ли способ добавить несколько трехмерных моделей gltf в один слой на карте.

Код карты:

this.modelOrigin = [148.9819, -35.3981];
this.modelOrigin2 = [148.9819, -35.4981];
this.iconImage = "https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf";


//map info here
var map = new mapboxgl.Map({
  container: 'map', // container id
  style: 'mapbox://styles/mapbox/streets-v9', //stylesheet location
  center: [148.9819, -35.3981], // starting position[35.890, -75.664]
  zoom: 17.5, // starting zoom
  hash: true,
  minZoom: 0,
  maxZoom: 22,
  preserveDrawingBuffer: true,
  pitch: 60
});

var self = this;

map.on('style.load', function () {
 //adding separate 3d model on map
  map.addLayer(new AddMapCustomLayer(self.modelOrigin, self.iconImage));

  map.addLayer(new AddMapCustomLayer(self.modelOrigin2, self.iconImage));
});

код для настраиваемого слоя:

class AddMapCustomLayer {
  id;
  type="custom";
  renderingMode="3d";

  //
  modelOrigin;
  modelAltitude = 0;
  modelRotate = [Math.PI / 2, 0, 0];
  modelScale = 5.41843220338983e-8;

  modelTransform;

  camera;
  scene;

  map;

  renderer;

  iconImage;

  constructor(modelOrigin, iconImage) {
    this.id = '3d-model' + this.uuidv4();
    this.type = 'custom';
    this.renderingMode = '3d';
    this.modelOrigin = modelOrigin;
    this.iconImage = iconImage;

    // transformation parameters to position, rotate and scale the 3D model onto the map
    this.modelTransformation(this.modelOrigin,this.iconImage)
  }

  modelTransformation(modelOrigin,modelAltitude){

    this.modelTransform = {
      translateX: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).x,
      translateY: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).y,
      translateZ: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).z,
      rotateX: this.modelRotate[0],
      rotateY: this.modelRotate[1],
      rotateZ: this.modelRotate[2],
      scale: this.modelScale
    };

  }

  uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  };

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

    // create two three.js lights to illuminate the model
    var directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(0, -70, 100).normalize();
    this.scene.add(directionalLight);

    var directionalLight2 = new THREE.DirectionalLight(0xffffff);
    directionalLight2.position.set(0, 70, 100).normalize();
    this.scene.add(directionalLight2);

    // use the three.js GLTF loader to add the 3D model to the three.js scene
    var loader = new THREE.GLTFLoader();
    loader.load(this.iconImage, (function (gltf) {
      this.scene.add(gltf.scene);
    }).bind(this));
    this.map = map;

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

  render(gl, matrix) {
    var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), this.modelTransform.rotateX);
    var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), this.modelTransform.rotateY);
    var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), this.modelTransform.rotateZ);

    var m = new THREE.Matrix4().fromArray(matrix);
    var l = new THREE.Matrix4().makeTranslation(this.modelTransform.translateX, this.modelTransform.translateY, this.modelTransform.translateZ)
      .scale(new THREE.Vector3(this.modelTransform.scale, -this.modelTransform.scale, this.modelTransform.scale))
      .multiply(rotationX)
      .multiply(rotationY)
      .multiply(rotationZ);

    this.camera.projectionMatrix.elements = matrix;
    this.camera.projectionMatrix = m.multiply(l);
    this.renderer.state.reset();
    this.renderer.render(this.scene, this.camera);
    this.map.triggerRepaint();
  }

Поэтому, пожалуйста, дайте предложение, как я могу добавить одну и ту же модель динамически в разные места на карте на одном слое.


person r08    schedule 03.04.2019    source источник


Ответы (2)


этот вопрос довольно старый, но я бы порекомендовал вам проверить последнюю версию threebox, поскольку она позволяет вы можете добавлять столько моделей и 3D-слоев, сколько хотите, а также делать такие вещи, как показано ниже, с помощью всего лишь нескольких строк кода.

        map.on('style.load', function () {
        map.addLayer({
            id: 'custom_layer',
            type: 'custom',
            renderingMode: '3d',
            onAdd: function (map, mbxContext) {

                window.tb = new Threebox(
                    map,
                    mbxContext,
                    { defaultLights: true }
                );

                var options = {
                    obj: '/3D/soldier/soldier.glb',
                    type: 'gltf',
                    scale: 1,
                    units: 'meters',
                    rotation: { x: 90, y: 0, z: 0 } //default rotation
                }

                tb.loadObj(options, function (model) {
                    soldier = model.setCoords(origin);
                    tb.add(soldier);
                })

            },
            render: function (gl, matrix) {
                tb.update();
            }
        });
    })

- Встроенные 3D-модели и настраиваемые анимации

 Встроенные 3D-модели и пользовательские анимации

- Полная поддержка Raycast MouseOver / Mouseout, Selected, Drag & Drop, Drag & Rotate, Wireframe

 MouseOver / Mouseout, Selected, Drag & Drop, Drag & Rotate, Wireframe

- Подсказки и ярлыки CSS2D, учитывающие высоту

 Подсказки и ярлыки CSS2D с учетом высоты

** - Камеры Three.js и Mapbox синхронизируются с настройкой глубины **

 Камеры Three.js и Mapbox синхронизируются с настройкой глубины

- Включите геолокационные модели памятников

Эйфелева башня gif

person jscastro    schedule 09.07.2020

Если модели близки друг к другу, пробовали ли вы загрузить две модели glTF и добавить их в один и тот же THREE.Scene ()?

т.е. this.scene.add (gltf1.scene); this.scene.add (gltf2.scene);

вам все равно нужно будет рассчитать смещение / поворот gltf2 относительно gltf1.

person michael beale    schedule 18.09.2019