Я использовал Добавление 3D-модели Пример Mapbox GL в качестве шаблона для добавления 3D-объектов на карту Mapbox. Это работает, но иногда возникают проблемы с текстурами.
Я загружаю файл OBJ и добавляю его в сцену. Вот как выглядит модель в простой сцене THREE.js :
Вот перегруженная версия кода для рендерингаэта сцена (см. 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, текстура выглядит странно:
Что происходит в моей сцене 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, мне не подходит.