|
@@ -17,7 +17,7 @@ import {TagTool} from "../objects/tool/TagTool.js";
|
|
|
import Compass from "../objects/tool/Compass.js";
|
|
|
import AxisViewer from "../objects/tool/AxisViewer.js";
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
import {ExtendScene} from '../../viewer/ExtendScene.js'
|
|
|
import {transitions, easing, lerp} from '../utils/transitions.js'
|
|
@@ -37,7 +37,7 @@ import {Message} from "../../utils/Message.js";
|
|
|
import {Sidebar} from "../../viewer/sidebarNew.js";
|
|
|
|
|
|
import {AnnotationTool} from "../../utils/AnnotationTool.js";
|
|
|
-import {MeasuringTool} from "../objects/tool/MeasuringTool.js";
|
|
|
+import {MeasuringTool} from "../objects/tool/MeasuringTool.js";
|
|
|
import CursorDeal from '../utils/CursorDeal.js'
|
|
|
import Common from '../utils/Common.js'
|
|
|
import browser from '../utils/browser.js'
|
|
@@ -59,6 +59,8 @@ import MergeEditor from "../modules/mergeModel/MergeEditor.js";
|
|
|
import {RouteGuider} from '../modules/route/RouteGuider.js'
|
|
|
import {Clipping} from '../modules/clipping/Clipping.js'
|
|
|
|
|
|
+
|
|
|
+
|
|
|
import ParticleEditor from '../modules/Particles/ParticleEditor.js'
|
|
|
import CamAniEditor from '../modules/CameraAnimation/CamAniEditor.js'
|
|
|
import PanoEditor from '../modules/panoEdit/panoEditor.js'
|
|
@@ -95,9 +97,12 @@ import { ClassificationScheme } from "../../materials/ClassificationScheme.js";
|
|
|
import { VRButton } from '../../../libs/three.js/extra/VRButton.js';
|
|
|
import DxfLoader from '../../loader/DxfLoader.js'
|
|
|
|
|
|
+import {Splat} from '../objects/3dgs/Splat.js'
|
|
|
|
|
|
-
|
|
|
-const manager = new THREE.LoadingManager();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
let loaders = {}
|
|
|
|
|
|
let mapArea;
|
|
@@ -115,6 +120,8 @@ Potree.isIframeChild = window.parent!=window //子页面
|
|
|
window.addEventListener('blur',()=>{
|
|
|
console.log('blur',window.winIndex)
|
|
|
}) */
|
|
|
+THREE.Cache.enabled = true //这样不会重复网络请求相同的图(如热点换图)。
|
|
|
+
|
|
|
|
|
|
export class Viewer extends ViewerBase{
|
|
|
|
|
@@ -125,10 +132,15 @@ export class Viewer extends ViewerBase{
|
|
|
window.viewer = this
|
|
|
mapArea = mapArea_
|
|
|
|
|
|
+ this.setLoaders()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
if(this.renderer.capabilities.isWebGL2){
|
|
|
Potree.settings.isWebgl2 = true //是否启用webgl2
|
|
|
}
|
|
|
|
|
|
+
|
|
|
if(Potree.settings.editType == "pano" || Potree.settings.editType == "merge"){
|
|
|
this.modules = {
|
|
|
Alignment,
|
|
@@ -202,11 +214,11 @@ export class Viewer extends ViewerBase{
|
|
|
//this.pageHiddenCollect = []
|
|
|
}
|
|
|
|
|
|
- setTimeout(()=>{
|
|
|
+ /* setTimeout(()=>{
|
|
|
console.log('depthSamChangeImg',Potree.timeCollect.depthSamChangeImg.median, 'sortByScore',Potree.timeCollect.sortByScore.median)
|
|
|
console.log('fps',Potree.fps, Potree.fps2,Potree.fpsRendered )
|
|
|
|
|
|
- },25000)
|
|
|
+ },25000) */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -528,12 +540,13 @@ export class Viewer extends ViewerBase{
|
|
|
this.scene.scene.add(this.reticule)
|
|
|
|
|
|
|
|
|
- if(Potree.settings.editType != "pano" && (Potree.settings.editType != 'merge' /* || Potree.settings.showObjectsOnMap */)){
|
|
|
+ if(Potree.settings.editType != "pano" && (Potree.settings.editType != 'merge' /* || Potree.settings.showObjectsOnMap */) && !args.noMap){
|
|
|
this.mapViewer = new MapViewer(mapArea/* $('#mapGaode')[0] */)
|
|
|
}
|
|
|
|
|
|
this.inputHandler = new InputHandler(this, this.scene.scene);
|
|
|
this.inputHandler.containsMouse = true//初始化,使键盘事件在mainViewer有效
|
|
|
+ this.inputHandler.registerInteractiveScene(this.scene.overlayScene);
|
|
|
//this.inputHandler.setScene(this.scene);
|
|
|
//this.inputHandler.addInputListener(this);//add
|
|
|
|
|
@@ -636,14 +649,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
this.scene.scene.add(this.objs);
|
|
|
|
|
|
- loaders = {
|
|
|
- objLoader : new OBJLoader( manager ),
|
|
|
- mtlLoader : new MTLLoader( manager ),
|
|
|
- glbLoader : new GLTFLoader(undefined, this.renderer, Potree.settings.libsUrl ),
|
|
|
- plyLoader : new PLYLoader( manager ),
|
|
|
- dxfLoader : new DxfLoader(),
|
|
|
- shapeLoader: new Potree.ShapefileLoader()
|
|
|
- }
|
|
|
+
|
|
|
//add test
|
|
|
/* const environment = new RoomEnvironment();
|
|
|
const pmremGenerator = new THREE.PMREMGenerator( this.renderer );
|
|
@@ -765,8 +771,24 @@ export class Viewer extends ViewerBase{
|
|
|
else this.lazyRenderViewports()
|
|
|
})
|
|
|
|
|
|
+ if(!Potree.settings.pathSmooth && Potree.settings.editType == 'merge' ){
|
|
|
+ viewer.addEventListener('camera_changed',(e)=>{
|
|
|
+ if(e.viewport == viewer.mainViewport && (e.changeInfo.positionChanged)){
|
|
|
+ Common.intervalTool.isWaiting('updatePathArrows', ()=>{
|
|
|
+ Potree.Path.updateArrows()
|
|
|
+ },1000)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
this.addEventListener('allLoaded', ()=>{
|
|
|
+
|
|
|
+ this.splatMesh = new Splat()
|
|
|
+ this.splatMesh.addPointcloud(this.scene.pointclouds[0])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
setTimeout(this.testPointcloudsMaxLevel.bind(this), 1000) //延迟一丢丢,等画面出现
|
|
|
|
|
|
//Potree.settings.renderAllViewports = browser.maybeQilin() && this.renderer.capabilities.maxCubemapSize <= 2048 && //麒麟chromium若获取过webgl2只渲染一个viewport的话其他的会变黑
|
|
@@ -798,6 +820,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
this.createHackMesh()
|
|
|
+
|
|
|
},{once:true})
|
|
|
|
|
|
|
|
@@ -865,7 +888,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge'){
|
|
|
|
|
|
- this.addEventListener('switchFloorplanSelect',(e)=>{//进入平面图设置后 切换选中的数据集
|
|
|
+ this.mapViewer && this.addEventListener('switchFloorplanSelect',(e)=>{//进入平面图设置后 切换选中的数据集
|
|
|
this.selectedFloorplan = e.pointcloud; //绝对显示
|
|
|
this.updateFpVisiDatasets()
|
|
|
let pointclouds;
|
|
@@ -880,7 +903,7 @@ export class Viewer extends ViewerBase{
|
|
|
})
|
|
|
|
|
|
|
|
|
- this.mapViewer.mapLayer.addEventListener('floorplanLoaded',()=>{
|
|
|
+ this.mapViewer?.mapLayer.addEventListener('floorplanLoaded',()=>{
|
|
|
this.updateCadVisibles(this.fpVisiDatasets, true) //加载完成后重新更新下
|
|
|
})
|
|
|
|
|
@@ -1021,8 +1044,13 @@ export class Viewer extends ViewerBase{
|
|
|
if(mesh.material){
|
|
|
let mats = (mesh.material instanceof Array) ? mesh.material : [mesh.material]
|
|
|
mats.forEach(mat =>{
|
|
|
- if(mat.map){
|
|
|
- texArea += mat.map.image.width * mat.map.image.height
|
|
|
+ let map = mat.map
|
|
|
+ if(map ){
|
|
|
+ if(!map.image){
|
|
|
+ console.error('!mat.map.image ??', mat.map.uuid)//obj可能会
|
|
|
+ return
|
|
|
+ }
|
|
|
+ texArea += map.image.width * map.image.height
|
|
|
//visi && (visiTexArea += a)
|
|
|
}
|
|
|
})
|
|
@@ -1093,6 +1121,7 @@ export class Viewer extends ViewerBase{
|
|
|
this.shelterCount.byTex ++ ;
|
|
|
//console.log('computeByTex direct', panoId, point, ifShelter)
|
|
|
}else{
|
|
|
+ //soon的无tex不敢写……
|
|
|
//console.log('延迟tex',panoId, point )
|
|
|
history.waitCompute = {panoId, forceGet:extraPanoId }
|
|
|
return useLastResult()
|
|
@@ -1150,21 +1179,23 @@ export class Viewer extends ViewerBase{
|
|
|
let history = shelterHistory[i];
|
|
|
|
|
|
if(history.waitCompute){
|
|
|
- if(history.waitCompute.panoId != void 0){
|
|
|
- if(!history.waitCompute.forceGet && (history.waitCompute.panoId != this.images360.currentPano.id || !this.images360.isAtPano(0.1))){
|
|
|
+ let panoId = history.waitCompute.panoId
|
|
|
+ if(panoId != void 0){
|
|
|
+ if(!history.waitCompute.forceGet && (panoId != this.images360.currentPano?.id || !this.images360.isAtPano(0.1))){
|
|
|
delete history.waitCompute //取消计算
|
|
|
}else{
|
|
|
- if(this.images360.currentPano.depthTex){
|
|
|
+ let pano = this.images360.getPano(panoId)
|
|
|
+ if(pano.depthTex){
|
|
|
if(byTex >= maxTexCount)break
|
|
|
|
|
|
byTex ++
|
|
|
- let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({point:history.point, margin:Potree.config.shelterMargin, useDepthTex:true, viewport:this.mainViewport } )
|
|
|
- history.panos[this.images360.currentPano.id] = ifShelter
|
|
|
+ let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({point:history.point, pano, margin:Potree.config.shelterMargin, useDepthTex:true, viewport:this.mainViewport } )
|
|
|
+ history.panos[panoId] = ifShelter
|
|
|
history.ifShelter = ifShelter
|
|
|
delete history.waitCompute
|
|
|
//console.log('补1', history.point.toArray())
|
|
|
}else{
|
|
|
- if(this.images360.currentPano.pointcloud.hasDepthTex){
|
|
|
+ if(pano.pointcloud.hasDepthTex){
|
|
|
//先等待加载完深度图
|
|
|
}else{
|
|
|
waitCloud.push(history)
|
|
@@ -1207,13 +1238,14 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
result.list.forEach(e=>{
|
|
|
let history = waitCloud2.find(a=>a.point.equals(e))
|
|
|
-
|
|
|
- let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({point:history.point, margin: Potree.config.shelterMargin , pickWindowSize:3, viewport:this.mainViewport} )
|
|
|
+ let panoId = history.waitCompute.panoId
|
|
|
+ let cameraPos = (panoId != void 0 && panoId != this.images360.currentPano?.id) && this.images360.getPano(panoId).position //如果非当前点,需要改相机位置
|
|
|
+ let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({point:history.point, cameraPos, margin: Potree.config.shelterMargin , pickWindowSize:3, viewport:this.mainViewport} )
|
|
|
|
|
|
if(history.waitCompute.cameraPos){
|
|
|
history.notAtPano = {cameraPos: history.waitCompute.cameraPos , ifShelter }
|
|
|
}else{
|
|
|
- history.panos[this.images360.currentPano.id] = ifShelter
|
|
|
+ history.panos[panoId] = ifShelter
|
|
|
}
|
|
|
history.ifShelter = ifShelter
|
|
|
byCloud++
|
|
@@ -1355,7 +1387,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
updateFpVisiDatasets(){
|
|
|
-
|
|
|
+ if(!this.mapViewer) return
|
|
|
let Clip = this.modules.Clip
|
|
|
let SiteModel = this.modules.SiteModel
|
|
|
let Alignment = this.modules.Alignment
|
|
@@ -3309,7 +3341,6 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
///let needsResize = viewports.length > 1 || params_.resize //去掉原因:因为不需要渲染的viewport不在此中所以无法判断几个viewport
|
|
|
-
|
|
|
for(let i=0; i<viewports.length; i++){
|
|
|
let viewport = viewports[i]
|
|
|
|
|
@@ -3320,7 +3351,10 @@ export class Viewer extends ViewerBase{
|
|
|
params.extraEnableLayers = viewport.extraEnableLayers
|
|
|
params.cameraLayers = viewport.cameraLayers
|
|
|
//}
|
|
|
-
|
|
|
+ params.useModelOnRT = Potree.settings.intersectOnObjs && pRenderer.canUseRTPoint()
|
|
|
+ && pRenderer.getIfRtEDL_(params) && !pRenderer.getIfuseEdl(params) //模型是否绘制在rtEDL上且能直接绘制到屏幕(感觉容易错)
|
|
|
+
|
|
|
+
|
|
|
|
|
|
var left,bottom,width,height
|
|
|
{
|
|
@@ -3377,6 +3411,11 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
viewport.beforeRender && viewport.beforeRender()
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
if(viewport.render){
|
|
|
if(!viewport.render($.extend({}, params, {
|
|
|
renderer, clear:params.clear || this.clear.bind(this), resize:null,
|
|
@@ -3389,9 +3428,11 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
this.renderBG(viewport)
|
|
|
|
|
|
- if(Potree.settings.notAdditiveBlending){
|
|
|
+
|
|
|
+
|
|
|
+ if(Potree.settings.notAdditiveBlending ){
|
|
|
params.renderBeforeCloud = true
|
|
|
- this.renderOverlay1(params) //先渲染不透明的model。 但drawedModelOnRT时这里提前多渲染了一遍
|
|
|
+ this.renderOverlay1(params) //先渲染不透明的model。
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3419,6 +3460,13 @@ export class Viewer extends ViewerBase{
|
|
|
this.renderOverlay(params)
|
|
|
}
|
|
|
|
|
|
+ if(this.splatMesh){
|
|
|
+ Potree.Utils.setCameraLayers(params.camera, ['model'])
|
|
|
+ this.renderer.render(this.splatMesh, params.camera)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
viewport.afterRender && viewport.afterRender()
|
|
|
|
|
|
this.dispatchEvent({type: "render.end", viewer: this, viewport });
|
|
@@ -3542,13 +3590,12 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
//为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖
|
|
|
let cameraLayers
|
|
|
-
|
|
|
if(params.cameraLayers) cameraLayers = params.cameraLayers
|
|
|
else{
|
|
|
if(params.viewport.name == "mapViewport" )cameraLayers = ['bothMapAndScene', 'light']
|
|
|
else {
|
|
|
cameraLayers = ['sceneObjects', 'light', 'bothMapAndScene' ];
|
|
|
- if(!params.drawedModelOnRT){
|
|
|
+ if(!params.useModelOnRT){
|
|
|
cameraLayers.push('model')
|
|
|
}
|
|
|
}
|
|
@@ -3559,8 +3606,10 @@ export class Viewer extends ViewerBase{
|
|
|
if(cameraLayers.length){
|
|
|
Potree.Utils.setCameraLayers(camera, cameraLayers, params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
|
|
|
|
|
|
+
|
|
|
if('renderBeforeCloud' in params){
|
|
|
this.scene.scene.traverse((object)=>{
|
|
|
+ if(params.useModelOnRT && viewer.objs.children.includes(object) )return {stopContinue:true} //already drawn on rt
|
|
|
if(object.material){
|
|
|
let transparent = object.material.opacity<1 || object.material.mapTransparent || !object.material.depthTest || !object.material.depthWrite //不写入深度的往往最后来比较
|
|
|
Potree.Utils.updateVisible(object, 'renderOpa', params.renderBeforeCloud != transparent)
|
|
@@ -3569,11 +3618,12 @@ export class Viewer extends ViewerBase{
|
|
|
})//ground的材质中opacity为1,所以被当做不透明了
|
|
|
}
|
|
|
|
|
|
- viewer.dispatchEvent({type: "render.begin2" , name:'scene', viewport:params.viewport })
|
|
|
+ viewer.dispatchEvent({type: "render.begin2" , name:'scene', viewport:params.viewport, viewer:this })
|
|
|
renderer.render(this.scene.scene, camera);
|
|
|
|
|
|
if('renderBeforeCloud' in params){
|
|
|
this.scene.scene.traverse((object)=>{
|
|
|
+ if(params.useModelOnRT && viewer.objs.children.includes(object) )return {stopContinue:true} //already drawn on rt
|
|
|
if(object.material){
|
|
|
Potree.Utils.updateVisible(object, 'renderOpa', true) //恢复
|
|
|
}
|
|
@@ -3587,51 +3637,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
|
|
|
|
|
|
- createHackMesh(){//为了防止无depthTex的全景在pick点云时画面中仅有一个材质时会黑屏,所以在镜头前再加一个mesh。具体bug表现见bug记录。
|
|
|
- if(this.scene.pointclouds.every(e=>e.hasDepthTex) || viewer.images360.panos.length == 0)return
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- let mesh = new THREE.Mesh(viewer.images360.panos[0].marker.geometry, new THREE.MeshBasicMaterial({color:"#F00",side:2/* ,depthTest:false */}))
|
|
|
- Potree.Utils.updateVisible(mesh,'show',false)
|
|
|
-
|
|
|
- this.images360.node.add(mesh)
|
|
|
-
|
|
|
-
|
|
|
- let updatePos = ()=>{
|
|
|
- let dir = this.mainViewport.view.direction
|
|
|
- let radius = this.images360.cube.scale.length()
|
|
|
- mesh.position.copy(this.mainViewport.view.position).add(dir.multiplyScalar(radius))//放置skybox之外
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- this.addEventListener('camera_changed', e => {
|
|
|
- if(e.viewport.name == 'MainView' && Potree.settings.displayMode == 'showPanos' && !this.images360.currentPano.depthTex
|
|
|
- && (e.changeInfo?.positionChanged || e.changeInfo?.quaternionChanged)){
|
|
|
-
|
|
|
- updatePos()
|
|
|
-
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- let judge = ()=>{
|
|
|
- if(!this.images360.currentPano?.depthTex && Potree.settings.displayMode == 'showPanos'){
|
|
|
- Potree.Utils.updateVisible(mesh,'show',true)
|
|
|
- }else{
|
|
|
- Potree.Utils.updateVisible(mesh,'show',false)
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- this.images360.addEventListener( 'flyToPanoDone', judge)
|
|
|
-
|
|
|
- this.images360.addEventListener( 'endChangeMode', judge)
|
|
|
-
|
|
|
-
|
|
|
- //不知道如果用点云计算非当前视角下的block会不会黑闪,如热点遮挡计算
|
|
|
-
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
renderOverlay2(params){//渲染剩余部分
|
|
|
let renderer = params.renderer || this.renderer
|
|
@@ -3698,8 +3704,8 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
let s = SiteModel.editing && SiteModel.selected && (SiteModel.selected.buildType == 'room' || SiteModel.selected.buildType == 'floor') //空间模型的房间选中材质是需要depth的,这时候需要绘制两次点云
|
|
|
|
|
|
- Potree.settings.pointEnableRT = !this.screenshoting && (this.scene.measurements.filter(e=>e.visible).length > 0 || s || PanoEditor?.entered || this.scene.tags.children.some(e=>e.visible))
|
|
|
-
|
|
|
+ Potree.settings.pointEnableRT = /* !this.screenshoting && */ (this.scene.measurements.filter(e=>e.visible).length > 0 || s || PanoEditor?.entered || this.tags.children.some(e=>e.visible))
|
|
|
+ //2024.12为什么截图时不遮挡?
|
|
|
|
|
|
if(vrActive){
|
|
|
this.renderVR();
|
|
@@ -4370,7 +4376,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
boundSize.x *= scale //稍微放大一些,不然会靠到屏幕边缘
|
|
|
boundSize.y *= scale
|
|
|
- let min = 0.0001
|
|
|
+ let min = 1
|
|
|
boundSize.x = Math.max(min, boundSize.x)
|
|
|
boundSize.y = Math.max(min, boundSize.y)
|
|
|
}
|
|
@@ -4467,7 +4473,7 @@ export class Viewer extends ViewerBase{
|
|
|
let facePlane = object.getFacePlane(target)
|
|
|
let normal = facePlane.normal.clone()
|
|
|
let angle = this.mainViewport.view.direction.angleTo(normal)
|
|
|
- let minDiff = THREE.Math.degToRad(60)
|
|
|
+ let minDiff = THREE.Math.degToRad(30)
|
|
|
//console.log('angle',angle)
|
|
|
if(angle>minDiff && angle<Math.PI-minDiff){//当几乎正对时就不执行
|
|
|
if(angle<Math.PI/2){ //在背面
|
|
@@ -4475,6 +4481,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
let dir = new THREE.Vector3().subVectors(camera.position, target).normalize()
|
|
|
let newDir = new THREE.Vector3().addVectors(dir,normal)//两个角度的中间
|
|
|
+ //console.log('newDir',newDir)
|
|
|
cameraPos.copy(target.clone().add(newDir))
|
|
|
}
|
|
|
}else if(object.points.length == 2){ //线段
|
|
@@ -4487,7 +4494,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
let dir = new THREE.Vector3().subVectors(camera.position, target).normalize()
|
|
|
let mid = new THREE.Vector3().addVectors(lineDir, dir).normalize() //中间法向量(如果刚好dir和lineDir反向,那得到的为零向量,就不移动了,但一般不会酱紫吧)
|
|
|
- let newDir = new THREE.Vector3().addVectors(dir, mid)
|
|
|
+ let newDir = new THREE.Vector3().addVectors(dir, mid)
|
|
|
cameraPos.copy(target.clone().add(newDir))
|
|
|
}
|
|
|
}else{
|
|
@@ -4566,7 +4573,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
}else if(Potree.settings.displayMode == 'showPanos'){//全景 (比较难校准)
|
|
|
let target2, dir
|
|
|
- if( object.measureType.includes('MulDistance')){//因为该线不闭合,可能看向target的方向会没有线,所以换一个target
|
|
|
+ if( object.measureType?.includes('MulDistance')){//因为该线不闭合,可能看向target的方向会没有线,所以换一个target
|
|
|
target2 = object.points[Math.round(object.points.length / 2) ]//直接看向中间点
|
|
|
dir = new THREE.Vector3().subVectors(target2, position).normalize()
|
|
|
}
|
|
@@ -4624,11 +4631,17 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
|
|
|
|
|
|
- if(Potree.settings.displayMode == 'showPointCloud'){
|
|
|
+ if(Potree.settings.displayMode == 'showPointCloud' && !o.requestShowPano){
|
|
|
if(o.dontChangePos){
|
|
|
position.copy(cameraPos)
|
|
|
- }else{
|
|
|
- dis = bestDistance
|
|
|
+ }else{
|
|
|
+ if(o.maxDis){
|
|
|
+ let disNow = cameraPos.distanceTo(target)
|
|
|
+ dis = THREE.Math.clamp(disNow, 1, o.maxDis)
|
|
|
+ }else{
|
|
|
+ dis = bestDistance
|
|
|
+ }
|
|
|
+
|
|
|
let dir = o.direction ? o.direction.clone().negate() : this.mainViewport.view.direction.negate()// */new THREE.Vector3().subVectors(camera.position, target).normalize()
|
|
|
if(o.dontLookUp && dir.z<0) dir.z *= -1
|
|
|
position.copy(target).add(dir.multiplyScalar(dis))
|
|
@@ -4668,7 +4681,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
}
|
|
|
|
|
|
- }else if(Potree.settings.displayMode == 'showPanos'){
|
|
|
+ }else{
|
|
|
let pano = viewer.images360.fitPanoTowardPoint({
|
|
|
point : target,
|
|
|
dir : this.mainViewport.view.direction, //尽量不改相机方向,避免镜头晃动
|
|
@@ -4685,6 +4698,8 @@ export class Viewer extends ViewerBase{
|
|
|
return result
|
|
|
}
|
|
|
}else if(object.boundingBox && type == 'boundingBox'){//使屏幕刚好看全boundingBox
|
|
|
+ //object.boundingBox.min.clamp(new THREE.Vector3(-1e4, -1e4, -1e4), new THREE.Vector3(1e4, 1e4, 1e4))//防止过大,ces崩溃
|
|
|
+ //object.boundingBox.max.clamp(new THREE.Vector3(-1e4, -1e4, -1e4), new THREE.Vector3(1e4, 1e4, 1e4))//防止过大,ces崩溃
|
|
|
target = object.boundingBox.getCenter(new THREE.Vector3)
|
|
|
if(o.dir){ //指定方向
|
|
|
cameraPos.copy(target).sub(o.dir)
|
|
@@ -5450,7 +5465,51 @@ export class Viewer extends ViewerBase{
|
|
|
return r && r.score > 1 ? result[0].item : null
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ createHackMesh(){//为了防止无depthTex的全景在pick点云时画面中仅有一个材质时会黑屏,所以在镜头前再加一个mesh。具体bug表现见bug记录。
|
|
|
+ if(this.scene.pointclouds.every(e=>e.hasDepthTex) || viewer.images360.panos.length == 0)return
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let mesh = new THREE.Mesh(viewer.images360.panos[0].marker.geometry, new THREE.MeshBasicMaterial({color:"#F00",side:2/* ,depthTest:false */}))
|
|
|
+ Potree.Utils.updateVisible(mesh,'show',false)
|
|
|
+
|
|
|
+ this.images360.node.add(mesh)
|
|
|
+
|
|
|
+
|
|
|
+ let updatePos = ()=>{
|
|
|
+ let dir = this.mainViewport.view.direction
|
|
|
+ let radius = this.images360.cube.scale.length()
|
|
|
+ mesh.position.copy(this.mainViewport.view.position).add(dir.multiplyScalar(radius))//放置skybox之外
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ this.addEventListener('camera_changed', e => {
|
|
|
+ if(e.viewport.name == 'MainView' && Potree.settings.displayMode == 'showPanos' && !this.images360.currentPano.depthTex
|
|
|
+ && (e.changeInfo?.positionChanged || e.changeInfo?.quaternionChanged)){
|
|
|
+
|
|
|
+ updatePos()
|
|
|
+
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ let judge = ()=>{
|
|
|
+ if(!this.images360.currentPano?.depthTex && Potree.settings.displayMode == 'showPanos'){
|
|
|
+ Potree.Utils.updateVisible(mesh,'show',true)
|
|
|
+ }else{
|
|
|
+ Potree.Utils.updateVisible(mesh,'show',false)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ this.images360.addEventListener( 'flyToPanoDone', judge)
|
|
|
+
|
|
|
+ this.images360.addEventListener( 'endChangeMode', judge)
|
|
|
+
|
|
|
+
|
|
|
+ //不知道如果用点云计算非当前视角下的block会不会黑闪,如热点遮挡计算
|
|
|
+
|
|
|
+ }
|
|
|
/* createRoomEv(){
|
|
|
|
|
|
const environment = new RoomEnvironment();
|
|
@@ -5458,6 +5517,36 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
+ setLoaders(){
|
|
|
+ this.fileManager = new THREE.LoadingManager(); //整体的load manager
|
|
|
+ this.fileManager.onLoad = () => {
|
|
|
+ console.log('All resources have been loaded');
|
|
|
+ this.fileManager.loading = false
|
|
|
+ this.dispatchEvent('managerOnLoad')
|
|
|
+ // 在这里可以执行模型渲染、动画等操作
|
|
|
+ };
|
|
|
+
|
|
|
+ // 设置加载进度的回调函数(可选)
|
|
|
+ this.fileManager.onProgress = (item, loaded, total) => {
|
|
|
+ if(loaded < total) this.fileManager.loading = true
|
|
|
+ console.log(`Loading ${item}: ${loaded} of ${total}`);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 设置加载失败的回调函数(可选)
|
|
|
+ this.fileManager.onError = (url) => {
|
|
|
+ console.error(`Failed to load resource: ${url}`);
|
|
|
+ };
|
|
|
+
|
|
|
+ loaders = {
|
|
|
+ objLoader : new OBJLoader( this.fileManager ),
|
|
|
+ mtlLoader : new MTLLoader( this.fileManager ),
|
|
|
+ glbLoader : new GLTFLoader(undefined, this.renderer, Potree.settings.libsUrl ),
|
|
|
+ plyLoader : new PLYLoader( this.fileManager ),
|
|
|
+ dxfLoader : new DxfLoader(),
|
|
|
+ shapeLoader: new Potree.ShapefileLoader()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
modelLoaded(object, fileInfo_={}, done){//普通模型加载完以后
|
|
|
object.isModel = true
|
|
|
let boundingBox = new THREE.Box3()
|
|
@@ -5575,21 +5664,31 @@ export class Viewer extends ViewerBase{
|
|
|
//Potree.Utils.makeTexDontResize(child.material.map)
|
|
|
//console.log(child.name, 'roughness',child.material.roughness,'metalness',child.material.metalness)
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- if(fileInfo_.unlit && (!(child.material instanceof BasicMaterial) /* || object.fileType == 'glb' */)){ //注释掉是因为已经写入到loader文件里了
|
|
|
- //let material = new THREE.MeshBasicMaterial({map:child.material.map})
|
|
|
- let material = new BasicMaterial({map : child.material.map, opacity:child.material.opacity, color:child.material.color}) //很奇怪glb的图会使原本的MeshBasicMaterial 会偏暗,所以自己重新写
|
|
|
- //child.material.dispose()
|
|
|
- child.material = material
|
|
|
- }
|
|
|
- if(fileInfo_.useStandandMat && !(child.material instanceof THREE.MeshStandardMaterial)){
|
|
|
- child.material = new THREE.MeshStandardMaterial()
|
|
|
- child.material.roughness = 0.7
|
|
|
- child.material.metalness = 0.5
|
|
|
- }
|
|
|
-
|
|
|
- //纯色的还是不能用BasicMaterial
|
|
|
+
|
|
|
+ let changeMat = (oldMat)=>{
|
|
|
+ let mat = oldMat
|
|
|
+ if(fileInfo_.unlit && (!(oldMat instanceof BasicMaterial) /* || object.fileType == 'glb' */)){ //注释掉是因为已经写入到loader文件里了
|
|
|
+ //mat = new THREE.MeshBasicMaterial({map:oldMat.map})
|
|
|
+ mat = new BasicMaterial({map : oldMat.map, opacity: oldMat.opacity, color: oldMat.color}) //很奇怪glb的图会使原本的MeshBasicMaterial 会偏暗,所以自己重新写
|
|
|
+ //oldMat.dispose()
|
|
|
+ }
|
|
|
+ if(fileInfo_.useStandandMat && !(oldMat instanceof THREE.MeshStandardMaterial)){
|
|
|
+ mat = new THREE.MeshStandardMaterial()
|
|
|
+ mat.roughness = 0.7
|
|
|
+ mat.metalness = 0.5
|
|
|
+ }
|
|
|
+ //纯色的还是不能用BasicMaterial
|
|
|
+ return mat
|
|
|
+ }
|
|
|
+ if(child.material instanceof Array){//obj
|
|
|
+ child.material = child.material.map(m=>changeMat(m))
|
|
|
+ }else{
|
|
|
+ child.material = changeMat(child.material)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
} );
|
|
|
}
|
|
@@ -5637,12 +5736,12 @@ export class Viewer extends ViewerBase{
|
|
|
console.log('开始加载', fileInfo.name, Common.getNameFromURL(fileInfo.url) )
|
|
|
|
|
|
let boundingBox = new THREE.Box3()
|
|
|
- /* if(!Potree.settings.boundAddObjs){
|
|
|
- boundingBox.min.set(-0.5,-0.5,-0.5); boundingBox.max.set(0.5,0.5,0.5)
|
|
|
- } */
|
|
|
+
|
|
|
if(fileInfo.objurl){
|
|
|
- fileInfo.url = fileInfo.objurl, fileInfo.fileType = 'obj' //兼容最早的
|
|
|
- }
|
|
|
+ /* fileInfo.url = fileInfo.objurl, */fileInfo.fileType = 'obj' //兼容最早的
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
if(fileInfo.url instanceof Array){
|
|
|
if(fileInfo.url.length == 1){
|
|
|
fileInfo.url = fileInfo.url[0]
|
|
@@ -5677,6 +5776,22 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ if(fileInfo.fileType == 'obj'){
|
|
|
+ let a = fileInfo.url.split('/')
|
|
|
+ let tails = a.pop().split('.')
|
|
|
+ let head = a.join('/') + '/'
|
|
|
+ let name = tails[0], fileType = tails[1]
|
|
|
+ if(fileType == 'obj'){
|
|
|
+ fileInfo.objurl || (fileInfo.objurl = fileInfo.url)
|
|
|
+ fileInfo.mtlurl || (fileInfo.mtlurl = head + name + '.mtl')
|
|
|
+ }else{
|
|
|
+ fileInfo.fileType = 'glb'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
if(fileInfo.fileType == 'obj'){ //暂时不支持数组
|
|
|
if(fileInfo.mtlurl){
|
|
|
loaders.mtlLoader.load( fileInfo.mtlurl , (materials)=>{
|
|
@@ -5778,9 +5893,14 @@ export class Viewer extends ViewerBase{
|
|
|
loadDone(object)
|
|
|
},fileInfo)
|
|
|
}else if(fileInfo.fileType == 'shp'){
|
|
|
- if(viewer.transform){
|
|
|
- loaders.shapeLoader.transform = viewer.transform.lonlatToLocal;
|
|
|
- }
|
|
|
+ /* if(viewer.transform){
|
|
|
+ loaders.shapeLoader.transform = (v)=>{
|
|
|
+ let a = viewer.transform.lonlatTo4550.inverse(v)
|
|
|
+ return viewer.transform.lonlatToLocal.forward(a)
|
|
|
+ }
|
|
|
+
|
|
|
+ //loaders.shapeLoader.transform = viewer.transform.lonlatToLocal.forward;
|
|
|
+ } */
|
|
|
const shp = await loaders.shapeLoader.load(fileInfo.url, fileInfo.color);
|
|
|
const shpModel = shp.node
|
|
|
|