Przeglądaj źródła

Update three.js demo

customisations
alemart 11 miesięcy temu
rodzic
commit
57e3e99331

BIN
demos/assets/mage.glb Wyświetl plik


BIN
demos/assets/magic-circle.png Wyświetl plik


+ 1
- 1
demos/hello-three/NOTICE.html Wyświetl plik

@@ -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 from asset pack "Animated Characters 2" by <a href="https://kenney.nl" target="_blank" rel="external">Kenney</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 from "Adventurers Character Pack" 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>
39 39
         <hr>
40 40
 
41 41
         <h2 id="lgpl">GNU Lesser General Public License</h2>

+ 71
- 57
demos/hello-three/demo.js Wyświetl plik

@@ -2,99 +2,113 @@ window.addEventListener('load', () => {
2 2
 
3 3
     const my = { };
4 4
 
5
-    async function initialize(ar)
5
+    // initialize the virtual scene
6
+    async function init(ar)
6 7
     {
7 8
         // add lights
8
-        const ambientLight = new THREE.AmbientLight(0xb7b7b7);
9
-        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.4);
10
-        directionalLight.position.set(0, 0, -1);
11
-        directionalLight.target.position.set(0, 0, 0);
12
-        ar.scene.add(directionalLight);
9
+        const ambientLight = new THREE.AmbientLight(0xffffff);
13 10
         ar.scene.add(ambientLight);
14 11
 
15
-        // create a group of objects as a child of ar.root
16
-        const group = createGroup('in-front');
17
-        //const group = createGroup('on-top'); // try this option!
12
+        const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
13
+        directionalLight.position.set(0, 1, 0);
14
+        ar.root.add(directionalLight);
15
+
16
+        //const directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight, 0.5);
17
+        //ar.scene.add(directionalLightHelper);
18
+
19
+        // create a group as a child of ar.root, which is aligned to the physical scene
20
+        const group = createMainGroup(true);
21
+        group.position.set(0, -0.5, 0);
22
+        group.scale.set(0.7, 0.7, 0.7);
18 23
         ar.root.add(group);
19 24
 
20
-        // create cubes
21
-        const cubeA = createCube(-0.75, 0, 0xffff00);
22
-        const cubeB = createCube(0.75, 0, 0x00ff00);
23
-        group.add(cubeA, cubeB);
25
+        // create the magic circle
26
+        const magicCircle = createPlane('../assets/magic-circle.png');
27
+        magicCircle.material.transparent = true;
28
+        magicCircle.material.opacity = 0.85;
29
+        magicCircle.material.color = new THREE.Color(0xbeefff);
30
+        magicCircle.scale.set(6, 6, 1);
31
+        group.add(magicCircle);
24 32
 
25
-        // create the ground
26
-        const ground = createGround(0x3d5afe);
27
-        group.add(ground);
33
+        // load the mage
34
+        const gltf = await loadGLTF('../assets/mage.glb');
35
+        const mage = gltf.scene;
36
+        group.add(mage);
28 37
 
29
-        // load a 3D model
30
-        const modelURL = '../assets/my-3d-model.glb';
31
-        const model = await loadModel(modelURL);
32
-        group.add(model);
38
+        // prepare the animation of the mage
39
+        const animationAction = createAnimationAction(gltf, 'Idle');
40
+        animationAction.loop = THREE.LoopRepeat;
41
+        animationAction.play();
33 42
 
34 43
         // export objects
35
-        my.cubes = [ cubeA, cubeB ];
36 44
         my.group = group;
37
-        my.model = model;
38
-        my.ground = ground;
45
+        my.magicCircle = magicCircle;
46
+        my.mage = mage;
47
+        my.animationAction = animationAction;
39 48
     }
40 49
 
41
-    function animate(ar)
50
+    // animate the virtual scene
51
+    function animate(ar, deltaSeconds)
42 52
     {
43
-        const ROTATION_CYCLES_PER_SECOND = 1.0;
44 53
         const TWO_PI = 2.0 * Math.PI;
45
-        const delta = ar.session.time.delta;
54
+        const ROTATIONS_PER_SECOND = 0.25;
55
+
56
+        // animate the mage
57
+        const mixer = my.animationAction.getMixer();
58
+        mixer.update(deltaSeconds);
46 59
 
47
-        // rotate the cubes
48
-        for(const cube of my.cubes)
49
-            cube.rotateY(TWO_PI * ROTATION_CYCLES_PER_SECOND * delta);
60
+        // animate the magic circle
61
+        my.magicCircle.rotateZ(TWO_PI * ROTATIONS_PER_SECOND * deltaSeconds);
50 62
     }
51 63
 
52
-    function createGroup(mode = 'in-front')
64
+    function createMainGroup(frontView = false)
53 65
     {
54 66
         const group = new THREE.Group();
55 67
 
56
-        if(mode == 'in-front') {
57
-            group.rotation.set(-Math.PI/2, 0, 0);
58
-            group.position.set(0, -0.5, 0.5);
59
-        }
60
-        else if(mode == 'on-top') {
61
-            group.rotation.set(0, 0, 0);
62
-            group.position.set(0, 0, 0);
63
-        }
68
+        // top view is the default
69
+        if(frontView)
70
+            group.rotateX(-Math.PI / 2);
64 71
 
65 72
         return group;
66 73
     }
67 74
 
68
-    function createCube(x, y, color, length = 0.25)
75
+    async function loadGLTF(filepath, yAxisIsUp = true)
69 76
     {
70
-        const geometry = new THREE.BoxGeometry(length, length, length);
71
-        const material = new THREE.MeshPhongMaterial({ color });
72
-        const cube = new THREE.Mesh(geometry, material);
77
+        const loader = new THREE.GLTFLoader();
78
+        const gltf = await loader.loadAsync(filepath);
73 79
 
74
-        cube.position.set(x, y, 1.25);
80
+        // glTF defines +y as up. We expect +z to be up.
81
+        if(yAxisIsUp)
82
+            gltf.scene.rotateX(Math.PI / 2);
75 83
 
76
-        return cube;
84
+        return gltf;
77 85
     }
78 86
 
79
-    function createGround(color)
87
+    function createAnimationAction(gltf, name = null)
80 88
     {
81
-        const geometry = new THREE.RingGeometry(0.001, 1, 8);
82
-        const material = new THREE.MeshPhongMaterial({ color: color, side: THREE.DoubleSide });
83
-        const ground = new THREE.Mesh(geometry, material);
89
+        const mixer = new THREE.AnimationMixer(gltf.scene);
90
+        const clips = gltf.animations;
91
+
92
+        if(clips.length == 0)
93
+            throw new Error('No animation clips');
84 94
 
85
-        material.transparent = true;
86
-        material.opacity = 0.75;
95
+        const clip = (name !== null) ? THREE.AnimationClip.findByName(clips, name) : clips[0];
96
+        const action = mixer.clipAction(clip);
87 97
 
88
-        return ground;
98
+        return action;
89 99
     }
90 100
 
91
-    async function loadModel(filepath)
101
+    function createPlane(imagepath)
92 102
     {
93
-        const loader = new THREE.GLTFLoader();
94
-        const gltf = await loader.loadAsync(filepath);
95
-        const model = gltf.scene;
103
+        const texture = new THREE.TextureLoader().load(imagepath);
104
+        const geometry = new THREE.PlaneGeometry(1, 1);
105
+        const material = new THREE.MeshBasicMaterial({
106
+            map: texture,
107
+            side: THREE.DoubleSide,
108
+        });
109
+        const mesh = new THREE.Mesh(geometry, material);
96 110
 
97
-        return model;
111
+        return mesh;
98 112
     }
99 113
 
100 114
     async function startARSession()
@@ -152,6 +166,6 @@ window.addEventListener('load', () => {
152 166
     }
153 167
 
154 168
     // enchant!
155
-    encantar(startARSession, animate, initialize);
169
+    encantar(startARSession, animate, init);
156 170
 
157 171
 });

Ładowanie…
Anuluj
Zapisz