1 | // Array element swap code by Richard Scarrott
|
---|
2 | // http://jsperf.com/array-prototype-move
|
---|
3 | Array.prototype.move = function(pos1, pos2) {
|
---|
4 | // local variables
|
---|
5 | var i, tmp;
|
---|
6 | // cast input parameters to integers
|
---|
7 | pos1 = parseInt(pos1, 10);
|
---|
8 | pos2 = parseInt(pos2, 10);
|
---|
9 | // if positions are different and inside array
|
---|
10 | if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) {
|
---|
11 | // save element from position 1
|
---|
12 | tmp = this[pos1];
|
---|
13 | // move element down and shift other elements up
|
---|
14 | if (pos1 < pos2) {
|
---|
15 | for (i = pos1; i < pos2; i++) {
|
---|
16 | this[i] = this[i + 1];
|
---|
17 | }
|
---|
18 | }
|
---|
19 | // move element up and shift other elements down
|
---|
20 | else {
|
---|
21 | for (i = pos1; i > pos2; i--) {
|
---|
22 | this[i] = this[i - 1];
|
---|
23 | }
|
---|
24 | }
|
---|
25 | // put element from position 1 to destination
|
---|
26 | this[pos2] = tmp;
|
---|
27 | }
|
---|
28 | }
|
---|
29 |
|
---|
30 | var panoContainer, camera, scene, renderer, projector;
|
---|
31 |
|
---|
32 | var mouse = { x: 0, y: 0 };
|
---|
33 |
|
---|
34 | var fov = 70, maxFov = 90, minFov = 15,
|
---|
35 | width,height, aspect,
|
---|
36 | isUserInteracting = false,
|
---|
37 | onMouseDownMouseX = 0, onMouseDownMouseY = 0,
|
---|
38 | lon = 0, onMouseDownLon = 0,
|
---|
39 | lat = 0, onMouseDownLat = 0,
|
---|
40 | phi = 0, theta = 0,
|
---|
41 | mesh, sphereRadius = 500,
|
---|
42 | meshRotation = Math.PI,
|
---|
43 | panoSelectionRadius = 40;
|
---|
44 |
|
---|
45 |
|
---|
46 | var panoDocList = new Array();
|
---|
47 | panoDocList.ids = new Array();
|
---|
48 | panoDocList.getDocByIndex = function(index) {
|
---|
49 | return panoDocList[panoDocList.ids[index]];
|
---|
50 | };
|
---|
51 |
|
---|
52 | var nearbyPanoList = new Array();
|
---|
53 | nearbyPanoList.ids = new Array();
|
---|
54 | nearbyPanoList.pos = new Array();
|
---|
55 |
|
---|
56 |
|
---|
57 | function initPanoramaViewer() {
|
---|
58 |
|
---|
59 | //Creating the document list to store data about the panoramams
|
---|
60 | var jsonNodeDiv = $("#jsonPanoNodes");
|
---|
61 | if(jsonNodeDiv.length) {
|
---|
62 | var jsonNodehtml = jsonNodeDiv.html();
|
---|
63 | var jsonNodes = eval(jsonNodehtml);
|
---|
64 | if(jsonNodes && jsonNodes.length > 0) {
|
---|
65 | for(var i = 0; i < jsonNodes.length; i++) {
|
---|
66 | panoDocList[jsonNodes[i].nodeID] = jsonNodes[i];
|
---|
67 | panoDocList.ids.push(jsonNodes[i].nodeID);
|
---|
68 | }
|
---|
69 | } else {
|
---|
70 | $("pano-container").css({visibility:"hidden", height:"0px"});
|
---|
71 | }
|
---|
72 | }
|
---|
73 |
|
---|
74 | panoContainer = document.getElementById( 'pano-container' );
|
---|
75 |
|
---|
76 | // Creating the camera
|
---|
77 | // Setting width and height variables as the container dimensions changes when fov is changed
|
---|
78 | width = panoContainer.offsetWidth;
|
---|
79 | height = panoContainer.offsetHeight;
|
---|
80 | aspect = width / height;
|
---|
81 |
|
---|
82 | // camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
|
---|
83 | // camera = new THREE.PerspectiveCamera( fov, container.offsetWidth / container.offsetHeight, 1, 1100 );
|
---|
84 | camera = new THREE.PerspectiveCamera( fov, aspect, 1, 1100 );
|
---|
85 | camera.target = new THREE.Vector3(0, 0, 0 );
|
---|
86 |
|
---|
87 | // Creating the scene
|
---|
88 | scene = new THREE.Scene();
|
---|
89 |
|
---|
90 | projector = new THREE.Projector();
|
---|
91 |
|
---|
92 | // Creating a sphere with the panorama applied as a texture
|
---|
93 | if (Detector.webgl) {
|
---|
94 | mesh = new THREE.Mesh( new THREE.SphereGeometry( sphereRadius, 60, 40 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( gs.collectionMetadata.httpPath + '/import/panorama/' + 'panorama0.jpg' ), wireframe: false } ) );
|
---|
95 | } else {
|
---|
96 | mesh = new THREE.Mesh( new THREE.SphereGeometry( sphereRadius, 30, 20 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( gs.collectionMetadata.httpPath + '/import/panorama/' + 'panorama0.jpg' ), wireframe: false, overdraw: true } ) );
|
---|
97 | }
|
---|
98 | mesh.scale.x = -1;
|
---|
99 | // mesh.rotation.y = meshRotation + (90 * Math.PI / 180);
|
---|
100 | scene.add( mesh ); // Adding the sphere to the scene
|
---|
101 |
|
---|
102 | switchPanorama(panoDocList.ids[0]);
|
---|
103 |
|
---|
104 | renderer = Detector.webgl? new THREE.WebGLRenderer(): new THREE.CanvasRenderer();
|
---|
105 | //renderer.setSize( window.innerWidth, window.innerHeight );
|
---|
106 | //renderer.setSize(container.offsetWidth,container.offsetHeight);
|
---|
107 | renderer.setSize(width,height);
|
---|
108 |
|
---|
109 | panoContainer.appendChild( renderer.domElement );
|
---|
110 |
|
---|
111 | // Adding in Mouse events
|
---|
112 | panoContainer.addEventListener( 'mousedown', onDocumentMouseDown, false );
|
---|
113 | document.addEventListener( 'mousemove', onDocumentMouseMove, false );
|
---|
114 | document.addEventListener( 'mouseup', onDocumentMouseUp, false );
|
---|
115 | panoContainer.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
|
---|
116 | panoContainer.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);
|
---|
117 |
|
---|
118 | // window.addEventListener( 'resize', onWindowResize, false );
|
---|
119 | }
|
---|
120 |
|
---|
121 | function degreesToCoords(degrees, radius) {
|
---|
122 | return new THREE.Vector3(Math.cos(degrees * Math.PI/180) * radius, 0, Math.sin(degrees * Math.PI/180) * radius);
|
---|
123 | }
|
---|
124 |
|
---|
125 |
|
---|
126 | function calculateBearing(from, to) {
|
---|
127 | // x is lat and y is long
|
---|
128 | var R = 6371; // km
|
---|
129 | var lat1 = from.x * Math.PI / 180;
|
---|
130 | var lat2 = to.x * Math.PI / 180;
|
---|
131 | var dLon = (to.y-from.y) * Math.PI / 180;
|
---|
132 | var y = Math.sin(dLon) * Math.cos(lat2);
|
---|
133 | var x = Math.cos(lat1)*Math.sin(lat2) -
|
---|
134 | Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
|
---|
135 | var brng = (Math.atan2(y, x)) * 180 / Math.PI;
|
---|
136 | return (brng + 360) % 360;
|
---|
137 | }
|
---|
138 |
|
---|
139 | function calculateDistance(from, to) {
|
---|
140 | // x is lat and y is long
|
---|
141 | var R = 6371; // km
|
---|
142 | var dLat = (from.x-to.x) * Math.PI / 180;
|
---|
143 | var dLon = (from.y-to.y) * Math.PI / 180;
|
---|
144 | var lat1 = from.x * Math.PI / 180;
|
---|
145 | var lat2 = to.x * Math.PI / 180;
|
---|
146 |
|
---|
147 | var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
---|
148 | Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
|
---|
149 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
---|
150 | var d = R * c;
|
---|
151 | // return distance in metres
|
---|
152 | return d * 1000;
|
---|
153 | }
|
---|
154 |
|
---|
155 | /*
|
---|
156 | function fullscreenToggle () {
|
---|
157 | console.log("blah");
|
---|
158 | if( THREEx.FullScreen.activated() ){
|
---|
159 | THREEx.FullScreen.cancel();
|
---|
160 |
|
---|
161 | camera.aspect = width / height;
|
---|
162 | camera.updateProjectionMatrix();
|
---|
163 |
|
---|
164 | renderer.setSize( width, height );
|
---|
165 |
|
---|
166 | }else{
|
---|
167 | console.log("Fullscreen");
|
---|
168 | THREEx.FullScreen.request(document.getElementById( 'asdf' ));
|
---|
169 |
|
---|
170 | //THREEx.FullScreen.request(panoContainer);
|
---|
171 |
|
---|
172 | // THREEx.FullScreen.request(document.getElementById( renderer ));
|
---|
173 | camera.aspect = window.innerWidth / window.innerHeight;
|
---|
174 | camera.updateProjectionMatrix();
|
---|
175 |
|
---|
176 | //renderer.setSize( window.innerWidth, window.innerHeight );
|
---|
177 |
|
---|
178 | }
|
---|
179 | }
|
---|
180 | */
|
---|
181 |
|
---|
182 | function switchPanorama( panoramaID, destMarker ) {
|
---|
183 | // Building the file path
|
---|
184 | var sourceFile = gs.documentMetadata[panoramaID].SourceFile;
|
---|
185 | var assocfilepath = gs.documentMetadata[panoramaID].assocfilepath;
|
---|
186 | var httpPath = gs.collectionMetadata.httpPath;
|
---|
187 |
|
---|
188 | var fullPanoURL = httpPath + "/index/assoc/" + assocfilepath + "/" + sourceFile;
|
---|
189 |
|
---|
190 | console.log("pano URL = " + fullPanoURL);
|
---|
191 |
|
---|
192 | // Creating the material
|
---|
193 | if (Detector.webgl) {
|
---|
194 | var texture = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( fullPanoURL ), opacity: 0 } );
|
---|
195 | } else {
|
---|
196 | var texture = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( fullPanoURL ), opacity: 0, wireframe: false, overdraw: true } );
|
---|
197 | }
|
---|
198 |
|
---|
199 | if (destMarker) {
|
---|
200 | new TWEEN.Tween(mesh.position).to({x: -destMarker.position.x, y: -destMarker.position.y, z: -destMarker.position.z}, 500).onComplete(function () {
|
---|
201 | mesh.position = new THREE.Vector3(destMarker.position.x,destMarker.position.y,destMarker.position.z);
|
---|
202 | new TWEEN.Tween(mesh.position).to({x: 0, y: 0,z: 0},500).start();
|
---|
203 | }).start();
|
---|
204 | }
|
---|
205 |
|
---|
206 | new TWEEN.Tween(mesh.materials[0]).to({opacity: 0}, 500).onComplete(function () {
|
---|
207 | mesh.materials[0] = texture;
|
---|
208 | new TWEEN.Tween(mesh.materials[0]).to({opacity: 1}, 500).start();
|
---|
209 | }).start();
|
---|
210 |
|
---|
211 | // Setting the mesh material
|
---|
212 |
|
---|
213 |
|
---|
214 | // Rotation
|
---|
215 | if (gs.documentMetadata[panoramaID].cv_rotation)
|
---|
216 | mesh.rotation.y = meshRotation + (gs.documentMetadata[panoramaID].cv_rotation * Math.PI / 180);
|
---|
217 | else
|
---|
218 | mesh.rotation.y = meshRotation;
|
---|
219 |
|
---|
220 | // Checking if there are markers to remove
|
---|
221 | if (nearbyPanoList.length > 1) {
|
---|
222 | for(var i = 0; i < nearbyPanoList.length; i++) {
|
---|
223 | panoContainer.removeChild(nearbyPanoList[i]);
|
---|
224 | // document.body.appendChild(nearbyPanoList[i]);
|
---|
225 | nearbyPanoList[i].deactivate();
|
---|
226 | }
|
---|
227 | }
|
---|
228 |
|
---|
229 | // Clearing the array
|
---|
230 | nearbyPanoList = new Array();
|
---|
231 |
|
---|
232 | // Moving the selected pano to the front of the panolist array
|
---|
233 | panoDocList.move(panoDocList.ids.indexOf(panoramaID), 0);
|
---|
234 | panoDocList.ids.move(panoDocList.ids.indexOf(panoramaID), 0);
|
---|
235 |
|
---|
236 | var startPanoLonLat = new THREE.Vector3(gs.documentMetadata[panoramaID].Latitude,gs.documentMetadata[panoramaID].Longitude);
|
---|
237 |
|
---|
238 | // going through the panolist checking the distance
|
---|
239 | for(var i = 1; i < panoDocList.ids.length; i++) {
|
---|
240 | var endPanoLonLat = new THREE.Vector3(gs.documentMetadata[panoDocList.ids[i]].Latitude,gs.documentMetadata[panoDocList.ids[i]].Longitude);
|
---|
241 | if(calculateDistance(startPanoLonLat,endPanoLonLat) < panoSelectionRadius) {
|
---|
242 | var bearing = calculateBearing(startPanoLonLat,endPanoLonLat);
|
---|
243 | console.log(bearing);
|
---|
244 | var pos = degreesToCoords(bearing, sphereRadius);
|
---|
245 | var navMarker = NavMarker.create(panoDocList.ids[i],pos);
|
---|
246 | nearbyPanoList.push(navMarker);
|
---|
247 | //navMarker.addEventListener('click', switchPanorama(hash), false);
|
---|
248 | navMarker.addEventListener('click', function(e) {
|
---|
249 | var sender = (e && e.target) || (window.event && window.event.srcElement);
|
---|
250 | switchPanorama(sender.hash, sender); }, false);
|
---|
251 | }
|
---|
252 | }
|
---|
253 |
|
---|
254 | // Going through the new nearbyPanoList and adding in the markers to the scene
|
---|
255 | for(var i = 0; i < nearbyPanoList.length; i++) {
|
---|
256 | panoContainer.appendChild(nearbyPanoList[i]);
|
---|
257 | nearbyPanoList[i].activate();
|
---|
258 | }
|
---|
259 |
|
---|
260 | }
|
---|
261 |
|
---|
262 | /*
|
---|
263 | function onWindowResize() {
|
---|
264 | camera.aspect = window.innerWidth / window.innerHeight;
|
---|
265 | camera.updateProjectionMatrix();
|
---|
266 |
|
---|
267 | renderer.setSize( window.innerWidth, window.innerHeight );
|
---|
268 | }
|
---|
269 | */
|
---|
270 |
|
---|
271 | function onDocumentMouseDown( event ) {
|
---|
272 | event.preventDefault();
|
---|
273 |
|
---|
274 | isUserInteracting = true;
|
---|
275 |
|
---|
276 | onPointerDownPointerX = event.clientX;
|
---|
277 | onPointerDownPointerY = event.clientY;
|
---|
278 |
|
---|
279 | onPointerDownLon = lon;
|
---|
280 | onPointerDownLat = lat;
|
---|
281 |
|
---|
282 | }
|
---|
283 |
|
---|
284 | function onDocumentMouseMove( event ) {
|
---|
285 | if ( isUserInteracting ) {
|
---|
286 |
|
---|
287 | lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
|
---|
288 | lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
|
---|
289 | }
|
---|
290 | }
|
---|
291 |
|
---|
292 | function onDocumentMouseUp( event ) {
|
---|
293 | var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
|
---|
294 | projector.unprojectVector( vector, camera );
|
---|
295 | isUserInteracting = false;
|
---|
296 | }
|
---|
297 |
|
---|
298 | function onDocumentMouseWheel( event ) {
|
---|
299 |
|
---|
300 | // WebKit
|
---|
301 |
|
---|
302 | if ( event.wheelDeltaY ) {
|
---|
303 |
|
---|
304 | fov -= event.wheelDeltaY * 0.05;
|
---|
305 |
|
---|
306 | // Opera / Explorer 9
|
---|
307 |
|
---|
308 | } else if ( event.wheelDelta ) {
|
---|
309 |
|
---|
310 | fov -= event.wheelDelta * 0.05;
|
---|
311 |
|
---|
312 | // Firefox
|
---|
313 |
|
---|
314 | } else if ( event.detail ) {
|
---|
315 |
|
---|
316 | fov += event.detail * 1.0;
|
---|
317 |
|
---|
318 | }
|
---|
319 |
|
---|
320 | if ( fov > maxFov) {
|
---|
321 | fov = maxFov;
|
---|
322 | } else if (fov < minFov) {
|
---|
323 | fov = minFov;
|
---|
324 | }
|
---|
325 |
|
---|
326 | // camera.projectionMatrix.makePerspective( fov, container.offsetWidth / container.offsetHeight, 1, 1100 );
|
---|
327 | camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, aspect , 1, 1100 );
|
---|
328 | _render();
|
---|
329 |
|
---|
330 | }
|
---|
331 |
|
---|
332 | function _animate() {
|
---|
333 |
|
---|
334 | requestAnimationFrame( _animate );
|
---|
335 | _render();
|
---|
336 | TWEEN.update();
|
---|
337 |
|
---|
338 | }
|
---|
339 |
|
---|
340 | function _render() {
|
---|
341 | /*
|
---|
342 | lat = Math.max( - 85, Math.min( 85, lat ) );
|
---|
343 | phi = THREE.Math.degToRad( 90 - lat );
|
---|
344 | theta = THREE.Math.degToRad( lon );
|
---|
345 | */
|
---|
346 |
|
---|
347 | lat = Math.max( - 85, Math.min( 85, lat ) );
|
---|
348 | phi = ( 90 - lat ) * Math.PI / 180;
|
---|
349 | theta = lon * Math.PI / 180;
|
---|
350 |
|
---|
351 | camera.target.x = sphereRadius * Math.sin( phi ) * Math.cos( theta );
|
---|
352 | camera.target.y = sphereRadius * Math.cos( phi );
|
---|
353 | camera.target.z = sphereRadius * Math.sin( phi ) * Math.sin( theta );
|
---|
354 |
|
---|
355 | camera.lookAt( camera.target );
|
---|
356 |
|
---|
357 | /*
|
---|
358 | // distortion
|
---|
359 | camera.position.x = - camera.target.x;
|
---|
360 | camera.position.y = - camera.target.y;
|
---|
361 | camera.position.z = - camera.target.z;
|
---|
362 | */
|
---|
363 |
|
---|
364 | var camUnitVector = camera.target.clone().normalize();
|
---|
365 | var i, angle, sameSide, p2D, marker;
|
---|
366 |
|
---|
367 | for (i = 0; i < nearbyPanoList.length; ++i) {
|
---|
368 | marker = nearbyPanoList[i];
|
---|
369 | p2D = projector.projectVector(marker.position.clone(), camera);
|
---|
370 |
|
---|
371 | p2D.x = (p2D.x + 1)/2 * width;
|
---|
372 | p2D.y = - (p2D.y - 1)/2 * height;
|
---|
373 |
|
---|
374 | //my trick
|
---|
375 | angle = Math.acos(camUnitVector.dot(marker.unitVector)) * 180 / 3.14;
|
---|
376 | sameSide = (angle < 90);
|
---|
377 |
|
---|
378 | if(!sameSide || p2D.x < 0 || p2D.x > width ||
|
---|
379 | p2D.y < 0 || p2D.y > height) {
|
---|
380 | marker.visible(false);
|
---|
381 | } else {
|
---|
382 | marker.visible(true);
|
---|
383 | marker.setPosition(p2D.x, p2D.y);
|
---|
384 | }
|
---|
385 | }
|
---|
386 |
|
---|
387 |
|
---|
388 | renderer.render( scene, camera );
|
---|
389 |
|
---|
390 | } |
---|