33
44import { Euler , EventDispatcher , MathUtils , Quaternion , Vector3 } from "three" ;
55
6+ const isIOS = navigator . userAgent . match ( / i P h o n e | i P a d | i P o d / i) ;
7+
68const _zee = new Vector3 ( 0 , 0 , 1 ) ;
79const _euler = new Euler ( ) ;
810const _q0 = new Quaternion ( ) ;
@@ -30,7 +32,7 @@ class DeviceOrientationControls extends EventDispatcher {
3032
3133 this . enabled = true ;
3234
33- this . deviceOrientation = { } ;
35+ this . deviceOrientation = null ;
3436 this . screenOrientation = 0 ;
3537
3638 this . alphaOffset = 0 ; // radians
@@ -44,8 +46,25 @@ class DeviceOrientationControls extends EventDispatcher {
4446
4547 this . smoothingFactor = 1 ;
4648
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+ ) ;
4968 } ;
5069
5170 const onScreenOrientationChangeEvent = function ( ) {
@@ -123,9 +142,10 @@ class DeviceOrientationControls extends EventDispatcher {
123142 ) ;
124143
125144 scope . enabled = false ;
145+ scope . deviceOrientation = null ;
126146 } ;
127147
128- this . update = function ( ) {
148+ this . update = function ( { theta = 0 } = { theta : 0 } ) {
129149 if ( scope . enabled === false ) return ;
130150
131151 const device = scope . deviceOrientation ;
@@ -143,45 +163,63 @@ class DeviceOrientationControls extends EventDispatcher {
143163 ? MathUtils . degToRad ( scope . screenOrientation )
144164 : 0 ; // O
145165
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 = {
150208 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+ } ;
168212 }
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+ ) ;
175220 }
176221
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
185223 if ( 8 * ( 1 - lastQuaternion . dot ( scope . object . quaternion ) ) > EPS ) {
186224 lastQuaternion . copy ( scope . object . quaternion ) ;
187225 scope . dispatchEvent ( _changeEvent ) ;
0 commit comments