import * as THREE from "../../../libs/three.js/build/three.module.js";
import { EventDispatcher } from "../../EventDispatcher.js";
import {TextSprite} from "../../TextSprite.js";
import ModelTextureMaterial from "./ModelTextureMaterial.js";
import Common from "../../utils/Common.js";
import math from "../../utils/math.js";
import cameraLight from "../../utils/cameraLight.js";
import Panorama from "./Panorama.js";
import QualityManager from './tile/QualityManager'
import TileDownloader from './tile/TileDownloader'
import PanoRenderer from './tile/PanoRenderer'
import TilePrioritizer from './tile/TilePrioritizer'
import { PanoSizeClass,Vectors} from '../../defines'
//import Axis from '../../viewer/Axis'
let raycaster = new THREE.Raycaster();
//let currentlyHovered = null;
var texLoader = new THREE.TextureLoader()
let cm = new ModelTextureMaterial()
let previousView = {
controls: null,
position: null,
target: null,
};
let sm = new THREE.MeshBasicMaterial({side: THREE.BackSide});
var tileArr = []
/* let sgHigh = new THREE.SphereGeometry(1, 128, 128);
*/
export class Images360 extends EventDispatcher{
constructor(viewer, params){
super();
this.viewer = viewer;
this.selectingEnabled = true;
this.panos = [];
this.node = new THREE.Object3D();
this.node.name = 'ImagesNode'
//this.node2 = new THREE.Object3D();
//add:
let size = params.boundSize
this.cube = new THREE.Mesh(new THREE.BoxBufferGeometry( size.x, size.y, size.z ), cm);
this.cube.position.copy(params.center)
this.cube.visible = false;
this.cube.layers.set(Potree.config.renderLayers.skybox)
this.cube.name = 'skybox'
viewer.scene.scene.add(this.cube)
this._visible = true;
this.currentPano = null;
this.mouseLastMoveTime = Date.now()
this.tileDownloader = new TileDownloader;
this.qualityManager = new QualityManager
this.panoRenderer = new PanoRenderer(viewer, this.tileDownloader, this.qualityManager)
this.basePanoSize = this.qualityManager.getPanoSize(PanoSizeClass.BASE);
this.standardPanoSize = this.qualityManager.getPanoSize(PanoSizeClass.STANDARD);
this.highPanoSize = this.qualityManager.getPanoSize(PanoSizeClass.HIGH);
this.ultraHighPanoSize = this.qualityManager.getPanoSize(PanoSizeClass.ULTRAHIGH);
this.tileDownloader.processPriorityQueue = !1;
this.tileDownloader.tilePrioritizer = new TilePrioritizer(this.qualityManager, this.basePanoSize, this.standardPanoSize, this.highPanoSize, this.ultraHighPanoSize);
viewer.addEventListener('global_click'/* "global_drop" */, (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
if(Potree.settings.unableNavigate || this.flying || e.button != THREE.MOUSE.LEFT )return //
/* if(currentlyHovered && currentlyHovered.pano){
this.focusPano(currentlyHovered.pano);
}else{//add */
if(!Potree.settings.dblToFocusPoint || this.currentPano){//双击不会focus点云 或者 已经focusPano了
this.flyToPanoClosestToMouse()
}
//}
})
viewer.addEventListener("global_mousemove", (e) => {
if(!Potree.settings.unableNavigate && Potree.settings.ifShowMarker && e.hoverViewport == viewer.mainViewport){//如果不显示marker,就在点击时再更新
this.updateClosestPano(e.intersectPoint)
}
});
if(!Potree.settings.isOfficial){
this.domRoot = viewer.renderer.domElement.parentElement;
let elUnfocus = $("");
elUnfocus.css({
position : "absolute",
right : '25%',
bottom: '20px',
zIndex: "10000",
fontSize:'1em', color:"black",
display:'none',
background:'rgba(255,255,255,0.8)',
})
elUnfocus.on("click", () => this.unfocus());
this.elUnfocus = elUnfocus;
this.domRoot.appendChild(elUnfocus[0]);
let elHide = $("")
elHide.css({
position : "absolute",
right : '40%',
bottom: '20px',
zIndex: "10000",
fontSize:'1em' ,color:"black",
width : '100px',
background:'rgba(255,255,255,0.8)',
})
this.domRoot.appendChild(elHide[0]);
elHide.on("click", (e) => {
let visi = viewer.getObjVisiByReason(viewer.scene.pointclouds[0], 'force')
viewer.scene.pointclouds.forEach(e=>{
viewer.updateVisible(e, 'force', !visi)
})
elHide.val(!visi ? "隐藏点云" : "显示点云")
});
let elDisplayModel = $("")
elDisplayModel.css({
position : "absolute",
right : '65%',
bottom: '20px',
zIndex: "10000",
fontSize:'1em',color:"black",
width : '100px',
background:'rgba(255,255,255,0.8)',
})
this.domRoot.appendChild(elDisplayModel[0]);
elDisplayModel.on("click", (e) => {
Potree.settings.displayMode = Potree.settings.displayMode == 'showPointCloud' ? 'showPanos' : 'showPointCloud'
});
this.elDisplayModel = elDisplayModel
}
{//切换模式
let displayMode = '';
Object.defineProperty(Potree.settings , "displayMode",{
get: function() {
return displayMode
},
set: (mode)=> {
if(mode != displayMode){
let config = Potree.config.displayMode[mode]
let config2
if(this.isAtPano() ){//this.currentPano
if(this.flying)config2 = config.transition
else config2 = config.atPano
}else{
config2 = config.atPano
if(mode == 'showPanos'){//自动飞入一个pano
//要改成飞进最近的。。。
this.flyToPano({
pano: /* this.currentPano || */Common.sortByScore(this.panos,null,[e=>-e.position.distanceTo(this.position)])[0].item,
callback: ()=>{
Potree.settings.displayMode = mode
}
})
return;
}else{
}
}
if(config2.showSkybox || config2.showPoint && config2.pointUsePanoTex){
this.tileDownloader.start()
}else{
this.tileDownloader.stop()
}
if(config2.showSkybox || config2.pointUsePanoTex){
if(this.checkAndWaitForPanoLoad(this.currentPano, "low", "low", this.basePanoSize, ()=> {
setTimeout( ()=>{
Potree.settings.displayMode = mode
},1)
})
){
return
}
}
viewer.scene.pointclouds.forEach(e=>{
viewer.updateVisible(e, 'displayMode', config2.showPoint)
})
this.cube.visible = config2.showSkybox
if(config2.pointUsePanoTex){
viewer.scene.pointclouds.forEach(e=>{
e.material.setProjectedPanos(this.currentPano,this.currentPano, 1)
})
}else{
viewer.scene.pointclouds.forEach(e=>{
e.material.stopProjectedPanos()
})
}
this.cube.visible = config.atPano.showSkybox
this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
/* viewer.dispatchEvent({
type: "enableChangePos",
canLeavePano : config.canLeavePano ,
viewport:
}) */
viewer.mainViewport.unableChangePos = !config.canLeavePano
displayMode = mode
if(this.elDisplayModel){
this.elDisplayModel.value = mode == 'showPointCloud' ? ">>全景" : '>>点云'
}
}
}
})
Potree.settings.displayMode = 'showPointCloud'
}// 切换模式 end
{//
let currentPano = null;
Object.defineProperty(this , "currentPano",{
get: function() {
return currentPano
},
set: function(e) {
if(e != currentPano){
currentPano && currentPano.exit()
e && e.enter()
currentPano = e
}
}
})
}
{//是否显示marker
let ifShowMarker = true;
Object.defineProperty(Potree.settings, "ifShowMarker",{
get: function() {
return ifShowMarker
},
set: (show)=>{
show = !!show
if(show != ifShowMarker){
this.panos.forEach(pano=>{
viewer.updateVisible(pano, 'ifShowMarker', show)
})
//this.emit('markersDisplayChange', show)
ifShowMarker = show
}
}
})
}
viewer.addEventListener("update", () => {
this.update(viewer);
});
//viewer.inputHandler.addInputListener(this);
var keys = {
FORWARD: ['W'.charCodeAt(0), 38],
BACKWARD: ['S'.charCodeAt(0), 40],
LEFT: ['A'.charCodeAt(0), 37],
RIGHT: ['D'.charCodeAt(0), 39],
}
viewer.inputHandler.addEventListener('keydown',(e)=>{
if(Potree.settings.displayMode == 'showPanos'){
for(let i in keys){
if(keys[i].some(a => a == e.keyCode)){
switch(i){
case 'FORWARD':
this.flyLocalDirection(Vectors.FORWARD.clone());
break;
case 'BACKWARD':
this.flyLocalDirection(Vectors.BACK.clone());
break;
case 'LEFT':
this.flyLocalDirection(Vectors.LEFT.clone());
break;
case 'RIGHT':
this.flyLocalDirection(Vectors.RIGHT.clone());
break;
}
break;
}
}
}
})
};
flyLocalDirection(dir) {
var direction = this.getDirection(dir),
option1 = 1 === dir.y ? .4 : .75,
option2 = 1 === Math.abs(dir.x);
return this.flyDirection(direction, option1, option2)
}
getDirection(e) {
if(!e){
return viewer.scene.view.direction
}else{
return e = e ? e : (new THREE.Vector3).copy(Vectors.FORWARD),
e.applyQuaternion(viewer.scene.getActiveCamera().quaternion)
}
}
get position(){
return this.viewer.scene.view.position.clone()
}
get visible(){
return this._visible;
}
set visible(visible){
if(this._visible === visible){
return;
}
for(const image of this.panos){
image.mesh.visible = visible && (this.currentPano == null);
}
//this.sphere.visible = visible && (this.currentPano != null);
this._visible = visible;
this.dispatchEvent({
type: "visibility_changed",
panos: this,
});
}
isAtPano(){//
return this.currentPano && viewer.scene.view.position.equals(this.currentPano.position)
}
flyToPano(toPano) {
if(toPano instanceof Panorama){
toPano = {pano: toPano}
}
if(!this.currentPano){
return this.focusPano(toPano)
}
let done = (makeIt)=>{
toPano.deferred && toPano.deferred.resolve(makeIt)
makeIt && toPano.callback && toPano.callback()
}
if(this.currentPano == pano && this.isAtPano() && !toPano.target ){
return done(true);
}
if(this.flying){
return done(false)
}
let target = toPano.target
let easeName = toPano.easeName || 'easeInOutQuad'
let config = Potree.config.displayMode[Potree.settings.displayMode]
var pointcloudVisi = config.atPano.showPoint //viewer.scene.pointclouds[0].visible
var pano = toPano.pano
var duration = toPano.duration || 300+Math.min(Potree.config.transitionsTime.flySpeed * this.position.distanceTo(pano.position), Potree.config.transitionsTime.panoToPano )
//console.log("flyto "+pano.id + ' duration: ' + duration )
this.nextPano = pano
//不飞的话是否不要执行这段?
if(config.atPano.showSkybox || config.atPano.pointUsePanoTex){
if(this.checkAndWaitForPanoLoad(pano, "high", "low", this.basePanoSize, ()=> {
setTimeout( ()=>{
this.flyToPano(toPano)
},1)
})
){
return
}
}
//this.load(pano).then( () => {
this.cube.visible = config.atPano.showSkybox
this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, pano, 0)
viewer.scene.pointclouds.forEach(e=>{
viewer.updateVisible(e, 'displayMode',config.transition.showPoint)
})
if(config.transition.pointUsePanoTex){
let easeInOutRatio = pointcloudVisi ? 0.3 : 0
viewer.scene.pointclouds.forEach(e=>{
e.material.setProjectedPanos(this.currentPano, pano, 0, easeInOutRatio)
})
}
const endPosition = pano.position.clone()
this.flying = true
viewer.scene.view.setView(endPosition, target ,duration, ()=>{//done
if(!config.atPano.pointUsePanoTex){
viewer.scene.pointclouds.forEach(e=>{
e.material.stopProjectedPanos()
})
}
//this.currentPano.exit()
//pano.enter()
this.currentPano = pano;
this.flying = false
this.nextPano = null;
viewer.scene.pointclouds.forEach(e=>{
viewer.updateVisible(e, 'displayMode',pointcloudVisi)
})
done(true);
},(progress)=>{//onUpdate
this.cube.material.uniforms.progress.value = progress
viewer.scene.pointclouds.forEach(e=>{
e.material.uniforms.progress.value = progress
})
}, easeName )
{
toPano.duration = duration
toPano.easeName = easeName
this.emit('flyToPano', toPano)
}
//})
}
focusPano(toPano ){
if(this.currentPano !== null){
return this.flyToPano(toPano);
}
if(toPano instanceof Panorama){
toPano = {pano: toPano}
}
let done = (makeIt)=>{
toPano.deferred && toPano.deferred.resolve(makeIt)
makeIt && toPano.callback && toPano.callback()
}
var pano = toPano.pano
let config = Potree.config.displayMode[Potree.settings.displayMode]
previousView = {
//controls: this.viewer.controls,
position: this.position,
target: viewer.scene.view.getPivot(),
};
//this.viewer.setControls(this.viewer.orbitControls);
this.viewer.orbitControls.doubleClockZoomEnabled = false;
for(let image of this.panos){
image.mesh.visible = false;
}
this.selectingEnabled = false;
//console.log("flyto "+pano.file.split('/').pop() )
var dur = toPano.duration == void 0 ? 700 : toPano.duration
if(config.atPano.showSkybox){
if ( this.checkAndWaitForPanoLoad(pano, "low", "low", this.basePanoSize, ()=> {
setTimeout( ()=>{
this.focusPano(toPano)
},1)
})
) {
return ;
}
}
//this.load(pano).then( () => {
//this.panos.forEach(e=>e.marker.material.depthTest = false)
this.cube.visible = config.atPano.showSkybox
this.cube.visible && this.cube.material.setProjectedPanos(pano, pano, 0)
if(config.atPano.pointUsePanoTex){//false
viewer.scene.pointclouds.forEach(e=>{
e.material.setProjectedPanos(pano, pano, 0)
})
}
//});
let newCamPos = pano.position.clone()
let target = newCamPos.clone().add(viewer.scene.view.direction)
this.flying = true
viewer.scene.view.setView( newCamPos, target, dur , ()=>{//done
//pano.enter()
this.flying = false
/* viewer.scene.pointclouds.forEach(e=>{
e.visible = pointcloudVisi
}) */
this.currentPano = pano;
done(true)
},(progress)=>{//onUpdate
/* this.cube.material.uniforms.progress.value = progress
viewer.scene.pointclouds.forEach(e=>{
e.material.uniforms.progress.value = progress
}) */
} )
this.elUnfocus && (this.elUnfocus[0].style.display = "");
}
unfocus(o={}){
this.selectingEnabled = true;
Potree.settings.displayMode = 'showPointCloud'
if(!this.currentPano && !o.position){
return;
}
this.cube.visible = false
viewer.orbitControls.doubleClockZoomEnabled = true;
viewer.scene.view.setView(
o.position || previousView.position,
o.target || previousView.target,
o.duration || 500,
()=>{ //done
for(let pano of this.panos){
pano.mesh.visible = true;
//pano.marker.material.depthTest = true
}
o.callback && o.callback()
}
);
//this.currentPano.exit()
this.currentPano = null;
this.elUnfocus && (this.elUnfocus[0].style.display = "none");
}
/* bump(direction) {//撞墙弹回效果
if (!this.flying) {
var t, i, n, r = settings.transition,
o = (r.flytimeMaxDistanceThreshold * r.flytimeDistanceMultiplier + r.flyTime) / 10,
a = this.camera.getWorldDirection().dot(direction),
s = Math.abs(a) > .5;
if (s)
t = function() {
transitions.start(lerp.property(this.cameraControls.cameras[ViewMode.PANORAMA], "zoom", a > 0 ? 1.04 : .96), o, i, 0, easing.easeInOutSine, "bumpZStart")
}
.bind(this),
i = function() {
transitions.start(lerp.property(this.cameraControls.cameras[ViewMode.PANORAMA], "zoom", 1), 3 * o, n, 0, easing.easeInOutSine, "bumpZRelax")
}
.bind(this);
else {
var l = this.camera.position.clone(),
c = direction.clone();
this.raycaster.set(l, c);
var h = this.model.floors.reduce(function(e, t) {
return e.concat(t.collider.children)
}, []),
d = this.raycaster.intersectObjects(h),
p = d.length > 0 ? d[0].distance / 25 : .04,
g = l.clone().add(c.multiplyScalar(p));
t = function() {
transitions.start(lerp.vector(this.cameraControls.cameras[ViewMode.PANORAMA].position, g), o, i, 0, easing.easeInOutSine, "bumpTStart")
}
.bind(this),
i = function() {
transitions.start(lerp.vector(this.cameraControls.cameras[ViewMode.PANORAMA].position, l), 5 * o, n, 0, easing.easeInOutSine, "bumpTRelax")
}
.bind(this)
}
n = (){
this.mode == "panorama" && (this.flying = !1) //改
}
this.flying = !0,
t()
}
};
*/
/* load(pano, ){
return new Promise(resolve => {
let texture = texLoader.load(pano.file, resolve);
texture.wrapS = THREE.RepeatWrapping;
texture.repeat.x = -1;
texture.flipY = false//add
pano.texture = texture;
//add
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.generateMipmaps = true;
});
} */
flyToPanoClosestToMouse() {
/* if (Date.now() - this.mouseLastMoveTime > 50) {
//this.intersect = this.getMouseIntersect();
this.intersect && this.updateClosestPano(this.intersect);
} */
if(!Potree.settings.ifShowMarker){//不显示marker的时候mousemove没更新鼠标最近点所以更新
this.updateClosestPano(viewer.inputHandler.intersectPoint)
}
if (this.closestPano) {
return this.flyToPano({
pano: this.closestPano
});
}
var direction = this.viewer.inputHandler.getMouseDirection().direction;
this.flyDirection(direction)
}
flyDirection(direction, option1, option2) {
var deferred = $.Deferred();
//this.history.invalidate();
var panoSet = this.closestPanoInDirection(direction, option1, option2);
if (panoSet) {
this.flyToPano({
pano: panoSet,
callback: deferred.resolve.bind(deferred, !0)
} );
} else {
//this.bump(direction);
deferred.resolve(!1);
}
return deferred.promise();
}
closestPanoInDirection(direction, option1, option2) {
return this.rankedPanoInDirection(0, direction, option1, option2)
}
rankedPanoInDirection(t, direction, option1, option2){
var panoSet = {
pano: null,
candidates: [] //缓存顺序--如果需要打印的话
};
t || (t = 0);
option1 = void 0 !== option1 ? option1 : .75;
var o = option2 ? "angle" : "direction";
var request = [//必要条件
Images360.filters.inPanoDirection( this.position, direction, option1),
//Images360.filters.isNeighbourPanoTo(this.currentPano),
Images360.filters.not(this.currentPano)
]
var list = [//决胜项目
Images360.scoreFunctions.distanceSquared(this.currentPano),
Images360.scoreFunctions[o]( this.position, direction)
];
this.findRankedByScore(t,request,list,panoSet);
return panoSet.pano;
}
updateClosestPano(intersect) {//距离reticule最近的点 可以是null
intersect = intersect && intersect.location
if(!intersect)return
//intersect = intersect && (intersect.location || intersect)
var filterFuncs = [];
//if (this.mode === ViewMode.PANORAMA) {
/* if (!Potree.settings.isOfficial && !this.currentPano) {
return;
} */
if(this.isAtPano() ){
filterFuncs.push(Images360.filters.not(this.currentPano));
filterFuncs.push(Images360.filters.inFloorDirection(this.position, viewer.scene.view.direction, .25)),//许钟文改
//filterFuncs.push(Images360.filters.isNeighbourPanoTo(this.currentPano));
filterFuncs.push(Images360.filters.isCloseEnoughTo(intersect, 0.35));
/* } else {
if(!this.linkEditor.noPanoHasNeighbor){//xzw add 如果不是全孤立点的话,就要避开孤立点
filterFuncs.push((pano)=>{return this.linkEditor.checkHasNeighbor(pano)})
}
objects.record.control.isRecording || filterFuncs.push(Panorama.filters.isOnVisibleFloor());
this.mode !== ViewMode.FLOORPLAN && filterFuncs.push(Panorama.filters.inDirection(this.position, this.getDirection(), .25));
} */
}
var pano = Common.find(this.panos, filterFuncs, [Images360.sortFunctions.floorDistanceToPoint(intersect)]);
if (pano != this.closestPano) {
pano && (this.isPanoHover = !0);
//触发事件,导致地面的marker变清晰
//this.emit(PlayerEvents.ClosestPanoChanging, this.closestPano, pano, this.mode);
this.closestPanoChanging(this.closestPano, pano)
this.closestPano = pano;
} else {
this.isPanoHover = !1;
}
}
closestPanoChanging(oldPano, newPano){
if(!Potree.settings.ifShowMarker)return
oldPano && oldPano.hoverOff()
newPano && newPano.hoverOn()
}
/* handleHovering(){
let pointer = viewer.inputHandler.pointer;
let camera = viewer.scene.getActiveCamera();
let domElement = viewer.renderer.domElement;
let ray = Potree.Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
// let tStart = performance.now();
raycaster.ray.copy(ray);
let intersections = raycaster.intersectObjects(this.node.children);
if(intersections.length === 0){
// label.visible = false;
return;
}
let intersection = intersections[0];
currentlyHovered = intersection.object;
currentlyHovered.material = smHovered;
//label.visible = true;
//label.setText(currentlyHovered.pano.file);
//currentlyHovered.getWorldPosition(label.position);
}
*/
update(){
let {viewer} = this;
/* if(currentlyHovered){
currentlyHovered.material = sm;
currentlyHovered = null;
}
if(this.selectingEnabled){
this.handleHovering();
} */
if(this.tileDownloader.started){
var vectorForward = viewer.scene.view.direction.clone()
vectorForward = math.convertVector.ZupToYup(vectorForward)
this.updateTileDownloader(tileArr,vectorForward);
this.updatePanoRenderer(vectorForward)
}
}
findRankedByScore(e, t, i, n) {
n && (n.candidates = null, //candidates 缓存顺序--如果需要打印的话
n.pano = null),
e || (e = 0);
var r = Common.sortByScore(this.panos, t, i);
return !r || 0 === r.length || e >= r.length ? null : (n && (n.candidates = r,
n.pano = r[e].item),
r[e].item)
}
updateTileDownloader(t, vectorForward) {
var i = this.nextPano || this.currentPano;
if(i){
this.tileDownloader.tilePrioritizer.updateCriteria(i, viewer.scene.view.position.clone() , vectorForward, t.length > 0 ? t : null),
this.tileDownloader.processPriorityQueue = !0
}
}
updatePanoRenderer(vectorForward) {
var i = this.nextPano || this.currentPano;
if(i){
if (this.panoRenderer.hasQueuedTiles() && i) {
this.panoRenderer.updateDirection(vectorForward);
}
}
}
checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, l) {
if (!pano) {
console.error("Player.checkAndWaitForTiledPanoLoad() -> Cannot load texture for null pano.");
}
var vectorForward = viewer.scene.view.direction.clone()
vectorForward = math.convertVector.ZupToYup(vectorForward)
if (!pano.isLoaded(basePanoSize)) {
iswait && viewer.waitForLoad(pano, function() {//发送loading
return pano.isLoaded(basePanoSize)
});
var fov = {//test for direction 预加载的边缘有一丢丢不准确,尤其在相机倾斜时(4dkk也是)。
hFov: cameraLight.getHFOVForCamera(viewer.scene.getActiveCamera(), viewer.renderArea.clientWidth, viewer.renderArea.clientHeight),
vFov: viewer.scene.getActiveCamera().fov
}//原先是null,不要求方向
pano.loadTiledPano(/* 1024 */ basePanoSize , vectorForward, fov, isclear, l, null).done(function(e, t) {
callback1 && callback1(e, t)
}
.bind(this)).fail(function(msg) {
callback2 && callback2(msg)
}
.bind(this)).progress(function(e, t, i) {
progressCallback && progressCallback(e, t, i)
}
.bind(this));
return !0;
}
}
fitPanoTowardPoint(o){ //寻找最适合的点位
var point = o.point,
require = o.require || [],
rank = o.rank || [],
force = o.force,
getAll = o.getAll,
bestDistance = o.bestDistance || 0
let camera = viewer.scene.getActiveCamera()
//if(o.floor)require.push(Panorama.filters.atFloor(o.floor))
if(o.boundSphere){//只接受boundSphere
let aspect = 1//size.x / size.y
let dis
if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
dis = /* size.y */o.boundSphere.radius/* / 2 *// THREE.Math.degToRad(camera.fov / 2)
}else{
let hfov = cameraLight.getHFOVForCamera(camera, camera.aspect, 1 );
dis = /* size.x */ o.boundSphere.radius /* / 2 */ / THREE.Math.degToRad(hfov / 2)
}
bestDistance = dis*0.8
}
let bestDisSquared = bestDistance * bestDistance
rank.push((pano)=>{
return -Math.abs(pano.position.distanceToSquared(point) - bestDisSquared)
})
/* var temp = {position:point}
rank.push(Panorama.scoreFunctions.distanceSquared(temp, -2)); */
var g = Common.sortByScore(this.panos, require, rank);
if(getAll)return g;
return g && g.length > 0 && g[0].item
}
};
//判断当前点是否加载了全景图
Images360.prototype.checkAndWaitForPanoLoad = function() {
var isLoadedPanos = {},
LoadedTimePanos = {},
maxTime = 5e3;
var overtime = function() {
for (var panoId in isLoadedPanos)
if (isLoadedPanos.hasOwnProperty(panoId) && isLoadedPanos[panoId]) {
var differTime = performance.now() - LoadedTimePanos[panoId];
if (differTime < maxTime)
return !0
}
return !1
}
return function(pano, imgQuality1, imgQuality2, basePanoSize, doneFun1, doneFun2, progressCallback, iswait, isclear, p ) {
if (overtime())
return !0;
var callback1 = (param1, param2)=>{
setTimeout(()=>{
isLoadedPanos[pano.id] = !1;
doneFun1 && doneFun1(param1, param2);
},1)
}
var callback2 = (param)=>{//没有看到有传doneFun2的
setTimeout(()=>{
isLoadedPanos[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 );
isLoadedPanos[pano.id] && (LoadedTimePanos[pano.id] = performance.now());
return isLoadedPanos[pano.id];
} catch (msg) {
isLoadedPanos[pano.id] = !1;
LoadedTimePanos[pano.id] = performance.now() - maxTime;
throw msg;
}
}
}()
Images360.filters = {
inPanoDirection : function(e, t, i) {
return function(n) {
var r = n.floorPosition.clone().sub(e).setZ(0).normalize() //忽略上下角度,这样即使看得很低也能走
, o = n.position.clone().sub(e).normalize();
return r.dot(t.clone().setZ(0).normalize()) > i || o.dot(t) > i
}
},
inFloorDirection: function(pos, e, o) {//许钟文 改 for鱼眼
return function(n) {
var i = n.floorPosition.clone().sub(pos).setZ(0).normalize();//改成在xz方向上,否则点击墙面不会移动
return i.dot(e) > o
}
},
isNotBehindNormal: function(e, t) {
var i = new THREE.Vector3;
return t = t.clone(),
function(n) {
var r = i.copy(n.position).sub(e).normalize();
return r.dot(t) > 0
}
},
isCloseEnoughTo: function(e, t) {
return function(i) {//因为marker可能比地面高,所以识别范围要比marker看起来更近一些。(因为投影到地板的位置比marker更近)
return e.distanceTo(i.floorPosition) < t //许钟文
}
},
not: function(e) {
return function(t) {
return t !== e
}
}
}
Images360.scoreFunctions = {
direction: function(e, t) {
return function(i) {
var pos = i.position.clone()
var n = pos.clone().sub(e).normalize();
return n.dot(t) * 10
}
},
distanceSquared: function(e) {
var pos1 = e.position.clone()
return function(i) {//许钟文 改
var pos2 = i.position.clone()
return pos1.distanceToSquared(pos2) * -1
}
},
angle: function(e, t) {
return function(i) {
var n = i.position.clone().sub(e).normalize();
return n.angleTo(t) * Potree.config.navigation.angleFactor
}
},
}
Images360.sortFunctions = {//排序函数,涉及到两个item相减
floorDistanceToPoint: function(e) {
return function(t, i) {
return t.floorPosition.distanceTo(e) - i.floorPosition.distanceTo(e)
}
},
}
export class Images360Loader{
static async load(viewer, params, callback ){
let center = viewer.transform.lonlatToLocal.inverse(viewer.bound.center)
center = {lat:center.y, lon:center.x} //中心点
Potree.loadPanos(center,(data)=>{
let images360 = new Images360(viewer, params);
data = data.sort(function(a,b){return a.id-b.id})
data.forEach((info,i)=>{
if(Potree.fileServer){
info.id = i //info的id是一长串数字,改简单点
}
let pano = new Panorama( info, params.transform, images360 );
/* pano.mesh.layers.set(Potree.config.renderLayers.marker)
pano.marker.layers.set(Potree.config.renderLayers.marker) */
images360.panos.push(pano);
})
viewer.setObjectLayers(images360.node, 'marker')
viewer.images360 = window.images360 = images360//add
images360.tileDownloader.setPanoData(images360.panos, [] /* , Potree.settings.number */);
{
var panosBound = new THREE.Box3
images360.panos.forEach(pano=>{
panosBound.expandByPoint(pano.position)
})
images360.bound = {
bounding:panosBound,
size: panosBound.getSize(new THREE.Vector3),
center: panosBound.getCenter(new THREE.Vector3)
}
}
callback && callback(images360)
})
}
};