瀏覽代碼

fix: 改了点云旋转方式,在数据集外绕整体中心旋转。 也支持3dTiles加载

xzw 2 年之前
父節點
當前提交
d88e3f399b

+ 1 - 1
gulpfile.js

@@ -21,7 +21,7 @@ let paths = {
 	],
 	html: [
 		"src/viewer/potree.css",
-		"src/viewer/sidebar.html",
+		"src/viewer/sidebar.html","src/viewer/sidebar2.html",
 		"src/viewer/profile.html"
 	],
 	resources: [

+ 71 - 14
libs/three.js/3dtiles/three-loader-3dtiles.esm.js

@@ -1,4 +1,4 @@
-import { CanvasTexture, LinearFilter, RepeatWrapping, Vector2 as Vector2$1, Frustum, Matrix4 as Matrix4$1, Group, PlaneGeometry, Vector3 as Vector3$1, MeshBasicMaterial, DoubleSide, Mesh, ArrowHelper, Color, BoxGeometry, EdgesGeometry, LineSegments, LineBasicMaterial, ShaderMaterial, Euler, BufferGeometry, Float32BufferAttribute, Uint8BufferAttribute, BufferAttribute, Points } from '../build/three.module.js';
+import { EventDispatcher, CanvasTexture, LinearFilter, RepeatWrapping, Vector2 as Vector2$1, Frustum, Matrix4 as Matrix4$1, Group, PlaneGeometry, Vector3 as Vector3$1, MeshBasicMaterial, DoubleSide, Mesh, ArrowHelper, Color, BoxGeometry, EdgesGeometry, LineSegments, LineBasicMaterial, ShaderMaterial, Euler, BufferGeometry, Float32BufferAttribute, Uint8BufferAttribute, BufferAttribute, Points } from '../build/three.module.js';
 import { GLTFLoader as GLTFLoader$1 } from '../loaders/GLTFLoader.js';
 import { DRACOLoader } from '../loaders/DRACOLoader.js';
 import { KTX2Loader } from '../loaders/KTX2Loader.js';
@@ -8552,6 +8552,13 @@ function getTiles3DScreenSpaceError(tile, frameState, useParentLodMetric) {
   } = tileset.options;
   let error = lodMetricValue * height * (viewDistanceScale || 1.0) / (distance * sseDenominator);
   error -= getDynamicScreenSpaceError(tileset, distance);
+                                                                                            
+                                                                                         
+   
+            
+                                                                                            
+                                                                                         
+   
   return error;
 }
 
@@ -8801,7 +8808,7 @@ class TilesetTraverser {
     this._emptyTraversalStack.reset();
   }
 
