|
|
@@ -4,7 +4,20 @@ import browser from '../../utils/browser.js'
|
|
|
|
|
|
import BasicMaterial from '../../materials/BasicMaterial.js'
|
|
|
|
|
|
-
|
|
|
+import {TextSprite} from "../../objects/TextSprite.js";
|
|
|
+
|
|
|
+window.showTileName = false
|
|
|
+//将原先的map写成3d的
|
|
|
+const radius = 6378137//.050041738 //地图mapSizeM / 2 / Math.PI
|
|
|
+const makeSphere = false
|
|
|
+const earthCenter = new THREE.Vector3(0,0,-radius)
|
|
|
+let camDisToEarth = 0 //离地面的最近距离
|
|
|
+function getPosOnEarth(vertice, transform){
|
|
|
+ vertice = new THREE.Vector2().fromArray(transform.forward(vertice))
|
|
|
+ let disToZoroAxis = vertice.length() //到(0,0,1)轴的距离
|
|
|
+ let z = Math.sqrt(radius * radius - disToZoroAxis * disToZoroAxis)//在(0,0,1)轴的垂足距离球心
|
|
|
+ return new THREE.Vector3(vertice.x, vertice.y, z - radius)//(0,0)处地表z为0,其余都在0之下
|
|
|
+}
|
|
|
|
|
|
let texLoader = new THREE.TextureLoader()
|
|
|
texLoader.crossOrigin = "anonymous"
|
|
|
@@ -51,8 +64,9 @@ const getSid = (function(){
|
|
|
|
|
|
|
|
|
export class MapLayer extends THREE.EventDispatcher{ // 包括了 MapLayerBase SceneLayer
|
|
|
- constructor(viewer_, viewport){
|
|
|
+ constructor(viewer_, viewport, is3d){
|
|
|
super()
|
|
|
+ this.is3d = is3d
|
|
|
this.sceneGroup = new THREE.Object3D;
|
|
|
this.sceneGroup.name = "MapLayer"
|
|
|
this.waitQueue = [] //等待加载的
|
|
|
@@ -184,6 +198,7 @@ export class MapLayer extends THREE.EventDispatcher{ // 包括了 MapLayerBase S
|
|
|
this.frustum.planes[5].setComponents(0, 0, 0, 0),
|
|
|
i = !0
|
|
|
|
|
|
+ camDisToEarth = makeSphere ? (e.position.distanceTo(earthCenter) - radius) : (e.position.z - this.sceneGroup.position.z);
|
|
|
//console.log('-------------update-----------')
|
|
|
for (r = 0; r < this.maps.length; r++){
|
|
|
var map = this.maps[r]
|
|
|
@@ -245,8 +260,29 @@ export class TiledMapBase extends THREE.EventDispatcher{
|
|
|
this.loadFailCount = 0
|
|
|
this.loadingInProgress = 0
|
|
|
|
|
|
+ //add:
|
|
|
+ this.cache = [] //缓存。要删除的tile不立刻dispose,以便迅速再显示。每次都从第一个删除。
|
|
|
+ this.maxTotalCount = 1000
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ cacheAutoClear(){//清除超出数量的缓存 add
|
|
|
+ let len = this.cache.length, cacheCopy = this.cache.slice()
|
|
|
+ let overCount = this.objectGroup.children.length + len - this.maxTotalCount
|
|
|
+ if(overCount > 0){
|
|
|
+ let i = 0, delCount = Math.min(len, overCount)
|
|
|
+ let dels = this.cache.splice(0,delCount)
|
|
|
+ dels.forEach(tile=>{
|
|
|
+ tile._mesh.material.dispose()
|
|
|
+ tile._mesh.geometry.dispose()
|
|
|
+ tile._mesh.material.map?.dispose()
|
|
|
+ tile._mesh = null
|
|
|
+ tile.textureLoaded = false
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
get zoomLevel(){
|
|
|
return this._zoomLevel
|
|
|
}
|
|
|
@@ -269,13 +305,13 @@ export class TiledMapBase extends THREE.EventDispatcher{
|
|
|
|
|
|
updateProjection(){
|
|
|
if(!this.transformMapToLocal){
|
|
|
- this.transformMapToLocal = proj4(this.projection, "LOCAL_MAP") //由地图原本的坐标转为本地坐标
|
|
|
+ this.transformMapToLocal = proj4(this.projection, "LOCAL"/* _MAP" */) //由地图原本的坐标转为本地坐标
|
|
|
}
|
|
|
}
|
|
|
|
|
|
clearProjection(){
|
|
|
this.transformMapToLocal = void 0
|
|
|
- this.projection !== 'LOCAL_MAP' && this.baseTile.remove()
|
|
|
+ this.projection !== 'LOCAL'/* _MAP' */ && this.baseTile.remove()
|
|
|
}
|
|
|
|
|
|
setEnable(enable){//add
|
|
|
@@ -298,6 +334,7 @@ export class TiledMapBase extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
update(frustum, sceneGroup){
|
|
|
+
|
|
|
this.computeCount = 0
|
|
|
var unavailable = (this.disabled || !this.objectGroup.visible)//地图即使不显示也要获得zoomlevel
|
|
|
if(this.name != 'map' && unavailable)return
|
|
|
@@ -320,102 +357,161 @@ export class TiledMapBase extends THREE.EventDispatcher{
|
|
|
o.project(viewport.camera);
|
|
|
var rx = viewport.resolution.x
|
|
|
, ry = viewport.resolution.y
|
|
|
- if (rx <= 0 || ry <= 0 || isNaN(i.x) || isNaN(o.x)) return !1;
|
|
|
+ if (rx <= 0 || ry <= 0 || isNaN(i.x) || isNaN(i.y) || isNaN(o.z)) return !1;
|
|
|
i.sub(o),
|
|
|
i.x *= rx / 2,
|
|
|
i.y *= ry / 2;
|
|
|
|
|
|
|
|
|
|
|
|
- let scale
|
|
|
- if(this.name == 'map'){
|
|
|
+ let scale=1, level
|
|
|
+ if(this.name == 'map' && !this.mapLayer.is3d){
|
|
|
//add 高纬度的因倾斜而造成tile较小,所以放大些,否则会造成显示的tile过多而卡
|
|
|
let lonlat = viewer.transform.lonlatToLocal.inverse(viewport.camera.position.clone())
|
|
|
let cos = Math.cos(THREE.Math.degToRad(lonlat.y)); //越小就在纬度上越高,tile表现越小
|
|
|
- //为什么lonlat.y会超出90?
|
|
|
- /* if(lonlat.y>90){
|
|
|
- console.log('lonlat.y>90',lonlat.y)
|
|
|
- } */
|
|
|
-
|
|
|
+ //为什么lonlat.y会超出90?
|
|
|
cos = THREE.Math.clamp(cos, 0,1)
|
|
|
let lonShift = Math.abs(viewer.mapViewer.camera.position.x / this.mapSizeM * 16 ) //越大就在经度离中心越远,tile表现越大 。
|
|
|
lonShift = THREE.Math.clamp(lonShift, 0, Math.PI)
|
|
|
lonShift = (1 - Math.sin( 1/2 * lonShift + Math.PI/2 )) * Math.PI // 0-Math.PI sin增速向上
|
|
|
|
|
|
scale = 0.5 * cos * (1+lonShift) + 0.5 * Math.pow(cos, lonShift)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if(this.mapLayer.is3d){
|
|
|
+ level = this.maxDepth
|
|
|
}else{
|
|
|
- scale = 1
|
|
|
+ var c = this.tileSizePx / i.length() / scale //多除以一个scale缩放因子,scale越大level越小
|
|
|
+ level = Math.ceil( -math.getBaseLog(2,c) - this.bias);
|
|
|
+
|
|
|
+ if(this.style == 'dark-standard'){ //该模式贴图比较小放大点
|
|
|
+ level -= 1
|
|
|
+ }
|
|
|
+ level = Math.max(level, 0)
|
|
|
+ level = Math.min(level, void 0 === this.maxDepth ? 1 / 0 : this.maxDepth)
|
|
|
+ this.zoomLevel = level//add
|
|
|
+ /* if(isNaN(this.zoomLevel )){
|
|
|
+ console.log(level, cos , scale , lonlat )
|
|
|
+ } */
|
|
|
}
|
|
|
|
|
|
- var c = this.tileSizePx / i.length() / scale //多除以一个scale缩放因子,scale越大level越小
|
|
|
- , level = Math.ceil( -math.getBaseLog(2,c) - this.bias);
|
|
|
-
|
|
|
- if(this.style == 'dark-standard'){ //该模式贴图比较小放大点
|
|
|
- level -= 1
|
|
|
- }
|
|
|
- level = Math.max(level, 0)
|
|
|
- level = Math.min(level, void 0 === this.maxDepth ? 1 / 0 : this.maxDepth)
|
|
|
-
|
|
|
-
|
|
|
- this.zoomLevel = level//add
|
|
|
-
|
|
|
-
|
|
|
- /* if(isNaN(this.zoomLevel )){
|
|
|
- console.log(level, cos , scale , lonlat )
|
|
|
- } */
|
|
|
|
|
|
if(!unavailable){
|
|
|
this.addToSceneGroup(sceneGroup)
|
|
|
- return this.baseTile.update(this, frustum, level, this.mapSizeM, 0, 0, "")
|
|
|
+ /* return */this.baseTile.update(this, frustum, level, this.mapSizeM, 0, 0, "", viewport)
|
|
|
+ this.cacheAutoClear()
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- isTileVisible(tileCenter, tileSize, frustum){
|
|
|
+ isTileVisible(tileCenter, tileSize, frustum, viewport, name){
|
|
|
if (tileSize > HALF_WORLD_SIZE) return !0; //root must visible
|
|
|
var halfSize = .5 * tileSize; //在地图上的size和local的差不多是吗
|
|
|
-
|
|
|
- //简单版:
|
|
|
- this.transformMapToLocal.forward(tileCenter) //e转化为local
|
|
|
+ let vertices = []
|
|
|
+ //简单版:
|
|
|
+ if(makeSphere){
|
|
|
+ tileCenter = getPosOnEarth(tileCenter.toArray(), this.transformMapToLocal )
|
|
|
+ }else{
|
|
|
+ this.transformMapToLocal.forward(tileCenter) //e转化为local
|
|
|
+ //tileCenter.sub(this.objectGroup.parent.position)
|
|
|
+ }
|
|
|
this.isTileVisibleBox.makeEmpty()
|
|
|
this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y - halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
+ vertices.push(this.isTileVisibleVec.clone())
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
+
|
|
|
this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y + halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
+ vertices.push(this.isTileVisibleVec.clone())
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
+
|
|
|
this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y - halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
+ vertices.push(this.isTileVisibleVec.clone())
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
+
|
|
|
this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y + halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
+ vertices.push(this.isTileVisibleVec.clone())
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ let visi = frustum.intersectsBox(this.isTileVisibleBox)
|
|
|
+
|
|
|
+
|
|
|
|
|
|
- //仿造createMesh写的准确版,但会因为大的tile非矩形,而视口是矩形,若视口刚好在tile的曲线边缘外却识别为可见,就会创建冗余tile。 但上面那个简单版在zoomlevel低的时候地球边缘容易有识别不到的tile,造成黑色三角形。
|
|
|
+ if(viewport && visi){
|
|
|
+ let canTraverse, vecs = []
|
|
|
+ let dis = tileCenter.distanceTo(viewport.camera.position)
|
|
|
+
|
|
|
+ //if(window.not111){
|
|
|
+
|
|
|
+ let centerToCam = tileCenter.clone().applyMatrix4(viewport.camera.matrixWorldInverse)//相对位置
|
|
|
+ centerToCam.normalize() //dir
|
|
|
+
|
|
|
+ let n = 1.1, v1 = 3, v2 = 7, v3 = 14
|
|
|
+ let a = dis / camDisToEarth
|
|
|
+
|
|
|
+ let r1 = math.linearClamp(a,[1,v1,v2,v3], [1, n, 1, 0.8]) //最近距离v1倍率处稍微提高
|
|
|
+
|
|
|
+ let r2 = math.linearClamp(Math.abs(centerToCam.x),[0, 0.7, 0.8], [1, 1.3, 1]) //相机两旁的提高
|
|
|
+ let r = r1 * r2 //使画面最近点附近的level提高些
|
|
|
+
|
|
|
+ r *= math.linearClamp(viewport.view.direction.z, [-1, -0.8 ], [a/r, 1]) //相机几乎垂直地面时,使全部level相同,类似2d
|
|
|
+
|
|
|
+ canTraverse = tileSize / dis * r > (window.number2 || 0.6)
|
|
|
+
|
|
|
+ /* }else{
|
|
|
+ canTraverse = tileSize / dis > (window.number2 || 0.6)
|
|
|
+
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /* let pos2ds = vertices.map(e=> e.clone().project( viewport.camera)) //不管是否在背面了,太麻烦
|
|
|
+ //对角线长度
|
|
|
+ vecs.push(new THREE.Vector2().subVectors(pos2ds[0],pos2ds[2]))
|
|
|
+ vecs.push(new THREE.Vector2().subVectors(pos2ds[1],pos2ds[3]))
|
|
|
+
|
|
|
+ let lens = vecs.map(vec=>vec.multiply(viewport.resolution).length())
|
|
|
+ let px = Math.max(...lens)
|
|
|
+ canTraverse = px > this.tileSizePx * 4//1.414 */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ visi = {canTraverse}
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* //仿造createMesh写的准确版,但会因为大的tile非矩形,而视口是矩形,若视口刚好在tile的曲线边缘外却识别为可见,就会创建冗余tile。 但上面那个简单版在zoomlevel低的时候地球边缘容易有识别不到的tile,造成黑色三角形。
|
|
|
//容易出现奇怪的mesh
|
|
|
- /* this.isTileVisibleBox.makeEmpty()
|
|
|
- this.isTileVisibleVec.set(e.x - r, e.y - r, e.z)
|
|
|
+ this.isTileVisibleBox.makeEmpty()
|
|
|
+ this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y - halfSize, tileCenter.z)
|
|
|
this.transformMapToLocal.forward(this.isTileVisibleVec)
|
|
|
this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
|
|
|
- this.isTileVisibleVec.set(e.x - r, e.y + r, e.z)
|
|
|
+ this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y + halfSize, tileCenter.z)
|
|
|
this.transformMapToLocal.forward(this.isTileVisibleVec)
|
|
|
this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
|
|
|
- this.isTileVisibleVec.set(e.x + r, e.y - r, e.z)
|
|
|
+ this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y - halfSize, tileCenter.z)
|
|
|
this.transformMapToLocal.forward(this.isTileVisibleVec)
|
|
|
this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
|
|
|
- this.isTileVisibleVec.set(e.x + r, e.y + r, e.z)
|
|
|
+ this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y + halfSize, tileCenter.z)
|
|
|
this.transformMapToLocal.forward(this.isTileVisibleVec)
|
|
|
this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
|
|
|
- this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec) */
|
|
|
-
|
|
|
+ this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
|
|
|
+ */
|
|
|
|
|
|
- return frustum.intersectsBox(this.isTileVisibleBox)
|
|
|
+ return visi
|
|
|
|
|
|
|
|
|
|
|
|
@@ -458,7 +554,8 @@ const loadDone = (tile, success)=>{
|
|
|
tile.map.mapLayer.dispatchEvent('loadDone')
|
|
|
}
|
|
|
}
|
|
|
- tile.mesh && (tile.mesh.material.needsUpdate = true)
|
|
|
+ let mesh = tile.mesh || tile._mesh
|
|
|
+ mesh && (mesh.material.needsUpdate = true)
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -485,15 +582,19 @@ function addLoadTile(tile){
|
|
|
|
|
|
|
|
|
let tex = tile.mesh.material.map = texLoader.load(tile.texURL, (tex)=>{ //如果一直加载不了会影响其他的加载,如google地图没有vpn会使全景图一直加载不了
|
|
|
- if(tile.mesh){//如果还要显示的话
|
|
|
+ let mesh = tile.mesh || tile._mesh
|
|
|
+ if(mesh){//如果还存在的话
|
|
|
tile.textureLoaded = true
|
|
|
- tile.mesh.material.opacity = 1
|
|
|
- tile.map.mapLayer.viewer.mapChanged = true
|
|
|
- tile.map.mapLayer.needUpdate = true //表示还要继续update(以removeChildren)
|
|
|
-
|
|
|
- if(tile.map instanceof TiledMapOpenStreetMap){
|
|
|
- tile.map.maxLoading = browser.isMobile() ? 5 : 10;
|
|
|
- }
|
|
|
+ mesh.material.opacity = mesh.clockwise ? 0 : 1
|
|
|
+ if(tile.mesh){//显示的话
|
|
|
+ tile.map.mapLayer.viewer.mapChanged = true
|
|
|
+ tile.map.mapLayer.needUpdate = true //表示还要继续update(以removeChildren)
|
|
|
+
|
|
|
+ if(tile.map instanceof TiledMapOpenStreetMap){
|
|
|
+ tile.map.maxLoading = browser.isMobile() ? 5 : 10;
|
|
|
+ }
|
|
|
+ tile.map.mapLayer.dispatchEvent('tileLoaded')
|
|
|
+ }
|
|
|
}else{
|
|
|
//tile.texURL && tile.texURL.includes('testdata') && console.log('loadDone and dispose', tile.texURL.split('map_tiles/')[1] )
|
|
|
tex.dispose()
|
|
|
@@ -513,11 +614,16 @@ function addLoadTile(tile){
|
|
|
tile.map.maxLoading = 2;
|
|
|
}
|
|
|
|
|
|
- }))
|
|
|
- tex.anisotropy = 0
|
|
|
- tex.generateMipmaps = !1
|
|
|
- tex.minFilter = THREE.LinearFilter
|
|
|
- tex.magFilter = THREE.LinearFilter
|
|
|
+ }))
|
|
|
+ if(tile.map.mapLayer.is3d){
|
|
|
+ tex.anisotropy = 2
|
|
|
+ }else{
|
|
|
+ tex.anisotropy = 0
|
|
|
+ tex.generateMipmaps = !1
|
|
|
+ tex.minFilter = THREE.LinearFilter
|
|
|
+ tex.magFilter = THREE.LinearFilter
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}else{
|
|
|
tile.map.mapLayer.waitQueue.includes(tile) || tile.map.mapLayer.waitQueue.push(tile)
|
|
|
@@ -546,8 +652,13 @@ export class MapTile{
|
|
|
this.children = []
|
|
|
this.id = getSid();
|
|
|
}
|
|
|
- update(entity, frustum, level, tileSize, centerX, centerY, treeStr){
|
|
|
- return !!this.doesNotContainTilesToBeDisplayed(entity) || (0 === level ? this.updateTileLeaf(entity, tileSize, centerX, centerY ) : this.updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr))
|
|
|
+ update(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport, canTraverse=true){
|
|
|
+ if(!this.doesNotContainTilesToBeDisplayed(entity) ){
|
|
|
+ let canTraverse_ = this.map.mapLayer.is3d ? canTraverse : level > 0
|
|
|
+ return (canTraverse_ ? this.updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport) : this.updateTileLeaf(entity, tileSize, centerX, centerY ) )
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
doesNotContainTilesToBeDisplayed(entity){
|
|
|
@@ -575,7 +686,7 @@ export class MapTile{
|
|
|
return this.textureLoaded
|
|
|
}
|
|
|
|
|
|
- updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr){
|
|
|
+ updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport){
|
|
|
//if(entity.name.includes('floorplan'))console.log('updateSubTiles',this.name) //名字越长代表level越高
|
|
|
|
|
|
let shiftX = [-.25 * tileSize, .25 * tileSize, -.25 * tileSize, .25 * tileSize],
|
|
|
@@ -592,13 +703,17 @@ export class MapTile{
|
|
|
tempVector.set(childCenterX, childCenterY, 0);
|
|
|
this.map.computeCount ++
|
|
|
//console.log(this.map.computeCount, this.name, 'level:',level)
|
|
|
-
|
|
|
- if (entity.isTileVisible(tempVector, .5 * tileSize, frustum)){
|
|
|
+ let checkLevel = entity.mapLayer.is3d && level > 1
|
|
|
+ if( entity.name == 'map' && checkLevel && entity.minDepth) checkLevel = level < entity.maxDepth - entity.minDepth //禁止地球显示层级过低否则无图且变形
|
|
|
+ let visi = entity.isTileVisible(tempVector, .5 * tileSize, frustum, checkLevel && viewport, this.name+p)
|
|
|
+ if (visi){
|
|
|
+ //entity.name == 'map' && console.log('visi', childTreeStr, childCenterX,childCenterY, tileSize)
|
|
|
this.children[p] || (this.children[p] = new MapTile(this.map, this.objectGroup,this.tileColor, this, this.name+p ))
|
|
|
//childrenLoaded = childrenLoaded && this.children[p].update(entity, frustum, level - 1, .5 * tileSize, childCenterX, childCenterY, childTreeStr) //这句会使若有一个tile还在加载,就阻断了。原版是这么写的。但是为了加快加载速度,改成下面两行。感觉直接全部updateTile也没太卡,不知道很大的场景会不会卡,单帧updateTile次数超过100次的话(应该不会吧,地图大小会限制住个数) -- 2023.12
|
|
|
- let childLoaded = this.children[p].update(entity, frustum, level - 1, .5 * tileSize, childCenterX, childCenterY, childTreeStr)
|
|
|
+ let childLoaded = this.children[p].update(entity, frustum, level - 1, .5 * tileSize, childCenterX, childCenterY, childTreeStr, viewport, level > 1 && visi.canTraverse)
|
|
|
childrenLoaded = childrenLoaded && childLoaded
|
|
|
} else {
|
|
|
+ //entity.name == 'map' && console.log('not visi', childTreeStr, childCenterX,childCenterY, tileSize)
|
|
|
if (this.children[p]){
|
|
|
this.children[p].remove()
|
|
|
delete this.children[p]
|
|
|
@@ -620,71 +735,118 @@ export class MapTile{
|
|
|
|
|
|
*/
|
|
|
createTileObject(entity, tileSize, centerXatMap, centerYatMap){
|
|
|
- var s = this;
|
|
|
- this.mesh = this.createMesh(entity.transformMapToLocal,tileSize, centerXatMap, centerYatMap),
|
|
|
- this.textureLoaded = !1;
|
|
|
- var c = entity.mapSizeM / tileSize
|
|
|
- , z = math.getBaseLog(2,c) //以2为底c的对数
|
|
|
- , x = centerXatMap / tileSize + .5 * (c - 1)
|
|
|
- , y = -centerYatMap / tileSize + .5 * (c - 1)
|
|
|
- , p = entity.getTileUrl(Math.round(x), Math.round(y), Math.round(z));
|
|
|
- Potree.Utils.setObjectLayers(this.mesh, 'map' )
|
|
|
- this.mesh.renderOrder = -(1e6 - z - 100 * (entity.zIndex || 0));
|
|
|
- this.mesh.name = this.name //add
|
|
|
- this.texURL = p
|
|
|
-
|
|
|
- /* let area = math.getArea(this.mesh.geometry.vertices.slice(0,3));
|
|
|
- if(area >0){
|
|
|
- this.mesh.visible = false
|
|
|
- console.log('area>0',this.mesh.name)
|
|
|
- } */
|
|
|
- addLoadTile(this)
|
|
|
-
|
|
|
+
|
|
|
+ let tileIndex = this.map.cache.findIndex(e=>e == this)
|
|
|
+
|
|
|
+ if(tileIndex == -1){
|
|
|
+ mesh = this.createMesh(entity.transformMapToLocal,tileSize, centerXatMap, centerYatMap),
|
|
|
+ mesh.name = this.name
|
|
|
+ if(showTileName){
|
|
|
+ this.textureLoaded = !0; //add
|
|
|
+ }else{
|
|
|
+ this.textureLoaded = !1;
|
|
|
+ var c = entity.mapSizeM / tileSize
|
|
|
+ , z = math.getBaseLog(2,c) //以2为底c的对数
|
|
|
+ , x = centerXatMap / tileSize + .5 * (c - 1)
|
|
|
+ , y = -centerYatMap / tileSize + .5 * (c - 1)
|
|
|
+ , p = entity.getTileUrl(Math.round(x), Math.round(y), Math.round(z));
|
|
|
+ Potree.Utils.setObjectLayers(mesh, 'map' )
|
|
|
+ mesh.renderOrder = -(1e6 - z - 100 * (entity.zIndex || 0));
|
|
|
+
|
|
|
+ this.texURL = p
|
|
|
+ newBuilt = true
|
|
|
+
|
|
|
+ }
|
|
|
+ //this.map.cacheAutoClear() //增加一个就可能要减少一个
|
|
|
+ }else{
|
|
|
+
|
|
|
+ mesh = this.map.cache.splice(tileIndex,1)[0]//从缓存取出
|
|
|
+ }
|
|
|
+
|
|
|
+ this.mesh = mesh
|
|
|
+ tileIndex > -1 && addLoadTile(this)
|
|
|
}
|
|
|
|
|
|
- createMesh(transform, tileSize, centerXatMap, centerYatMap){
|
|
|
- var a = new THREE.Geometry;
|
|
|
- return tempVector.set(centerXatMap - tileSize / 2, centerYatMap - tileSize / 2, 0),
|
|
|
- a.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
+ /* getVertices(transform, tileSize, centerXatMap, centerYatMap){
|
|
|
+ this.vertices = []
|
|
|
+ tempVector.set(centerXatMap - tileSize / 2, centerYatMap - tileSize / 2, 0),
|
|
|
+ this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
tempVector.set(centerXatMap + tileSize / 2, centerYatMap - tileSize / 2, 0),
|
|
|
- a.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
+ this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
tempVector.set(centerXatMap + tileSize / 2, centerYatMap + tileSize / 2, 0),
|
|
|
- a.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
+ this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
tempVector.set(centerXatMap - tileSize / 2, centerYatMap + tileSize / 2, 0),
|
|
|
- a.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
|
|
|
+ this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector)))
|
|
|
+
|
|
|
+ } */
|
|
|
+
|
|
|
+ createMesh(transform, tileSize, centerXatMap, centerYatMap){
|
|
|
+ var a = new THREE.Geometry;
|
|
|
+ let vertices = [
|
|
|
+ [centerXatMap - tileSize / 2, centerYatMap - tileSize / 2],
|
|
|
+ [centerXatMap + tileSize / 2, centerYatMap - tileSize / 2],
|
|
|
+ [centerXatMap + tileSize / 2, centerYatMap + tileSize / 2],
|
|
|
+ [centerXatMap - tileSize / 2, centerYatMap + tileSize / 2]
|
|
|
+ ]
|
|
|
+ vertices.forEach(vertice=>{//计算在球面上的位置, xy已经有了,算z
|
|
|
+ if(makeSphere){
|
|
|
+ a.vertices.push(getPosOnEarth(vertice, transform) )//(0,0)处地表z为0,其余都在0之下
|
|
|
+ }else{
|
|
|
+ a.vertices.push(new THREE.Vector3().fromArray([...transform.forward(vertice),0]))
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
a.faces.push(face1),
|
|
|
a.faces.push(face2),
|
|
|
a.faceVertexUvs[0].push(face1UV),
|
|
|
- a.faceVertexUvs[0].push(face2UV),
|
|
|
- new THREE.Mesh(a,this.createMaterial())
|
|
|
+ a.faceVertexUvs[0].push(face2UV)
|
|
|
+ let label
|
|
|
+ if(showTileName){
|
|
|
+ //let center = this.tilePos || new THREE.Vector3().fromArray(transform.forward([centerXatMap,centerYatMap,0]))
|
|
|
+ label = new TextSprite({text: this.name, sizeInfo:{width2d:200}, fontsize:60,
|
|
|
+ textColor: {r:30, g: 30, b: 30, a:1}, backgroundColor: {r:255, g: 255, b: 255, a:0.98},
|
|
|
+ })
|
|
|
+ /* label.position.copy(center)
|
|
|
+ mesh.add(label) */
|
|
|
+ }
|
|
|
+
|
|
|
+ let mesh = new THREE.Mesh(a,this.createMaterial(label))
|
|
|
+
|
|
|
+ if(this.map.mapLayer.is3d){
|
|
|
+ let clockwise = math.getArea(a.vertices) > 0;
|
|
|
+ mesh.clockwise = clockwise
|
|
|
+ showTileName && (mesh.material.opacity = clockwise ? 0 : 1)//soon
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return mesh
|
|
|
}
|
|
|
|
|
|
- createMaterial(){
|
|
|
+ createMaterial(label){
|
|
|
+ let color
|
|
|
+
|
|
|
+ if(Potree.settings.isTest) {
|
|
|
+ var colorHue = Math.random()
|
|
|
+ color = new THREE.Color().setHSL(colorHue, 0.6, 0.92)
|
|
|
+ }else{
|
|
|
+ color = this.tileColor ? this.tileColor : new THREE.Color(16777215)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
var t = new THREE.MeshBasicMaterial({
|
|
|
transparent: !0,
|
|
|
depthWrite: !1,
|
|
|
- depthTest: !0,
|
|
|
+ depthTest: !1, //!0
|
|
|
opacity: 0,
|
|
|
side: THREE.DoubleSide,
|
|
|
-
|
|
|
+ color,
|
|
|
});
|
|
|
|
|
|
-
|
|
|
- /* var t = new BasicMaterial({
|
|
|
- transparent: !0,
|
|
|
- depthWrite: !1,
|
|
|
- depthTest: !0,
|
|
|
- opacity: 0,
|
|
|
- side: THREE.DoubleSide
|
|
|
- })
|
|
|
- t.defines.InverseColor = '' */
|
|
|
-
|
|
|
- if(Potree.settings.isTest) {
|
|
|
- var colorHue = Math.random()
|
|
|
- t.color = new THREE.Color().setHSL(colorHue, 0.6, 0.92)
|
|
|
- }else{
|
|
|
- t.color = this.tileColor ? this.tileColor : new THREE.Color(16777215)
|
|
|
- }
|
|
|
+ label && (t.map = label.sprite.material.map) //add
|
|
|
+
|
|
|
|
|
|
return t
|
|
|
}
|
|
|
@@ -701,20 +863,28 @@ export class MapTile{
|
|
|
removeObject3D(){
|
|
|
let hasMesh = !!this.mesh
|
|
|
if (this.mesh){
|
|
|
+
|
|
|
+ if(this.mesh.material.map){//add 已经有图或在加载图
|
|
|
+ this.mesh_ = this.mesh
|
|
|
+ this.map.cache.push(this) //加入缓存
|
|
|
+ }else{
|
|
|
+ cancelLoad(this)
|
|
|
+ }
|
|
|
this.objectGroup.remove(this.mesh)
|
|
|
- if (this.textureLoaded){
|
|
|
+
|
|
|
+ /* if (this.textureLoaded){
|
|
|
var t = this.mesh.material.map;
|
|
|
t && t.dispose()
|
|
|
}else{
|
|
|
cancelLoad(this)
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
this.mesh.material.dispose() //o.disposeMeshMaterial(this.mesh),
|
|
|
- this.mesh.geometry.dispose()
|
|
|
+ this.mesh.geometry.dispose() */
|
|
|
this.mesh = void 0
|
|
|
}
|
|
|
- this.meshAdded = !1,
|
|
|
- this.textureLoaded = !1
|
|
|
+ this.meshAdded = !1
|
|
|
+
|
|
|
//this.texURL && this.texURL.includes('testdata') && console.log('removeObject3D', this.id, 'hasMesh',hasMesh, this.texURL.split('map_tiles/')[1] )
|
|
|
}
|
|
|
|
|
|
@@ -737,9 +907,11 @@ export class MapTile{
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
+//墨卡托全球矩形,无任何偏移: (地图资源是按照这个来获取的,不能偏移;而每个tile的具体位置则是这映射到local坐标后得到的,可以通过变换local的定义来改变transform映射。 )
|
|
|
proj4.defs("EPSG:3857", "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs")
|
|
|
-//这里地图世界的中心是不是lon:0,lat:0
|
|
|
+ //注意在traverse四叉树会因为local的偏移而使边缘tile分裂为2块以上,尤其在子结点createMesh时就能看到那些图片拉伸的怪怪的tile, 我通过过滤掉clockwise来过滤掉这些错误mesh,因此缺少了一部分,全局看map左右不完整
|
|
|
+
|
|
|
+
|
|
|
|
|
|
export class TiledMapOpenStreetMap extends TiledMapBase{
|
|
|
constructor(mapLayer, tileColor){
|
|
|
@@ -751,9 +923,9 @@ export class TiledMapOpenStreetMap extends TiledMapBase{
|
|
|
//this.baseUrl = "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}" //最高只到18 level
|
|
|
this.switchStyle()
|
|
|
this.tileSizePx = 256
|
|
|
- this.mapSizeM = 40075017 //总占据多少米(地球赤道周长) 和三维空间的不一样 - -, 空间上的是直径,地图上的是半个圆周
|
|
|
+ this.mapSizeM = Math.floor(6378137 * Math.PI * 2)//40075016, 不要超出地图projection范围 // 40075017 //总占据多少米(地球赤道周长) 和三维空间的不一样 - -, 空间上的是直径,地图上的是半个圆周
|
|
|
this.bias = 0.5
|
|
|
-
|
|
|
+ this.minDepth = 1 //add 因0的无图或不全
|
|
|
if(Potree.settings.mapCompany == 'google'){
|
|
|
this.attribution = "© PopSmart, © 谷歌地图"
|
|
|
this.projection = "EPSG:900913" //"EPSG:4326"//4550
|
|
|
@@ -786,8 +958,7 @@ export class TiledMapOpenStreetMap extends TiledMapBase{
|
|
|
+ (glPos ? ("&gl=" + glPos) : '')
|
|
|
+ "&x=${x}&y=${y}&z=${z}&s=mt1"
|
|
|
|
|
|
- this.maxDepth = 22
|
|
|
-
|
|
|
+ this.maxDepth = 22
|
|
|
/* 1)lyrs= 表示的是图层类型,即瓦片类型,具体含义如下:
|
|
|
m:路线图
|
|
|
t:地形图
|
|
|
@@ -810,6 +981,7 @@ export class TiledMapOpenStreetMap extends TiledMapBase{
|
|
|
}else{
|
|
|
//baseUrl = "https://webst01.is.autonavi.com/appmaptile?lang=zh_cn&style=6&yrs=m&x=${x}&y=${y}&z=${z}" //卫星 maxDepth = 18
|
|
|
//搜索高德地图瓦片url
|
|
|
+
|
|
|
if(Potree.settings.isJiangMen){
|
|
|
if(style == 'satellite'){//卫星
|
|
|
this.maxDepth = 18
|
|
|
@@ -901,7 +1073,7 @@ export class TiledMapFromEntity extends TiledMapBase{
|
|
|
|
|
|
|
|
|
computeLocalCoordinates(){
|
|
|
- if(proj4.defs("LOCAL_MAP")){
|
|
|
+ if(proj4.defs("LOCAL"/* _MAP" */)){
|
|
|
|
|
|
let lonlat = this.tiledMapEntity.globalLocation
|
|
|
/* if(window.AMapWith84){//需要转换
|
|
|
@@ -984,7 +1156,9 @@ export class TiledMapFromEntity extends TiledMapBase{
|
|
|
|
|
|
/*
|
|
|
note:
|
|
|
-
|
|
|
+ google地图看国内某个84经纬度和矫正后的高德的不一样,和未矫正后的高德接近.
|
|
|
+ map3d效果和高德地图差不多,原来高德也有三维的 https://www.amap.com/
|
|
|
+ 高德限制了相机高度,使之不会到没有图的低level;且支持x轴无限滚动连接
|
|
|
|
|
|
|
|
|
目前缩小了能看出形态是一个地球。相机在高空朝下观测,地球平放着。
|