|
@@ -16,7 +16,7 @@ import TilePrioritizer from './tile/TilePrioritizer.js'
|
|
|
import {transitions, easing, lerp} from "../../utils/transitions.js";
|
|
|
import DepthImageSampler from './DepthImageSampler.js'
|
|
|
let {PanoSizeClass,Vectors,GLCubeFaces, PanoramaEvents} = Potree.defines
|
|
|
-
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -47,7 +47,12 @@ const directionFactor = 400 //原先10,几乎只往距离近的走了;设置
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
+let getID = (function(){
|
|
|
+ let id = 0
|
|
|
+ return function(){
|
|
|
+ return id ++
|
|
|
+ }
|
|
|
+})()
|
|
|
|
|
|
|
|
|
|
|
@@ -60,7 +65,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
this.panos = [];
|
|
|
this.neighbourMap = {}
|
|
|
-
|
|
|
+ this.disMap = {}
|
|
|
|
|
|
this.node = new THREE.Object3D();
|
|
|
this.node.name = 'ImagesNode'
|
|
@@ -75,28 +80,23 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
this.cube.layers.set(Potree.config.renderLayers.skybox)
|
|
|
this.cube.name = 'skyboxCube'
|
|
|
viewer.scene.scene.add(this.cube)
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
if(Potree.settings.mergeType2 && Potree.settings.modelSkybox){
|
|
|
this.materialInside = new ModelTextureMaterial( )
|
|
|
this.materialInside.dontChangeDepth = true //chunk本身深度是对的,不用深度图,否则过渡会有很多裂痕
|
|
|
this.cube.material.defines.depth_background = '' //skybox的深度改得向后一些, 避免盖住chunk,造成坑坑洼洼
|
|
|
|
|
|
- this.addEventListener('endChangeMode',(e)=>{
|
|
|
- if( this.currentPano?.pointcloud?.is4dkkModel){
|
|
|
- let model = this.currentPano.pointcloud
|
|
|
- if(model.fileType == '3dTiles'){
|
|
|
- viewer.setAllTilesets(model, (child)=>{
|
|
|
- child.runtime.limit2lowestDepth(e.mode == 'showPanos')
|
|
|
- child.runtime.getTileset().tiles.forEach(e=>{
|
|
|
- this.judgeModelMat(e.tileContent)
|
|
|
- })
|
|
|
- })
|
|
|
- }else{
|
|
|
- this.judgeModelMat(model)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
+ this.addEventListener('endChangeMode',(e)=>{
|
|
|
+ viewer.objs.children.forEach(e=>{
|
|
|
+ if(e.panos) this.changeModelMat(e)
|
|
|
+ }) //干脆全部换,就不容易错
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
if(Potree.settings.testCube){
|
|
@@ -177,10 +177,10 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
let click = (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
|
|
|
if(e.clickElement ||
|
|
|
Potree.settings.unableNavigate || this.flying || !e.isTouch && e.button != THREE.MOUSE.LEFT || e.drag && e.drag.object //拖拽结束时不算
|
|
|
- || Potree.settings.editType == 'pano' && viewer.modules.PanoEditor.activeViewName != 'mainView'
|
|
|
+ /* || Potree.settings.editType == 'pano' && viewer.modules.PanoEditor.entered */
|
|
|
//|| Potree.settings.editType == 'merge' && !e.intersectPoint || viewer.inputHandler.hoveredElements[0] && viewer.inputHandler.hoveredElements[0].isModel && e.intersectPoint.distance > viewer.inputHandler.hoveredElements[0].distance
|
|
|
|| Potree.settings.editType == 'merge' && !Potree.settings.mergeType2
|
|
|
- || Potree.settings.mergeType2 && Potree.settings.displayMode == 'showPointCloud'
|
|
|
+ //|| Potree.settings.mergeType2 && Potree.settings.displayMode == 'showPointCloud'
|
|
|
) return
|
|
|
|
|
|
if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge'){
|
|
@@ -610,15 +610,29 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
};
|
|
|
|
|
|
|
|
|
+ changeModelMat(model/* , isCurModel */){
|
|
|
+ if(model?.is4dkkModel){
|
|
|
+ if(model.fileType == '3dTiles'){
|
|
|
+ viewer.setAllTilesets(model, (child)=>{
|
|
|
+ child.runtime.limit2lowestDepth(Potree.settings.displayMode == 'showPanos')
|
|
|
+ child.runtime.getTileset().tiles.forEach(e=>{
|
|
|
+ this.judgeModelMat(e.tileContent/* , isCurModel */)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }else{
|
|
|
+ this.judgeModelMat(model/* , isCurModel */)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- judgeModelMat(object){
|
|
|
+ judgeModelMat(object/* , isCurModel */){
|
|
|
if(!(Potree.settings.mergeType2 && Potree.settings.modelSkybox))return
|
|
|
object.traverse(mesh=>{
|
|
|
if(mesh.material){
|
|
|
if(!mesh.materialOutside){
|
|
|
mesh.materialOutside = mesh.material
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+ //mesh.material = Potree.settings.displayMode == 'showPanos' && (this.nextPano?.pointcloud == object || this.currentPano.pointcloud == object || isCurModel) ? this.materialInside : mesh.materialOutside
|
|
|
mesh.material = Potree.settings.displayMode == 'showPanos' ? this.materialInside : mesh.materialOutside
|
|
|
Potree.Utils.setObjectLayers(mesh, Potree.settings.displayMode == 'showPanos' ? 'skybox' : 'model' ) //为了渲染到rtEDL
|
|
|
|
|
@@ -638,7 +652,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
findNearestPano(pos, panos=this.panos){
|
|
|
pos = pos ? new THREE.Vector3().copy(pos) : this.position
|
|
|
- let result = Common.sortByScore(panos,[Images360.filters.isEnabled()],[e=>-e.position.distanceTo(pos)])
|
|
|
+ let result = Common.sortByScore(panos,[Images360.filters.isEnabled()],[e=>-e.position.distanceTo(pos) / e.pointcloud.scale.x])
|
|
|
let pano = result[0] && result[0].item
|
|
|
return pano
|
|
|
|
|
@@ -778,6 +792,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
this.nextPano = pano
|
|
|
this.latestToPano = toPano
|
|
|
+
|
|
|
//this.flying = true //防止新的请求
|
|
|
//Potree.Log('flyToPano:'+pano.id + ' , duration:'+toPano.duration, null, 12)
|
|
|
|
|
@@ -980,6 +995,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
this.lastPano = this.currentPano //记录,调试
|
|
|
this.currentPano = pano;
|
|
|
|
|
|
+
|
|
|
this.nextPano = null;
|
|
|
if(Potree.settings.displayMode == 'showPanos'){
|
|
|
viewer.scene.pointclouds.forEach(e=>{
|
|
@@ -1009,10 +1025,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
beforeFlyToPano(toPano){
|
|
|
if(this.currentPano != toPano.pano) {
|
|
|
if(Potree.settings.displayMode == 'showPanos'){
|
|
@@ -1275,7 +1288,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
isNeighbour(pano0, pano1, {dontCompute, onlyUseTex, computeDirFirst, computeTwoDir}={}){//是否之间没有遮挡(在加载visibles之前,自己算) 最好pano0是currentPano
|
|
|
|
|
|
if(!pano0 || !pano1 )return
|
|
|
-
|
|
|
+ if(!viewer.scene.pointclouds.some(e=>e.hasDepthTex))return true
|
|
|
let margin = 0.1;
|
|
|
|
|
|
let map0 = this.neighbourMap[pano0.id]; //主
|
|
@@ -1303,7 +1316,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
|
|
|
- let logSids = [/* '1739923562316697600|3','1739923562316697600|2' */]
|
|
|
+ let logSids = [ /* '1566756240057044992|4','1566756240057044992|5' */ ]
|
|
|
let ifLog = pano0.sid == logSids[0] && pano1.sid == logSids[1] || pano0.sid == logSids[1] && pano1.sid == logSids[0]
|
|
|
if(ifLog){
|
|
|
console.log(2)
|
|
@@ -1362,27 +1375,30 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
*/
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
|
|
|
//三个方向 : position0到position1, position0到floorPosition1, position1到floorPosition0。 只要有一个满足ifNeighbour就为true。 不过为了不使sampler总换图,先只考虑从主pano到副pano的方向
|
|
|
|
|
|
let getNeighbour = (mainPano, subPano )=>{
|
|
|
|
|
|
let dirPoints = [[subPano.position, mainPano.position]] //注: 点A能到B不代表点B能到A,因为拍摄时物体会移动,或点位相对位置不对,无论是否是意外遮挡都且记下来,反正最后只要有一方可行就算相邻。
|
|
|
-
|
|
|
- if(dis < 20){//在远处去掉对floorPosition的判断
|
|
|
- dirPoints.push([subPano.floorPosition.clone().add(new THREE.Vector3(0,0,0.1)), mainPano.position])
|
|
|
- }
|
|
|
- if(dis < 12){//为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
|
|
|
- dirPoints.push([subPano.position.clone().add(new THREE.Vector3(0,0,0.8)), mainPano.position])
|
|
|
-
|
|
|
- let normal = math.getNormal2d({p1:subPano.position, p2:mainPano.position}).multiplyScalar(0.3) //左右方向
|
|
|
-
|
|
|
- dirPoints.push([subPano.position.clone().add(new THREE.Vector3(normal.x,normal.y,0.1)), mainPano.position])
|
|
|
- dirPoints.push([subPano.position.clone().add(new THREE.Vector3(-normal.x,-normal.y,0.1)), mainPano.position])
|
|
|
- }
|
|
|
-
|
|
|
+ if(new THREE.Vector2().subVectors(subPano.position,mainPano.position).length()>1e-4){//xy都不同
|
|
|
+
|
|
|
+ if(dis < 25){//在远处去掉对floorPosition的判断
|
|
|
+ dirPoints.push([subPano.floorPosition.clone().add(new THREE.Vector3(0,0,0.1)), mainPano.position])
|
|
|
+ }
|
|
|
+ if(dis < 15){//为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
|
|
|
+ dirPoints.push([subPano.position.clone().add(new THREE.Vector3(0,0,0.8)), mainPano.position])
|
|
|
+
|
|
|
+ let normal = math.getNormal2d({p1:subPano.position, p2:mainPano.position}).multiplyScalar(0.3) //左右方向
|
|
|
+
|
|
|
+ dirPoints.push([subPano.position.clone().add(new THREE.Vector3(normal.x,normal.y,0.1)), mainPano.position])
|
|
|
+ dirPoints.push([subPano.position.clone().add(new THREE.Vector3(-normal.x,-normal.y,0.1)), mainPano.position])
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ console.warn('两个点位的xy几乎相同', mainPano.id, subPano.id)
|
|
|
+ }
|
|
|
//console.warn('getNeighbour', mainPano.id,subPano.id)
|
|
|
for(let i=0; i<dirPoints.length; i++){
|
|
|
let dir = new THREE.Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
|
|
@@ -1415,7 +1431,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
if( map0[pano1.id] === false || map1[pano0.id] === false){
|
|
|
- if(dis<20) {//再检查下 只要两方都没有被完全遮挡就算可通行 针对杂点较多的情况
|
|
|
+ if(dis<25) {//再检查下 只要两方都没有被完全遮挡就算可通行 针对杂点较多的情况
|
|
|
if(pano0.depthTex && pano1.depthTex){
|
|
|
ifNeighbour = false
|
|
|
let a = ifSheltered(pano0,pano1)
|
|
@@ -1429,8 +1445,8 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
}
|
|
|
}else{
|
|
|
//标记为无需再计算, 因已经失败。 当map0和map1都不为void 0后就无法再计算了。
|
|
|
- if(map0[pano1.id] === void 0) map0[pano1.id] = 0 ;
|
|
|
- if(map1[pano0.id] === void 0) map1[pano0.id] = 0 ;
|
|
|
+ if(map0[pano1.id] === void 0) map0[pano1.id] = false;
|
|
|
+ if(map1[pano0.id] === void 0) map1[pano0.id] = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1489,7 +1505,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
|
|
|
- if(map0[pano1.id] && map1[pano0.id]){
|
|
|
+ if(map0[pano1.id] && map1[pano0.id]){ //要获得双向需要depthTex都加载好,可能要很久时间
|
|
|
pano0.neighbours.includes(pano1) || pano0.neighbours.push(pano1)
|
|
|
pano1.neighbours.includes(pano0) || pano1.neighbours.push(pano0)
|
|
|
}
|
|
@@ -1505,7 +1521,7 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
bump(direction) {//撞墙弹回效果
|
|
|
if (!this.bumping && !this.latestToPano) {
|
|
|
- let distance = Potree.settings.displayMode == 'showPanos' ? 0.15 : 0.12;//感觉点云模式比全景模式更明显,所以降低
|
|
|
+ let distance = (Potree.settings.displayMode == 'showPanos' ? 0.15 : 0.12) * (this.currentPano?.pointcloud.scale.x||1);//感觉点云模式比全景模式更明显,所以降低
|
|
|
let currentPos = this.position.clone()
|
|
|
let endPosition = new THREE.Vector3().addVectors(this.position, direction.clone().multiplyScalar(distance))
|
|
|
|
|
@@ -1626,71 +1642,39 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
var o = option2 ? "angle" : "direction";
|
|
|
|
|
|
var floor = viewer.modules.SiteModel.currentFloor;
|
|
|
- var entity = viewer.modules.SiteModel.inEntity;
|
|
|
-
|
|
|
- var getHeightDis = (pano)=>{
|
|
|
- if(floor && !floor.panos.includes(pano) && pano.position.z < this.position.z){ //若是上方的漫游点,就正常走。因为一般不会点击天花板。
|
|
|
- return this.position.z - pano.position.z
|
|
|
- }else{
|
|
|
- return 0
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- let disSquareMap = new Map()
|
|
|
- this.panos.forEach(pano=>{
|
|
|
- let dis2 = pano.position.distanceToSquared(this.position); //距离目标点
|
|
|
- disSquareMap.set(pano, dis2)
|
|
|
- })
|
|
|
-
|
|
|
+ var entity = viewer.modules.SiteModel.inEntity;
|
|
|
+ let scaleFactor = Math.pow( this.currentPano?.pointcloud.scale.x || 1 , 2)
|
|
|
let changeTexCount = 0, maxWaitDur = 300
|
|
|
//maxSamplerChangeTex = THREE.Math.clamp( maxWaitDur / Potree.timeCollect.depthSampler.median, 2, 10) //计算换贴图最大数目
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
|
|
|
var request = [//必要条件
|
|
|
Images360.filters.not(this.currentPano),
|
|
|
Images360.filters.isEnabled(),
|
|
|
//Images360.filters.inFloorDirection( this.position, direction, option1 ), //原先用inPanoDirection,但容易穿楼层,当mouse较低或较高 //因不束缚纵向所以可能往相反反向
|
|
|
(pano)=>{
|
|
|
- /* let isNeighbour = this.isNeighbour(this.currentPano, pano, true, true); //不计算的
|
|
|
- if(isNeighbour == void 0){
|
|
|
- let willChangeTex = pano.depthTex && !this.depthSampler.imgDatas.some(e=>e.pano == pano)
|
|
|
- if(changeTexCount < maxSamplerChangeTex || !willChangeTex ){
|
|
|
- isNeighbour = this.isNeighbour(this.currentPano, pano, false, true);//计算
|
|
|
- if(willChangeTex && isNeighbour != void 0) changeTexCount++
|
|
|
- }else{
|
|
|
- if(disSquareMap.get(pano) < 500)return true //因为费时,超过一定个数就不计算了,距离近的话先可通行。
|
|
|
- }
|
|
|
- } */
|
|
|
+
|
|
|
// 不会再changeTex了
|
|
|
let isNeighbour = this.isNeighbour(this.currentPano, pano, {onlyUseTex:true});
|
|
|
|
|
|
- if(isNeighbour || pano.noNeighbour && disSquareMap.get(pano) < 200){//在靠近孤立点时可以通行。但是不好把握这个距离,太远的话很多地方都会不小心到孤立点,太近的话可能永远到不了。
|
|
|
+ if(isNeighbour || pano.noNeighbour && Images360.scoreFunctions.distanceSquaredNew(this.currentPano)(pano) > -200 /* disSquareMap.get(pano) < 200 */){//在靠近孤立点时可以通行。但是不好把握这个距离,太远的话很多地方都会不小心到孤立点,太近的话可能永远到不了。
|
|
|
return true
|
|
|
}
|
|
|
},
|
|
|
- /* (pano)=>{ //防止不小心穿越地板到下一层, 尽量走楼梯,实在没有楼梯或楼梯漫游点稀疏的话就通过楼层按钮。
|
|
|
- let dis = getHeightDis(pano)
|
|
|
- //console.log('getHeightDis',pano.id,dis)
|
|
|
- if(dis < 3){//不能超过最大高度差( 最大高度差暂定为接近一层楼的高度。)(最好的解决方案是设置漫游可行)
|
|
|
- return true
|
|
|
- }else{
|
|
|
- return this.isNeighbour(this.currentPano, pano)
|
|
|
- }
|
|
|
- } */
|
|
|
+
|
|
|
]
|
|
|
-
|
|
|
- if(!byKey){
|
|
|
+ if(byKey){
|
|
|
+ request.push(Images360.filters.inPanoDirection( this.position, direction, option1))
|
|
|
+ }else{
|
|
|
request.push(Images360.filters.inPanoDirection( this.position, this.getDirection(), option1/* , true */)) //垂直方向上再稍微限制一下, 要接近视线方向,避免点击前方时因无路而到下一楼。但不能太高,否则楼梯上稍微朝下点击都到不了上方。之所以使用视线方向是因为镜头方向比鼠标方向目的性更强。
|
|
|
}
|
|
|
|
|
|
|
|
|
var list = [//决胜项目
|
|
|
- (pano)=>{
|
|
|
- return -disSquareMap.get(pano)
|
|
|
- },
|
|
|
-
|
|
|
+ /* (pano)=>{
|
|
|
+ return -disSquareMap.get(pano)
|
|
|
+ }, */
|
|
|
+ Images360.scoreFunctions.distanceSquaredNew(this.currentPano),
|
|
|
Images360.scoreFunctions[o]( this.position, direction, true),
|
|
|
|
|
|
(pano)=>{
|
|
@@ -2142,10 +2126,13 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
|
|
|
updateZoomPano() {
|
|
|
+
|
|
|
if (!this.panoRenderer.zoomPanoRenderingDisabled && Potree.settings.displayMode == 'showPanos') {
|
|
|
var currentPano = this.currentPano;
|
|
|
if (currentPano) {
|
|
|
|
|
|
+
|
|
|
+
|
|
|
let levelThreshold1 = Potree.settings.navTileClass == '1k' ? 1.3 : 1.7 , levelThreshold2 = 2
|
|
|
|
|
|
var t = this.zoomLevel > levelThreshold1,
|
|
@@ -2160,7 +2147,12 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
this.panoRenderer.renderPanoTiles(pano.id, null, !1, !1);
|
|
|
pano.setZoomed(ifZoom);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+ if(currentPano.pointcloud.tileRes == '2k'){//融合页面
|
|
|
+ return currentPano.zoomed && o(currentPano, !1);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
if (r && (!currentPano.zoomed || this.qualityManager.zoomLevelResolution && this.qualityManager.zoomLevelResolution != '4k')) {//needZoom
|
|
|
currentPano.zoomed || o(currentPano, !0);
|
|
@@ -2531,13 +2523,16 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
data.forEach((info)=>{
|
|
|
//if(Potree.fileServer){
|
|
|
- info.id = this.panos.length //把info的id的一长串数字改简单点
|
|
|
+ info.id = getID() //把info的id的一长串数字改简单点
|
|
|
info.pointcloud = pointcloud
|
|
|
//}
|
|
|
let pano = new Panorama( info, this );
|
|
|
|
|
|
pano.addEventListener('dispose',(e)=>{
|
|
|
if(this.closestPano == pano) this.closestPano = null
|
|
|
+ if(this.currentPano == pano && Potree.settings.displayMode == 'showPanos') {
|
|
|
+ Potree.settings.displayMode = 'showPointCloud'
|
|
|
+ }
|
|
|
})
|
|
|
|
|
|
this.panos.push(pano);
|
|
@@ -2553,19 +2548,11 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
}
|
|
|
|
|
|
|
|
|
- loadDone(){
|
|
|
- Potree.Utils.setObjectLayers(this.node, 'sceneObjects')
|
|
|
-
|
|
|
-
|
|
|
+ loadDone(){
|
|
|
|
|
|
this.tileDownloader.setPanoData(this.panos, [] );
|
|
|
|
|
|
- {
|
|
|
- let minSize = new THREE.Vector3(1,1,1)
|
|
|
- this.bound = math.getBoundByPoints(this.panos.map(e=>e.position), minSize)
|
|
|
- viewer.scene.pointclouds.forEach(pointcloud=>pointcloud.getPanosBound())
|
|
|
-
|
|
|
- }
|
|
|
+ this.updatePanoBound()
|
|
|
|
|
|
if(viewer.scene.pointclouds.some(e=>e.panos.length == 0)){
|
|
|
//console.warn('存在数据集没有pano');
|
|
@@ -2573,6 +2560,11 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ updatePanoBound(){
|
|
|
+ let minSize = new THREE.Vector3(1,1,1)
|
|
|
+ this.bound = math.getBoundByPoints(this.panos.map(e=>e.position), minSize)
|
|
|
+ Potree.settings.editType == 'pano' || viewer.scene.pointclouds.forEach(pointcloud=>pointcloud.getPanosBound())
|
|
|
+ }
|
|
|
|
|
|
|
|
|
getPano(value, typeName='id'){ //默认找的是id,也可以是sid、uuid
|
|
@@ -2587,28 +2579,38 @@ export class Images360 extends THREE.EventDispatcher{
|
|
|
|
|
|
//判断当前点是否加载了全景图
|
|
|
Images360.prototype.checkAndWaitForPanoLoad = function() {
|
|
|
- var isLoadedPanos = {},
|
|
|
- LoadedTimePanos = {},
|
|
|
- loadedCallback = {}, //add
|
|
|
- maxTime = 5e3;
|
|
|
- var withinTime = function() {
|
|
|
- for (var panoId in isLoadedPanos)
|
|
|
- if (isLoadedPanos.hasOwnProperty(panoId) && isLoadedPanos[panoId]) {
|
|
|
+ var loadingPanos = {},
|
|
|
+ LoadedTimePanos = {},
|
|
|
+ loadedCallback = {}, //add
|
|
|
+ maxTime = 5e3
|
|
|
+ /* var withinTime = function() {
|
|
|
+ for (var panoId in loadingPanos)
|
|
|
+ if (loadingPanos.hasOwnProperty(panoId) && loadingPanos[panoId]) {
|
|
|
var differTime = performance.now() - LoadedTimePanos[panoId];
|
|
|
if (differTime < maxTime)
|
|
|
return !0
|
|
|
}
|
|
|
return !1
|
|
|
- }
|
|
|
+ } */
|
|
|
+
|
|
|
+ // withinTime 改为只判断当前请求的点。原始代码的callback是针对任意pano的,所以遍历所有漫游点,只要有在加载的就返回,但已不满足需求(4dkk)。2024:9 发现bim分屏有问题,然后发现4dkk已经改过这,遂搬过来
|
|
|
|
|
|
+ var withinTime = function (pano) {
|
|
|
+ //5秒之内还在加载的话,直接返回仍在加载状态,否则重新判断
|
|
|
+ if (loadingPanos.hasOwnProperty(pano.id) && loadingPanos[pano.id]) {
|
|
|
+ //还在加载
|
|
|
+ var differTime = performance.now() - LoadedTimePanos[pano.id]
|
|
|
+ if (differTime < maxTime) return !0
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
return function(pano, basePanoSize, doneFun1, doneFun2, progressCallback, iswait, isclear, p ) {
|
|
|
loadedCallback[pano.id] = doneFun1//add 因为有可能之前请求的没加doneFun1, 如果加载好就执行最新的doneFun1
|
|
|
|
|
|
- if (withinTime()){//距离上次请求时间很近
|
|
|
- //console.log(11)
|
|
|
+ if (withinTime(pano)){//距离上次请求时间很近
|
|
|
+ //console.log('withinTime',window.name)
|
|
|
return !0; //这里感觉应该是!1
|
|
|
}
|
|
|
|
|
@@ -2616,7 +2618,7 @@ Images360.prototype.checkAndWaitForPanoLoad = function() {
|
|
|
let changeMode = (e)=>{
|
|
|
if(e.mode == 'showPointCloud'){
|
|
|
console.warn('切到点云模式了,就删除loadedCallback记录',pano.id)//否则再次转为showPanos会被withinTime阻拦
|
|
|
- delete isLoadedPanos[pano.id]
|
|
|
+ delete loadingPanos[pano.id]
|
|
|
viewer.cancelLoad(pano)
|
|
|
|
|
|
loadedCallback[pano.id] && loadedCallback[pano.id](); //可以飞行了
|
|
@@ -2626,14 +2628,11 @@ Images360.prototype.checkAndWaitForPanoLoad = function() {
|
|
|
}
|
|
|
this.addEventListener('requestMode', changeMode)
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
|
|
|
var callback1 = (param1, param2)=>{
|
|
|
- setTimeout(()=>{
|
|
|
- isLoadedPanos[pano.id] = !1;
|
|
|
+ setTimeout(()=>{
|
|
|
+ loadingPanos[pano.id] = !1;
|
|
|
loadedCallback[pano.id] && loadedCallback[pano.id](param1, param2);
|
|
|
this.removeEventListener('requestMode', changeMode)
|
|
|
},1)
|
|
@@ -2642,19 +2641,21 @@ Images360.prototype.checkAndWaitForPanoLoad = function() {
|
|
|
|
|
|
var callback2 = (param)=>{//没有看到有传doneFun2的
|
|
|
setTimeout(()=>{
|
|
|
- isLoadedPanos[pano.id] = !1;
|
|
|
+ loadingPanos[pano.id] = !1;
|
|
|
doneFun2 && doneFun2(param);
|
|
|
},1)
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
null !== iswait && void 0 !== iswait || (iswait = !0);
|
|
|
- isLoadedPanos[pano.id] = this.checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, p );
|
|
|
+ loadingPanos[pano.id] = this.checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, p );
|
|
|
//true代表没加载好
|
|
|
- isLoadedPanos[pano.id] && (LoadedTimePanos[pano.id] = performance.now());
|
|
|
- return isLoadedPanos[pano.id];
|
|
|
+ if (loadingPanos[pano.id]) {
|
|
|
+ LoadedTimePanos[pano.id] = performance.now()
|
|
|
+ }
|
|
|
+ return loadingPanos[pano.id];
|
|
|
} catch (msg) {
|
|
|
- isLoadedPanos[pano.id] = !1;
|
|
|
+ loadingPanos[pano.id] = !1;
|
|
|
LoadedTimePanos[pano.id] = performance.now() - maxTime;
|
|
|
throw msg;
|
|
|
}
|
|
@@ -2664,32 +2665,36 @@ Images360.prototype.checkAndWaitForPanoLoad = function() {
|
|
|
|
|
|
Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours。 200个点差不多在半分钟内算完
|
|
|
let lastIndex, inited//标记上次查询到哪,防止重新sortByScore
|
|
|
-
|
|
|
+ let startTime = 0, lastTime = 0
|
|
|
|
|
|
|
|
|
return function( interacted){
|
|
|
-
|
|
|
- if(!this.currentPano || viewer.mainViewport.view.isFlying() || viewer.lastFrameChanged || viewer.inputHandler.drag /* interacted */){ //拖拽时不更新,否则移动端卡
|
|
|
+
|
|
|
+ if(!this.currentPano || viewer.mainViewport.view.isFlying() || viewer.lastFrameChanged || viewer.inputHandler.drag //拖拽时不更新,否则移动端卡
|
|
|
+ || !viewer.scene.pointclouds.some(e=>e.hasDepthTex) //目前无深度图的话不判断可行,全部可通行
|
|
|
+ ){
|
|
|
return lastIndex = 0;
|
|
|
}
|
|
|
|
|
|
let nearPanos = this.tileDownloader.tilePrioritizer.nearPanos;
|
|
|
if(!nearPanos)return;
|
|
|
- //let startTime = Date.now()
|
|
|
+ if(Date.now() - lastTime < 50)return//不要每帧都算
|
|
|
+
|
|
|
|
|
|
+ startTime = lastTime = Date.now()
|
|
|
let panos = [this.currentPano, ...nearPanos ]
|
|
|
this.depthSampler.updateNearPanos(panos)
|
|
|
|
|
|
- let maxWaitDur = browser.isMobile() ? 40 : 60
|
|
|
- let changeCount = 0, maxChangeTex = browser.isMobile() ? 1 : 3, getCount = 0
|
|
|
+ let maxWaitDur = browser.isMobile() ? 2 : 4
|
|
|
+ let changeCount = 0, getCount = 0, maxChangeTex = 1
|
|
|
let changeTexCount = ()=>{
|
|
|
changeCount ++;
|
|
|
}
|
|
|
let median = Potree.timeCollect.depthSamChangeImg.median
|
|
|
-
|
|
|
+ let loopOutCount = 0
|
|
|
|
|
|
let ifOverTime = ()=>{
|
|
|
- let is = changeCount >= maxChangeTex || changeCount * median + getCount * 0.01 > maxWaitDur//不换贴图也要一丢丢计算时间
|
|
|
+ let is = changeCount >= maxChangeTex || changeCount * median + getCount * 0.01 + 0.0004 * panos.length * loopOutCount > maxWaitDur//不换贴图也要一丢丢计算时间
|
|
|
/* if(is){
|
|
|
console.log('OverTime, changeCount', changeCount)
|
|
|
} */
|
|
@@ -2697,15 +2702,24 @@ Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours
|
|
|
}
|
|
|
this.depthSampler.addEventListener('changeImg', changeTexCount)
|
|
|
|
|
|
- outer: for(let i=lastIndex,j=panos.length; i<j; i++){
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const maxChangePanoCount = Math.min(panos.length,this.depthSampler.maxDataCount) //在lastIndex清空前最多可以有的mainPano的数量。 限制数量,否则一直changeTex很卡
|
|
|
+
|
|
|
+ outer: for(let i=lastIndex,j=panos.length; i<maxChangePanoCount/* j */; i++){
|
|
|
let pano = panos[i];
|
|
|
let others = panos.slice(i+1, j)
|
|
|
lastIndex = i
|
|
|
if(!pano.pointcloud.hasDepthTex && i>0)break; //点云的情况下最好不改相机位置,因为其他位置点云还没加载完,所以不判断当前点以外的漫游点
|
|
|
- var g = Common.sortByScore(others, [ ], [
|
|
|
- Images360.scoreFunctions.distanceSquared(pano.position)
|
|
|
- ]);
|
|
|
|
|
|
+ viewer.addTimeMark('sortByScore','start')
|
|
|
+ var g = Common.sortByScore(others, [ ], [
|
|
|
+ Images360.scoreFunctions.distanceSquaredNew(pano) //900个点时至少耗时0.3
|
|
|
+ ]);
|
|
|
+ loopOutCount ++
|
|
|
+ viewer.addTimeMark('sortByScore','end')
|
|
|
+
|
|
|
for(let a=0, b=g.length; a<b; a++){
|
|
|
let item = g[a]
|
|
|
if(item.item == pano)continue
|
|
@@ -2714,7 +2728,12 @@ Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours
|
|
|
//console.log('check isNeighbour', pano.id, item.item.id)
|
|
|
|
|
|
let byCloud = !pano.pointcloud.hasDepthTex
|
|
|
- let result = this.isNeighbour(pano, item.item, {onlyUseTex: !byCloud, computeDirFirst:true, computeTwoDir:true})//计算
|
|
|
+ //const computeTwoDir = <maxChangePanoCount
|
|
|
+
|
|
|
+ const computeTwoDir = this.depthSampler.nearPanos.includes(item.item) || this.depthSampler.imgDatas.some(e=>e.pano == item.item)
|
|
|
+ //一定数量内允许双向计算,也就是允许changeTex. 这样一来,每到一个新的pano最多只有开头一秒卡一点,不然一直changeTex很卡
|
|
|
+
|
|
|
+ let result = this.isNeighbour(pano, item.item, {onlyUseTex: !byCloud, computeDirFirst:true, computeTwoDir})//计算
|
|
|
|
|
|
if(result != void 0){//计算了 (byTex时其实并不一定)
|
|
|
//console.log('提前计算neighbor', pano.id, item.item.id)
|
|
@@ -2734,6 +2753,11 @@ Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours
|
|
|
}
|
|
|
|
|
|
lastIndex = i+1 //这轮结束
|
|
|
+
|
|
|
+
|
|
|
+ if(ifOverTime()){
|
|
|
+ break outer
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* if(changeCount){
|
|
@@ -2746,13 +2770,18 @@ Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours
|
|
|
if(!inited){
|
|
|
inited = true
|
|
|
this.addEventListener('loadedDepthImg',(e)=>{
|
|
|
- //console.log('loadedDepthImg',e.pano)
|
|
|
- lastIndex = 0 //主要针对刚打开场景第一个点有杂点时单向不成功,要立即进一步双向计算ifShelter
|
|
|
+ //console.log('loadedDepthImg',e.pano)
|
|
|
+ const computeTwoDir = this.depthSampler.nearPanos.includes(e.pano) || this.depthSampler.imgDatas.some(a=>e.pano == a.pano)
|
|
|
+ if(computeTwoDir){
|
|
|
+ lastIndex = 0 //主要针对刚打开场景第一个点有杂点时单向不成功,要立即进一步双向计算ifShelter
|
|
|
+ }
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- /* let costTime = Date.now() - startTime
|
|
|
- costTime > maxWaitDur && console.log( 'costTime:',costTime) */
|
|
|
+ let costTime = Date.now() - startTime //控制好时间,否则转动时卡(主要是开始拖拽时延迟). 尽量在转完一圈使附近disMap都算完后costTime和maxWaitDur接近
|
|
|
+ //costTime > maxWaitDur && changeCount == 0 && console.log( 'costTime:',costTime)
|
|
|
+ //console.log('getCount',getCount)
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}()
|
|
@@ -2761,10 +2790,11 @@ Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours
|
|
|
Images360.filters = {
|
|
|
inPanoDirection : function(pos, dir, i, log) { //pano在mouse的方向上
|
|
|
return function(pano) {
|
|
|
+ var o = pano.position.clone().sub(pos).normalize()
|
|
|
+ if(o.dot(dir) > i)return true
|
|
|
var r = pano.floorPosition.clone().sub(pos).normalize()
|
|
|
- var o = pano.position.clone().sub(pos).normalize()
|
|
|
- log && console.log('dire',pano.id, r.dot(dir), o.dot(dir) )
|
|
|
- return r.dot(dir) > i || o.dot(dir) > i
|
|
|
+ if(r.dot(dir) > i)return true
|
|
|
+
|
|
|
}
|
|
|
},
|
|
|
inFloorDirection: function(pos, dir, min, log) { //pano在mouse的水平方向上
|
|
@@ -2816,7 +2846,7 @@ Images360.filters = {
|
|
|
Images360.scoreFunctions = {
|
|
|
direction: function(curPos, dir, ifLog) {
|
|
|
return function(pano) {
|
|
|
- var pos1 = /* pano.floorPosition */ pano.position //旧:改为权重放在marker上,这样对有斜坡的更准确,如上楼, 但这样近距离的pano角度就会向下了,以致于走不到
|
|
|
+ var pos1 = /* pano.floorPosition */ pano.position //旧:改为权重放在marker上,这样对有斜坡的更准确,如上楼, 但这样近距离的pano角度就会向下了,以致于走不到
|
|
|
var n = pos1.clone().sub(curPos).normalize();
|
|
|
//ifLog && console.log('direction', pano.id, n.dot(dir) * directionFactor )
|
|
|
return n.dot(dir) * directionFactor
|
|
@@ -2834,12 +2864,28 @@ Images360.scoreFunctions = {
|
|
|
},
|
|
|
distanceSquared: function(pos1, r=1 ) {
|
|
|
if(pos1.position)pos1 = pos1.position
|
|
|
- return function(pano) {//许钟文 改
|
|
|
+ return function(pano) {//许钟文 改
|
|
|
var pos2 = pano.position.clone()
|
|
|
return pos1.distanceToSquared(pos2) * -1 * r;
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
+ distanceSquaredNew: function(mainPano, r=1 ) {
|
|
|
+ let disMap = viewer.images360.disMap
|
|
|
+
|
|
|
+ return function(pano) {//许钟文 改
|
|
|
+ if(!disMap[mainPano.id]) disMap[mainPano.id] = {}
|
|
|
+ if(!disMap[pano.id]) disMap[pano.id] = {}
|
|
|
+ let dis
|
|
|
+ if(disMap[mainPano.id][pano.id] != void 0) dis = disMap[mainPano.id][pano.id]
|
|
|
+ else if(disMap[pano.id][mainPano.id]) dis = disMap[pano.id][mainPano.id]
|
|
|
+ else{
|
|
|
+ dis = Images360.scoreFunctions.distanceSquared(mainPano,1)(pano)
|
|
|
+ disMap[mainPano.id][pano.id] = dis
|
|
|
+ }
|
|
|
+ return dis * r
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
angle: function(e, t) {
|
|
|
return function(i) {
|
|
|
var n = i.position.clone().sub(e).normalize();
|
|
@@ -3103,7 +3149,7 @@ Images360.prototype.updateCube = (function(){//增加细分的版本,且垂直
|
|
|
//let r = maxR - ( maxR - minR) * THREE.Math.clamp((dis2d - minDis) / (maxDis - minDis),0,1) //dis2d越大,角度要越小 //THREE.Math.smoothstep(currentDis, op.nearBound, op.farBound);
|
|
|
let r = math.linearClamp(dis2d, [minDis,maxDis], [maxR, minR])
|
|
|
//console.log('dis2d',dis2d,'r',r)
|
|
|
-
|
|
|
+
|
|
|
|
|
|
let angles = ((browser.isMobile()/* || dis2d<4 */)? [60] : [50,70] /* [35,65] */).map(deg=>{ //正的在左边 尽量能够平分中间这段墙体。 (角度为从中心向外)
|
|
|
let angle = THREE.Math.clamp(deg * r, 5, 80);
|