Browse Source

Update three.js demo

customisations
alemart 11 months ago
parent
commit
896bc2cb23

+ 1
- 1
demos/hello-three/NOTICE.html View File

@@ -35,7 +35,7 @@
35 35
                 <a href="https://threejs.org" target="_blank" rel="external">https://threejs.org</a>
36 36
             </li>
37 37
         </ol>
38
-        <p>This application also contains a 3D model of a mage by <a href="https://kaylousberg.com" target="_blank" rel="external">Kay Lousberg</a>, released under the <a href="#cc0">Creative Commons Zero 1.0 Universal</a>.</p>
38
+        <p>This application also contains a 3D model of a mage by <a href="https://kaylousberg.com" target="_blank" rel="external">Kay Lousberg</a> and a 3D model of a cat by <a href="https://opengameart.org/content/cat-pilot-rigged-animated" target="_blank" rel="external">Tomcat94</a>, both released under the <a href="#cc0">Creative Commons Zero 1.0 Universal</a>.</p>
39 39
         <hr>
40 40
 
41 41
         <h2 id="lgpl">GNU Lesser General Public License</h2>

+ 1
- 1
demos/hello-three/README.html View File

@@ -48,7 +48,7 @@
48 48
     </head>
49 49
     <body>
50 50
         <h1>encantAR.js with three.js</h1>
51
-        <p>Scan the QR code to launch the web-based Augmented Reality experience. Next, scan <a href="../assets/my-reference-image.webp" target="_blank">this cartoon</a>.</p>
51
+        <p>Scan the QR code to launch the web-based Augmented Reality experience. Next, scan <a href="../assets/mage.webp" target="_blank">this cartoon</a> or <a href="../assets/cat.webp" target="_blank">this picture</a>.</p>
52 52
 
53 53
         <h2>Menu</h2>
54 54
         <ul>

+ 144
- 47
demos/hello-three/demo.js View File

@@ -28,7 +28,7 @@ class DemoUtils
28 28
         return gltf;
29 29
     }
30 30
 
31
-    createAnimationAction(gltf, name = null)
31
+    createAnimationAction(gltf, name = null, loop = THREE.LoopRepeat)
32 32
     {
33 33
         const mixer = new THREE.AnimationMixer(gltf.scene);
34 34
         const clips = gltf.animations;
@@ -43,6 +43,7 @@ class DemoUtils
43 43
 
44 44
         const clip = THREE.AnimationClip.findByName(clips, name);
45 45
         const action = mixer.clipAction(clip);
46
+        action.loop = loop;
46 47
 
47 48
         return action;
48 49
     }
@@ -66,7 +67,7 @@ class DemoUtils
66 67
         ar.root.rotation.set(-Math.PI / 2, 0, 0);
67 68
     }
68 69
 
69
-    referenceImage(ar)
70
+    referenceImageName(ar)
70 71
     {
71 72
         if(ar.frame === null)
72 73
             return null;
@@ -75,23 +76,13 @@ class DemoUtils
75 76
             if(result.tracker.type == 'image-tracker') {
76 77
                 if(result.trackables.length > 0) {
77 78
                     const trackable = result.trackables[0];
78
-                    return trackable.referenceImage;
79
+                    return trackable.referenceImage.name;
79 80
                 }
80 81
             }
81 82
         }
82 83
 
83 84
         return null;
84 85
     }
85
-
86
-    referenceImageName(ar)
87
-    {
88
-        const referenceImage = this.referenceImage(ar);
89
-
90
-        if(referenceImage === null)
91
-            return null;
92
-
93
-        return referenceImage.name;
94
-    }
95 86
 }
96 87
 
97 88
 
@@ -126,10 +117,16 @@ class DemoScene extends ARScene
126 117
         }
127 118
 
128 119
         const tracker = AR.Tracker.ImageTracker();
129
-        await tracker.database.add([{
130
-            name: 'my-reference-image',
131
-            image: document.getElementById('my-reference-image')
132
-        }]);
120
+        await tracker.database.add([
121
+        {
122
+            name: 'mage',
123
+            image: document.getElementById('mage')
124
+        },
125
+        {
126
+            name: 'cat',
127
+            image: document.getElementById('cat')
128
+        }
129
+        ]);
133 130
 
