xzw пре 2 месеци
родитељ
комит
fd59b08efa

+ 2 - 2
examples/splatter.html

@@ -5,7 +5,7 @@
 	<meta name="description" content="">
 	<meta name="description" content="">
 	<meta name="author" content="">
 	<meta name="author" content="">
 	<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 	<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-	<title>Potree Viewer</title>
+	<title>splatter</title>
 
 
 	<link rel="stylesheet" type="text/css" href="../../build/potree/potree.css">
 	<link rel="stylesheet" type="text/css" href="../../build/potree/potree.css">
 	<link rel="stylesheet" type="text/css" href="../../libs/jquery-ui/jquery-ui.min.css">
 	<link rel="stylesheet" type="text/css" href="../../libs/jquery-ui/jquery-ui.min.css">
@@ -145,7 +145,7 @@
     var splatId = browser.urlHasValue('m',true)  
     var splatId = browser.urlHasValue('m',true)  
     var urlAtSplatter = !browser.urlHasValue('urlAtCurrent') ; 
     var urlAtSplatter = !browser.urlHasValue('urlAtCurrent') ; 
     
     
-    Potree.settings.firstCtrlRotInvSmooth = true 
+    Potree.settings.ctrlRotInvSmooth = true 
     Potree.settings.rotAroundPoint = false  
     Potree.settings.rotAroundPoint = false  
     Potree.settings.noAA = true 
     Potree.settings.noAA = true 
     
     

+ 21 - 6
libs/three.js/build/three.module.js

