1 // Various global variables
\r
2 var mouseX = 0, mouseY = 0,camera, scene, renderer, projector;
\r
3 var sTestEventType = 'mousedown';
\r
4 //var window3DWidth = window.innerWidth * 0.8;
\r
5 //var window3DHeight=window.innerHeight*0.75;
\r
6 var window3DWidth, window3DHeight;
\r
9 phi = -100, theta = 0, distance = 130;
\r
12 var info, nodelist, help;
\r
17 // list of selected nodes
\r
18 var selectedNodes = [];
\r
20 var div3d, nodebox, infobox;
\r
25 var particles, particle;
\r
27 div3d = JQuery('#div3d');
\r
28 nodebox = JQuery('#nodebox');
\r
29 infobox = JQuery('#infobox');
\r
30 titlebox = JQuery('#titlebox');
\r
32 var offset = div3d.offset;
\r
36 //titlebox.innerHTML = 'Grenoble Site ' + nodes.length + " nodes";
\r
37 infobox.innerHTML = 'Node info : ';
\r
41 camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000);
\r
43 scene = new THREE.Scene();
\r
45 renderer = new THREE.CanvasRenderer();
\r
47 div3d.append(renderer.domElement);
\r
49 window.addEventListener('resize', set3dsize, false);
\r
54 var PI2 = Math.PI * 2;
\r
55 var geometry = new THREE.Geometry();
\r
57 // let's find the center of the nodes
\r
58 xmin = ymin = zmin = 0;
\r
59 xmax = ymax = zmax = 0;
\r
61 for (var i = 0; i < nodes.length; i++) {
\r
62 if (nodes[i][1] > xmax) xmax = nodes[i][1];
\r
63 if (nodes[i][1] < xmin) xmin = nodes[i][1];
\r
64 if (nodes[i][2] > ymax) ymax = nodes[i][2];
\r
65 if (nodes[i][2] < ymin) ymin = nodes[i][2];
\r
66 if (nodes[i][3] > zmax) zmax = nodes[i][3];
\r
67 if (nodes[i][3] < zmin) zmin = nodes[i][3];
\r
70 xcenter = (xmax + xmin) / 2;
\r
71 ycenter = (ymax + ymin) / 2;
\r
72 zcenter = (zmax + zmin) / 2;
\r
74 // display nodes as TREE particles
\r
75 for (var i = 0; i < nodes.length; i++) {
\r
76 material = new THREE.ParticleCanvasMaterial({
\r
78 program: function (context) {
\r
79 context.beginPath();
\r
80 context.arc(0, 0, 1, 0, PI2, true);
\r
81 context.closePath();
\r
85 particle = new THREE.Particle(material);
\r
86 particle.name = nodes[i][0];
\r
87 particle.position.x = nodes[i][1] - xcenter;
\r
88 particle.position.y = nodes[i][2] - ycenter;
\r
89 particle.position.z = nodes[i][3] - zcenter;
\r
90 particle.uid = nodes[i][4];
\r
91 particle.state = nodes[i][5];
\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
102 // a projector is needed to find which node is under the mouse
\r
103 projector = new THREE.Projector();
\r
105 nodebox.onkeyup = parseNodebox;
\r
106 // set mouse event handlers
\r
107 div3d.onmousedown = OnMouseDown;
\r
108 div3d.onmouseup = OnMouseUp;
\r
109 div3d.onmousemove = displayNodeInfo;
\r
110 if (div3d.addEventListener)
\r
111 /** DOMMouseScroll is for mozilla. */
\r
112 div3d.addEventListener('DOMMouseScroll', wheel, false);
\r
114 div3d.onmousewheel = div3d.onmousewheel = wheel;
\r
118 function set3dsize() {
\r
119 var offset = div3d.offset;
\r
121 offX = offset.left;
\r
122 window3DWidth = offset.width;
\r
123 window3DHeight = offset.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
234 if (selectedNodes.indexOf(objects[i].name) != -1) {
\r
235 objects[i].material.color.setHex(0x0099CC);
\r
238 if(objects[i].state == "Busy") {
\r
239 objects[i].material.color.setHex(0x9943BE);
\r
241 else if(objects[i].state == "Alive") {
\r
242 objects[i].material.color.setHex(0x7FFF00);
\r
245 objects[i].material.color.setHex(0xFF3030);
\r
251 renderer.render(scene, camera);
\r
254 // rigthbutton is used for rotations
\r
255 function onDocumentMouseMoveRot(event) {
\r
256 NewmouseX = event.clientX;
\r
257 NewmouseY = event.clientY;
\r
258 DeltaX = NewmouseX - mouseX;
\r
259 DeltaY = NewmouseY - mouseY;
\r
261 mouseX = NewmouseX;
\r
262 mouseY = NewmouseY;
\r
266 if (phi > 180) phi = 180;
\r
267 if (phi < -180) phi = -180;
\r
270 // mousewheel is used for zoom
\r
271 function Zoom(delta) {
\r
272 distance += delta * 5;
\r
276 // return the graphical node under the mouse
\r
277 function findNodeUnderMouse(event) {
\r
278 var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5);
\r
279 projector.unprojectVector(vector, camera);
\r
280 var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());
\r
281 var intersects = ray.intersectObjects(objects);
\r
282 if (intersects.length > 0) {
\r
283 return intersects[0];
\r
284 } else return null;
\r
287 // display some info of the node under the mouse
\r
288 function displayNodeInfo(e) {
\r
289 obj = findNodeUnderMouse(e);
\r
291 if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + obj.object.uid;
\r
292 // else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY;
\r
295 // select/unselect nodes
\r
296 function toggleNode(obj) {
\r
297 nodeId = obj.object.name;
\r
298 i = selectedNodes.indexOf(nodeId);
\r
299 if (i == -1) selectedNodes.push(nodeId);
\r
300 else selectedNodes.splice(i, 1);
\r
301 nodebox.value = factorize().join(",");
\r
305 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
306 // Mouse handling functions
\r
308 function OnMouseDown(e) {
\r
309 var clickType = 'LEFT';
\r
310 if (e.type != sTestEventType) return true
\r
312 if (e.which == 3) clickType = 'RIGHT';
\r
313 if (e.which == 2) clickType = 'MIDDLE';
\r
314 //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;
\r
316 mouseX = e.clientX;
\r
317 mouseY = e.clientY;
\r
318 if (clickType == 'RIGHT') {
\r
319 document.onmousemove = onDocumentMouseMoveRot;
\r
321 if (clickType == 'LEFT') {
\r
322 obj = findNodeUnderMouse(e);
\r
323 if (obj != null) toggleNode(obj);
\r
327 function OnMouseUp(e) {
\r
328 document.onmousemove = displayNodeInfo;
\r
331 // This function was taken here : http://www.adomas.org/javascript-mouse-wheel/
\r
332 // Event handler for mouse wheel event.
\r
334 function wheel(event) {
\r
336 if (!event) /* For IE. */
\r
337 event = window.event;
\r
338 if (event.wheelDelta) { /* IE/Opera. */
\r
339 delta = event.wheelDelta / 120;
\r
340 } else if (event.detail) { /** Mozilla case. */
\r
341 /** In Mozilla, sign of delta is different than in IE.
\r
342 * Also, delta is multiple of 3.
\r
344 delta = -event.detail / 3;
\r
346 /** If delta is nonzero, handle it.
\r
347 * Basically, delta is now positive if wheel was scrolled up,
\r
348 * and negative, if wheel was scrolled down.
\r
352 /** Prevent default actions caused by mouse wheel.
\r
353 * That might be ugly, but we handle scrolls somehow
\r
354 * anyway, so don't bother here..
\r
356 if (event.preventDefault)
\r
357 event.preventDefault();
\r
358 event.returnValue = false;
\r