291
|
1 <link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
|
|
2
|
|
3 <dom-module id="house-model">
|
|
4 <template>
|
|
5 <style>
|
|
6 #scene {
|
|
7 position: relative;
|
|
8 overflow: hidden;
|
|
9 }
|
|
10 .label {
|
|
11 position: absolute;
|
|
12 color: white;
|
|
13 font-family: sans-serif;
|
|
14 font-size: 10px;
|
|
15 font-weight: bold;
|
|
16 text-shadow: 0 0 1px black;
|
|
17 }
|
|
18 </style>
|
|
19 <div id="scene"></div>
|
|
20 </template>
|
|
21 <script src="/lib/threejs/r78/three.js"></script>
|
|
22 <script src="dat.gui.js"></script>
|
|
23
|
|
24 <script>
|
|
25
|
|
26 function Bar(sceneParent, domParent, pos) {
|
|
27 this.domParent = domParent;
|
|
28 this.mesh = new THREE.Mesh(Bar.geometry, Bar.material);
|
|
29 this.mesh.scale.set(.1, 1, .1);
|
|
30 this.mesh.translateX(pos.x);
|
|
31 this.mesh.translateZ(pos.z);
|
|
32 this.pos = pos;
|
|
33
|
|
34 sceneParent.add(this.mesh);
|
|
35
|
|
36 }
|
|
37 Bar.material = new THREE.MeshLambertMaterial({
|
|
38 "color": 0xe314a3,
|
|
39 "emissive": 0x531251
|
|
40 });
|
|
41 Bar.geometry = new THREE.CylinderGeometry( 1, 1, 1, 32 );
|
|
42 Bar.prototype.setValue = function(value, label) {
|
|
43 this.value = value;
|
|
44 this.label = label;
|
|
45 this.mesh.position.setY(this.pos.y + value / 2);
|
|
46 this.mesh.scale.setY(value);
|
|
47 if (this.div) {
|
|
48 this.div.innerText = '' + label;
|
|
49 }
|
|
50 };
|
|
51 Bar.prototype.update2d = function(camera, screenSize) {
|
|
52 if (!this.div) {
|
|
53 this.div = document.createElement("div");
|
|
54 this.div.classList.add("label");
|
|
55 this.domParent.appendChild(this.div);
|
|
56 }
|
|
57
|
|
58 var vector = this.mesh.position.clone().project(camera);
|
|
59 vector.x = (vector.x + 1) / 2 * screenSize.x;
|
|
60 vector.y = -(vector.y - 1) / 2 * screenSize.y;
|
|
61
|
|
62 this.div.style.left = vector.x + 'px';
|
|
63 this.div.style.top = vector.y + 'px';
|
|
64 };
|
|
65
|
|
66
|
|
67
|
|
68 Polymer({
|
|
69 is: "house-model",
|
|
70 properties: {
|
|
71 positionEstimates: {type: Object, notify: true, observer: 'onPositionEstimates'},
|
|
72 beacons: {type: Array, notify: true, observer: 'onBeacons'},
|
|
73 },
|
|
74 addLights: function(scene) {
|
|
75 var addLight = function(color, pos) {
|
|
76 var light = new THREE.PointLight(color, 1, 0, 0);
|
|
77 light.position.set.apply(pos);
|
|
78 scene.add(light);
|
|
79 return light;
|
|
80 };
|
|
81 addLight(0xffafff, [0, 6, 0]);
|
|
82 addLight(0xffffaf, [-6, 6, 9]);
|
|
83 addLight(0xffcfaf, [5, 5, 0]);
|
|
84 addLight(0xefffef, [6, 4, 2]);
|
|
85 },
|
|
86 setMaterials: function(scene) {
|
|
87 this.wall = new THREE.MeshPhongMaterial({
|
|
88 color : 0x7c7c7c,
|
|
89 emissive: 0x303030,
|
|
90 name : "wall",
|
|
91 opacity : 0.34,
|
|
92 shininess : 1.3,
|
|
93 side : THREE.DoubleSide,
|
|
94 specular : 16777215,
|
|
95 transparent : true,
|
|
96 depthTest: true,
|
|
97 depthWrite: false,
|
|
98 alphaTest: 0.01,
|
|
99 });
|
|
100
|
|
101
|
|
102 scene.children.forEach(function(obj) {
|
|
103 obj.material = this.wall;
|
|
104 }.bind(this));
|
|
105 },
|
|
106 ready: function() {
|
|
107 var container = this.$.scene;
|
|
108
|
|
109 this.renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
110 this.size = new THREE.Vector2(800, 500);
|
|
111 this.renderer.setSize(this.size.x, this.size.y);
|
|
112 container.appendChild( this.renderer.domElement );
|
|
113
|
|
114 this.config = {
|
|
115 camRotSpeed: 5,
|
|
116 camY: 8.5,
|
|
117 camDist: 11,
|
|
118 cursorX: 0, cursorY: 0, cursorZ: 0,
|
|
119 };
|
|
120
|
|
121 var gui = new dat.GUI();
|
|
122 gui.add(this.config, 'camRotSpeed', -80, 80);
|
|
123 gui.add(this.config, 'camY', -2, 10);
|
|
124 gui.add(this.config, 'camDist', 1, 25);
|
|
125 gui.add(this.config, 'cursorX', -7, 7);
|
|
126 gui.add(this.config, 'cursorY', -7, 7);
|
|
127 gui.add(this.config, 'cursorZ', -7, 7);
|
|
128
|
|
129 this.bars = {}; // pos : Bar
|
|
130 this.scene = null;
|
|
131
|
|
132 var loader = new THREE.ObjectLoader();
|
|
133 loader.load('house.json', function(scene) {
|
|
134 window.scene = scene;
|
|
135 this.scene = scene;
|
|
136 this.addLights(scene);
|
|
137
|
|
138 this.setMaterials(scene);
|
|
139
|
|
140 gui.add(this.wall, 'depthTest');
|
|
141 gui.add(this.wall, 'depthWrite');
|
|
142 gui.add(this.wall, 'transparent');
|
|
143 gui.add(this.wall, 'opacity', 0, 1);
|
|
144 gui.add(this.wall, 'shininess', 0, 3);
|
|
145 gui.add(this.wall, 'alphaTest', 0, 1);
|
|
146 gui.listen({updateDisplay: function() { this.wall.needsUpdate = true; }.bind(this)});
|
|
147
|
|
148 this.camera = new THREE.PerspectiveCamera( 45, this.size.x / this.size.y, .1, 100 );
|
|
149 scene.add(this.camera);
|
|
150
|
|
151 var geometry = new THREE.SphereGeometry( .3, 32, 32 );
|
|
152 var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
|
|
153 this.cursor = new THREE.Mesh( geometry, material );
|
|
154 scene.add(this.cursor);
|
|
155
|
|
156 this.rotY = 0;
|
|
157 this.startAnimLoop();
|
|
158 }.bind(this));
|
|
159 },
|
|
160 startAnimLoop: function() {
|
|
161 var lastTime = Date.now();
|
|
162 requestAnimationFrame(function animate(){
|
|
163 var now = Date.now();
|
|
164 var dt = (now - lastTime) / 1000;
|
|
165 lastTime = now;
|
|
166 this.step(dt);
|
|
167 requestAnimationFrame(animate.bind(this));
|
|
168 }.bind(this))
|
|
169 },
|
|
170 step: function(dt) {
|
|
171 this.rotY += this.config.camRotSpeed * dt;
|
|
172
|
|
173 var p = new THREE.Vector3(this.config.camDist, this.config.camY, 0);
|
|
174 p.applyAxisAngle(new THREE.Vector3(0, 1, 0), this.rotY / 360 * 6.28);
|
|
175 this.camera.position.copy(p);
|
|
176
|
|
177 this.camera.lookAt(new THREE.Vector3(-1, 0, 0));
|
|
178
|
|
179 this.cursor.position.set(this.config.cursorX, this.config.cursorY, this.config.cursorZ);
|
|
180 for (var p of Object.keys(this.bars)) {
|
|
181 var b = this.bars[p];
|
|
182 b.update2d(this.camera, this.size);
|
|
183 b.setValue(b.value, b.label);
|
|
184 }
|
|
185 this.renderer.render(this.scene, this.camera);
|
|
186 },
|
|
187 onPositionEstimates: function() {
|
|
188 if (!this.scene) {
|
|
189 return;
|
|
190 }
|
|
191
|
|
192 for (var p of Object.keys(this.bars)) {
|
|
193 var b = this.bars[p];
|
|
194 b.setValue(0.001, '');
|
|
195 }
|
|
196 this.positionEstimates.forEach(function(row) {
|
|
197 var posKey = (Math.round(row[1][0] * 100) + ' ' +
|
|
198 Math.round(row[1][1] * 100) + ' ' +
|
|
199 Math.round(row[1][2] * 100));
|
|
200 var b = this.bars[posKey];
|
|
201 if (!b) {
|
|
202 b = new Bar(this.scene, this.$.scene,
|
|
203 new THREE.Vector3(-row[1][0], row[1][2], row[1][1]));
|
|
204 this.bars[posKey] = b;
|
|
205 }
|
|
206 b.setValue(10 / row[0], Math.round(row[0] * 100) / 100);
|
|
207 }.bind(this));
|
|
208 },
|
|
209 onBeacons: function() {
|
|
210 this.beacons.forEach(function(b) {
|
|
211 this.config.cursorX = -b.pos[0];
|
|
212 this.config.cursorY = b.pos[2];
|
|
213 this.config.cursorZ = b.pos[1];
|
|
214 }.bind(this));
|
|
215 }
|
|
216 });
|
|
217 </script>
|
|
218 </dom-module>
|