source: main/trunk/greenstone3/web/interfaces/default_new/js/panoramaViewer.js@ 29852

Last change on this file since 29852 was 29852, checked in by Georgiy Litvinov, 9 years ago

Ckeditor integration commit

File size: 11.5 KB
Line 
1// Array element swap code by Richard Scarrott
2// http://jsperf.com/array-prototype-move
3Array.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
30var panoContainer, camera, scene, renderer, projector;
31
32var mouse = { x: 0, y: 0 };
33
34var 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
45var panoDocList = new Array();
46panoDocList.ids = new Array();
47panoDocList.getDocByIndex = function(index) {
48 return panoDocList[panoDocList.ids[index]];
49};
50
51var nearbyPanoList = new Array();
52nearbyPanoList.ids = new Array();
53
54function 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
125function 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
130function 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
143function 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
159function 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
240function onWindowResize() {
241 camera.aspect = window.innerWidth / window.innerHeight;
242 camera.updateProjectionMatrix();
243
244 renderer.setSize( window.innerWidth, window.innerHeight );
245}
246
247
248function 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
258function onDocumentMouseMove( event ) {
259 if ( isUserInteracting ) {
260 lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
261 lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
262 }
263}
264
265function onDocumentMouseUp( event ) {
266 var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
267 projector.unprojectVector( vector, camera );
268 isUserInteracting = false;
269}
270
271function 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
293function _animate() {
294 requestAnimationFrame( _animate );
295 _render();
296 TWEEN.update();
297
298}
299
300function _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}
Note: See TracBrowser for help on using the repository browser.