134 131
         const viewport = AR.Viewport({
135 132
             container: document.getElementById('ar-viewport'),
@@ -138,9 +135,7 @@ class DemoScene extends ARScene
138 135
 
139 136
         const video = document.getElementById('my-video');
140 137
         const useWebcam = (video === null);
141
-        const source = useWebcam ?
142
-            AR.Source.Camera({ resolution: 'md' }) :
143
-            AR.Source.Video(video);
138
+        const source = useWebcam ? AR.Source.Camera() : AR.Source.Video(video);
144 139
 
145 140
         const session = await AR.startSession({
146 141
             mode: 'immersive',
@@ -157,12 +152,16 @@ class DemoScene extends ARScene
157 152
             session.gizmos.visible = false;
158 153
             if(scan)
159 154
                 scan.hidden = true;
155
+
156
+            this._onTargetFound(event.referenceImage);
160 157
         });
161 158
 
162 159
         tracker.addEventListener('targetlost', event => {
163 160
             session.gizmos.visible = true;
164 161
             if(scan)
165 162
                 scan.hidden = false;
163
+
164
+            this._onTargetLost(event.referenceImage);
166 165
         });
167 166
 
168 167
         return session;
@@ -180,56 +179,154 @@ class DemoScene extends ARScene
180 179
         // Adjusting ar.root will adjust all virtual objects.
181 180
         this._utils.switchToFrontView(ar);
182 181
         ar.root.position.set(0, -0.5, 0);
183
-        ar.root.scale.set(0.7, 0.7, 0.7);
184 182
 
185
-        // add light
183
+        // initialize objects
184
+        this._initLight(ar);
185
+        this._initText(ar);
186
+        this._initMagicCircle(ar);
187
+
188
+        await Promise.all([
189
+            this._initMage(ar),
190
+            this._initCat(ar),
191
+        ]);
192
+    }
193
+
194
+    /**
195
+     * Update / animate the augmented scene
196
+     * @param {ARSystem} ar
197
+     * @returns {void}
198
+     */
199
+    update(ar)
200
+    {
201
+        const delta = ar.session.time.delta; // given in seconds
202
+
203
+        // animate the objects of the scene
204
+        this._animateMagicCircle(delta);
205
+        this._animateMage(delta);
206
+        this._animateCat(delta);
207
+    }
208
+
209
+
210
+    // ------------------------------------------------------------------------
211
+
212
+
213
+    _initLight(ar)
214
+    {
186 215
         const ambientLight = new THREE.AmbientLight(0xffffff);
187 216
         ambientLight.intensity = 1.5;
217
+
188 218
         ar.scene.add(ambientLight);
219
+    }
189 220
 
190
-        // create the magic circle
221
+    _initMagicCircle(ar)
222
+    {
223
+        // load the object
191 224
         const magicCircle = this._utils.createImagePlane('../assets/magic-circle.png');
192
-        magicCircle.material.color = new THREE.Color(0xbeefff);
193 225
         magicCircle.material.transparent = true;
194 226
         magicCircle.material.opacity = 1;
195
-        magicCircle.scale.set(6, 6, 1);
227
+        magicCircle.scale.set(4, 4, 1);
228
+
229
+        // add the object to the scene
196 230
         ar.root.add(magicCircle);
197 231
 
232
+        // save a reference
233
+        this._objects.magicCircle = magicCircle;
234
+    }
235
+
236
+    _initText(ar)
237
+    {
238
+        const text = this._utils.createImagePlane('../assets/it-works.png');
239
+        text.material.transparent = true;
240
+        text.material.opacity = 1;
241
+        text.position.set(0, -0.5, 2);
242
+        text.scale.set(3, 1.5, 1);
243
+        text.rotateX(Math.PI / 2);
244
+
245
+        ar.root.add(text);
246
+
247
+        this._objects.text = text;
248
+    }
249
+
250
+    async _initMage(ar)
251
+    {
198 252
         // load the mage
199 253
         const gltf = await this._utils.loadGLTF('../assets/mage.glb');
200 254
         const mage = gltf.scene;
201
-        ar.root.add(mage);
255
+        mage.scale.set(0.7, 0.7, 0.7);
202 256
 
203 257
         // prepare the animation of the mage
204
-        const animationAction = this._utils.createAnimationAction(gltf, 'Idle');
205
-        animationAction.loop = THREE.LoopRepeat;
206
-        animationAction.play();
258
+        const mageAction = this._utils.createAnimationAction(gltf, 'Idle');
259
+        mageAction.play();
207 260
 
208
-        // save objects
261
+        // add the mage to the scene
262
+        ar.root.add(mage);
263
+
264
+        // save references
209 265
         this._objects.mage = mage;
210
-        this._objects.magicCircle = magicCircle;
211
-        this._objects.animationAction = animationAction;
266
+        this._objects.mageAction = mageAction;
212 267
     }
213 268
 
214
-    /**
215
-     * Update / animate the augmented scene
216
-     * @param {ARSystem} ar
217
-     * @returns {void}
218
-     */
219
-    update(ar)
269
+    async _initCat(ar)
220 270
     {
221
-        const TWO_PI = 2.0 * Math.PI;
222
-        const ROTATIONS_PER_SECOND = 0.25;
223
-        const delta = ar.session.time.delta; // given in seconds
271
+        const gltf = await this._utils.loadGLTF('../assets/cat.glb');
272
+        const cat = gltf.scene;
273
+        cat.scale.set(0.7, 0.7, 0.7);
274
+
275
+        const catAction = this._utils.createAnimationAction(gltf, 'Cheer');
276
+        catAction.play();
277
+
278
+        ar.root.add(cat);
279
+
280
+        this._objects.cat = cat;
281
+        this._objects.catAction = catAction;
282
+    }
224 283
 
225
-        // animate the mage
226
-        const animationAction = this._objects.animationAction;
227
-        const mixer = animationAction.getMixer();
284
+    _animate(action, delta)
285
+    {
286
+        const mixer = action.getMixer();
228 287
         mixer.update(delta);
288
+    }
289
+
290
+    _animateMage(delta)
291
+    {
292
+        this._animate(this._objects.mageAction, delta);
293
+    }
229 294
 
230
-        // animate the magic circle
231
-        const magicCircle = this._objects.magicCircle;
232
-        magicCircle.rotateZ(-TWO_PI * ROTATIONS_PER_SECOND * delta);
295
+    _animateCat(delta)
296
+    {
297
+        this._animate(this._objects.catAction, delta);
298
+    }
299
+
300
+    _animateMagicCircle(delta)
301
+    {
302
+        const TWO_PI = 2.0 * Math.PI;
303
+        const ROTATIONS_PER_SECOND = 1.0 / 8.0;
304
+
305
+        this._objects.magicCircle.rotateZ(-TWO_PI * ROTATIONS_PER_SECOND * delta);
306
+    }
307
+
308
+    _onTargetFound(referenceImage)
309
+    {
310
+        // change the scene based on the scanned image
311
+        switch(referenceImage.name) {
312
+            case 'mage':
313
+                this._objects.mage.visible = true;
314
+                this._objects.cat.visible = false;
315
+                this._objects.text.visible = false;
316
+                this._objects.magicCircle.material.color.set(0xbeefff);
317
+                break;
318
+
319
+            case 'cat':
320
+                this._objects.mage.visible = false;
321
+                this._objects.cat.visible = true;
322
+                this._objects.text.visible = true;
323
+                this._objects.magicCircle.material.color.set(0xffffaa);
324
+                break;
325
+        }
326
+    }
327
+
328
+    _onTargetLost(referenceImage)
329
+    {
233 330
     }
234 331
 }
235 332
 

+ 2
- 1
demos/hello-three/index.html View File

@@ -18,6 +18,7 @@
18 18
                 <a id="about" href="NOTICE.html"></a>
19 19
             </div>
20 20
         </div>
21
-        <img id="my-reference-image" src="../assets/mage.webp" hidden>
21
+        <img id="mage" src="../assets/mage.webp" hidden>
22
+        <img id="cat" src="../assets/cat.webp" hidden>
22 23
     </body>
23 24
 </html>

+ 2
- 1
demos/hello-three/video.html View File

@@ -18,7 +18,8 @@
18 18
                 <a id="about" href="NOTICE.html"></a>
19 19
             </div>
20 20
         </div>
21
-        <img id="my-reference-image" src="../assets/mage.webp" hidden>
21
+        <img id="mage" src="../assets/mage.webp" hidden>
22
+        <img id="cat" src="../assets/cat.webp" hidden>
22 23
         <video id="my-video" hidden muted loop playsinline autoplay>
23 24
             <source src="../assets/my-video.webm" type="video/webm" />
24 25
             <source src="../assets/my-video.mp4" type="video/mp4" />

Loading…
Cancel
Save