1
- import * as THREE from 'three'
2
- import { useRef } from 'react'
3
- import { useFrame } from '@react-three/fiber'
4
1
import { useKeyboardControls } from '@react-three/drei'
5
- import { CapsuleCollider , interactionGroups , RapierRigidBody , RigidBody , useRapier } from '@react-three/rapier'
2
+ import { useFrame } from '@react-three/fiber'
3
+ import {
4
+ CapsuleCollider ,
5
+ interactionGroups ,
6
+ RapierRigidBody ,
7
+ RigidBody ,
8
+ useRapier ,
9
+ Vector3Object ,
10
+ } from '@react-three/rapier'
6
11
import { IfInSessionMode } from '@react-three/xr'
12
+ import { useRef } from 'react'
13
+ import * as THREE from 'three'
7
14
8
15
import { Axe } from './Axe.jsx'
9
16
import { VRPlayerControl } from './VRPlayerControl.jsx'
@@ -15,10 +22,13 @@ const sideVector = new THREE.Vector3()
15
22
const rotation = new THREE . Vector3 ( )
16
23
17
24
const vectorHelper = new THREE . Vector3 ( )
25
+ const quaternionHelper = new THREE . Quaternion ( )
26
+ const quaternionHelper2 = new THREE . Quaternion ( )
27
+ const eulerHelper = new THREE . Euler ( )
18
28
19
29
export function Player ( { lerp = THREE . MathUtils . lerp } ) {
20
30
const axe = useRef < THREE . Group > ( null )
21
- const ref = useRef < RapierRigidBody > ( null )
31
+ const rigidBodyRef = useRef < RapierRigidBody > ( null )
22
32
const { rapier, world } = useRapier ( )
23
33
const [ , getKeys ] = useKeyboardControls ( )
24
34
@@ -27,32 +37,54 @@ export function Player({ lerp = THREE.MathUtils.lerp }) {
27
37
backward,
28
38
left,
29
39
right,
30
- rotation ,
40
+ rotationVelocity ,
31
41
velocity,
42
+ newVelocity,
32
43
} : {
33
44
forward : boolean
34
45
backward : boolean
35
46
left : boolean
36
47
right : boolean
37
- rotation : THREE . Euler
38
- velocity ?: any
48
+ rotationVelocity : number
49
+ velocity ?: Vector3Object
50
+ newVelocity ?: THREE . Vector3
39
51
} ) => {
52
+ if ( rigidBodyRef . current == null ) {
53
+ return
54
+ }
40
55
if ( ! velocity ) {
41
- velocity = ref . current ?. linvel ( )
56
+ velocity = rigidBodyRef . current ?. linvel ( )
57
+ }
58
+
59
+ //apply rotation
60
+ const { x, y, z, w } = rigidBodyRef . current . rotation ( )
61
+ quaternionHelper . set ( x , y , z , w )
62
+ quaternionHelper . multiply ( quaternionHelper2 . setFromEuler ( eulerHelper . set ( 0 , rotationVelocity , 0 , 'YXZ' ) ) )
63
+ rigidBodyRef . current ?. setRotation ( quaternionHelper , true )
64
+
65
+ if ( newVelocity ) {
66
+ // If we have a new velocity, we're in VR mode
67
+ rigidBodyRef . current ?. setLinvel ( { x : newVelocity . x , y : velocity ?. y ?? 0 , z : newVelocity . z } , true )
68
+ return
42
69
}
43
70
44
71
frontVector . set ( 0 , 0 , ( backward ? 1 : 0 ) - ( forward ? 1 : 0 ) )
45
72
sideVector . set ( ( left ? 1 : 0 ) - ( right ? 1 : 0 ) , 0 , 0 )
46
- direction . subVectors ( frontVector , sideVector ) . normalize ( ) . multiplyScalar ( SPEED ) . applyEuler ( rotation )
47
- ref . current ?. setLinvel ( { x : direction . x , y : velocity . y , z : direction . z } , true )
73
+ direction
74
+ . subVectors ( frontVector , sideVector )
75
+ . applyQuaternion ( quaternionHelper )
76
+ . setComponent ( 1 , 0 )
77
+ . normalize ( )
78
+ . multiplyScalar ( SPEED )
79
+ rigidBodyRef . current ?. setLinvel ( { x : direction . x , y : velocity ?. y ?? 0 , z : direction . z } , true )
48
80
}
49
81
50
82
const playerJump = ( ) => {
51
- if ( ref . current == null ) {
83
+ if ( rigidBodyRef . current == null ) {
52
84
return
53
85
}
54
86
const ray = world . castRay (
55
- new rapier . Ray ( ref . current . translation ( ) , { x : 0 , y : - 1 , z : 0 } ) ,
87
+ new rapier . Ray ( rigidBodyRef . current . translation ( ) , { x : 0 , y : - 1 , z : 0 } ) ,
56
88
Infinity ,
57
89
false ,
58
90
undefined ,
@@ -61,21 +93,21 @@ export function Player({ lerp = THREE.MathUtils.lerp }) {
61
93
const grounded = ray != null && Math . abs ( ray . timeOfImpact ) <= 1.25
62
94
63
95
if ( grounded ) {
64
- ref . current . setLinvel ( { x : 0 , y : 7.5 , z : 0 } , true )
96
+ rigidBodyRef . current . setLinvel ( { x : 0 , y : 7.5 , z : 0 } , true )
65
97
}
66
98
}
67
99
68
100
useFrame ( ( state ) => {
69
- if ( ref . current == null ) {
101
+ if ( rigidBodyRef . current == null ) {
70
102
return
71
103
}
72
104
const { forward, backward, left, right, jump } = getKeys ( )
73
- const velocity = ref . current . linvel ( )
105
+ const velocity = rigidBodyRef . current . linvel ( )
74
106
75
107
vectorHelper . set ( velocity . x , velocity . y , velocity . z )
76
108
77
109
// update camera
78
- const { x, y, z } = ref . current . translation ( )
110
+ const { x, y, z } = rigidBodyRef . current . translation ( )
79
111
state . camera . position . set ( x , y , z )
80
112
81
113
// update axe
@@ -90,13 +122,13 @@ export function Player({ lerp = THREE.MathUtils.lerp }) {
90
122
}
91
123
92
124
// movement
93
- if ( ref . current ) {
125
+ if ( rigidBodyRef . current ) {
94
126
playerMove ( {
95
127
forward,
96
128
backward,
97
129
left,
98
130
right,
99
- rotation : state . camera . rotation ,
131
+ rotationVelocity : 0 ,
100
132
velocity,
101
133
} )
102
134
@@ -109,7 +141,7 @@ export function Player({ lerp = THREE.MathUtils.lerp }) {
109
141
return (
110
142
< >
111
143
< RigidBody
112
- ref = { ref }
144
+ ref = { rigidBodyRef }
113
145
colliders = { false }
114
146
mass = { 1 }
115
147
type = "dynamic"
0 commit comments