|
@@ -17,9 +17,10 @@ import {TagTool} from "../objects/tool/TagTool.js";
|
|
|
import Compass from "../objects/tool/Compass.js";
|
|
|
import {FloorCompass} from "../objects/tool/FloorCompass.js";
|
|
|
import AxisViewer from "../objects/tool/AxisViewer.js";
|
|
|
-
|
|
|
+import Monitor from "../objects/Monitor.js";
|
|
|
|
|
|
|
|
|
+
|
|
|
import {ExtendScene} from '../../viewer/ExtendScene.js'
|
|
|
import {transitions, easing, lerp} from '../utils/transitions.js'
|
|
|
import {Renderer} from "../../PotreeRendererNew.js";
|
|
@@ -77,7 +78,7 @@ import {ViewerBase} from "../viewer/viewerBase.js"
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
+import {Gradients} from "../../materials/Gradients.js";
|
|
|
import SSAARenderPass from "../materials/postprocessing/SSAARenderPass.js"
|
|
|
import EffectComposer from '../materials/postprocessing/EffectComposer.js'
|
|
|
import {ShaderPass} from '../materials/postprocessing/ShaderPass.js'
|
|
@@ -135,7 +136,15 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
this.setLoaders()
|
|
|
|
|
|
-
|
|
|
+ this.tempRange = {
|
|
|
+ ir:{min:Infinity, max:-Infinity},//红外
|
|
|
+ temp:{min:Infinity, max:-Infinity}//火灾
|
|
|
+ }
|
|
|
+
|
|
|
+ /* if(Potree.settings.number == 'SS-t-g45LdhXGdYv'){
|
|
|
+ this.tempRange.temp = {min:473.1, max:1273.1}
|
|
|
+ } */
|
|
|
+
|
|
|
|
|
|
if(this.renderer.capabilities.isWebGL2){
|
|
|
Potree.settings.isWebgl2 = true //是否启用webgl2
|
|
@@ -155,8 +164,10 @@ export class Viewer extends ViewerBase{
|
|
|
}else if(Potree.settings.editType == "merge"){
|
|
|
this.modules.MergeEditor = MergeEditor
|
|
|
this.modules.CamAniEditor = CamAniEditor
|
|
|
+ this.modules.AnimationEditor = new AnimationEditor
|
|
|
+
|
|
|
Potree.settings.useDepthTex = Potree.settings.mergeType2
|
|
|
- //this.modules.AnimationEditor = new AnimationEditor
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}else{
|
|
@@ -360,9 +371,9 @@ export class Viewer extends ViewerBase{
|
|
|
this.edlOpacity = 1.0;
|
|
|
this.useEDL = false;
|
|
|
this.description = "";
|
|
|
-
|
|
|
- this.classifications = ClassificationScheme.DEFAULT;
|
|
|
-
|
|
|
+
|
|
|
+ this.setClassifications(ClassificationScheme['user'])
|
|
|
+
|
|
|
this.moveSpeed = 1;
|
|
|
|
|
|
this.lengthUnit = LengthUnits.METER;
|
|
@@ -909,7 +920,14 @@ export class Viewer extends ViewerBase{
|
|
|
/* this.modules.Clip.bus.addEventListener('updateSelectedDatasets',()=>{
|
|
|
this.updateFpVisiDatasets()
|
|
|
}) */
|
|
|
-
|
|
|
+
|
|
|
+ let count = 0
|
|
|
+ viewer.addEventListener('pointcloud_changed',(e)=>{
|
|
|
+ if(count > 5 && !Potree.settings.showHotIr && !Potree.settings.showHotTemp)return;
|
|
|
+ Common.intervalTool.isWaiting('gatherTempRange', (e)=>{
|
|
|
+ if(this.gatherTempRange() && Potree.visibleNodes?.length) count ++ //成功获取
|
|
|
+ } , THREE.Math.clamp(200, count * 200, 1200 ) )
|
|
|
+ })
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1318,10 +1336,13 @@ export class Viewer extends ViewerBase{
|
|
|
let inEntity = currentFloor
|
|
|
|
|
|
//console.error('updatePanosVisibles', currentFloor)
|
|
|
-
|
|
|
+ let SiteModel = this.modules.SiteModel
|
|
|
viewer.images360.panos.forEach(pano=>{
|
|
|
let visible = inEntity ? inEntity.panos.includes(pano) : this.atDatasets.some(e=>e.panos.includes(pano))
|
|
|
-
|
|
|
+ /* if(!visible && inEntity && SiteModel.noEditBefore && !SiteModel.entities.some(e=>e.panos.includes(pano))){
|
|
|
+ //没编辑过的空间模型很有错的可能,如果pano不在任何楼里就显示2025.3 for https://laser.4dkankan.com/?lang=zh&m=SG-y2wVWYmrM7u#/
|
|
|
+ visible = true
|
|
|
+ } */
|
|
|
Potree.Utils.updateVisible(pano, 'buildingChange', visible, 2)
|
|
|
})
|
|
|
this.dispatchEvent('content_changed')
|
|
@@ -1958,8 +1979,17 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
|
|
|
setClassifications(classifications){
|
|
|
- this.classifications = classifications;
|
|
|
-
|
|
|
+ for(let i in classifications){
|
|
|
+ let color = classifications[i].color
|
|
|
+ if(typeof color == 'string'){
|
|
|
+ color = new THREE.Color(color)
|
|
|
+ color = [color.r, color.g, color.b, 1]
|
|
|
+ classifications[i].color = color
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ this.classifications = classifications;
|
|
|
this.dispatchEvent({'type': 'classifications_changed', 'viewer': this});
|
|
|
}
|
|
|
|
|
@@ -2890,9 +2920,10 @@ export class Viewer extends ViewerBase{
|
|
|
material.uniforms.uFilterNumberOfReturnsRange.value = this.filterNumberOfReturnsRange;
|
|
|
material.uniforms.uFilterGPSTimeClipRange.value = this.filterGPSTimeRange;
|
|
|
material.uniforms.uFilterPointSourceIDClipRange.value = this.filterPointSourceIDRange;
|
|
|
-
|
|
|
- material.classification = this.classifications;
|
|
|
- material.recomputeClassification();
|
|
|
+
|
|
|
+ //material.classificationName = this.classificationName
|
|
|
+ //material.classification = this.classifications;
|
|
|
+ //material.recomputeClassification();
|
|
|
|
|
|
this.updateMaterialDefaults(pointcloud);
|
|
|
}
|
|
@@ -3604,7 +3635,7 @@ export class Viewer extends ViewerBase{
|
|
|
else{
|
|
|
if(params.viewport.name == "mapViewport" )cameraLayers = ['bothMapAndScene', 'light']
|
|
|
else {
|
|
|
- cameraLayers = ['sceneObjects', 'light', 'bothMapAndScene' ];
|
|
|
+ cameraLayers = ['sceneObjects', 'light', 'bothMapAndScene', 'monitor' ];
|
|
|
if(!params.useModelOnRT){
|
|
|
cameraLayers.push('model')
|
|
|
}
|
|
@@ -5082,14 +5113,16 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
this.setAllTilesets(model=>model.runtime.update(deltaTime, this.renderer, this.mainViewport.camera))
|
|
|
|
|
|
- let hasAnimation
|
|
|
- this.objs.children.forEach(model=>{
|
|
|
- if(model.aniMixer){
|
|
|
- hasAnimation = true
|
|
|
- model.aniMixer.update(deltaTime)
|
|
|
- }
|
|
|
- })
|
|
|
- hasAnimation && (this.dispatchEvent('content_changed'))
|
|
|
+ {
|
|
|
+ let hasAnimation
|
|
|
+ window.pauseAni || this.objs.children.forEach(model=>{
|
|
|
+ if(model.mixer && model.mixer._nActiveActions){
|
|
|
+ hasAnimation = true
|
|
|
+ model.mixer.update(deltaTime)
|
|
|
+ }
|
|
|
+ }) //以后有空的话用frust判断是否在画面内,不在的话即使有动画也不要 update 和 render, 如果paused的话是不是也可以不update
|
|
|
+ hasAnimation && (this.dispatchEvent('content_changed'))
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
@@ -5553,12 +5586,12 @@ export class Viewer extends ViewerBase{
|
|
|
};
|
|
|
|
|
|
// 设置加载失败的回调函数(可选)
|
|
|
- this.fileManager.onError = (url) => {
|
|
|
+ /* this.fileManager.onError = (url) => {
|
|
|
console.error(`Failed to load resource: ${url}`);
|
|
|
- };
|
|
|
+ }; */
|
|
|
|
|
|
loaders = {
|
|
|
- objLoader : new OBJLoader( this.fileManager ),
|
|
|
+ objLoaders : [],//new OBJLoader( this.fileManager ),
|
|
|
mtlLoader : new MTLLoader( this.fileManager ),
|
|
|
glbLoader : new GLTFLoader(undefined, this.renderer, Potree.settings.libsUrl ),
|
|
|
plyLoader : new PLYLoader( this.fileManager ),
|
|
@@ -5567,6 +5600,18 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ getObjLoader(){
|
|
|
+ let loader = loaders.objLoaders.find(e=>!e.inUse)
|
|
|
+ if(!loader){
|
|
|
+ loader = new OBJLoader( this.fileManager )
|
|
|
+ loader.inUse = true
|
|
|
+ loaders.objLoaders.push(loader)
|
|
|
+ }
|
|
|
+ return loader
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
modelLoaded(object, fileInfo_={}, done){//普通模型加载完以后
|
|
|
object.isModel = true
|
|
|
let boundingBox = new THREE.Box3()
|
|
@@ -5581,10 +5626,10 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- object.name = fileInfo_.name != void 0 ? fileInfo_.name : fileInfo_.fileType
|
|
|
+ object.name = fileInfo_.name != void 0 ? fileInfo_.name : Potree.Common.getNameFromURL(fileInfo_.url,true) // fileInfo_.fileType
|
|
|
object.fileType = fileInfo_.fileType
|
|
|
object.boundingBox = boundingBox //未乘上matrixWorld的本地boundingBox
|
|
|
- //object.scale.set(1,1,1);//先获取原始的大小时的boundingBox
|
|
|
+ //fileInfo_.parentInfo || object.scale.set(1,1,1);//先获取原始的大小时的boundingBox
|
|
|
object.opacity = 1 //初始化 记录
|
|
|
object.updateMatrixWorld()
|
|
|
|
|
@@ -5673,29 +5718,35 @@ export class Viewer extends ViewerBase{
|
|
|
object.traverse( ( child )=>{
|
|
|
let is = child.isMesh || child instanceof THREE.Points || child.isLine
|
|
|
|
|
|
- if (is){
|
|
|
-
|
|
|
- child.renderOrder = Potree.config.renderOrders.model;
|
|
|
- //if(Potree.settings.boundAddObjs){
|
|
|
+ if (is){
|
|
|
+ child.renderOrder = Potree.config.renderOrders.model;
|
|
|
+ let boundingBox_
|
|
|
+ if(child instanceof THREE.SkinnedMesh){//animation
|
|
|
+ child.computeBoundingBox();
|
|
|
+ boundingBox_ = child.boundingBox
|
|
|
+ }else{
|
|
|
child.geometry.computeBoundingBox()
|
|
|
- //console.log(child.matrixWorld.clone())
|
|
|
- boundingBox.union(child.geometry.boundingBox.clone().applyMatrix4(child.matrixWorld)) //但感觉如果最外层object大小不为1,要还原下scale再乘
|
|
|
- //}//获取在scale为1时,表现出的大小
|
|
|
- //Potree.Utils.makeTexDontResize(child.material.map)
|
|
|
- //console.log(child.name, 'roughness',child.material.roughness,'metalness',child.material.metalness)
|
|
|
+ boundingBox_ = child.geometry.boundingBox
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取在scale为1时,表现出的大小
|
|
|
+ boundingBox.union(boundingBox_.clone().applyMatrix4(child.matrixWorld)) //但感觉如果最外层object大小不为1,要还原下scale再乘
|
|
|
+
|
|
|
|
|
|
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_.unlit && (!(oldMat instanceof THREE.MeshBasicMaterial) /* || object.fileType == 'glb' */)){ //注释掉是因为已经写入到loader文件里了
|
|
|
+ mat = new THREE.MeshBasicMaterial({name:oldMat.name, map : oldMat.map, opacity: oldMat.opacity, color: oldMat.color, skinning:oldMat.skinning})
|
|
|
+ }
|
|
|
+
|
|
|
if(fileInfo_.useStandandMat && !(oldMat instanceof THREE.MeshStandardMaterial)){
|
|
|
mat = new THREE.MeshStandardMaterial()
|
|
|
mat.roughness = 0.7
|
|
|
mat.metalness = 0.5
|
|
|
- }
|
|
|
+ }
|
|
|
+ fileInfo_.metalness != void 0 && (mat.metalness = fileInfo_.metalness)
|
|
|
+ fileInfo_.roughness != void 0 && (mat.roughness = fileInfo_.roughness)
|
|
|
+ if(mat != oldMat)oldMat.dispose()
|
|
|
//纯色的还是不能用BasicMaterial
|
|
|
return mat
|
|
|
}
|
|
@@ -5738,9 +5789,10 @@ export class Viewer extends ViewerBase{
|
|
|
object.matrixWorldNeedsUpdate = true
|
|
|
}
|
|
|
object.updateMatrixWorld()
|
|
|
- MergeEditor.getBoundCenter(object) //初始化
|
|
|
+ MergeEditor.getBoundCenter(object) //初始化
|
|
|
+ fileInfo_.objLoader && (fileInfo_.objLoader.inUse = false)
|
|
|
done && done(object, fileInfo_)
|
|
|
-
|
|
|
+
|
|
|
this.dispatchEvent({type:'modelLoaded',model:object})
|
|
|
|
|
|
|
|
@@ -5812,41 +5864,52 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
if(fileInfo.fileType == 'obj'){ //暂时不支持数组
|
|
|
+ let objLoader = fileInfo.objLoader = this.getObjLoader()
|
|
|
+ let loadobj = ()=>{
|
|
|
+ objLoader.load(fileInfo.objurl, (object, total)=>{
|
|
|
+ loadDone(object/* , total, fileInfo.objurl */)
|
|
|
+ }, onProgress, onError )
|
|
|
+ }
|
|
|
if(fileInfo.mtlurl){
|
|
|
loaders.mtlLoader.load( fileInfo.mtlurl , (materials)=>{
|
|
|
+
|
|
|
+ objLoader.setMaterials( materials ) //因为这句所以不同obj不能用同一个objLoader,否则材质紊乱,模型变白
|
|
|
materials.preload();
|
|
|
-
|
|
|
- loaders.objLoader.setMaterials( materials ).load(fileInfo.objurl, (object, total)=>{
|
|
|
- loadDone(object/* , total, fileInfo.objurl */)
|
|
|
- }, onProgress, onError )
|
|
|
- } , onProgress, onError );
|
|
|
+ loadobj()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ } , onProgress, ()=>{
|
|
|
+ //console.log('mtl load failed, load obj directly')
|
|
|
+ loadobj()
|
|
|
+ });
|
|
|
}else{
|
|
|
- loaders.objLoader.load(fileInfo.objurl, (object, total)=>{
|
|
|
- loadDone(object)
|
|
|
- }, onProgress, onError)
|
|
|
- }
|
|
|
+ loadobj()
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
}else if(fileInfo.fileType == 'glb'){
|
|
|
loaders.glbLoader.unlitMat = true//!!fileInfo.unlit
|
|
|
loaders.glbLoader.load(fileInfo.url, ( gltf, total )=>{
|
|
|
- console.log('loadGLTF', gltf)
|
|
|
+ console.log('loadGLTF', gltf, 'aniCount:',gltf.animations.length)
|
|
|
let model = gltf.scene
|
|
|
if(gltf.animations.length){
|
|
|
- //let skeleton = new THREE.SkeletonHelper( model );
|
|
|
- //skeleton.visible = true;
|
|
|
- //model.add( skeleton );
|
|
|
- /* viewer.scene.scene.add(skeleton)
|
|
|
+ let skeleton = new THREE.SkeletonHelper( model );
|
|
|
+ //skeleton.visible = false;
|
|
|
+ viewer.scene.scene.add(skeleton)
|
|
|
model.skeletonHelper = skeleton //注意:不能覆盖model.skeleton,因其另有 */
|
|
|
-
|
|
|
+ skeleton.material.opacity = 0.1
|
|
|
let mixer = new THREE.AnimationMixer( model);
|
|
|
-
|
|
|
+ model.actions = []
|
|
|
gltf.animations.forEach(ani=>{
|
|
|
- let action = mixer.clipAction( ani );
|
|
|
+ if(ani.tracks.filter(e=>e instanceof THREE.QuaternionKeyframeTrack).length > 1){ //>一帧的
|
|
|
+ model.actions.push(mixer.clipAction( ani ));
|
|
|
+ }
|
|
|
})
|
|
|
- model.aniMixer = mixer
|
|
|
+ model.mixer = mixer
|
|
|
}
|
|
|
model.gltf = gltf
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
|
|
|
loadDone(model)
|
|
|
}, onProgress, onError)
|
|
@@ -6022,7 +6085,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
|
|
|
removeModel(model){
|
|
|
- this.objs.remove(model);
|
|
|
+ model.parent.remove(model)
|
|
|
let dispose = (e)=>{
|
|
|
e.geometry && e.geometry.dispose()
|
|
|
e.material && e.material.dispose()
|
|
@@ -6031,7 +6094,7 @@ export class Viewer extends ViewerBase{
|
|
|
dispose(e)
|
|
|
})
|
|
|
|
|
|
- if(Potree.settings.boundAddObjs){
|
|
|
+ if(Potree.settings.boundAddObjs && model.isChildOf(viewer.objs)){
|
|
|
this.updateModelBound()
|
|
|
}
|
|
|
}
|
|
@@ -6273,14 +6336,14 @@ export class Viewer extends ViewerBase{
|
|
|
video.play();
|
|
|
video.currentTime = 0
|
|
|
Potree.settings.zoom.enabled = false
|
|
|
-
|
|
|
+
|
|
|
transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{
|
|
|
|
|
|
}, 0, easing['easeInOutQuad'])
|
|
|
}, e.toPano.duration*0.6) //时间上不能和消失的重叠 延迟
|
|
|
+
|
|
|
|
|
|
-
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
//消失
|
|
|
transitions.start(lerp.property(plane.material, "opacity", 0, ) , e.toPano.duration*0.4, ()=>{
|
|
@@ -6389,7 +6452,37 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
} */
|
|
|
-
|
|
|
+ addMonitor(data, model){
|
|
|
+ if(!model){
|
|
|
+ return console.warn('必须指定第二个参数为所附模型')
|
|
|
+ }
|
|
|
+ data = data || {
|
|
|
+ "sid": "gSMVdb159299",
|
|
|
+ "name": "1",
|
|
|
+ "panoId": "0",
|
|
|
+ "video": "https://newcntv.qcloudcdn.com/asp/hls/4000/0303000a/3/default/d907ef756138493e9fe5b35b4ab69642/4000.m3u8",
|
|
|
+ "posOri": {
|
|
|
+ "x": 0.75,
|
|
|
+ "y": 0.07,
|
|
|
+ "z": 1.5
|
|
|
+ },
|
|
|
+ "posOffset": {
|
|
|
+ "x": 0,
|
|
|
+ "y": 0,
|
|
|
+ "z": 0
|
|
|
+ },
|
|
|
+ "fov": 70,
|
|
|
+ "far": 3,
|
|
|
+ "yaw": 24,
|
|
|
+ "roll": 0,
|
|
|
+ "pitch": -1,
|
|
|
+ "videoType": 1
|
|
|
+ }
|
|
|
+ let monitor = new Monitor(data)
|
|
|
+ model.add(monitor)
|
|
|
+ this.scene.monitors.push(monitor)
|
|
|
+ this.dispatchEvent('content_changed')
|
|
|
+ }
|
|
|
|
|
|
addTube(datas){//加水管 自动生成
|
|
|
|
|
@@ -6487,8 +6580,102 @@ export class Viewer extends ViewerBase{
|
|
|
return sprite
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ switchHotType(){// add
|
|
|
+ let type = Potree.settings.showHotTemp ? 'temp' : Potree.settings.showHotIr ? 'ir' : null
|
|
|
+ let _gradient = Gradients[type ? 'ir' : 'RAINBOW'] //e.material._gradient = Gradients[type == 'ir' ? 'ir' : 'RAINBOW']//渐变色阶
|
|
|
+ let gradientTex = Potree.ExtendPointCloudMaterial.generateGradientTexture(_gradient);
|
|
|
+ let min,max
|
|
|
+ if(type){
|
|
|
+ min = this.tempRange[type].min
|
|
|
+ max = this.tempRange[type].max
|
|
|
+ if(min > 0){
|
|
|
+ let expand = (max - min) * 0.015 //微扩大,因为比min还小的是0, 0是未探测到温度,要区别出0和min,否则这俩将是一个颜色(但不能扩太多,因为界面标记了最低值,否则0就是最低值了)
|
|
|
+ min-=expand
|
|
|
+ }else if(max < 0){
|
|
|
+ let expand = (max - min) * 0.015
|
|
|
+ max-=expand
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let objects = [viewer.images360.cube].concat(viewer.scene.pointclouds)
|
|
|
+ objects.forEach(e=>{
|
|
|
+ e.material.uniforms.gradient.value = e.material.gradientTexture = gradientTex
|
|
|
+ type && e.material.uniforms.temperRange.value.set(min, max )
|
|
|
+ })
|
|
|
+
|
|
|
+ viewer.scene.pointclouds.forEach(e=>e.updateAttrAuto())
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ gatherTempRange(type, range){ //收集温度范围
|
|
|
+ let oldRange = Common.CloneObject(this.tempRange)
|
|
|
+
|
|
|
+ if(range){ //全景模式时
|
|
|
+ let {min,max} = this.tempRange[type]
|
|
|
+ min = Math.min(range.min, min)
|
|
|
+ max = Math.max(range.max, max)
|
|
|
+ this.tempRange[type] = {min,max}
|
|
|
+
|
|
|
+ }else{//点云模式随着加载而扩充温度范围
|
|
|
+ viewer.scene.pointclouds.forEach(pointcloud=>{
|
|
|
+ let rootAttr = pointcloud.root.geometryNode?.geometry.attributes || pointcloud.root.geometry?.attributes
|
|
|
+ if(!rootAttr)return false
|
|
|
+ let types = ['temp','ir'].filter(e=>rootAttr[e])
|
|
|
+ if(types.length == 0)return true
|
|
|
+
|
|
|
+ let nodesAttr = pointcloud.visibleNodes.map(e=>e.geometryNode.geometry.attributes)
|
|
|
+ nodesAttr = [rootAttr].concat(nodesAttr).filter(e=>!e[types[0]].tempRangeVisited_)
|
|
|
+ nodesAttr.forEach(attributes=>{
|
|
|
+ types.forEach(type_=>{
|
|
|
+ let {min,max} = this.tempRange[type_]
|
|
|
+ let range = attributes[type_].tempRange
|
|
|
+ min = Math.min(range[0], min)
|
|
|
+ max = Math.max(range[1], max)
|
|
|
+ this.tempRange[type_] = {min,max}
|
|
|
+ attributes[type_].tempRangeVisited_ = true
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ /* pointcloud.visibleNodes.forEach(e=>{
|
|
|
+ if(e.tempRangeVisited)return
|
|
|
+ types.forEach(type_=>{
|
|
|
+ let {min,max} = this.tempRange[type_]
|
|
|
+ let range = e.geometryNode.geometry.attributes[type_].tempRange
|
|
|
+ min = Math.min(range[0], min)
|
|
|
+ max = Math.max(range[1], max)
|
|
|
+ this.tempRange[type_] = {min,max}
|
|
|
+ })
|
|
|
+ e.tempRangeVisited = true
|
|
|
+ }) */
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if(!Common.ifSame(oldRange, this.tempRange)){
|
|
|
+ this.switchHotType() //update
|
|
|
+ console.log('tempRangeChanged', Common.CloneObject(this.tempRange))
|
|
|
+ this.dispatchEvent('tempRangeChanged')
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ //其实可以只识别低nodeLevel的range,会快一些吗,甚至只root的就行,不知道后面的会不会超过root的范围
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+
|
|
|
//------ CLIP 默认clipTask都是clipInside ----------------------
|
|
|
/*
|
|
|
并集相当于加法,交集相当于乘法。 所有结果都能展开成多个乘积相加。
|