|
@@ -11,40 +11,142 @@ __THIS_PLUGIN_HAS_BEEN_TESTED_WITH__({
|
11
|
11
|
});
|
12
|
12
|
|
13
|
13
|
/**
|
14
|
|
- * Use this object to create your augmented scene
|
15
|
|
- * @typedef {object} ARSystem
|
16
|
|
- * @property {Session} session AR Session
|
17
|
|
- * @property {Frame} frame current Frame
|
18
|
|
- * @property {ReferenceImage | null} referenceImage corresponds to the target being tracked (if any)
|
19
|
|
- * @property {THREE.Scene} scene three.js Scene
|
20
|
|
- * @property {THREE.Group} root a 3D object that is automatically aligned to the physical target
|
21
|
|
- * @property {THREE.Camera} camera a camera adjusted for AR
|
22
|
|
- * @property {THREE.WebGLRenderer} renderer three.js renderer
|
|
14
|
+ * Base class for augmented scenes
|
23
|
15
|
*/
|
|
16
|
+class ARScene
|
|
17
|
+{
|
|
18
|
+ /**
|
|
19
|
+ * Start the AR session
|
|
20
|
+ * @abstract
|
|
21
|
+ * @returns {Promise<Session> | SpeedyPromise<Session>}
|
|
22
|
+ */
|
|
23
|
+ startSession()
|
|
24
|
+ {
|
|
25
|
+ throw new Error('Abstract method');
|
|
26
|
+ }
|
|
27
|
+
|
|
28
|
+ /**
|
|
29
|
+ * Initialize the augmented scene
|
|
30
|
+ * @abstract
|
|
31
|
+ * @param {ARPluginSystem} ar
|
|
32
|
+ * @returns {void | Promise<void> | SpeedyPromise<void>}
|
|
33
|
+ */
|
|
34
|
+ init(ar)
|
|
35
|
+ {
|
|
36
|
+ throw new Error('Abstract method');
|
|
37
|
+ }
|
|
38
|
+
|
|
39
|
+ /**
|
|
40
|
+ * Update / animate the augmented scene
|
|
41
|
+ * @abstract
|
|
42
|
+ * @param {ARPluginSystem} ar
|
|
43
|
+ * @returns {void}
|
|
44
|
+ */
|
|
45
|
+ update(ar)
|
|
46
|
+ {
|
|
47
|
+ throw new Error('Abstract method');
|
|
48
|
+ }
|
|
49
|
+
|
|
50
|
+ /**
|
|
51
|
+ * Release the augmented scene
|
|
52
|
+ * @param {ARPluginSystem} ar
|
|
53
|
+ * @returns {void}
|
|
54
|
+ */
|
|
55
|
+ release(ar)
|
|
56
|
+ {
|
|
57
|
+ // optional implementation
|
|
58
|
+ }
|
|
59
|
+}
|
|
60
|
+
|
|
61
|
+/**
|
|
62
|
+ * Helper for augmenting the scenes with three.js
|
|
63
|
+ */
|
|
64
|
+class ARPluginSystem
|
|
65
|
+{
|
|
66
|
+ /**
|
|
67
|
+ * AR Session
|
|
68
|
+ * @returns {Session}
|
|
69
|
+ */
|
|
70
|
+ get session()
|
|
71
|
+ {
|
|
72
|
+ return this._session;
|
|
73
|
+ }
|
|
74
|
+
|
|
75
|
+ /**
|
|
76
|
+ * Current frame: an object holding data to augment the physical scene.
|
|
77
|
+ * If the AR scene is not initialized, this will be null.
|
|
78
|
+ * @returns {Frame | null}
|
|
79
|
+ */
|
|
80
|
+ get frame()
|
|
81
|
+ {
|
|
82
|
+ return this._frame;
|
|
83
|
+ }
|
|
84
|
+
|
|
85
|
+ /**
|
|
86
|
+ * The root is a 3D object that is automatically aligned to the physical
|
|
87
|
+ * scene. Objects of your virtual scene should be descendants of this node.
|
|
88
|
+ * The root is only visible if something is being tracked.
|
|
89
|
+ * @returns {THREE.Group}
|
|
90
|
+ */
|
|
91
|
+ get root()
|
|
92
|
+ {
|
|
93
|
+ return this._root;
|
|
94
|
+ }
|
|
95
|
+
|
|
96
|
+ /**
|
|
97
|
+ * The three.js scene
|
|
98
|
+ * @returns {THREE.Scene}
|
|
99
|
+ */
|
|
100
|
+ get scene()
|
|
101
|
+ {
|
|
102
|
+ return this._scene;
|
|
103
|
+ }
|
|
104
|
+
|
|
105
|
+ /**
|
|
106
|
+ * A camera that is automatically adjusted for AR
|
|
107
|
+ * @returns {THREE.Camera}
|
|
108
|
+ */
|
|
109
|
+ get camera()
|
|
110
|
+ {
|
|
111
|
+ return this._camera;
|
|
112
|
+ }
|
|
113
|
+
|
|
114
|
+ /**
|
|
115
|
+ * The three.js renderer
|
|
116
|
+ * @returns {THREE.WebGLRenderer}
|
|
117
|
+ */
|
|
118
|
+ get renderer()
|
|
119
|
+ {
|
|
120
|
+ return this._renderer;
|
|
121
|
+ }
|
|
122
|
+
|
|
123
|
+ /**
|
|
124
|
+ * Constructor
|
|
125
|
+ */
|
|
126
|
+ constructor()
|
|
127
|
+ {
|
|
128
|
+ this._session = null;
|
|
129
|
+ this._frame = null;
|
|
130
|
+ this._origin = null;
|
|
131
|
+ this._root = null;
|
|
132
|
+ this._scene = null;
|
|
133
|
+ this._camera = null;
|
|
134
|
+ this._renderer = null;
|
|
135
|
+ }
|
|
136
|
+}
|
24
|
137
|
|
25
|
138
|
/**
|
26
|
139
|
* Do magic to connect encantar.js to three.js
|
27
|
|
- * @param {() => Promise<Session> | SpeedyPromise<Session>} startARSession
|
28
|
|
- * @param {(ar: ARSystem, deltaSeconds?: number) => void} [animateVirtualScene] animation callback
|
29
|
|
- * @param {(ar: ARSystem) => void | Promise<void> | SpeedyPromise<Session>} [initializeVirtualScene] initialization callback
|
30
|
|
- * @returns {Promise<ARSystem> | SpeedyPromise<ARSystem>}
|
|
140
|
+ * @param {ARScene} scene
|
|
141
|
+ * @returns {Promise<ARPluginSystem> | SpeedyPromise<ARPluginSystem>}
|
31
|
142
|
*/
|
32
|
|
-function encantar(startARSession, animateVirtualScene, initializeVirtualScene)
|
|
143
|
+function encantar(scene)
|
33
|
144
|
{
|
34
|
|
- const ar = /** @type {ARSystem} */ ({
|
35
|
|
- session: null,
|
36
|
|
- frame: null,
|
37
|
|
- referenceImage: null,
|
38
|
|
- scene: null,
|
39
|
|
- root: null,
|
40
|
|
- camera: null,
|
41
|
|
- renderer: null,
|
42
|
|
- });
|
|
145
|
+ const ar = new ARPluginSystem();
|
43
|
146
|
|
44
|
147
|
function mix(frame)
|
45
|
148
|
{
|
46
|
|
- ar.root.visible = false;
|
47
|
|
- ar.referenceImage = null;
|
|
149
|
+ ar._root.visible = false;
|
48
|
150
|
|
49
|
151
|
for(const result of frame.results) {
|
50
|
152
|
if(result.tracker.type == 'image-tracker') {
|
|
@@ -54,10 +156,10 @@ function encantar(startARSession, animateVirtualScene, initializeVirtualScene)
|
54
|
156
|
const viewMatrixInverse = result.viewer.pose.transform.matrix;
|
55
|
157
|
const modelMatrix = trackable.pose.transform.matrix;
|
56
|
158
|
|
57
|
|
- ar.root.visible = true;
|
58
|
|
- ar.referenceImage = trackable.referenceImage;
|
59
|
|
-
|
60
|
159
|
align(projectionMatrix, viewMatrixInverse, modelMatrix);
|
|
160
|
+ ar._root.visible = true;
|
|
161
|
+
|
|
162
|
+ return;
|
61
|
163
|
}
|
62
|
164
|
}
|
63
|
165
|
}
|
|
@@ -65,64 +167,59 @@ function encantar(startARSession, animateVirtualScene, initializeVirtualScene)
|
65
|
167
|
|
66
|
168
|
function align(projectionMatrix, viewMatrixInverse, modelMatrix)
|
67
|
169
|
{
|
68
|
|
- ar.camera.projectionMatrix.fromArray(projectionMatrix.read());
|
69
|
|
- ar.camera.projectionMatrixInverse.copy(ar.camera.projectionMatrix).invert();
|
70
|
|
- ar.camera.matrix.fromArray(viewMatrixInverse.read());
|
71
|
|
- ar.camera.updateMatrixWorld(true);
|
72
|
|
- ar.root.matrix.fromArray(modelMatrix.read());
|
73
|
|
- ar.root.updateMatrixWorld(true);
|
|
170
|
+ ar._camera.projectionMatrix.fromArray(projectionMatrix.read());
|
|
171
|
+ ar._camera.projectionMatrixInverse.copy(ar._camera.projectionMatrix).invert();
|
|
172
|
+ ar._camera.matrix.fromArray(viewMatrixInverse.read());
|
|
173
|
+ ar._camera.updateMatrixWorld(true);
|
|
174
|
+ ar._origin.matrix.fromArray(modelMatrix.read());
|
|
175
|
+ ar._origin.updateMatrixWorld(true);
|
74
|
176
|
}
|
75
|
177
|
|
76
|
178
|
function animate(time, frame)
|
77
|
179
|
{
|
78
|
|
- ar.frame = frame;
|
79
|
|
- mix(ar.frame);
|
|
180
|
+ ar._frame = frame;
|
|
181
|
+ mix(frame);
|
80
|
182
|
|
81
|
|
- animateVirtualScene.call(undefined, ar, ar.session.time.delta);
|
|
183
|
+ scene.update(ar);
|
82
|
184
|
|
83
|
|
- ar.renderer.render(ar.scene, ar.camera);
|
84
|
|
- ar.session.requestAnimationFrame(animate);
|
|
185
|
+ ar._renderer.render(ar._scene, ar._camera);
|
|
186
|
+ ar._session.requestAnimationFrame(animate);
|
85
|
187
|
}
|
86
|
188
|
|
|
189
|
+ return scene.startSession().then(session => {
|
87
|
190
|
|
|
191
|
+ ar._session = session;
|
88
|
192
|
|
|
193
|
+ ar._scene = new THREE.Scene();
|
89
|
194
|
|
90
|
|
- if(typeof animateVirtualScene !== 'function')
|
91
|
|
- animateVirtualScene = (ar => void 0);
|
92
|
|
-
|
93
|
|
- if(typeof initializeVirtualScene !== 'function')
|
94
|
|
- initializeVirtualScene = (ar => void 0);
|
95
|
|
-
|
96
|
|
- return startARSession().then(session => {
|
|
195
|
+ ar._origin = new THREE.Group();
|
|
196
|
+ ar._origin.matrixAutoUpdate = false;
|
|
197
|
+ ar._scene.add(ar._origin);
|
97
|
198
|
|
98
|
|
- ar.session = session;
|
|
199
|
+ ar._root = new THREE.Group();
|
|
200
|
+ ar._origin.add(ar._root);
|
99
|
201
|
|
100
|
|
- ar.scene = new THREE.Scene();
|
101
|
|
- ar.camera = new THREE.PerspectiveCamera();
|
102
|
|
- ar.camera.matrixAutoUpdate = false;
|
|
202
|
+ ar._camera = new THREE.PerspectiveCamera();
|
|
203
|
+ ar._camera.matrixAutoUpdate = false;
|
103
|
204
|
|
104
|
|
- ar.root = new THREE.Group();
|
105
|
|
- ar.root.matrixAutoUpdate = false;
|
106
|
|
- ar.scene.add(ar.root);
|
107
|
|
-
|
108
|
|
- ar.renderer = new THREE.WebGLRenderer({
|
109
|
|
- canvas: ar.session.viewport.canvas,
|
|
205
|
+ ar._renderer = new THREE.WebGLRenderer({
|
|
206
|
+ canvas: session.viewport.canvas,
|
110
|
207
|
alpha: true,
|
111
|
208
|
});
|
112
|
209
|
|
113
|
|
- ar.session.addEventListener('end', event => {
|
114
|
|
- ar.root.visible = false;
|
115
|
|
- ar.frame = null;
|
116
|
|
- ar.referenceImage = null;
|
|
210
|
+ session.addEventListener('end', event => {
|
|
211
|
+ ar._root.visible = false;
|
|
212
|
+ scene.release(ar);
|
|
213
|
+ ar._frame = null;
|
117
|
214
|
});
|
118
|
215
|
|
119
|
|
- ar.session.viewport.addEventListener('resize', event => {
|
120
|
|
- const size = ar.session.viewport.virtualSize;
|
121
|
|
- ar.renderer.setPixelRatio(1.0);
|
122
|
|
- ar.renderer.setSize(size.width, size.height, false);
|
|
216
|
+ session.viewport.addEventListener('resize', event => {
|
|
217
|
+ const size = session.viewport.virtualSize;
|
|
218
|
+ ar._renderer.setPixelRatio(1.0);
|
|
219
|
+ ar._renderer.setSize(size.width, size.height, false);
|
123
|
220
|
});
|
124
|
221
|
|
125
|
|
- let init = initializeVirtualScene.call(undefined, ar);
|
|
222
|
+ let init = scene.init(ar);
|
126
|
223
|
if(!(typeof init === 'object' && 'then' in init))
|
127
|
224
|
init = Promise.resolve();
|
128
|
225
|
|
|
@@ -135,7 +232,7 @@ function encantar(startARSession, animateVirtualScene, initializeVirtualScene)
|
135
|
232
|
|
136
|
233
|
console.error(error);
|
137
|
234
|
alert(error.message);
|
138
|
|
- return ar;
|
|
235
|
+ throw error;
|
139
|
236
|
|
140
|
237
|
});
|
141
|
238
|
}
|
|
@@ -157,4 +254,4 @@ function __THIS_PLUGIN_HAS_BEEN_TESTED_WITH__(json)
|
157
|
254
|
alert(e.message);
|
158
|
255
|
}
|
159
|
256
|
});
|
160
|
|
-}
|
|
257
|
+}
|