feat: 补全高德地图 2.0 的模型加载能力,增加模型的经纬度移动能力

This commit is contained in:
2912401452 2021-09-18 16:02:27 +08:00
parent 1a161121ff
commit 3da2676b0e
9 changed files with 198 additions and 50 deletions

View File

@ -275,6 +275,12 @@ export default class AMapService
};
}
public lngLatToCoord(lnglat: [number, number]): any {
// @ts-ignore
let { x, y } = this.map.lngLatToGeodeticCoord(lnglat)
return [x, -y]
}
public lngLatToMercator(
lnglat: [number, number],
altitude: number,

View File

@ -370,7 +370,10 @@ export default class AMapService
scale: [number, number, number] = [1, 1, 1],
origin: IMercator = { x: 0, y: 0, z: 0 },
): number[] {
const flat = this.viewport.projectFlat(lnglat);
// const flat = this.viewport.projectFlat(lnglat);
// @ts-ignore
const flat = this.map.customCoords.lngLatToCoord(lnglat)
// @ts-ignore
const modelMatrix = mat4.create();
@ -379,6 +382,7 @@ export default class AMapService
modelMatrix,
vec3.fromValues(flat[0], flat[1], altitude),
);
mat4.scale(
modelMatrix,
modelMatrix,

View File

@ -236,6 +236,18 @@ export default class MapboxService
public lngLatToContainer(lnglat: [number, number]): IPoint {
return this.map.project(lnglat);
}
/**
*
* @param lnglat
* @returns
*/
public lngLatToCoord(lnglat: [number, number]) {
// @ts-ignore
let { x, y } = this.lngLatToMercator(lnglat, 0);
return [x, y] as [number, number];
}
public lngLatToMercator(
lnglat: [number, number],
altitude: number,

View File

@ -0,0 +1,33 @@
import { ILayer } from '@antv/l7';
import {
AnimationMixer,
Matrix4,
Object3D
} from 'three';
export type ILngLat = [number, number]
export interface IThreeJSLayer extends ILayer {
// 获取对应地图的经纬度模型矩阵
getModelMatrix(
lnglat: ILngLat,
altitude: number,
rotation: [number, number, number],
scale: [number, number, number],
): Matrix4;
// 获取对应地图的经纬度平移矩阵
getTranslateMatrix(lnglat: ILngLat, altitude?: number): Matrix4;
// 设置模型对应地图在经纬度和高度方向的平移
setObjectLngLat(object: Object3D, lnglat: ILngLat, altitude?: number): void;
// 根据经纬度设置模型对应地图的平移
setObjectLngLat(object: Object3D, lnglat: ILngLat, altitude?: number): void;
// 返回物体在场景中的经纬度
getObjectLngLat(object: Object3D): ILngLat;
// 增加加载模型的动画混合器
addAnimateMixer(mixer: AnimationMixer): void;
}

View File

@ -7,21 +7,14 @@ import {
PerspectiveCamera,
Scene,
WebGLRenderer,
Object3D
} from 'three';
import {
IThreeRenderService,
ThreeRenderServiceType,
} from './threeRenderService';
import { IThreeJSLayer, ILngLat } from './IThreeJSLayer'
const DEG2RAD = Math.PI / 180;
interface IThreeJSLayer extends ILayer {
getModelMatrix(
lnglat: [number, number],
altitude: number,
rotation: [number, number, number],
scale: [number, number, number],
): Matrix4;
addAnimateMixer(mixer: AnimationMixer): void;
}
export default class ThreeJSLayer
extends BaseLayer<{
onAddMeshes: (threeScene: Scene, layer: ThreeJSLayer) => void;
@ -36,10 +29,9 @@ export default class ThreeJSLayer
// 地图中点墨卡托坐标
private center: IMercator;
// 初始状态相机变换矩阵
/**
*
*
*/
public getModelMatrix(
lnglat: [number, number],
@ -58,7 +50,53 @@ export default class ThreeJSLayer
);
}
/**
*
* @param lnglat
* @param altitude
* @returns
*/
public getTranslateMatrix( lnglat: ILngLat, altitude: number = 0,) {
return this.getModelMatrix( lnglat, altitude, [0, 0, 0], [1, 1, 1] )
}
/**
*
* @param object
* @param lnglat
* @param altitude
*/
public applyObjectLngLat(object: Object3D, lnglat: ILngLat, altitude = 0) {
let positionMatrix = this.getTranslateMatrix(lnglat, altitude)
object.applyMatrix4(positionMatrix)
}
/**
*
* @param object
* @param lnglat
* @param altitude
*/
public setObjectLngLat(object: Object3D, lnglat: ILngLat, altitude = 0) {
// @ts-ignore
let [x, y] = this.mapService?.lngLatToCoord(lnglat)
// @ts-ignore
// console.log(this.mapService?.lngLatToCoord(lnglat))
// if(x && y) {
// console.log('------')
object.position.set(x, y, altitude)
// }
}
public getObjectLngLat(object: Object3D) {
// let coord = [object.position.x, object.position.y];
// // @ts-ignore
// return this.mapService.coordToLngLat(coord);
return [0,0] as ILngLat
}
public buildModels() {
// @ts-ignore
this.threeRenderService = this.getContainer().get<IThreeRenderService>(
ThreeRenderServiceType,
);

View File

@ -1,3 +1,8 @@
import ThreeLayer from './core/baseLayer';
import ThreeRender from './core/threeRender';
export { ThreeLayer, ThreeRender };
import { IThreeJSLayer, ILngLat } from './core/IThreeJSLayer';
import {
Object3D
} from 'three';
export { ThreeLayer, ThreeRender, IThreeJSLayer, ILngLat, Object3D };

View File

@ -1,6 +1,6 @@
import { Scene } from '@antv/l7';
import { GaodeMap, GaodeMapV2, Mapbox } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import { ThreeLayer, ThreeRender, ILngLat, Object3D } from '@antv/l7-three';
import * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE from 'three';
@ -27,7 +27,7 @@ export default class GlTFThreeJSDemo extends React.Component {
center: [111.4453125, 32.84267363195431],
pitch: 45,
rotation: 30,
zoom: 15,
zoom: 13,
}),
});
this.scene = scene;
@ -37,10 +37,21 @@ export default class GlTFThreeJSDemo extends React.Component {
enableMultiPassRenderer: false,
onAddMeshes: (threeScene: THREE.Scene, layer: ThreeLayer) => {
threeScene.add(new THREE.AmbientLight(0xffffff));
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
sunlight.position.set(0, 80000000, 100000000);
sunlight.matrixWorldNeedsUpdate = true;
threeScene.add(sunlight);
// threeScene.applyMatrix4(
// layer.getModelMatrix(
// [111.4453125, 32.84267363195431], // 经纬度坐标
// 0, // 高度,单位米/
// [Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
// [100, 100, 100], // 沿 XYZ 轴缩放比例
// ),
// )
// 使用 Three.js glTFLoader 加载模型
const loader = new GLTFLoader();
loader.load(
@ -52,37 +63,22 @@ export default class GlTFThreeJSDemo extends React.Component {
// 'https://gw.alipayobjects.com/os/antvdemo/assets/gltf/man/CesiumMan.gltf',
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
(gltf) => {
// console.log(gltf)
const gltfScene = gltf.scene;
// gltfScene.rotation.set(90, 90, 0)
const model: Object3D = gltf.scene;
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
const gltfScene = gltf.scene;
gltfScene.scale.set(10, 10, 10);
// gltfScene.applyMatrix4(
// // 生成模型矩阵
// layer.getModelMatrix(
// [coordinates[0], coordinates[1]], // 经纬度坐标
// 0, // 高度,单位米/
// [Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
// [100, 100, 100], // 沿 XYZ 轴缩放比例
// ),
// );
// gltfScene.applyMatrix4(
// // 生成模型矩阵
// layer.getModelMatrix(
// // [coordinates[0], coordinates[1]], // 经纬度坐标
// [0, 0], // 经纬度坐标
// 0, // 高度,单位米/
// [Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
// [10000, 10000, 10000], // 沿 XYZ 轴缩放比例
// ),
// );
model.applyMatrix4(
// 生成模型矩阵
layer.getModelMatrix(
[coordinates[0], coordinates[1]], // 经纬度坐标
0, // 高度,单位米/
[Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
[100, 100, 100], // 沿 XYZ 轴缩放比例
),
);
const animations = gltf.animations;
if (animations && animations.length) {
const mixer = new THREE.AnimationMixer(gltfScene);
const mixer = new THREE.AnimationMixer(model);
// @ts-ignore
// for (let i = 0; i < 1; i++) {
const animation = animations[2];
@ -97,11 +93,27 @@ export default class GlTFThreeJSDemo extends React.Component {
layer.addAnimateMixer(mixer);
}
// 向场景中添加模型
// threeScene.add(gltfScene);
});
// 向场景中添加模型
threeScene.add(model);
let lnglat = [121.107, 30.267069] as [number, number]
let altitude = 0
let center = scene.getCenter()
// layer.setObjectLngLat(model, lnglat, altitude)
// console.log()
// layer.setObjectLngLat(model, [center.lng + 0.05, center.lat] as ILngLat, 0)
// layer.setObjectLngLat(model, [center.lng + 0.05, center.lat] as ILngLat, 0)
layer.setObjectLngLat(model, [center.lng + 0.05, center.lat] as ILngLat, 0)
let t = 0
setInterval(() => {
t += 0.01
layer.setObjectLngLat(model, [center.lng, center.lat + Math.sin(t) * 0.1] as ILngLat, 0)
// layer.setObjectLngLat(model, [center.lng + 0.2, center.lat], 0)
}, 16)
threeScene.add(gltfScene);
// 重绘图层
layer.render();
},
@ -117,6 +129,7 @@ export default class GlTFThreeJSDemo extends React.Component {
geometry: {
type: 'Point',
coordinates: [111.4453125, 32.84267363195431],
// coordinates: [121.107, 30.267069], // 该坐标点在钱塘江入海口附近
},
},
],

View File

@ -1,6 +1,6 @@
import { Scene } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import { ThreeLayer, ThreeRender, ILngLat } from '@antv/l7-three';
import * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE from 'three';
@ -41,6 +41,16 @@ export default class GlTFThreeJSDemo extends React.Component {
sunlight.position.set(0, 80000000, 100000000);
sunlight.matrixWorldNeedsUpdate = true;
threeScene.add(sunlight);
// threeScene.applyMatrix4(
// layer.getModelMatrix(
// [111.4453125, 32.84267363195431], // 经纬度坐标
// 0, // 高度,单位米/
// [Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
// [1, 1, 1], // 沿 XYZ 轴缩放比例
// ),
// )
// 使用 Three.js glTFLoader 加载模型
const loader = new GLTFLoader();
loader.load(
@ -61,7 +71,7 @@ export default class GlTFThreeJSDemo extends React.Component {
[coordinates[0], coordinates[1]], // 经纬度坐标
0, // 高度,单位米/
[Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
[100, 100, 100], // 沿 XYZ 轴缩放比例
[1000, 1000, 1000], // 沿 XYZ 轴缩放比例
),
);
const animations = gltf.animations;
@ -80,6 +90,18 @@ export default class GlTFThreeJSDemo extends React.Component {
// }
layer.addAnimateMixer(mixer);
}
// console.log(gltfScene.position)
let center = scene.getCenter()
console.log(center)
console.log(layer.getObjectLngLat(gltfScene))
// layer.setObjectLngLat(gltfScene, [center.lng + 0.05, center.lat] as ILngLat, 0)
// layer.setObjectLngLat(gltfScene, [center.lng, center.lat] as ILngLat, 0)
let t = 0
setInterval(() => {
t += 0.01
layer.setObjectLngLat(gltfScene, [center.lng, center.lat + Math.sin(t) * 0.1] as ILngLat, 0)
// layer.setObjectLngLat(model, [center.lng + 0.2, center.lat], 0)
}, 16)
// 向场景中添加模型
threeScene.add(gltfScene);
@ -98,7 +120,7 @@ export default class GlTFThreeJSDemo extends React.Component {
properties: {},
geometry: {
type: 'Point',
coordinates: [111.4453125, 32.84267363195431],
coordinates: [111.4453125, 32.84267363195431]
},
},
],

View File

@ -1,6 +1,6 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import { ThreeLayer, ThreeRender, ILngLat } from '@antv/l7-three';
import * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE from 'three';
@ -73,8 +73,9 @@ export default class GlTFThreeJSDemo extends React.Component {
// 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
(gltf) => {
// 根据 GeoJSON 数据放置模型
const gltfScene = gltf.scene.clone();
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
const gltfScene = gltf.scene.clone();
gltfScene.applyMatrix4(
// 生成模型矩阵
layer.getModelMatrix(
@ -105,6 +106,20 @@ export default class GlTFThreeJSDemo extends React.Component {
// 向场景中添加模型
threeScene.add(gltfScene);
});
let center = scene.getCenter()
console.log(center)
console.log(layer.getObjectLngLat(gltfScene))
// layer.setObjectLngLat(gltfScene, [center.lng + 0.05, center.lat] as ILngLat, 0)
// let t = 0
// setInterval(() => {
// t += 0.01
// layer.setObjectLngLat(gltfScene, [center.lng, center.lat + Math.sin(t) * 0.1] as ILngLat, 0)
// // layer.setObjectLngLat(model, [center.lng + 0.2, center.lat], 0)
// }, 16)
// 重绘图层
layer.render();
},