Skip to content

Commit a10ab8e

Browse files
authored
Merge pull request #7 from ma2yama/marmot_iosfix-manual
ios fix (AR-js-org#466) applied manually to existing DeviceOrientationControls AR-js-org#657
2 parents cc67928 + 9a20724 commit a10ab8e

File tree

9 files changed

+119
-47
lines changed

9 files changed

+119
-47
lines changed

aframe/build/aframe-ar-new-location-only.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aframe/build/aframe-ar-new-location-only.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

aframe/build/aframe-ar-nft.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aframe/build/aframe-ar-nft.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

aframe/build/aframe-ar.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aframe/build/aframe-ar.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

three.js/build/ar-threex-location-only.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

three.js/build/ar-threex-location-only.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

three.js/src/location-based/js/device-orientation-controls.js

Lines changed: 111 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
import { Euler, EventDispatcher, MathUtils, Quaternion, Vector3 } from "three";
55

6+
const isIOS =
7+
navigator.userAgent.match(/iPhone|iPad|iPod/i) ||
8+
(/Macintosh/i.test(navigator.userAgent) &&
9+
navigator.maxTouchPoints != null &&
10+
navigator.maxTouchPoints > 1); // for iPad Safari
11+
612
const _zee = new Vector3(0, 0, 1);
713
const _euler = new Euler();
814
const _q0 = new Quaternion();
@@ -11,6 +17,11 @@ const _q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); // - PI/2 aro
1117
const _changeEvent = { type: "change" };
1218

