|
@@ -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
|