2 // Various global variables
\r
3 var mouseX = 0, mouseY = 0,
\r
4 camera, scene, renderer, projector;
\r
5 var sTestEventType = 'mousedown';
\r
6 //var window3DWidth = window.innerWidth * 0.8;
\r
7 //var window3DHeight=window.innerHeight*0.75;
\r
8 var window3DWidth, window3DHeight;
\r
10 // Camera parameters
\r
11 phi = -100, theta = 0, distance = 150;
\r
14 var info, nodelist, help;
\r
19 // list of selected nodes
\r
20 var selectedNodes = [];
\r
22 var div3d, nodebox, infobox;
\r
25 var particles, particle;
\r
27 // jordan : modifier document.getElementById
\r
28 div3d = jQuery('#div3d');
\r
29 nodebox = jQuery('#nodebox');
\r
30 infobox = jQuery('#infobox');
\r
31 titlebox = jQuery('#titlebox');
\r
33 var offset = div3d.offset();
\r
37 titlebox.innerHTML = 'Grenoble Site ' + nodes_gre.length + " nodes";
\r
38 infobox.innerHTML = 'Node info : ';
\r
42 camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000);
\r
44 scene = new THREE.Scene();
\r
46 renderer = new THREE.CanvasRenderer();
\r
48 // jordan XXX div3d.appendChild(renderer.domElement);
\r
49 div3d.append(renderer.domElement);
\r
51 window.addEventListener('resize', set3dsize, false);
\r
56 var PI2 = Math.PI * 2;
\r
57 var geometry = new THREE.Geometry();
\r
59 // let's find the center of the nodes
\r
60 xmin = ymin = zmin = 0;
\r
61 xmax = ymax = zmax = 0;
\r
63 for (var i = 0; i < nodes_gre.length; i++) {
\r
64 if (nodes_gre[i][1] > xmax) xmax = nodes_gre[i][1];
\r
65 if (nodes_gre[i][1] < xmin) xmin = nodes_gre[i][1];
\r
66 if (nodes_gre[i][2] > ymax) ymax = nodes_gre[i][2];
\r
67 if (nodes_gre[i][2] < ymin) ymin = nodes_gre[i][2];
\r
68 if (nodes_gre[i][3] > zmax) zmax = nodes_gre[i][3];
\r
69 if (nodes_gre[i][3] < zmin) zmin = nodes_gre[i][3];
\r
72 xcenter = (xmax + xmin) / 2;
\r
73 ycenter = (ymax + ymin) / 2;
\r
74 zcenter = (zmax + zmin) / 2;
\r
76 // display nodes as TREE particles
\r
77 for (var i = 0; i < nodes_gre.length; i++) {
\r
78 material = new THREE.ParticleCanvasMaterial({
\r
80 program: function (context) {
\r
81 context.beginPath();
\r
82 context.arc(0, 0, 1, 0, PI2, true);
\r
83 context.closePath();
\r
87 particle = new THREE.Particle(material);
\r
88 particle.name = nodes_gre[i][0];
\r
89 particle.position.x = nodes_gre[i][1] - xcenter;
\r
90 particle.position.y = nodes_gre[i][2] - ycenter;
\r
91 particle.position.z = nodes_gre[i][3] - zcenter;
\r
92 particle.position.multiplyScalar(10);
\r
93 particle.scale.x = particle.scale.y = 1;
\r
94 scene.add(particle);
\r
95 v = new THREE.Vertex(particle.position);
\r
96 geometry.vertices.push(v);
\r
97 objects.push(particle)
\r
101 // a projector is needed to find which node is under the mouse
\r
102 projector = new THREE.Projector();
\r
104 nodebox.onkeyup = parseNodebox;
\r
105 // set mouse event handlers // TODO jordan
\r
106 document.onmousedown = OnMouseDown;
\r
107 document.onmouseup = OnMouseUp;
\r
108 document.onmousemove = displayNodeInfo;
\r
109 if (window.addEventListener)
\r
110 /** DOMMouseScroll is for mozilla. */
\r
111 window.addEventListener('DOMMouseScroll', wheel, false);
\r
113 window.onmousewheel = document.onmousewheel = wheel;
\r
117 function set3dsize() {
\r
119 var offset = div3d.offset();
\r
121 offX = offset.left;
\r
122 window3DWidth = div3d.width();
\r
123 window3DHeight = div3d.height();
\r
124 renderer.setSize(window3DWidth, window3DHeight);
\r
126 camera.aspect = window3DWidth / window3DHeight;
\r
127 camera.updateProjectionMatrix();
\r
132 function sortfunction(a, b) {
\r
133 return (a - b) //causes an array to be sorted numerically and ascending
\r
136 // factorize the expanded list in selectedNode to produce dash intervals
\r
137 // 1,2,3,5,9 -> 1-3,5,9
\r
138 function factorize() {
\r
141 var intervalStart = 0;
\r
142 selectedNodes.sort(sortfunction);
\r
143 for (j = 0; j < selectedNodes.length; j++) {
\r
144 if (intervalStart) {
\r
145 // we are in an interval
\r
146 if (selectedNodes[j] == previous + 1) {
\r
151 fact.push(intervalStart + "-" + previous);
\r
153 previous = selectedNodes[j];
\r
156 // we are not in an interval
\r
157 if (selectedNodes[j] == previous + 1) {
\r
158 // let's begin an interval
\r
159 intervalStart = previous;
\r
162 if (previous) fact.push(previous);
\r
163 previous = selectedNodes[j];
\r
167 // at the end of the loop, two cases
\r
168 // we were still in an interval, then add it to the result
\r
169 // we were not in an interval, then add the last selectednode (previous)
\r
170 if (intervalStart) {
\r
171 fact.push(intervalStart + "-" + previous);
\r
173 if (previous) fact.push(previous);
\r
178 // expand a list of nodes containing dash intervals
\r
179 // 1-3,5,9 -> 1,2,3,5,9
\r
180 function expand(factExp) {
\r
182 for (i = 0; i < factExp.length; i++) {
\r
183 dashExpression = factExp[i].split("-");
\r
184 if (dashExpression.length == 2) {
\r
185 for (j = parseInt(dashExpression[0]); j < (parseInt(dashExpression[1]) + 1); j++)
\r
187 } else exp.push(parseInt(factExp[i]));
\r
189 exp.sort(sortfunction);
\r
190 for (var i = 1; i < exp.length; i++) { if (exp[i] == exp[i - 1]) { exp.splice(i--, 1); } }
\r
194 function parseNodebox() {
\r
195 input = nodebox.value;
\r
196 selectedNodes = expand(input.split(","));
\r
200 function debugaxis(axisLength) {
\r
201 //Shorten the vertex function
\r
202 function v(x, y, z) {
\r
203 return new THREE.Vertex(new THREE.Vector3(x, y, z));
\r
206 //Create axis (point1, point2, colour)
\r
207 function createAxis(p1, p2, color) {
\r
208 var line, lineGeometry = new THREE.Geometry(),
\r
209 lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });
\r
210 lineGeometry.vertices.push(p1, p2);
\r
211 line = new THREE.Line(lineGeometry, lineMat);
\r
215 createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);
\r
216 createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);
\r
217 createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);
\r
220 // set the camera position according two angles theta and phi and the distance
\r
221 // and display the scene
\r
222 function myrender() {
\r
223 //infobox.innerHTML = " Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z
\r
224 // + " - " + theta + "," + phi + ","+ distance;
\r
225 //infobox.innerHTML = selectedNodes;
\r
226 camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);
\r
227 camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);
\r
228 camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);
\r
229 camera.lookAt(scene.position);
\r
230 camera.updateMatrix();
\r
232 for (i = 0; i < objects.length; i++)
\r
233 if (selectedNodes.indexOf(objects[i].name) != -1) objects[i].material.color.setHex(0xff0000);
\r
234 else objects[i].material.color.setHex(0xffffff);
\r
235 renderer.render(scene, camera);
\r
238 // rigthbutton is used for rotations
\r
239 function onDocumentMouseMoveRot(event) {
\r
240 NewmouseX = event.clientX;
\r
241 NewmouseY = event.clientY;
\r
242 DeltaX = NewmouseX - mouseX;
\r
243 DeltaY = NewmouseY - mouseY;
\r
245 mouseX = NewmouseX;
\r
246 mouseY = NewmouseY;
\r
250 if (phi > 180) phi = 180;
\r
251 if (phi < -180) phi = -180;
\r
254 // mousewheel is used for zoom
\r
255 function Zoom(delta) {
\r
256 distance += delta * 5;
\r
260 // return the graphical node under the mouse
\r
261 function findNodeUnderMouse(event) {
\r
262 var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5);
\r
263 projector.unprojectVector(vector, camera);
\r
264 var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());
\r
265 var intersects = ray.intersectObjects(objects);
\r
266 if (intersects.length > 0) {
\r
267 return intersects[0];
\r
268 } else return null;
\r
271 // display some info of the node under the mouse
\r
272 function displayNodeInfo(e) {
\r
273 obj = findNodeUnderMouse(e);
\r
274 if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + nodes_gre[obj.object.id][4];
\r
275 // else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY;
\r
278 // select/unselect nodes
\r
279 function toggleNode(obj) {
\r
280 nodeId = obj.object.name;
\r
281 i = selectedNodes.indexOf(nodeId);
\r
282 if (i == -1) selectedNodes.push(nodeId);
\r
283 else selectedNodes.splice(i, 1);
\r
284 nodebox.value = factorize().join(",");
\r
288 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
289 // Mouse handling functions
\r
291 function OnMouseDown(e) {
\r
292 var clickType = 'LEFT';
\r
293 if (e.type != sTestEventType) return true
\r
295 if (e.which == 3) clickType = 'RIGHT';
\r
296 if (e.which == 2) clickType = 'MIDDLE';
\r
297 //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;
\r
299 mouseX = e.clientX;
\r
300 mouseY = e.clientY;
\r
301 if (clickType == 'RIGHT') {
\r
302 document.onmousemove = onDocumentMouseMoveRot;
\r
304 if (clickType == 'LEFT') {
\r
305 obj = findNodeUnderMouse(e);
\r
306 if (obj != null) toggleNode(obj);
\r
310 function OnMouseUp(e) {
\r
311 document.onmousemove = displayNodeInfo;
\r
314 // This function was taken here : http://www.adomas.org/javascript-mouse-wheel/
\r
315 // Event handler for mouse wheel event.
\r
317 function wheel(event) {
\r
319 if (!event) /* For IE. */
\r
320 event = window.event;
\r
321 if (event.wheelDelta) { /* IE/Opera. */
\r
322 delta = event.wheelDelta / 120;
\r
323 } else if (event.detail) { /** Mozilla case. */
\r
324 /** In Mozilla, sign of delta is different than in IE.
\r
325 * Also, delta is multiple of 3.
\r
327 delta = -event.detail / 3;
\r
329 /** If delta is nonzero, handle it.
\r
330 * Basically, delta is now positive if wheel was scrolled up,
\r
331 * and negative, if wheel was scrolled down.
\r
335 /** Prevent default actions caused by mouse wheel.
\r
336 * That might be ugly, but we handle scrolls somehow
\r
337 * anyway, so don't bother here..
\r
339 if (event.preventDefault)
\r
340 event.preventDefault();
\r
341 event.returnValue = false;
\r