1319
class DeviceOrientationControls extends EventDispatcher {
20+
/**
21+
* Create an instance of DeviceOrientationControls.
22+
* @param {Object} object - the object to attach the controls to
23+
* (usually your Three.js camera)
24+
*/
1425
constructor(object) {
1526
super();
1627

@@ -30,10 +41,11 @@ class DeviceOrientationControls extends EventDispatcher {
3041

3142
this.enabled = true;
3243

33-
this.deviceOrientation = {};
44+
this.deviceOrientation = null;
3445
this.screenOrientation = 0;
3546

3647
this.alphaOffset = 0; // radians
48+
this.initialOffset = null; // used in fix provided in issue #466, iOS related
3749

3850
this.TWO_PI = 2 * Math.PI;
3951
this.HALF_PI = 0.5 * Math.PI;
@@ -44,8 +56,25 @@ class DeviceOrientationControls extends EventDispatcher {
4456

4557
this.smoothingFactor = 1;
4658

47-
const onDeviceOrientationChangeEvent = function (event) {
48-
scope.deviceOrientation = event;
59+
const onDeviceOrientationChangeEvent = function ({
60+
alpha,
61+
beta,
62+
gamma,
63+
webkitCompassHeading,
64+
}) {
65+
if (isIOS) {
66+
const ccwNorthHeading = 360 - webkitCompassHeading;
67+
scope.alphaOffset = MathUtils.degToRad(ccwNorthHeading - alpha);
68+
scope.deviceOrientation = { alpha, beta, gamma, webkitCompassHeading };
69+
} else {
70+
if (alpha < 0) alpha += 360;
71+
scope.deviceOrientation = { alpha, beta, gamma };
72+
}
73+
window.dispatchEvent(
74+
new CustomEvent("camera-rotation-change", {
75+
detail: { cameraRotation: object.rotation },
76+
}),
77+
);
4978
};
5079

5180
const onScreenOrientationChangeEvent = function () {
@@ -70,6 +99,10 @@ class DeviceOrientationControls extends EventDispatcher {
7099
quaternion.multiply(_q0.setFromAxisAngle(_zee, -orient)); // adjust for screen orientation
71100
};
72101

102+
/**
103+
* Update the device orientation controls.
104+
* Should be called from your three.js rendering/animation function.
105+
*/
73106
this.connect = function () {
74107
onScreenOrientationChangeEvent(); // run once on load
75108

@@ -123,9 +156,11 @@ class DeviceOrientationControls extends EventDispatcher {
123156
);
124157

125158
scope.enabled = false;
159+
scope.initialOffset = false;
160+
scope.deviceOrientation = null;
126161
};
127162

128-
this.update = function () {
163+
this.update = function ({ theta = 0 } = { theta: 0 }) {
129164
if (scope.enabled === false) return;
130165

131166
const device = scope.deviceOrientation;
@@ -143,45 +178,63 @@ class DeviceOrientationControls extends EventDispatcher {
143178
? MathUtils.degToRad(scope.screenOrientation)
144179
: 0; // O
145180

146-
if (this.smoothingFactor < 1) {
147-
if (this.lastOrientation) {
148-
const k = this.smoothingFactor;
149-
alpha = this._getSmoothedAngle(
181+
if (isIOS) {
182+
const currentQuaternion = new Quaternion();
183+
setObjectQuaternion(currentQuaternion, alpha, beta, gamma, orient);
184+
// Extract the Euler angles from the quaternion and add the heading angle to the Y-axis rotation of the Euler angles
185+
// (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.)
186+
const currentEuler = new Euler().setFromQuaternion(
187+
currentQuaternion,
188+
"YXZ",
189+
);
190+
// Replace the current alpha value of the Euler angles and reset the quaternion
191+
currentEuler.y = MathUtils.degToRad(
192+
360 - device.webkitCompassHeading,
193+
);
194+
currentQuaternion.setFromEuler(currentEuler);
195+
scope.object.quaternion.copy(currentQuaternion);
196+
} else {
197+
if (this.smoothingFactor < 1) {
198+
if (this.lastOrientation) {
199+
const k = this.smoothingFactor;
200+
alpha = this._getSmoothedAngle(
201+
alpha,
202+
this.lastOrientation.alpha,
203+
k,
204+
);
205+
beta = this._getSmoothedAngle(
206+
beta + Math.PI,
207+
this.lastOrientation.beta,
208+
k,
209+
);
210+
gamma = this._getSmoothedAngle(
211+
gamma + this.HALF_PI,
212+
this.lastOrientation.gamma,
213+
k,
214+
Math.PI,
215+
);
216+
} else {
217+
beta += Math.PI;
218+
gamma += this.HALF_PI;
219+
}
220+
221+
this.lastOrientation = {
150222
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;
223+
beta,
224+
gamma,
225+
};
168226
}
169-
170-
this.lastOrientation = {
171-
alpha: alpha,
172-
beta: beta,
173-
gamma: gamma,
174-
};
227+
setObjectQuaternion(
228+
scope.object.quaternion,
229+
alpha + theta,
230+
this.smoothingFactor < 1 ? beta - Math.PI : beta,
231+
this.smoothingFactor < 1 ? gamma - this.HALF_PI : gamma,
232+
orient,
233+
);
175234
}
176235

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-
236+
// NB - NOT present in IOS fixed version issue #466
237+
// Is it needed?
185238
if (8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
186239
lastQuaternion.copy(scope.object.quaternion);
187240
scope.dispatchEvent(_changeEvent);
@@ -218,10 +271,29 @@ class DeviceOrientationControls extends EventDispatcher {
218271
return newangle;
219272
};
220273

274+
// Provided in fix on issue #466 - iOS related
275+
this.updateAlphaOffset = function () {
276+
scope.initialOffset = false;
277+
};
278+
221279
this.dispose = function () {
222280
scope.disconnect();
223281
};
224282

283+
// provided with fix on issue #466
284+
this.getAlpha = function () {
285+
const { deviceOrientation: device } = scope;
286+
return device && device.alpha
287+
? MathUtils.degToRad(device.alpha) + scope.alphaOffset
288+
: 0;
289+
};
290+
291+
// provided with fix on issue #466
292+
this.getBeta = function () {
293+
const { deviceOrientation: device } = scope;
294+
return device && device.beta ? MathUtils.degToRad(device.beta) : 0;
295+
};
296+
225297
this.connect();
226298
}
227299
}

0 commit comments

Comments
 (0)