-  executeTraversal(root, frameState) {
+  executeTraversal(root, frameState) {// 遍历root
     const stack = this._traversalStack;
     root._selectionDepth = 1;
     stack.push(root);
@@ -8810,7 +8817,9 @@ class TilesetTraverser {
       const tile = stack.pop();
       let shouldRefine = false;
 
-      if (this.canTraverse(tile, frameState)) {
+
+        // !zeg改 循环遍历子tile, maxDepth用来限制可加载的最大深度 
+      if (this.canTraverse(tile, frameState) && tile.depth < this.options.maxDepth) {//add maxDepth
         this.updateChildTiles(tile, frameState);
         shouldRefine = this.updateAndPushChildren(tile, frameState, stack, tile.hasRenderContent ? tile._selectionDepth + 1 : tile._selectionDepth);
       }
@@ -9316,6 +9325,12 @@ class TileHeader {
       };
       this.content = await load(contentUrl, loader, options);
 
+        // !zeg改
+        if (this.tileset.options.maxDepth < this.depth) {
+            this.unloadContent()
+            return false
+        }
+
       if (this.tileset.options.contentLoader) {
         await this.tileset.options.contentLoader(this);
       }
@@ -9762,8 +9777,9 @@ const TILES_UNLOADED = 'Tiles Unloaded';
 const TILES_LOAD_FAILED = 'Failed Tile Loads';
 const POINTS_COUNT = 'Points';
 const TILES_GPU_MEMORY = 'Tile Memory Use';
-class Tileset3D {
+class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
   constructor(json, options) {
+      super()
     _defineProperty(this, "options", void 0);
 
     _defineProperty(this, "loadOptions", void 0);
@@ -10181,11 +10197,14 @@ class Tileset3D {
         this.stats.get(TILES_TOTAL).incrementCount();
         const children = tile.header.children || [];
 
-        for (const childHeader of children) {
-          const childTile = new TileHeader(this, childHeader, tile);
-          tile.children.push(childTile);
-          childTile.depth = tile.depth + 1;
-          stack.push(childTile);
+        // !zeg改  
+        if(tile.depth < this.options.maxDepth){                                     
+            for (const childHeader of children) {
+              const childTile = new TileHeader(this, childHeader, tile);
+              tile.children.push(childTile);
+              childTile.depth = tile.depth + 1;
+              stack.push(childTile);
+            }
         }
       }
     }
@@ -10230,7 +10249,7 @@ class Tileset3D {
     } catch (error) {
       this._onTileLoadError(tile, error);
     } finally {
-      this._onEndTileLoading();
+      this._onEndTileLoading(tile);//
 
       this._onTileLoad(tile, loaded);
     }
@@ -10263,9 +10282,10 @@ class Tileset3D {
     this.stats.get(TILES_LOADING).incrementCount();
   }
 
-  _onEndTileLoading() {
+  _onEndTileLoading(tile) {
     this._pendingCount--;
     this.stats.get(TILES_LOADING).decrementCount();
+    this.dispatchEvent({type:'endTileLoading',  tile, loadingCount: this._pendingCount }) // !zeg改
   }
 
   _addTileToCache(tile) {
@@ -16207,6 +16227,7 @@ async function parseComposite3DTile(tile, arrayBuffer, byteOffset, options, cont
   return byteOffset;
 }
 
+                                                                     
 async function parseGltf3DTile(tile, arrayBuffer, options, context) {
   tile.rotateYtoZ = true;
   tile.gltfUpAxis = options['3d-tiles'] && options['3d-tiles'].assetGltfUpAxis ? options['3d-tiles'].assetGltfUpAxis : 'Y';
@@ -17266,7 +17287,7 @@ class Loader3DTiles {
             });
             let cameraReference = null;
             let rendererReference = null;
-            const gltfLoader = new GLTFLoader$1();
+            const gltfLoader = props.gltfLoader || new GLTFLoader$1();  //xzw改
             let ktx2Loader = undefined;
             let dracoLoader = undefined;
             if (options.basisTranscoderPath) {
@@ -17291,6 +17312,7 @@ class Loader3DTiles {
                 updateTransforms: options.updateTransforms,
                 throttleRequests: options.throttleRequests,
                 maxRequests: options.maxRequests,
+                maxDepth: options.maxDepth || 50,  // !zeg改
                 contentLoader: (tile) => __awaiter(this, void 0, void 0, function* () {
                     let tileContent = null;
                     switch (tile.type) {
@@ -17419,9 +17441,10 @@ class Loader3DTiles {
                     tileset.modelMatrix = new Matrix4(threeMat.toArray());
                 }
             }
+            // 更新瓦片显隐和瓦片迭代更新                                  
             function tilesetUpdate(tileset, renderMap, renderer, camera) {
-                if (disposeFlag) {
-                    return;
+                if (disposeFlag || options.pauseTilesetUpdate) {// !zeg改 pauseTilesetUpdate 
+                    return
                 }
                 // Assumes camera fov, near and far are not changing
                 if (!sseDenominator || camera.aspect != lastCameraAspect) {
@@ -17444,6 +17467,9 @@ class Loader3DTiles {
                 renderer.getSize(rendererSize);
                 const frameState = {
                     camera: {
+                                                   
+                                                                                
+                                                         
                         position: lastCameraPosition.toArray(),
                     },
                     height: rendererSize.y,
@@ -17456,6 +17482,7 @@ class Loader3DTiles {
                 };
                 tileset._cache.reset();
                 tileset._traverser.traverse(tileset.root, frameState, tileset.options);
+                                                   
                 for (const tile of tileset.tiles) {
                     if (tile.selected) {
                         if (!renderMap[tile.id]) {
@@ -17472,6 +17499,7 @@ class Loader3DTiles {
                         }
                     }
                 }
+                                                
                 while (unloadQueue.length > 0) {
                     const tile = unloadQueue.pop();
                     if (renderMap[tile.id] && tile.contentState == TILE_CONTENT_STATE.UNLOADED) {
@@ -17630,7 +17658,28 @@ class Loader3DTiles {
                             dracoLoader.dispose();
                         }
                     },
+                                                                                      
+                                            
+                                                        
+                                            
+                                                                                           
+                      
                 },
+                                                      
+                                                          
+                                    
+                                              
+                                                                                             
+                       
+                      
+                                                     
+                                             
+                                             
+                                            
+                                                                                           
+                      
+                  
+              
             };
         });
     }
@@ -17649,9 +17698,17 @@ function createGLTFNodes(gltfLoader, tile, unlitMaterial, options, rootTransform
             gltfLoader.parse(tile.content.gltfArrayBuffer, tile.contentUrl ? tile.contentUrl.substr(0, tile.contentUrl.lastIndexOf('/') + 1) : '', (gltf) => {
                 const tileContent = gltf.scenes[0];
                 tileContent.applyMatrix4(contentTransform);
+                
+                 
+                // !zeg改
+                                                                                                                                                 
+                tileContent.position.set(tile.header.boundingVolume.box[0], tile.header.boundingVolume.box[1], tile.header.boundingVolume.box[2])//add
+                //这个链接需要加上这句https://testgis.4dage.com/LVBADUI_qp/tileset.json
+                
                 tileContent.traverse((object) => {
                     if (object.type == "Mesh") {
                         const mesh = object;
+                        //mesh.tileId = tile.id//add
                         const originalMaterial = mesh.material;
                         const originalMap = originalMaterial.map;
                         if (options.material) {

+ 9 - 3
libs/three.js/loaders/GLTFLoader.js

@@ -68,7 +68,7 @@ import {DRACOLoader} from './DRACOLoader.js'
 import {KTX2Loader} from './KTX2Loader.js'
 import { MeshoptDecoder } from '../libs/meshopt_decoder.module.js';
 import {DDSLoader} from './DDSLoader.js'
-
+import Common  from '../../../src/custom/utils/Common.js';
 
 
 var GLTFLoader = ( function () {
@@ -2553,6 +2553,9 @@ var GLTFLoader = ( function () {
 
                 parser.textureLoader.load(sourceURI, (tex)=>{
                     tex.minFilter = THREE.LinearMipmapLinearFilter //原本:NearestMipMapNearestFilter 闪烁
+                    
+                    Common.makeTexDontResize(tex) 
+                    //console.log(tex.image.width, tex.image.height)
                     //tex.needsUpdate
                     resolve(tex) 
                 })  
@@ -2604,12 +2607,15 @@ var GLTFLoader = ( function () {
 
 			var samplers = json.samplers || {};
 			var sampler = samplers[ textureDef.sampler ] || {};
-
+/* 
 			texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;
 			texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;
 			texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;
 			texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;
-
+ */
+ //xzw 删除设置,因为已经makeTexDontResize
+ 
+ 
 			parser.associations.set( texture, {
 				type: 'textures',
 				index: textureIndex

+ 22 - 6
src/mergeStartTest.js

@@ -1,11 +1,14 @@
-import * as THREE from "../libs/three.js/build/three.module.js";
+import * as THREE from "../../libs/three.js/build/three.module.js";
 import {settings, config} from './settings.js' 
 import math from './utils/math.js' 
 import browser from './utils/browser.js' 
-import './extensions/three.shim.js' 
+import {Utils} from "./../utils.js"
 import cameraLight from './utils/cameraLight.js' 
+import './three.shim.js'  
+import "./potree.shim.js"
+
+
 
-import {Utils} from "./utils.js"
 
 
 //多元融合模块
@@ -170,7 +173,7 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
         data.forEach((dataset,index)=>{  
             if(!ifReload){
                 var datasetCode = dataset.sceneCode || dataset.name //对应4dkk的场景码
-                var cloudPath = `${Potree.settings.urls.prefix}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js` 
+                var cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js` 
                 var timeStamp = dataset.createTime ? dataset.createTime.replace(/[^0-9]/ig,'') : '';  //每重算一次后缀随createTime更新一次 
                 //console.warn(dataset.name, 'timeStamp', timeStamp)
                 Potree.loadPointCloud(cloudPath, dataset.name ,datasetCode, timeStamp, e => {
@@ -518,8 +521,21 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
                   
                 
             }else if(name == '3dTiles'){
-                
-                
+                 
+                viewer.loadModel({ 
+                    name, 
+                    /* tilesUrl: 'https://4dkk.4dage.com/scene_view_data/SS-Ds19qsmuFA/images/3dtiles/tileset.json',
+                    transform : { 
+                        rotation : [Math.PI/2,  0,   0],
+                        position : [0,0,0]  
+                    }  */
+  
+                      tilesUrl: 'https://testgis.4dage.com/LVBADUI_qp/tileset.json',
+                    transform : { 
+                        rotation : [0,  0,   0],
+                        position : [0,0,0]  
+                    }  
+                },callback,onprogress)
             }
              
         }  

+ 1 - 1
src/custom/modules/mergeModel/MergeEditor.js

@@ -600,7 +600,7 @@ let MergeEditor = {
     
     
     
- 
+  
     
     
 export default MergeEditor  

+ 2 - 2
src/custom/potree.shim.js

@@ -759,7 +759,7 @@ Potree.updatePointClouds =  function(pointclouds,camera, areaSize /* renderer */
 		pointcloud.updateVisibleBounds();
 	}
 
-	exports.lru.freeMemory();//即Potree.lru 能看到所有在加载的node
+	Potree.lru.freeMemory();//即Potree.lru 能看到所有在加载的node
 
 	return result;
 };
@@ -1042,7 +1042,7 @@ Potree.updateVisibility = function(pointclouds, camera, areaSize){
 		}
 
 		if (node.isTreeNode()) {
-			exports.lru.touch(node.geometryNode);
+			Potree.lru.touch(node.geometryNode);
 			node.sceneNode.visible = true;
 			node.sceneNode.material = pointcloud.material;
 

+ 5 - 1
src/custom/utils/Common.js

@@ -307,9 +307,13 @@ var Common = {
     },
     
     makeTexDontResize(map){//避免贴图因非2的次方而缩小。小心使用
-        if(!map || map.image && THREE.Math.isPowerOfTwo(map.image.width ) && THREE.Math.isPowerOfTwo(map.image.height ))return
+        if(!map || !map.image){  
+            return console.log('!map || !map.image', map, map&&map.image)
+        } 
+        if(THREE.Math.isPowerOfTwo(map.image.width ) && THREE.Math.isPowerOfTwo(map.image.height ))return
         map.wrapS = map.wrapT = THREE.ClampToEdgeWrapping; //原默认 RepeatWrapping 
         map.minFilter = THREE.LinearFilter; // or THREE.NearestFilter  原默认 LinearMipmapLinearFilter
+        map.needsUpdate = true
     }
     
 }  

+ 34 - 16
src/navigation/FirstPersonControlsNew.js

@@ -108,31 +108,35 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                 if(!this.pointerDragStart){
                    return this.pointerDragStart = e.pointer.clone()
                 }
-                
-                
+                 
                 
                 let view = this.scene.view;
-                if(Potree.settings.rotAroundPoint && this.intersectStart && this.canMovePos(viewport) && !viewer.images360.isAtPano() && !this.viewer.inputHandler.pressedKeys[17]){//定点旋转:   以当前intersect的点为target旋转,不改点在屏幕中的位置
-                    let distance = camera.position.distanceTo(this.intersectStart.location)                                               //不按下ctrl的话                 
+                
+                 
+                if(this.rotateStartInfo.rotAroundPoint){//定点旋转:   以当前intersect的点为target旋转,不改点在屏幕中的位置
+                     
+                    let distance = camera.position.distanceTo(this.rotateStartInfo.rotCenter/* this.intersectStart.location */)                                               //不按下ctrl的话                 
+                      
+                    if(this.rotateStartInfo.rotCenter2d.z>1)distance *= -1 //在背面  
                       
                     //按照orbitControl的方式旋转:
-                    /* let rotationSpeed = 1//2.5;   
-                    this.yawDelta += e.drag.pointerDelta.x * rotationSpeed;
-                    this.pitchDelta -= e.drag.pointerDelta.y * rotationSpeed; */
+                    let rotationSpeed = 1//2.5;   
+                    this.yawDelta -= e.drag.pointerDelta.x * rotationSpeed;
+                    this.pitchDelta += e.drag.pointerDelta.y * rotationSpeed; 
 
-                    //旋转方向和偏移量尽量和在漫游点处旋转方式的一样
+                    /* //旋转方向和偏移量尽量和在漫游点处旋转方式的一样
                     this.yawDelta += e.drag.pointerDelta.x / 500 * viewport.resolution.x
-                    this.pitchDelta -= e.drag.pointerDelta.y / 500 * viewport.resolution.y
+                    this.pitchDelta -= e.drag.pointerDelta.y / 500 * viewport.resolution.y */
                    
                     //先更新一下相机:    
                     this.update() 
                     view.applyToCamera(camera)
                     
-                    //然后得到新的相机角度下,原先点在屏幕中的位置所对应的3d点现在的坐标。只需要平移一下新旧坐标差值即可。
-                    let newPointerDir = viewer.inputHandler.getMouseDirection(this.intersectStart.pointer).direction.clone().multiplyScalar(distance)
+                    //然后得到新的相机角度下,原先点在屏幕中的位置所对应的3d点现在的坐标。只需要平移一下新旧坐标差值即可。//感觉貌似也可以用project和unproject后的差值的方式,还不用判断z背面
+                    let newPointerDir = viewer.inputHandler.getMouseDirection(this.rotateStartInfo.rotCenter2d).direction.clone().multiplyScalar(distance)
                     let pivot = new THREE.Vector3().addVectors(camera.position, newPointerDir)  //新的3d点
                      
-                    let moveVec = new THREE.Vector3().subVectors(pivot, this.intersectStart.location)
+                    let moveVec = new THREE.Vector3().subVectors(pivot, this.rotateStartInfo.rotCenter)
                      
                     this.translationWorldDelta.copy(moveVec.negate()) 
                     //立即更新下,防止因update和此drag频率不同而打滑。
@@ -446,11 +450,25 @@ export class FirstPersonControls extends THREE.EventDispatcher {
             this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
         }
         let prepareRotate = (e)=>{ 
-            this.pointerDragStart = e.pointer.clone()  
-            this.intersectStart = e.intersect && e.intersect.location && {
-                location : e.intersect.location,
-                pointer :  e.intersect.location.clone().project(e.dragViewport.camera) //intersect点在屏幕中的位置
+            this.pointerDragStart = e.pointer.clone()
+            if(e.viewer.name == 'mapViewer' )return
+            let intersect = e.intersect || e.dragViewport.lastIntersect
+            //在数据集外部时绕中心点旋转,在数据集内部时绕intersect点旋转 或者 原地旋转镜头
+            let rotAroundPoint = Potree.settings.rotAroundPoint && (viewer.atDatasets.length == 0 || intersect) && this.canMovePos(viewport) && !viewer.images360.isAtPano() && !this.viewer.inputHandler.pressedKeys[17]
+            this.rotateStartInfo = {  
+                rotAroundPoint, //定点旋转 
+                /* intersectPos : e.intersect && e.intersect.location,
+                pointer :  e.intersect && e.intersect.location.clone().project(e.dragViewport.camera) //intersect点在屏幕中的位置 */
+            }
+            if(rotAroundPoint){
+                let pivotType = viewer.atDatasets.length > 0 ? 'intersect' : 'boundCenter'  
+                this.rotateStartInfo.rotCenter = pivotType == 'intersect' ? intersect.location :  viewer.bound.center
+                this.rotateStartInfo.rotCenter2d = this.rotateStartInfo.rotCenter.clone().project(e.dragViewport.camera) //点在屏幕中的位置
+                console.log('pivotType',pivotType,  this.rotateStartInfo.rotCenter2d)
             }
+            
+            
+            
             //console.log('prepareRotate' )
         }
         let preparePan = (e)=>{//触屏的pan点云    还是会偏移

+ 2 - 2
src/viewer/sidebarNew.js

@@ -135,7 +135,7 @@ export class Sidebar{
         
         
     }
-    
+     
     
     initMergeBar(){//多元融合模块
         var pannel = $('#mergeModel');
@@ -153,7 +153,7 @@ export class Sidebar{
             
             if($elem.attr('name') == 'select'){ 
                 return Potree.selectModel(name)
-            }
+            } 
             
             if($elem.text() == '添加'){
                 let startTime = Date.now()