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( public lngLatToMercator(
lnglat: [number, number], lnglat: [number, number],
altitude: number, altitude: number,

View File

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

View File

@ -236,6 +236,18 @@ export default class MapboxService
public lngLatToContainer(lnglat: [number, number]): IPoint { public lngLatToContainer(lnglat: [number, number]): IPoint {
return this.map.project(lnglat); 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( public lngLatToMercator(
lnglat: [number, number], lnglat: [number, number],
altitude: 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, PerspectiveCamera,
Scene, Scene,
WebGLRenderer, WebGLRenderer,
Object3D
} from 'three'; } from 'three';
import { import {
IThreeRenderService, IThreeRenderService,
ThreeRenderServiceType, ThreeRenderServiceType,
} from './threeRenderService'; } from './threeRenderService';
import { IThreeJSLayer, ILngLat } from './IThreeJSLayer'
const DEG2RAD = Math.PI / 180; 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 export default class ThreeJSLayer
extends BaseLayer<{ extends BaseLayer<{
onAddMeshes: (threeScene: Scene, layer: ThreeJSLayer) => void; onAddMeshes: (threeScene: Scene, layer: ThreeJSLayer) => void;
@ -36,10 +29,9 @@ export default class ThreeJSLayer
// 地图中点墨卡托坐标 // 地图中点墨卡托坐标
private center: IMercator; private center: IMercator;
// 初始状态相机变换矩阵
/** /**
* *
*/ */
public getModelMatrix( public getModelMatrix(
lnglat: [number, number], 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() { public buildModels() {
// @ts-ignore
this.threeRenderService = this.getContainer().get<IThreeRenderService>( this.threeRenderService = this.getContainer().get<IThreeRenderService>(
ThreeRenderServiceType, ThreeRenderServiceType,
); );

View File

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

View File

@ -1,6 +1,6 @@
import { Scene } from '@antv/l7'; import { Scene } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps'; 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 * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three'; // import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE 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.position.set(0, 80000000, 100000000);
sunlight.matrixWorldNeedsUpdate = true; sunlight.matrixWorldNeedsUpdate = true;
threeScene.add(sunlight); 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 加载模型 // 使用 Three.js glTFLoader 加载模型
const loader = new GLTFLoader(); const loader = new GLTFLoader();
loader.load( loader.load(
@ -61,7 +71,7 @@ export default class GlTFThreeJSDemo extends React.Component {
[coordinates[0], coordinates[1]], // 经纬度坐标 [coordinates[0], coordinates[1]], // 经纬度坐标
0, // 高度,单位米/ 0, // 高度,单位米/
[Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度 [Math.PI / 2, -Math.PI, 0], // 沿 XYZ 轴旋转角度
[100, 100, 100], // 沿 XYZ 轴缩放比例 [1000, 1000, 1000], // 沿 XYZ 轴缩放比例
), ),
); );
const animations = gltf.animations; const animations = gltf.animations;
@ -80,6 +90,18 @@ export default class GlTFThreeJSDemo extends React.Component {
// } // }
layer.addAnimateMixer(mixer); 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); threeScene.add(gltfScene);
@ -98,7 +120,7 @@ export default class GlTFThreeJSDemo extends React.Component {
properties: {}, properties: {},
geometry: { geometry: {
type: 'Point', 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 { PolygonLayer, Scene } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps'; 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 * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three'; // import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE 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', // 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
(gltf) => { (gltf) => {
// 根据 GeoJSON 数据放置模型 // 根据 GeoJSON 数据放置模型
const gltfScene = gltf.scene.clone();
layer.getSource().data.dataArray.forEach(({ coordinates }) => { layer.getSource().data.dataArray.forEach(({ coordinates }) => {
const gltfScene = gltf.scene.clone();
gltfScene.applyMatrix4( gltfScene.applyMatrix4(
// 生成模型矩阵 // 生成模型矩阵
layer.getModelMatrix( layer.getModelMatrix(
@ -105,6 +106,20 @@ export default class GlTFThreeJSDemo extends React.Component {
// 向场景中添加模型 // 向场景中添加模型
threeScene.add(gltfScene); 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(); layer.render();
}, },