最近,我发现在三个框中有一个非常方便的方法,用于在地图上放置three.js对象,即"projectToworld“。
在尝试使用该方法放置three.js对象时,我意识到方法返回的Vector3非常大,而不是在地图上。
根据三盒的文档,上面写着
projectToWorld
tb.projectToWorld(lnglat):THREE.Vector3
为给定的lnglat计算相应的THREE.Vector3。它的逆方法是tb.unprojectFromWorld。
因此,我决定使用这种方法在三个js画布中定位我的动画对象。但是这些方法的回报是非常巨大的。

因此,正如我所预期的,这些值并没有将这三个物体放置在地图上,所有的物体都消失了,因为它们可能被放置在非常遥远的位置。
我该如何解决这个问题?
我做了一个最低限度的代码来演示这个问题,如下所示。
var viewOrigin = [-73.8, 40.7];
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/jotnajoa/ckpj6g4ho3nvf18pg0r98pjes/draft',
zoom: 12,
center: viewOrigin,
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
});
var modelAltitude = 0;function translateCoords(lon, lat) {
let destination = [lon, lat];
let finalCoord = mapboxgl.MercatorCoordinate.fromLngLat(destination, 0);
return finalCoord
}
var modelAsMercatorCoordinate = translateCoords(viewOrigin[0], viewOrigin[1]);
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};const camera = new THREE.Camera();
const scene = new THREE.Scene();
// Setting map, canvas, renderer variable from the outside to access that from outside later
var map;
var canvas;
var renderer;
let particleGroup;
var frameCount = 0; function generateMap() {
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function(map, gl) {
map = map;
canvas = map.getCanvas()
renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true,
preserveDrawingBuffer: true
});
renderer.autoClear = false;
},
render: function(gl, matrix) {
frameCount += 0.1;
rotate(frameCount)
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4()
.makeTranslation(
modelTransform.translateX,
modelTransform.translateY,
modelTransform.translateZ
)
.scale(
new THREE.Vector3(
modelTransform.scale, -modelTransform.scale,
modelTransform.scale
)
)
camera.projectionMatrix = m.multiply(l);
renderer.resetState();
renderer.render(scene, camera);
map.triggerRepaint();
}
};
map.on('style.load', function() {
map.addLayer(customLayer, 'waterway-label');
});
}function fillingSpheres(group) {
const meshGroup = new THREE.Group();
const { count } = group.geometry.attributes.position
const { array } = group.geometry.attributes.position
for (let i = 0; i < count; i++) {
let i3 = i * 3;
const x = array[i3]
const y = array[i3 + 1]
const z = array[i3 + 2];
const posVec = new THREE.Vector3(x, y, z);
const circleGeo = new THREE.SphereGeometry(10, 10, 10);
const circleMtl = new THREE.MeshBasicMaterial({ color: 'green' });
const circleMesh = new THREE.Mesh(circleGeo, circleMtl);
circleMesh.userData.destination = posExample[i % 10];
circleMesh.position.set(posVec.x, posVec.y, posVec.z)
meshGroup.add(circleMesh)
};
console.log(meshGroup)
return meshGroup;
}首先,基于当前映射设置实例化tb对象。
function setThreeBox() {
window.tb = new Threebox(
map,
map.getCanvas().getContext('webgl'), {
realSunlight: true,
enableSelectingObjects: true, //change this to false to disable 3D objects selection
enableTooltips: true, // change this to false to disable default tooltips on fill-extrusion and 3D models
}
);
tb.altitudeStep = 1;
}第二,通过projectToWorld获取坐标并定位它们。
function moveSphere() {
// instantiate threebox object based on map
setThreeBox()
const { children } = particleGroup
children.forEach((d) => {
const { destination } = d.userData;
const coordVec = tb.projectToWorld([destination.lng, destination.lat])
console.log(coordVec)
d.position.set(coordVec)
})
}然后,所有的坐标都是x:200000,不再显示场景中的三个物体。
我做错什么了?
我不只是基于三盒,而是基于three.js,因为我不能说明three.js坐标空间中三盒的旋转圆。
正在运行的代码位于下面的链接中。
https://codepen.io/jotnajoa/pen/poeKoOW (由于某种原因,示例在刷新代码之后运行,打开后不会立即启动)
如果能有一个对三盒了如指掌的人能帮我做这件事,我将不胜感激。如果我可以直接访问只在三盒环境中的场景()对象,那么解决这个问题就更容易了。如果它是可访问的,我可以很容易地使基于帧的动画在三个框。(也许我错了)
单击按钮时会触发放置。
发布于 2021-06-12 22:39:09
奇怪的是,没有人能回答这个问题。所以我终于想出了自己的办法。
解决方案在下面的链接中。
主要原因是mapbox绘制的东西不是基于它的矢量配置。它通过矩阵来呈现事物,如下所示。
变量m=新的THREE.Matrix4().makeTranslation(modelTransform.translateX,().fromArray(矩阵);var l=新的modelTransform.translateY,modelTransform.translateZ) .scale( THREE.Vector3(modelTransform.scale,-modelTransform.scale,modelTransform.scale))
sphere.position.y = 0.2;
camera.projectionMatrix.elements = matrix;
camera.projectionMatrix = m.multiply(l);
renderer.state.reset();
renderer.render(scene, camera);https://stackoverflow.com/questions/67864751
复制相似问题