@@ -12703,7 +12703,7 @@ function WebGLAttributes( gl, capabilities ) {
 		const buffer = gl.createBuffer();
 		const buffer = gl.createBuffer();
 
 
 		gl.bindBuffer( bufferType, buffer );
 		gl.bindBuffer( bufferType, buffer );
-		gl.bufferData( bufferType, array, usage );
+		gl.bufferData( bufferType, array, usage ); 
 
 
 		attribute.onUploadCallback();
 		attribute.onUploadCallback();
 
 
@@ -12775,11 +12775,26 @@ function WebGLAttributes( gl, capabilities ) {
 
 
 		gl.bindBuffer( bufferType, buffer );
 		gl.bindBuffer( bufferType, buffer );
 
 
-		if ( updateRange.count === - 1 ) {
+         
+         
+        //xzw add:
+        if(attribute.updateWhole){//expand 
+            //重置
+            gl.bufferData( bufferType, attribute.count * attribute.itemSize * array.BYTES_PER_ELEMENT, attribute.usage );
+            //gl.bufferData( bufferType, array, attribute.usage );
+            delete attribute.updateWhole
+		}
 
 
-			// Not using update ranges
 
 
-			gl.bufferSubData( bufferType, 0, array );
+        /* if(attribute.updateWhole){//expand 
+            //重置
+             //gl.bufferData( bufferType, attribute.count * attribute.itemSize * array.BYTES_PER_ELEMENT, attribute.usage );
+            gl.bufferData( bufferType, array, attribute.usage );
+            delete attribute.updateWhole
+		}else   */if ( updateRange.count === - 1 ) { 
+			// Not using update ranges 
+             gl.bufferSubData( bufferType, 0, array );
+             //gl.bufferSubData(bufferType, 0, array, 0, array.length )  
 
 
 		} else {
 		} else {
 
 
@@ -24125,9 +24140,9 @@ function WebGLRenderer( parameters ) {
 
 
 		} else if ( geometry.isInstancedBufferGeometry ) {
 		} else if ( geometry.isInstancedBufferGeometry ) {
 
 
-			const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
+			//const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
 
 
-			renderer.renderInstances( drawStart, drawCount, instanceCount );
+			renderer.renderInstances( drawStart, drawCount, geometry.instanceCount  /* instanceCount */ );  //xzw改
 
 
 		} else {
 		} else {
 
 

+ 2 - 0
libs/three.js/loaders/GLTFLoader.js

@@ -2966,6 +2966,8 @@ class GLTFDracoMeshCompressionExtension {
 			/* // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
 			/* // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
 			if ( material.map ) material.map.encoding = sRGBEncoding;  //xzw delete, sRGB会造成颜色偏深。新版本的loader也没加srgb
 			if ( material.map ) material.map.encoding = sRGBEncoding;  //xzw delete, sRGB会造成颜色偏深。新版本的loader也没加srgb
 			if ( material.emissiveMap ) material.emissiveMap.encoding = sRGBEncoding;   */
 			if ( material.emissiveMap ) material.emissiveMap.encoding = sRGBEncoding;   */
+            if ( material.map ) material.map.encoding = THREE.LinearEncoding //有的不知道为啥变成sRGBEncoding了还原下
+
 
 
 			assignExtrasToUserData( material, materialDef );
 			assignExtrasToUserData( material, materialDef );
 
 

+ 6 - 6
src/custom/modules/panos/Images360.js

@@ -232,7 +232,7 @@ export class Images360 extends THREE.EventDispatcher{
             
             
             if(Potree.settings.editType != 'merge'){
             if(Potree.settings.editType != 'merge'){
             
             
-                let elHide = $("<input type='button' value='隐藏点云'></input>")
+                let elHide = $("<button index=0>隐藏点云</button>" )
                 elHide.css({
                 elHide.css({
                     position : "absolute",
                     position : "absolute",
                     right : '40%',
                     right : '40%',
@@ -249,7 +249,7 @@ export class Images360 extends THREE.EventDispatcher{
                     viewer.scene.pointclouds.forEach(e=>{ 
                     viewer.scene.pointclouds.forEach(e=>{ 
                         Potree.Utils.updateVisible(e, 'force', !visi) 
                         Potree.Utils.updateVisible(e, 'force', !visi) 
                     })
                     })
-                    elHide.val(!visi ? "隐藏点云" : "显示点云")  
+                    elHide.text(!visi ? "隐藏点云" : "显示点云")  
                 });
                 });
                 
                 
                 
                 
@@ -296,7 +296,7 @@ export class Images360 extends THREE.EventDispatcher{
                 
                 
             }
             }
             
             
-            let elDisplayModel = $("<input type='button' value='>>全景'></input>")
+            let elDisplayModel = $("<button index='1'>全景</button>")
             elDisplayModel.css({
             elDisplayModel.css({
                 position : "absolute",
                 position : "absolute",
                 right : '65%',
                 right : '65%',
@@ -304,7 +304,7 @@ export class Images360 extends THREE.EventDispatcher{
                 zIndex: "10000",
                 zIndex: "10000",
                 fontSize:'1em',color:"black",
                 fontSize:'1em',color:"black",
                 width : '100px',
                 width : '100px',
-                background:'rgba(255,255,255,0.8)',                
+                background:'rgba(255,255,255,0.8)',  
             })
             })
             
             
             this.domRoot.appendChild(elDisplayModel[0]);
             this.domRoot.appendChild(elDisplayModel[0]);
@@ -318,7 +318,7 @@ export class Images360 extends THREE.EventDispatcher{
             
             
              
              
             if(viewer.mapViewer){
             if(viewer.mapViewer){
-                let mapStyleBtn = $("<input type='button' value='普通'></input>")
+                let mapStyleBtn = $("<button index='2'>普通</button>"  )
                 mapStyleBtn.css({
                 mapStyleBtn.css({
                     position : "absolute",
                     position : "absolute",
                     right : '50%',
                     right : '50%',
@@ -332,7 +332,7 @@ export class Images360 extends THREE.EventDispatcher{
                 let map = viewer.mapViewer.mapLayer.maps.find(e=>e.name == 'map') 
                 let map = viewer.mapViewer.mapLayer.maps.find(e=>e.name == 'map') 
                 mapStyleBtn.on("click", (e) => {  
                 mapStyleBtn.on("click", (e) => {  
                     map.switchStyle(map.style == 'satellite' ? 'standard' : 'satellite') 
                     map.switchStyle(map.style == 'satellite' ? 'standard' : 'satellite') 
-                    mapStyleBtn.val(map.style == 'satellite' ? '卫星' : '普通')
+                    mapStyleBtn.text(map.style == 'satellite' ? '卫星' : '普通')
                 });
                 });
                 
                 
             }
             }

+ 29 - 21
src/custom/objects/3dgs/splatter/SplatterThree.js

@@ -2,7 +2,7 @@
 import * as THREE from "../../../../../libs/three.js/build/three.module.js"; 
 import * as THREE from "../../../../../libs/three.js/build/three.module.js"; 
 
 
 import browser from '../../../utils/browser.js'
 import browser from '../../../utils/browser.js'
- 
+import math from '../../../utils/math.js'
 import Collider from './Collider.js' 
 import Collider from './Collider.js' 
 
 
 import Queue from '../../../utils/Queue.js'
 import Queue from '../../../utils/Queue.js'
@@ -648,9 +648,15 @@ var Buffer = class {
     }
     }
     expand(A) {
     expand(A) {
         let g = this.gl;
         let g = this.gl;
-        this.maxSize < A && (this.bind(),
-        g.bufferData(g.ARRAY_BUFFER, A * this.itemByte, g.DYNAMIC_DRAW),
-        this.maxSize = A)
+        if(this.maxSize < A){
+            let expandRatio = math.linearClamp(A/10000, [300, 1200],[1.5, 1.1])//点越多,增加倍率越小
+            this.bind()  
+            this.maxSize = A * expandRatio 
+            g.bufferData(g.ARRAY_BUFFER, this.maxSize * this.itemByte, g.DYNAMIC_DRAW) 
+            
+        }
+       
+        
     }
     }
     upload(start, data, offset, count) {
     upload(start, data, offset, count) {
         this.bind(),
         this.bind(),
@@ -1515,6 +1521,7 @@ var Lodder = class {
         if (!this.worker.working && !this.pauseSort) {
         if (!this.worker.working && !this.pauseSort) {
             if (!(distanceSq(A.eye, this.eye3) > .001))
             if (!(distanceSq(A.eye, this.eye3) > .001))
                 return !1;
                 return !1;
+             
             this.worker.working = !0,
             this.worker.working = !0,
             this.send("sort", {
             this.send("sort", {
                 eye: A.eye,
                 eye: A.eye,
@@ -1896,25 +1903,27 @@ uniform lowp sampler2D gtable;
 in lowp vec4 color;
 in lowp vec4 color;
 in vec2 uv;
 in vec2 uv;
 out vec4 fragColor;
 out vec4 fragColor;
-void main(){float A=dot(uv,uv);
-if(A>4.)discard;
+void main(){
+    float A=dot(uv,uv);
+    if(A>4.)discard;
 
 
-#if 1
-float B=min(color.a,1.)*max(texture(gtable,vec2(0.25*A,color.a-1.)).r,options.x);
+    #if 1
+        float B=min(color.a,1.)*max(texture(gtable,vec2(0.25*A,color.a-1.)).r,options.x);
 
 
-#else
-float B=min(color.a,1.);
-B*=max(exp(-A),options.x);
+    #else
+        float B=min(color.a,1.);
+        B*=max(exp(-A),options.x);
 
 
-#endif
-#ifndef RENDER_DEPTH
-fragColor=vec4(color.rgb*B,B);
+    #endif
+    
+    #ifndef RENDER_DEPTH
+        fragColor=vec4(color.rgb*B,B);
 
 
-#else 
-if(B<options.z)discard;
-fragColor=vec4(color.rgb,1.);
+    #else 
+    if(B<options.z)discard;
+        fragColor=vec4(color.rgb,1.);
 
 
-#endif
+    #endif
 }
 }
 `
 `
  
  
@@ -3490,7 +3499,7 @@ export class Splatter extends THREE.EventDispatcher{
         } */  
         } */  
         if(this.renderDepth_){
         if(this.renderDepth_){
             I.disable(I.DEPTH_TEST), //disable  
             I.disable(I.DEPTH_TEST), //disable  
-            I.depthMask(true)    //失败了,无法遮住其他mesh
+            I.depthMask(true)    //失败了,无法遮住其他mesh  
         }else{
         }else{
             I.enable(I.DEPTH_TEST),   
             I.enable(I.DEPTH_TEST),   
             I.depthMask(false)   //是否depthWrite
             I.depthMask(false)   //是否depthWrite
@@ -3683,8 +3692,7 @@ export class Splatter extends THREE.EventDispatcher{
         viewer.addTimeMark('hitTest', 'start')
         viewer.addTimeMark('hitTest', 'start')
         console.log('hitTest', Date.now() - lastHit),
         console.log('hitTest', Date.now() - lastHit),
         lastHit = Date.now()
         lastHit = Date.now()
-        
-        if (!Array.isArray(mouse))
+         
         if (!Array.isArray(mouse))
         if (!Array.isArray(mouse))
             throw new Error("hitTest: points must be an array like [x, y], or an array of arrays [[x1, y1], ..., [xn, yn]].");
             throw new Error("hitTest: points must be an array like [x, y], or an array of arrays [[x1, y1], ..., [xn, yn]].");
         const B = Array.isArray(mouse[0]) ? mouse : [mouse];
         const B = Array.isArray(mouse[0]) ? mouse : [mouse];

+ 22 - 14
src/custom/viewer/ViewerNew.js

@@ -1,6 +1,6 @@
  
  
 
 
-//import * as GaussianSplats3D from "../../../libs/gaussian/gaussian-splats-3d.module.js";
+ import * as GaussianSplats3D from "../../../libs/gaussian/gaussian-splats-3d.module.js";
 
 
 import {Loader3DTiles} from '../../../libs/three.js/3dtiles/three-loader-3dtiles.esm.js'; 
 import {Loader3DTiles} from '../../../libs/three.js/3dtiles/three-loader-3dtiles.esm.js'; 
 import {OBJLoader} from "../../../libs/three.js/loaders/OBJLoader.js";
 import {OBJLoader} from "../../../libs/three.js/loaders/OBJLoader.js";
@@ -366,6 +366,7 @@ export class Viewer extends ViewerBase{
                                 let info = this.mainViewport.view.getJson()
                                 let info = this.mainViewport.view.getJson()
                                 if(this.controls instanceof CharacterControl){
                                 if(this.controls instanceof CharacterControl){
                                     info.modelPos = this.controls.modelPos.toObject()
                                     info.modelPos = this.controls.modelPos.toObject()
+                                    info.modelQua = this.controls.modelQua.toObject()
                                 }
                                 }
                                 info = JSON.stringify( info );
                                 info = JSON.stringify( info );
                                 console.log(`Copy view params: ${info}`),
                                 console.log(`Copy view params: ${info}`),
@@ -373,19 +374,8 @@ export class Viewer extends ViewerBase{
                                   
                                   
                             }else if(e.event.key.toLowerCase() == 'v'){
                             }else if(e.event.key.toLowerCase() == 'v'){
                                 navigator.clipboard.readText().then(A=>{
                                 navigator.clipboard.readText().then(A=>{
-                                    let info = JSON.parse(A);
-                                    if(info.yaw != void 0){
-                                        this.mainViewport.view.applyJson(info) 
-                                        if(this.controls instanceof CharacterControl){
-                                            if(info.modelPos){
-                                                this.controls.modelPos.copy(info.modelPos)
-                                            }else{
-                                                this.controls.modelPos.copy(this.mainViewport.view.position)
-                                            }
-                                        }
-                                        
-                                        console.log(`pasteViewParams ${A}`) 
-                                    }
+                                    this.applyViewJson( JSON.parse(A)) 
+                                    console.log(`pasteViewParams ${A}`) 
                                 })
                                 })
                             }  
                             }  
                         } 
                         } 
@@ -6808,6 +6798,24 @@ export class Viewer extends ViewerBase{
         this.switchHotType()
         this.switchHotType()
     }
     }
      
      
+     
+    applyViewJson(info) { 
+        if(info.yaw != void 0){
+            this.mainViewport.view.applyJson(info) 
+            if(this.controls instanceof CharacterControl){
+                if(info.modelPos){
+                    this.controls.modelPos.copy(info.modelPos)
+                    this.controls.switchEdgeState('canWalkOrFall')
+                }else{
+                    this.controls.modelPos.copy(this.mainViewport.view.position)
+                }
+                if(info.modelQua){
+                    this.controls.modelQua.copy(info.modelQua)
+                }
+            } 
+            
+        }
+    } 
     
     
 };
 };
 
 

+ 19 - 3
src/custom/viewer/Viewport.js

@@ -25,8 +25,16 @@ export default class Viewport extends THREE.EventDispatcher{
         this.extraEnableLayers = prop.extraEnableLayers || [];//额外可展示的层
         this.extraEnableLayers = prop.extraEnableLayers || [];//额外可展示的层
         this.cameraLayers = prop.cameraLayers 
         this.cameraLayers = prop.cameraLayers 
         this.pixelRatio = prop.pixelRatio  //如果规定pixelRatio的话要传,这样就覆盖devicePicelRatio, 如magnifier
         this.pixelRatio = prop.pixelRatio  //如果规定pixelRatio的话要传,这样就覆盖devicePicelRatio, 如magnifier
+        this.needRender_ = false
     }
     }
      
      
+    set needRender(s){
+        this.needRender_ = s
+    } 
+    
+    get needRender(){
+        return this.needRender_
+    } 
     
     
     clone(){ 
     clone(){ 
         return Common.CloneClassObject(this)
         return Common.CloneClassObject(this)
@@ -55,14 +63,20 @@ export default class Viewport extends THREE.EventDispatcher{
     
     
 	cameraChanged() {
 	cameraChanged() {
 		var copy = ()=>{
 		var copy = ()=>{
-            this.previousState = {
+            /* this.previousState = {
                 projectionMatrix: this.camera.projectionMatrix.clone(),//worldMatrix在this.control时归零了所以不用了吧,用position和qua也一样
                 projectionMatrix: this.camera.projectionMatrix.clone(),//worldMatrix在this.control时归零了所以不用了吧,用position和qua也一样
                 position: this.camera.position.clone(),
                 position: this.camera.position.clone(),
                 quaternion: this.camera.quaternion.clone(),
                 quaternion: this.camera.quaternion.clone(),
                 active:this.active,
                 active:this.active,
                 resolution:this.resolution.clone(),
                 resolution:this.resolution.clone(),
                 resolution2:this.resolution2.clone(), //有时clientWidth没变但是ratio缩放了
                 resolution2:this.resolution2.clone(), //有时clientWidth没变但是ratio缩放了
-            }; 
+            };  */ 
+            projectionChanged && (this.previousState.projectionMatrix = this.camera.projectionMatrix.clone())
+            positionChanged && (this.previousState.position = this.camera.position.clone())
+            quaternionChanged && (this.previousState.quaternion = this.camera.quaternion.clone())
+            resolutionChanged && (this.previousState.resolution = this.resolution.clone(), this.previousState.resolution2 = this.resolution2.clone())
+            this.previousState.active = this.active
+            
         }
         }
         let projectionChanged = true, positionChanged = true, quaternionChanged = true, activeChanged = true, resolutionChanged = true
         let projectionChanged = true, positionChanged = true, quaternionChanged = true, activeChanged = true, resolutionChanged = true
         let getChanged = ()=>{
         let getChanged = ()=>{
@@ -74,9 +88,11 @@ export default class Viewport extends THREE.EventDispatcher{
         if (this.previousState){ 
         if (this.previousState){ 
             projectionChanged = !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix) 
             projectionChanged = !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix) 
             positionChanged = !this.camera.position.equals(this.previousState.position)  
             positionChanged = !this.camera.position.equals(this.previousState.position)  
-            quaternionChanged = !this.camera.quaternion.equals(this.previousState.quaternion) 
+            quaternionChanged = !Potree.math.closeTo(this.camera.quaternion,this.previousState.quaternion)   //!this.camera.quaternion.equals(this.previousState.quaternion)//改为close是因为controls加了缓动会一直变 
             activeChanged = this.active != this.previousState.active
             activeChanged = this.active != this.previousState.active
             resolutionChanged = !this.resolution.equals(this.previousState.resolution) || !this.resolution2.equals(this.previousState.resolution2)
             resolutionChanged = !this.resolution.equals(this.previousState.resolution) || !this.resolution2.equals(this.previousState.resolution2)
+        }else{
+            this.previousState = {}
         }   
         }   
         copy() 
         copy() 
         
         

+ 65 - 30
src/navigation/CharacterControl.js

@@ -26,7 +26,7 @@ export class CharacterControl extends THREE.EventDispatcher{
     constructor(viewer, url){
     constructor(viewer, url){
         super()
         super()
         this.model = null
         this.model = null
-        this.viewer = viewer
+        this.viewer = viewer 
         
         
         this.url = Potree.resourcePath + '/models/glb/animation/'+modelInfo[modelIndex].name+'.glb'//  soldier    why qiyu only one action?
         this.url = Potree.resourcePath + '/models/glb/animation/'+modelInfo[modelIndex].name+'.glb'//  soldier    why qiyu only one action?
         
         
@@ -37,7 +37,7 @@ export class CharacterControl extends THREE.EventDispatcher{
         this.fallMaxHeight = this.getMaxFall() 
         this.fallMaxHeight = this.getMaxFall() 
         this.modelPos = new THREE.Vector3
         this.modelPos = new THREE.Vector3
         this.modelQua = new THREE.Quaternion
         this.modelQua = new THREE.Quaternion
-        
+        this.onGround2 = true
         this.keys = {
         this.keys = {
             FORWARD: ['W'.charCodeAt(0), 38],
             FORWARD: ['W'.charCodeAt(0), 38],
             BACKWARD: ['S'.charCodeAt(0), 40],
             BACKWARD: ['S'.charCodeAt(0), 40],
@@ -50,7 +50,7 @@ export class CharacterControl extends THREE.EventDispatcher{
         }
         }
         
         
         this.boundingBox = new THREE.Box3()
         this.boundingBox = new THREE.Box3()
-        
+        this.switchEdgeState('canWalkOrFall')
         
         
         
         
         this.keyDir = new THREE.Vector3()
         this.keyDir = new THREE.Vector3()
@@ -92,6 +92,9 @@ export class CharacterControl extends THREE.EventDispatcher{
 	 
 	 
     }
     }
     
     
+    switchEdgeState(state){
+        this.edgeState = state
+    }
     
     
     getMaxFall(){//要保证降落到地面时最后一帧降落高度不能大于collRadius否则穿模
     getMaxFall(){//要保证降落到地面时最后一帧降落高度不能大于collRadius否则穿模
         let c = miniDelta * miniDelta * this.gravity
         let c = miniDelta * miniDelta * this.gravity
@@ -169,12 +172,17 @@ export class CharacterControl extends THREE.EventDispatcher{
             
             
             let view = this.viewer.mainViewport.view
             let view = this.viewer.mainViewport.view
             this.modelPos.copy(view.position)
             this.modelPos.copy(view.position)
+            //let {height,willFall} = this.edgeDetect()
+            
+            this.modelPos.z -= this.targetShiftUp // + this.collRadius-0.05 
             
             
             let dir = view.direction
             let dir = view.direction
             const angle = new THREE.Vector2().copy(dir).angle() //- Math.PI/2  // unwrapRad( Math.atan2( ease.x, ease.z ) + azimuth );
             const angle = new THREE.Vector2().copy(dir).angle() //- Math.PI/2  // unwrapRad( Math.atan2( ease.x, ease.z ) + azimuth );
             qua_.setFromAxisAngle( up, angle ); 
             qua_.setFromAxisAngle( up, angle ); 
             this.modelQua.copy(qua_)
             this.modelQua.copy(qua_)
             this.updatetModelPose() 
             this.updatetModelPose() 
+            
+            this.switchEdgeState('canWalkOrFall')
         }
         }
         
         
         this.model && Potree.Utils.updateVisible(this.model, 'enable', state)
         this.model && Potree.Utils.updateVisible(this.model, 'enable', state)
@@ -193,7 +201,7 @@ export class CharacterControl extends THREE.EventDispatcher{
         let moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
         let moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
         let fast = this.keys.SHIFT.some(e => ih.pressedKeys[e]); 
         let fast = this.keys.SHIFT.some(e => ih.pressedKeys[e]); 
         let ignoreColl = this.keys.X.some(e => ih.pressedKeys[e]); 
         let ignoreColl = this.keys.X.some(e => ih.pressedKeys[e]); 
-        
+       
         
         
         let deltaRatio = delta / 16 * 1000 //如果帧率为60,该值为1
         let deltaRatio = delta / 16 * 1000 //如果帧率为60,该值为1
         let moveSpeed = 0.05 //* deltaRatio 
         let moveSpeed = 0.05 //* deltaRatio 
@@ -307,32 +315,48 @@ export class CharacterControl extends THREE.EventDispatcher{
             this.onGround && this.velocity.set(0, 0, 0)
             this.onGround && this.velocity.set(0, 0, 0)
             this.velocity.z += miniDelta * this.gravity
             this.velocity.z += miniDelta * this.gravity
             let fall = this.velocity.clone().multiplyScalar(miniDelta)  
             let fall = this.velocity.clone().multiplyScalar(miniDelta)  
+            fall.z = Math.max(-this.collRadius, fall.z)//安全起见,限制最大降落速度
             moveWorld.add(fall)  
             moveWorld.add(fall)  
-        
-            if(this.edgeDetect(moveWorld)){
+            
+            let fall_ = this.edgeDetect(moveWorld);
+            /* if(!this.onGround){
+                console.log('this.onGround == false', fall_.willFall)
+            } */
+          
+            //onGround太难弄了。要么在边缘时不让走,要么可直接走出边缘。前者缺点是会卡在半空。
+            //只好加个参数edgeState,限时开启后者的模式,直到再次onGround
+             
+            if(this.edgeState == 'canWalkOrFall' && !this.onGround && fall_.height == Infinity){//刚开始很可能在空中,不做判断直接降落吧? 但万一下面没地儿……怎么办
+                //在空中且下面没地 ,直接行走. 但可惜从边缘走出去也会执行这段
+                this.velocity.set(0, 0, 0)
+                moveWorld.setZ(0) 
+                this.stuckDur = 0
+            }else if((this.edgeState != 'canWalkOrFall' || this.onGround) && fall_.willFall){//ps:若在空中的话直接落地或继续走,不进入该段落
                 if(moveDis > 0){
                 if(moveDis > 0){
                      this.stuckDur += delta
                      this.stuckDur += delta
                 }
                 }
-                if(this.stuckDur > 3){//可能朝任何方向都走不动,超过一定时间解除重力
-                    moveWorld.setZ(0)
-                    console.log('你好像被卡在空中了?解除重力')
+                if(this.stuckDur > 3){//可能朝任何方向都走不动 
+                    //moveWorld.setZ(0)
+                    this.switchEdgeState('canWalkOrFall')
+                    console.log('你好像被卡在空中了?切换到canWalkOrFall')
                 }else{
                 }else{
-                    moveWorld.set(0, 0, 0)
+                    moveWorld.set(0, 0, 0) //不允许行走
+                    this.velocity.set(0, 0, 0)
                 }
                 }
-                this.velocity.set(0, 0, 0)
+                //this.velocity.set(0, 0, 0)
                 
                 
             }else{
             }else{
+                /* fall_.willFall */this.onGround && this.switchEdgeState('normal')
                 this.stuckDur = 0
                 this.stuckDur = 0
             } 
             } 
         } 
         } 
         this.modelPos.add(moveWorld)
         this.modelPos.add(moveWorld)
         
         
-        if(useCollider){ 
         
         
-            let moveD = moveWorld.length()
-            //if(moveD > 0.000001)console.log('moveD', moveD)
+         
+        if(useCollider){ 
         
         
-            
+            let moveD = moveWorld.length() 
             let collCount = window.mulColl ? THREE.Math.clamp(Math.ceil(moveDis / this.collRadius * 12), 1, 6) : 1
             let collCount = window.mulColl ? THREE.Math.clamp(Math.ceil(moveDis / this.collRadius * 12), 1, 6) : 1
              
              
             this.modelPos.sub(moveWorld)
             this.modelPos.sub(moveWorld)
@@ -344,9 +368,7 @@ export class CharacterControl extends THREE.EventDispatcher{
             
             
             for(let i=0;i<collCount;i++){
             for(let i=0;i<collCount;i++){
                 this.modelPos.add(move_)
                 this.modelPos.add(move_)
-                
-                
-                
+                 
                 let start = new THREE.Vector3().addVectors(this.modelPos, new THREE.Vector3(0,0, this.collRadius-0.05)) 
                 let start = new THREE.Vector3().addVectors(this.modelPos, new THREE.Vector3(0,0, this.collRadius-0.05)) 
                 let end = start.clone()
                 let end = start.clone()
                     end.z += this.targetShiftUp
                     end.z += this.targetShiftUp
@@ -354,24 +376,29 @@ export class CharacterControl extends THREE.EventDispatcher{
                 if(coll?.hit){  
                 if(coll?.hit){  
                     this.modelPos.add(coll.delta);
                     this.modelPos.add(coll.delta);
                     
                     
-                    this.onGround = coll.delta.z > Math.abs(miniDelta * this.velocity.z * 0.25 / collCount)  
+                    this.onGround = coll.delta.z > 0//Math.abs(miniDelta * this.velocity.z * 0.25 / collCount)  
                     if(!this.onGround){
                     if(!this.onGround){
+                        console.log('this.onGround', this.onGround)
                         //coll.delta.normalize()
                         //coll.delta.normalize()
                         //this.velocity.addScaledVector(coll.delta, -coll.delta.dot(this.velocity)) ;
                         //this.velocity.addScaledVector(coll.delta, -coll.delta.dot(this.velocity)) ;
                     } 
                     } 
                      
                      
                 }else{
                 }else{
                     this.onGround = false
                     this.onGround = false
-                } 
-         
-            } 
-            
-            
+                }  
+            }  
         }
         }
         
         
         
         
-       /*  let d = this.modelPos.clone().sub(oldPos)
-        let d1 = d.length()
+        
+        
+        /*let d = this.modelPos.clone().sub(oldPos)
+        console.log('d',d)
+         this.onGround2 = d.z > -0.01 
+        if(!this.onGround2){
+            console.log('this.onGround2 == false')
+        } */
+         /* let d1 = d.length()
         d1>0.01 && console.log(d1)   */
         d1>0.01 && console.log(d1)   */
 
 
         
         
@@ -414,15 +441,23 @@ export class CharacterControl extends THREE.EventDispatcher{
     }
     }
     
     
     
     
-    edgeDetect(moveDelta){ //_checkNoGoZone
+    edgeDetect(moveDelta=new THREE.Vector3){ //_checkNoGoZone
         let endPos = vec3.addVectors(moveDelta, this.modelPos)  
         let endPos = vec3.addVectors(moveDelta, this.modelPos)  
         endPos.z += 1 
         endPos.z += 1 
         raycaster.set(endPos,  down) 
         raycaster.set(endPos,  down) 
-        let intersect = viewer.collider.pickWithRay(raycaster, this.fallMaxHeight)//设置太高的话,掉到地面时速度太大会穿过去
+        /* let intersect = viewer.collider.pickWithRay(raycaster, this.fallMaxHeight)//设置太高的话,掉到地面时速度太大会穿过去
         let willFall = !intersect
         let willFall = !intersect
-        if(willFall)console.log('willFall')
-        return willFall
+        if(willFall)console.log('willFall') */
+        
+        let intersect = viewer.collider.pickWithRay(raycaster, Infinity)
+        let fall 
+        if(intersect){
+            fall = {willFall: intersect.distance > this.fallMaxHeight ,   height: intersect.distance}
+        }else fall =  {willFall: true ,   height: Infinity}
+         
+        return fall
     }
     }
+     
     
     
     /* updateCollRadius(moveDis, lastHeightDelta){//上坡且速度快时增大,主要防止楼梯抖
     /* updateCollRadius(moveDis, lastHeightDelta){//上坡且速度快时增大,主要防止楼梯抖
         this.collRadius
         this.collRadius

+ 2 - 2
src/navigation/FirstPersonControlsNew.js

@@ -939,10 +939,10 @@ export class FirstPersonControls extends THREE.EventDispatcher {
         }  
         }  
         
         
         
         
-        let ignoreColl = this.keys.X.some(e => ih.pressedKeys[e]);
+        let ignoreColl = this.keys.X.some(e => ih.pressedKeys[e]) || window.stopColl || !viewer.collider;
         let moveDelta = new THREE.Vector3().subVectors(view.position, lastPos)
         let moveDelta = new THREE.Vector3().subVectors(view.position, lastPos)
         if(!ignoreColl && moveDelta.lengthSq() > 0 ){
         if(!ignoreColl && moveDelta.lengthSq() > 0 ){
-            let coll = viewer.collider?.moveDeltaCorrecting({start: view.position,  radius: 0.3 } )  
+            let coll = viewer.collider.moveDeltaCorrecting({start: view.position,  radius: 0.3 } )  
             if(coll?.hit){ 
             if(coll?.hit){ 
                 let collDelta = coll.delta
                 let collDelta = coll.delta
                 view.translateWorld( collDelta.x, collDelta.y, collDelta.z   );
                 view.translateWorld( collDelta.x, collDelta.y, collDelta.z   );

+ 3 - 3
src/viewer/ExtendView.js

@@ -487,7 +487,7 @@ class ExtendView extends View {
     
     
     getJson(){
     getJson(){
         let json = {
         let json = {
-            yaw: this.yaw,  pitch: this.pitch,  position: this.position
+            yaw: this.yaw,  pitch: this.pitch,  position: this.position, radius: this.radius
         }
         }
         return json  //JSON.stringify(json)
         return json  //JSON.stringify(json)
     } 
     } 
@@ -495,9 +495,9 @@ class ExtendView extends View {
     applyJson(json){
     applyJson(json){
         typeof json == 'string' &&  (json = JSON.parse(json))
         typeof json == 'string' &&  (json = JSON.parse(json))
         this.position.copy(json.position)
         this.position.copy(json.position)
-        this.yaw = json.yaw,  this.pitch = json.pitch
+        this.yaw = json.yaw,  this.pitch = json.pitch, this.radius = json.radius
     }
     }
-    
+     
 
 
 };
 };