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