|
1 function RotationSupport(accelerationCallback) { |
|
2 this.controls = new RotationControls(accelerationCallback); |
|
3 } |
|
4 |
|
5 function RotationControls(accelCallback) { |
|
6 var width = 50, height = 100, depth = 10; |
|
7 var margin = 5, bottomMargin = 15; |
|
8 var angleX = 180; |
|
9 var angleY = 180; |
|
10 var angleZ = 180; |
|
11 var accelerationCallback = accelCallback; |
|
12 |
|
13 $("#sliderX").slider( { |
|
14 slide : updateAngleX, |
|
15 animate : true, |
|
16 max : 360, |
|
17 min : 0, |
|
18 value : angleX |
|
19 }); |
|
20 $("#sliderY").slider( { |
|
21 slide : updateAngleY, |
|
22 animate : true, |
|
23 max : 360, |
|
24 min : 0, |
|
25 value : angleY |
|
26 }); |
|
27 $("#sliderZ").slider( { |
|
28 slide : updateAngleZ, |
|
29 animate : true, |
|
30 max : 360, |
|
31 min : 0, |
|
32 value : angleZ |
|
33 }); |
|
34 renderUI(); |
|
35 |
|
36 function translateFace(xy, xz, yz) { |
|
37 var px = width / 2; |
|
38 var py = height / 2; |
|
39 var pz = depth/2; |
|
40 var points = [ { |
|
41 x : px, |
|
42 y : py, |
|
43 z : pz |
|
44 }, { |
|
45 x : px, |
|
46 y : -py, |
|
47 z : pz |
|
48 }, { |
|
49 x : -px, |
|
50 y : -py, |
|
51 z : pz |
|
52 }, { |
|
53 x : -px, |
|
54 y : py, |
|
55 z : pz |
|
56 } ]; |
|
57 return rotate(points, xy, xz, yz); |
|
58 } |
|
59 |
|
60 function translateScreen(xy, xz, yz) { |
|
61 var px = width / 2; |
|
62 var py = height / 2; |
|
63 var pz = depth/2; |
|
64 var points = [ { |
|
65 x : px - margin, |
|
66 y : py - bottomMargin, |
|
67 z : pz |
|
68 }, { |
|
69 x : px - margin, |
|
70 y : -py + bottomMargin, |
|
71 z : pz |
|
72 }, { |
|
73 x : -px + margin, |
|
74 y : -py + margin, |
|
75 z : pz |
|
76 }, { |
|
77 x : -px + margin, |
|
78 y : py - margin, |
|
79 z : pz |
|
80 } ]; |
|
81 return rotate(points, xy, xz, yz); |
|
82 } |
|
83 |
|
84 function translateBack(xy, xz, yz) { |
|
85 var px = width / 2; |
|
86 var py = height / 2; |
|
87 var pz = -depth/2; |
|
88 var points = [ { |
|
89 x : px, |
|
90 y : py, |
|
91 z : pz |
|
92 }, { |
|
93 x : px, |
|
94 y : -py, |
|
95 z : pz |
|
96 }, { |
|
97 x : -px, |
|
98 y : -py, |
|
99 z : pz |
|
100 }, { |
|
101 x : -px, |
|
102 y : py, |
|
103 z : pz |
|
104 } ]; |
|
105 return rotate(points, xy, xz, yz); |
|
106 } |
|
107 |
|
108 function translateTop(xy, xz, yz) { |
|
109 var px = width / 2; |
|
110 var py = height / 2; |
|
111 var pz = depth/2; |
|
112 var points = [ { |
|
113 x : px, |
|
114 y : -py, |
|
115 z : pz |
|
116 }, { |
|
117 x : px, |
|
118 y : -py, |
|
119 z : -pz |
|
120 }, { |
|
121 x : px, |
|
122 y : py, |
|
123 z : -pz |
|
124 }, { |
|
125 x : px, |
|
126 y : py, |
|
127 z : pz |
|
128 } ]; |
|
129 return rotate(points, xy, xz, yz); |
|
130 } |
|
131 |
|
132 function translateBottom(xy, xz, yz) { |
|
133 var px = -width / 2; |
|
134 var py = height / 2; |
|
135 var pz = depth/2; |
|
136 var points = [ { |
|
137 x : px, |
|
138 y : -py, |
|
139 z : pz |
|
140 }, { |
|
141 x : px, |
|
142 y : -py, |
|
143 z : -pz |
|
144 }, { |
|
145 x : px, |
|
146 y : py, |
|
147 z : -pz |
|
148 }, { |
|
149 x : px, |
|
150 y : py, |
|
151 z : pz |
|
152 } ]; |
|
153 return rotate(points, xy, xz, yz); |
|
154 } |
|
155 |
|
156 function translateLeft(xy, xz, yz) { |
|
157 var px = width / 2; |
|
158 var py = height / 2; |
|
159 var pz = depth/2; |
|
160 var points = [ { |
|
161 x : px, |
|
162 y : py, |
|
163 z : pz |
|
164 }, { |
|
165 x : px, |
|
166 y : py, |
|
167 z : -pz |
|
168 }, { |
|
169 x : -px, |
|
170 y : py, |
|
171 z : -pz |
|
172 }, { |
|
173 x : -px, |
|
174 y : py, |
|
175 z : pz |
|
176 } ]; |
|
177 return rotate(points, xy, xz, yz); |
|
178 } |
|
179 |
|
180 function translateRight(xy, xz, yz) { |
|
181 var px = width / 2; |
|
182 var py = -height / 2; |
|
183 var pz = depth/2; |
|
184 var points = [ { |
|
185 x : px, |
|
186 y : py, |
|
187 z : pz |
|
188 }, { |
|
189 x : px, |
|
190 y : py, |
|
191 z : -pz |
|
192 }, { |
|
193 x : -px, |
|
194 y : py, |
|
195 z : -pz |
|
196 }, { |
|
197 x : -px, |
|
198 y : py, |
|
199 z : pz |
|
200 } ]; |
|
201 return rotate(points, xy, xz, yz); |
|
202 } |
|
203 |
|
204 |
|
205 function renderUI() { |
|
206 var canvas = document.getElementById("phoneposition"); |
|
207 var ctx = canvas.getContext("2d"); |
|
208 ctx.clearRect(0, 0, canvas.width, canvas.height); |
|
209 |
|
210 var r = 62; |
|
211 |
|
212 var xy = (180 - angleX) * Math.PI / 180; |
|
213 var yz = (angleY - 180) * Math.PI / 180; |
|
214 var xz = (180 - angleZ) * Math.PI / 180 + Math.PI / 2; |
|
215 |
|
216 var back = translateBack(xy, xz, yz); |
|
217 if ((back[0].z + back[2].z)/2 < 0) { |
|
218 paint(canvas, ctx, back); |
|
219 } else { |
|
220 paint(canvas, ctx, translateFace(xy, xz, yz)); |
|
221 paintScreen(canvas, ctx, translateScreen(xy, xz, yz)); |
|
222 } |
|
223 |
|
224 var dz = 0; |
|
225 if (back[0].z > back[3].z) { |
|
226 var bottom = translateBottom(xy, xz, yz); |
|
227 paint(canvas, ctx, bottom); |
|
228 dz = bottom[1].y - bottom[0].y; |
|
229 } else if (back[0].z != back[3].z) { |
|
230 var top = translateTop(xy, xz, yz); |
|
231 paint(canvas, ctx, top); |
|
232 dz = top[1].y - top[0].y; |
|
233 } |
|
234 |
|
235 if (back[1].z > back[0].z) { |
|
236 paint(canvas, ctx, translateLeft(xy, xz, yz)); |
|
237 } else if (back[1].z != back[0].z) { |
|
238 paint(canvas, ctx, translateRight(xy, xz, yz)); |
|
239 } |
|
240 var accelX = (back[1].y - back[0].y) / width; |
|
241 var accelY = (back[0].y - back[3].y) / height; |
|
242 var accelZ = dz / depth; |
|
243 |
|
244 notifyAcceleration(accelX, accelY, accelZ); |
|
245 } |
|
246 |
|
247 function rotate(points, xy, xz, yz) { |
|
248 var res = new Array(); |
|
249 for ( var p in points) { |
|
250 var px = points[p].x; |
|
251 var py = points[p].y; |
|
252 var pz = points[p].z; |
|
253 |
|
254 var rx = Math.sqrt(px * px + py * py); |
|
255 var angXY = Math.atan(px / py) + (px < 0 ? Math.PI : 0); |
|
256 |
|
257 px = rx * Math.sin(angXY + xy); |
|
258 py = rx * Math.cos(angXY + xy); |
|
259 |
|
260 var rz = Math.sqrt(px * px + pz * pz); |
|
261 var angXZ = (px == 0 ? 0 : Math.atan(pz / px)) |
|
262 + (px < 0 ? Math.PI : 0); |
|
263 |
|
264 px = rz * Math.sin(angXZ + xz); |
|
265 pz = rz * Math.cos(angXZ + xz); |
|
266 |
|
267 var ry = Math.sqrt(py * py + pz * pz); |
|
268 var angYZ = (pz == 0 ? 0 : Math.atan(py / pz)) |
|
269 + (pz < 0 ? Math.PI : 0); |
|
270 |
|
271 py = ry * Math.sin(angYZ + yz); |
|
272 pz = ry * Math.cos(angYZ + yz); |
|
273 |
|
274 res.push( { |
|
275 x : px, |
|
276 y : py, |
|
277 z : pz |
|
278 }); |
|
279 } |
|
280 return res; |
|
281 } |
|
282 |
|
283 function updateAngleX(event, ui) { |
|
284 angleX = ui.value; |
|
285 renderUI(); |
|
286 } |
|
287 |
|
288 function updateAngleY(event, ui) { |
|
289 angleY = ui.value; |
|
290 renderUI(); |
|
291 } |
|
292 |
|
293 function updateAngleZ(event, ui) { |
|
294 angleZ = ui.value; |
|
295 renderUI(); |
|
296 } |
|
297 |
|
298 function paint(canvas, ctx, points) { |
|
299 var xcoord = canvas.width / 2; |
|
300 var ycoord = canvas.height / 2; |
|
301 |
|
302 ctx.fillStyle = "yellow"; |
|
303 ctx.strokeStyle = "black"; |
|
304 ctx.beginPath(); |
|
305 ctx.moveTo(xcoord + points[3].x, ycoord + points[3].y); |
|
306 for (point in points) { |
|
307 ctx.lineTo(xcoord + points[point].x, ycoord + points[point].y); |
|
308 } |
|
309 ctx.fill(); |
|
310 ctx.beginPath(); |
|
311 ctx.moveTo(xcoord + points[3].x, ycoord + points[3].y); |
|
312 for (point in points) { |
|
313 ctx.lineTo(xcoord + points[point].x, ycoord + points[point].y); |
|
314 } |
|
315 ctx.stroke(); |
|
316 } |
|
317 |
|
318 function paintScreen(canvas, ctx, screen) { |
|
319 var xcoord = canvas.width / 2; |
|
320 var ycoord = canvas.height / 2; |
|
321 |
|
322 ctx.fillStyle = "grey"; |
|
323 ctx.beginPath(); |
|
324 ctx.moveTo(xcoord + screen[3].x, ycoord + screen[3].y); |
|
325 for (point in screen) { |
|
326 ctx.lineTo(xcoord + screen[point].x, ycoord + screen[point].y); |
|
327 } |
|
328 ctx.fill(); |
|
329 } |
|
330 |
|
331 function notifyAcceleration(x, y, z) { |
|
332 accelerationCallback(x, y, z); |
|
333 } |
|
334 } |