Browse Source

Update three.js demo

customisations
alemart 11 months ago
parent
commit
896bc2cb23

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

35
                 <a href="https://threejs.org" target="_blank" rel="external">https://threejs.org</a>
35
                 <a href="https://threejs.org" target="_blank" rel="external">https://threejs.org</a>
36
             </li>
36
             </li>
37
         </ol>
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
         <hr>
39
         <hr>
40
 
40
 
41
         <h2 id="lgpl">GNU Lesser General Public License</h2>
41
         <h2 id="lgpl">GNU Lesser General Public License</h2>

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

48
     </head>
48
     </head>
49
     <body>
49
     <body>
50
         <h1>encantAR.js with three.js</h1>
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
         <h2>Menu</h2>
53
         <h2>Menu</h2>
54
         <ul>
54
         <ul>

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

28
         return gltf;
28
         return gltf;
29
     }
29
     }
30
 
30
 
31
-    createAnimationAction(gltf, name = null)
31
+    createAnimationAction(gltf, name = null, loop = THREE.LoopRepeat)
32
     {
32
     {
33
         const mixer = new THREE.AnimationMixer(gltf.scene);
33
         const mixer = new THREE.AnimationMixer(gltf.scene);
34
         const clips = gltf.animations;
34
         const clips = gltf.animations;
43
 
43
 
44
         const clip = THREE.AnimationClip.findByName(clips, name);
44
         const clip = THREE.AnimationClip.findByName(clips, name);
45
         const action = mixer.clipAction(clip);
45
         const action = mixer.clipAction(clip);
46
+        action.loop = loop;
46
 
47
 
47
         return action;
48
         return action;
48
     }
49
     }
66
         ar.root.rotation.set(-Math.PI / 2, 0, 0);
67
         ar.root.rotation.set(-Math.PI / 2, 0, 0);
67
     }
68
     }
68
 
69
 
69
-    referenceImage(ar)
70
+    referenceImageName(ar)
70
     {
71
     {
71
         if(ar.frame === null)
72
         if(ar.frame === null)
72
             return null;
73
             return null;
75
             if(result.tracker.type == 'image-tracker') {
76
             if(result.tracker.type == 'image-tracker') {
76
                 if(result.trackables.length > 0) {
77
                 if(result.trackables.length > 0) {
77
                     const trackable = result.trackables[0];
78
                     const trackable = result.trackables[0];
78
-                    return trackable.referenceImage;
79
+                    return trackable.referenceImage.name;
79
                 }
80
                 }
80
             }
81
             }
81
         }
82
         }
82
 
83
 
83
         return null;
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
         }
117
         }
127
 
118
 
128
         const tracker = AR.Tracker.ImageTracker();
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
         const viewport = AR.Viewport({
131
         const viewport = AR.Viewport({
135
             container: document.getElementById('ar-viewport'),
132
             container: document.getElementById('ar-viewport'),
138
 
135
 
139
         const video = document.getElementById('my-video');
136
         const video = document.getElementById('my-video');
140
         const useWebcam = (video === null);
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
         const session = await AR.startSession({
140
         const session = await AR.startSession({
146
             mode: 'immersive',
141
             mode: 'immersive',
157
             session.gizmos.visible = false;
152
             session.gizmos.visible = false;
158
             if(scan)
153
             if(scan)
159
                 scan.hidden = true;
154
                 scan.hidden = true;
155
+
156
+            this._onTargetFound(event.referenceImage);
160
         });
157
         });
161
 
158
 
162
         tracker.addEventListener('targetlost', event => {
159
         tracker.addEventListener('targetlost', event => {
163
             session.gizmos.visible = true;
160
             session.gizmos.visible = true;
164
             if(scan)
161
             if(scan)
165
                 scan.hidden = false;
162
                 scan.hidden = false;
163
+
164
+            this._onTargetLost(event.referenceImage);
166
         });
165
         });
167
 
166
 
168
         return session;
167
         return session;
180
         // Adjusting ar.root will adjust all virtual objects.
179
         // Adjusting ar.root will adjust all virtual objects.
181
         this._utils.switchToFrontView(ar);
180
         this._utils.switchToFrontView(ar);
182
         ar.root.position.set(0, -0.5, 0);
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
         const ambientLight = new THREE.AmbientLight(0xffffff);
215
         const ambientLight = new THREE.AmbientLight(0xffffff);
187
         ambientLight.intensity = 1.5;
216
         ambientLight.intensity = 1.5;
217
+
188
         ar.scene.add(ambientLight);
218
         ar.scene.add(ambientLight);
219
+    }
189
 
220
 
190
-        // create the magic circle
221
+    _initMagicCircle(ar)
222
+    {
223
+        // load the object
191
         const magicCircle = this._utils.createImagePlane('../assets/magic-circle.png');
224
         const magicCircle = this._utils.createImagePlane('../assets/magic-circle.png');
192
-        magicCircle.material.color = new THREE.Color(0xbeefff);
193
         magicCircle.material.transparent = true;
225
         magicCircle.material.transparent = true;
194
         magicCircle.material.opacity = 1;
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
         ar.root.add(magicCircle);
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
         // load the mage
252
         // load the mage
199
         const gltf = await this._utils.loadGLTF('../assets/mage.glb');
253
         const gltf = await this._utils.loadGLTF('../assets/mage.glb');
200
         const mage = gltf.scene;
254
         const mage = gltf.scene;
201
-        ar.root.add(mage);
255
+        mage.scale.set(0.7, 0.7, 0.7);
202
 
256
 
203
         // prepare the animation of the mage
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
         this._objects.mage = mage;
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
         mixer.update(delta);
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
                 <a id="about" href="NOTICE.html"></a>
18
                 <a id="about" href="NOTICE.html"></a>
19
             </div>
19
             </div>
20
         </div>
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
     </body>
23
     </body>
23
 </html>
24
 </html>

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

18
                 <a id="about" href="NOTICE.html"></a>
18
                 <a id="about" href="NOTICE.html"></a>
19
             </div>
19
             </div>
20
         </div>
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
         <video id="my-video" hidden muted loop playsinline autoplay>
23
         <video id="my-video" hidden muted loop playsinline autoplay>
23
             <source src="../assets/my-video.webm" type="video/webm" />
24
             <source src="../assets/my-video.webm" type="video/webm" />
24
             <source src="../assets/my-video.mp4" type="video/mp4" />
25
             <source src="../assets/my-video.mp4" type="video/mp4" />

Loading…
Cancel
Save