summaryrefslogtreecommitdiff
path: root/src/client/pages/room/preview.vue
blob: 22228cf8cbe25cf91f6b244a60d8a9b483bd3d8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<template>
<canvas width="224" height="128"></canvas>
</template>

<script lang="ts">
import Vue from 'vue';
import * as THREE from 'three';

export default Vue.extend({
	data() {
		return {
			selected: null,
			objectHeight: 0,
			orbitRadius: 5
		};
	},

	mounted() {
		const canvas = this.$el;

		const width = canvas.width;
		const height = canvas.height;

		const scene = new THREE.Scene();

		const renderer = new THREE.WebGLRenderer({
			canvas: canvas,
			antialias: true,
			alpha: false
		});
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(width, height);
		renderer.setClearColor(0x000000);
		renderer.autoClear = false;
		renderer.shadowMap.enabled = true;
		renderer.shadowMap.cullFace = THREE.CullFaceBack;

		const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100);
		camera.zoom = 10;
		camera.position.x = 0;
		camera.position.y = 2;
		camera.position.z = 0;
		camera.updateProjectionMatrix();
		scene.add(camera);

		const ambientLight = new THREE.AmbientLight(0xffffff, 1);
		ambientLight.castShadow = false;
		scene.add(ambientLight);

		const light = new THREE.PointLight(0xffffff, 1, 100);
		light.position.set(3, 3, 3);
		scene.add(light);

		const grid = new THREE.GridHelper(5, 16, 0x444444, 0x222222);
		scene.add(grid);

		const render = () => {
			const timer = Date.now() * 0.0004;
			requestAnimationFrame(render);
			
			camera.position.y = Math.sin(Math.PI / 6) * this.orbitRadius;	// Math.PI / 6 => 30deg
			camera.position.z = Math.cos(timer) * this.orbitRadius;
			camera.position.x = Math.sin(timer) * this.orbitRadius;
			camera.lookAt(new THREE.Vector3(0, this.objectHeight / 2, 0));
			renderer.render(scene, camera);
		};

		this.selected = selected => {
			const obj = selected.clone();

			// Remove current object
			const current = scene.getObjectByName('obj');
			if (current != null) {
				scene.remove(current);
			}

			// Add new object
			obj.name = 'obj';
			obj.position.x = 0;
			obj.position.y = 0;
			obj.position.z = 0;
			obj.rotation.x = 0;
			obj.rotation.y = 0;
			obj.rotation.z = 0;
			obj.traverse(child => {
				if (child instanceof THREE.Mesh) {
					child.material = child.material.clone();
					return child.material.emissive.setHex(0x000000);
				}
			});
			const objectBoundingBox = new THREE.Box3().setFromObject(obj);
			this.objectHeight = objectBoundingBox.max.y - objectBoundingBox.min.y;

			const objectWidth = objectBoundingBox.max.x - objectBoundingBox.min.x;
			const objectDepth = objectBoundingBox.max.z - objectBoundingBox.min.z;

			const horizontal = Math.hypot(objectWidth, objectDepth) / camera.aspect;
			this.orbitRadius = Math.max(horizontal, this.objectHeight) * camera.zoom * 0.625 / Math.tan(camera.fov * 0.5 * (Math.PI / 180));
		
			scene.add(obj);
		};

		render();
	},
});
</script>