3
3
4
4
import { Euler , EventDispatcher , MathUtils , Quaternion , Vector3 } from "three" ;
5
5
6
+ const isIOS = navigator . userAgent . match ( / i P h o n e | i P a d | i P o d / i) ;
7
+
6
8
const _zee = new Vector3 ( 0 , 0 , 1 ) ;
7
9
const _euler = new Euler ( ) ;
8
10
const _q0 = new Quaternion ( ) ;
@@ -30,7 +32,7 @@ class DeviceOrientationControls extends EventDispatcher {
30
32
31
33
this . enabled = true ;
32
34
33
- this . deviceOrientation = { } ;
35
+ this . deviceOrientation = null ;
34
36
this . screenOrientation = 0 ;
35
37
36
38
this . alphaOffset = 0 ; // radians
@@ -44,8 +46,25 @@ class DeviceOrientationControls extends EventDispatcher {
44
46
45
47
this . smoothingFactor = 1 ;
46
48
47
- const onDeviceOrientationChangeEvent = function ( event ) {
48
- scope . deviceOrientation = event ;
49
+ const onDeviceOrientationChangeEvent = function ( {
50
+ alpha,
51
+ beta,
52
+ gamma,
53
+ webkitCompassHeading,
54
+ } ) {
55
+ if ( isIOS ) {
56
+ const ccwNorthHeading = 360 - webkitCompassHeading ;
57
+ scope . alphaOffset = MathUtils . degToRad ( ccwNorthHeading - alpha ) ;
58
+ scope . deviceOrientation = { alpha, beta, gamma, webkitCompassHeading } ;
59
+ } else {
60
+ if ( alpha < 0 ) alpha += 360 ;
61
+ scope . deviceOrientation = { alpha, beta, gamma } ;
62
+ }
63
+ window . dispatchEvent (
64
+ new CustomEvent ( "camera-rotation-change" , {
65
+ detail : { cameraRotation : object . rotation } ,
66
+ } ) ,
67
+ ) ;
49
68
} ;
50
69
51
70
const onScreenOrientationChangeEvent = function ( ) {
@@ -123,9 +142,10 @@ class DeviceOrientationControls extends EventDispatcher {
123
142
) ;
124
143
125
144
scope . enabled = false ;
145
+ scope . deviceOrientation = null ;
126
146
} ;
127
147
128
- this . update = function ( ) {
148
+ this . update = function ( { theta = 0 } = { theta : 0 } ) {
129
149
if ( scope . enabled === false ) return ;
130
150
131
151
const device = scope . deviceOrientation ;
@@ -143,45 +163,63 @@ class DeviceOrientationControls extends EventDispatcher {
143
163
? MathUtils . degToRad ( scope . screenOrientation )
144
164
: 0 ; // O
145
165
146
- if ( this . smoothingFactor < 1 ) {
147
- if ( this . lastOrientation ) {
148
- const k = this . smoothingFactor ;
149
- alpha = this . _getSmoothedAngle (
166
+ if ( isIOS ) {
167
+ const currentQuaternion = new THREE . Quaternion ( ) ;
168
+ setObjectQuaternion ( currentQuaternion , alpha , beta , gamma , orient ) ;
169
+ // Extract the Euler angles from the quaternion and add the heading angle to the Y-axis rotation of the Euler angles
170
+ // (If we replace only the alpha value of the quaternion without using Euler angles, the camera will rotate unexpectedly. This is because a quaternion does not represent rotation values individually but rather through a combination of rotation axes and weights.)
171
+ const currentEuler = new THREE . Euler ( ) . setFromQuaternion (
172
+ currentQuaternion ,
173
+ "YXZ" ,
174
+ ) ;
175
+ console . log ( currentEuler . x , currentEuler . y , currentEuler . z ) ;
176
+ // Replace the current alpha value of the Euler angles and reset the quaternion
177
+ currentEuler . y = THREE . MathUtils . degToRad (
178
+ 360 - device . webkitCompassHeading ,
179
+ ) ;
180
+ currentQuaternion . setFromEuler ( currentEuler ) ;
181
+ scope . object . quaternion . copy ( currentQuaternion ) ;
182
+ } else {
183
+ if ( this . smoothingFactor < 1 ) {
184
+ if ( this . lastOrientation ) {
185
+ const k = this . smoothingFactor ;
186
+ alpha = this . _getSmoothedAngle (
187
+ alpha ,
188
+ this . lastOrientation . alpha ,
189
+ k ,
190
+ ) ;
191
+ beta = this . _getSmoothedAngle (
192
+ beta + Math . PI ,
193
+ this . lastOrientation . beta ,
194
+ k ,
195
+ ) ;
196
+ gamma = this . _getSmoothedAngle (
197
+ gamma + this . HALF_PI ,
198
+ this . lastOrientation . gamma ,
199
+ k ,
200
+ Math . PI ,
201
+ ) ;
202
+ } else {
203
+ beta += Math . PI ;
204
+ gamma += this . HALF_PI ;
205
+ }
206
+
207
+ this . lastOrientation = {
150
208
alpha,
151
- this . lastOrientation . alpha ,
152
- k ,
153
- ) ;
154
- beta = this . _getSmoothedAngle (
155
- beta + Math . PI ,
156
- this . lastOrientation . beta ,
157
- k ,
158
- ) ;
159
- gamma = this . _getSmoothedAngle (
160
- gamma + this . HALF_PI ,
161
- this . lastOrientation . gamma ,
162
- k ,
163
- Math . PI ,
164
- ) ;
165
- } else {
166
- beta += Math . PI ;
167
- gamma += this . HALF_PI ;
209
+ beta,
210
+ gamma,
211
+ } ;
168
212
}
169
-
170
- this . lastOrientation = {
171
- alpha : alpha ,
172
- beta : beta ,
173
- gamma : gamma ,
174
- } ;
213
+ setObjectQuaternion (
214
+ scope . object . quaternion ,
215
+ alpha + theta ,
216
+ this . smoothingFactor < 1 ? beta - Math . PI : beta ,
217
+ this . smoothingFactor < 1 ? gamma - this . HALF_PI : gamma ,
218
+ orient ,
219
+ ) ;
175
220
}
176
221
177
- setObjectQuaternion (
178
- scope . object . quaternion ,
179
- alpha ,
180
- this . smoothingFactor < 1 ? beta - Math . PI : beta ,
181
- this . smoothingFactor < 1 ? gamma - this . HALF_PI : gamma ,
182
- orient ,
183
- ) ;
184
-
222
+ // NB - NOT present in IOS fixed version
185
223
if ( 8 * ( 1 - lastQuaternion . dot ( scope . object . quaternion ) ) > EPS ) {
186
224
lastQuaternion . copy ( scope . object . quaternion ) ;
187
225
scope . dispatchEvent ( _changeEvent ) ;
0 commit comments