1 // Various global variables
\r
2 var mouseX = 0, mouseY = 0, camera, scene, renderer, projector;
\r
5 var phi = -100, theta = 0, distance = 130;
\r
10 // list of selected nodes
\r
11 var selectedNodes = [];
\r
13 var div3d, nodebox, infobox;
\r
15 function onResize() {
\r
16 renderer.setSize(div3d.offsetWidth, div3d.offsetHeight);
\r
17 camera.aspect = div3d.offsetWidth / div3d.offsetHeight;
\r
18 camera.updateProjectionMatrix();
\r
22 function getCenter(nodes) {
\r
23 var xmin = 0, ymin = 0, zmin = 0;
\r
24 var xmax = 0, ymax = 0, zmax = 0;
\r
26 for (var i = 0; i < nodes.length; i++) {
\r
27 if (nodes[i][1] > xmax) xmax = nodes[i][1];
\r
28 if (nodes[i][1] < xmin) xmin = nodes[i][1];
\r
29 if (nodes[i][2] > ymax) ymax = nodes[i][2];
\r
30 if (nodes[i][2] < ymin) ymin = nodes[i][2];
\r
31 if (nodes[i][3] > zmax) zmax = nodes[i][3];
\r
32 if (nodes[i][3] < zmin) zmin = nodes[i][3];
\r
34 return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};
\r
37 function debugaxis(axisLength) {
\r
38 var v = function(x, y, z) {
\r
39 return new THREE.Vertex(new THREE.Vector3(x, y, z));
\r
42 var createAxis = function (p1, p2, color) {
\r
43 var lineGeometry = new THREE.Geometry();
\r
44 var lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });
\r
45 lineGeometry.vertices.push(p1, p2);
\r
46 var line = new THREE.Line(lineGeometry, lineMat);
\r
50 createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);
\r
51 createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);
\r
52 createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);
\r
55 function drawNodes(nodes) {
\r
56 var geometry = new THREE.Geometry();
\r
57 var center = getCenter(nodes);
\r
60 for (var i = 0; i < nodes.length; i++) {
\r
61 var material = new THREE.ParticleCanvasMaterial({
\r
63 program: function (context) {
\r
64 context.beginPath();
\r
65 context.arc(0, 0, 1, 0, Math.PI * 2, true);
\r
66 context.closePath();
\r
70 var particle = new THREE.Particle(material);
\r
71 particle.name = nodes[i][0];
\r
72 particle.position.x = nodes[i][1] - center.x;
\r
73 particle.position.y = nodes[i][2] - center.y;
\r
74 particle.position.z = nodes[i][3] - center.z;
\r
75 particle.uid = nodes[i][4];
\r
76 particle.state = nodes[i][5];
\r
77 particle.position.multiplyScalar(10);
\r
78 particle.scale.x = particle.scale.y = 1;
\r
79 scene.add(particle);
\r
81 var vertex = new THREE.Vertex(particle.position);
\r
82 geometry.vertices.push(vertex);
\r
83 objects.push(particle)
\r
90 function init(nodes) {
\r
91 div3d = document.getElementById('div3d');
\r
92 nodebox = document.getElementById('nodebox');
\r
93 infobox = document.getElementById('infobox');
\r
95 infobox.innerHTML = 'Node info : ';
\r
98 camera = new THREE.PerspectiveCamera(75, div3d.offsetWidth / div3d.offsetHeight, 1, 10000);
\r
99 scene = new THREE.Scene();
\r
100 renderer = new THREE.CanvasRenderer();
\r
101 projector = new THREE.Projector();
\r
103 div3d.appendChild(renderer.domElement);
\r
105 window.addEventListener('resize', onResize, false);
\r
108 nodebox.onkeyup = parseNodebox;
\r
110 div3d.onmousedown = OnMouseDown;
\r
111 div3d.onmouseup = OnMouseUp;
\r
112 div3d.onmousemove = displayNodeInfo;
\r
113 if (div3d.addEventListener) {
\r
114 div3d.addEventListener('DOMMouseScroll', wheel, false); // mozilla
\r
116 div3d.onmousewheel = wheel; // IE & Opera
\r
119 function sortfunction(a, b) {
\r
120 return (a - b) //causes an array to be sorted numerically and ascending
\r
123 // factorize the expanded list in selectedNode to produce dash intervals
\r
124 // 1,2,3,5,9 -> 1-3,5,9
\r
125 function factorize() {
\r
128 var intervalStart = 0;
\r
129 selectedNodes.sort(sortfunction);
\r
130 for (j = 0; j < selectedNodes.length; j++) {
\r
131 if (intervalStart) {
\r
132 // we are in an interval
\r
133 if (selectedNodes[j] == previous + 1) {
\r
138 fact.push(intervalStart + "-" + previous);
\r
140 previous = selectedNodes[j];
\r
143 // we are not in an interval
\r
144 if (selectedNodes[j] == previous + 1) {
\r
145 // let's begin an interval
\r
146 intervalStart = previous;
\r
150 fact.push(previous);
\r
152 previous = selectedNodes[j];
\r
156 // at the end of the loop, two cases
\r
157 // we were still in an interval, then add it to the result
\r
158 // we were not in an interval, then add the last selectednode (previous)
\r
159 if (intervalStart) {
\r
160 fact.push(intervalStart + "-" + previous);
\r
161 } else if (previous) {
\r
162 fact.push(previous);
\r
167 // expand a list of nodes containing dash intervals
\r
168 // 1-3,5,9 -> 1,2,3,5,9
\r
169 function expand(input) {
\r
170 var factorized = input.split(",");
\r
172 for (var i = 0; i < factorized.length; i++) {
\r
173 var d = factorized[i].split("-");
\r
174 if (d.length == 2) {
\r
175 for (var j = parseInt(d[0]); j < parseInt(d[1]) + 1; j++) {
\r
179 expanded.push(parseInt(factorized[i]));
\r
182 expanded.sort(sortfunction);
\r
183 for (var i = 1; i < expanded.length; i++) {
\r
184 if (expanded[i] == expanded[i - 1]) {
\r
185 expanded.splice(i--, 1);
\r
191 function parseNodebox() {
\r
192 selectedNodes = expand(nodebox.value);
\r
196 // set the camera position according two angles theta and phi and the distance
\r
197 // and display the scene
\r
198 function myrender() {
\r
199 camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);
\r
200 camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);
\r
201 camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);
\r
202 camera.lookAt(scene.position);
\r
203 camera.updateMatrix();
\r
205 for (i = 0; i < objects.length; i++) {
\r
206 if (selectedNodes.indexOf(objects[i].name) != -1) {
\r
207 objects[i].material.color.setHex(0x0099CC);
\r
209 if (objects[i].state == "Busy") {
\r
210 objects[i].material.color.setHex(0x9943BE);
\r
211 } else if (objects[i].state == "Alive") {
\r
212 objects[i].material.color.setHex(0x7FFF00);
\r
214 objects[i].material.color.setHex(0xFF3030);
\r
218 renderer.render(scene, camera);
\r
221 // rigthbutton is used for rotations
\r
222 function onDocumentMouseMoveRot(event) {
\r
223 var NewmouseX = event.clientX;
\r
224 var NewmouseY = event.clientY;
\r
225 var DeltaX = NewmouseX - mouseX;
\r
226 var DeltaY = NewmouseY - mouseY;
\r
228 mouseX = NewmouseX;
\r
229 mouseY = NewmouseY;
\r
233 if (phi > 180) phi = 180;
\r
234 if (phi < -180) phi = -180;
\r
237 // mousewheel is used for zoom
\r
238 function Zoom(delta) {
\r
239 distance += delta * 5;
\r
243 // return the graphical node under the mouse
\r
244 function findNodeUnderMouse(event) {
\r
247 event.preventDefault();
\r
249 x = ((event.clientX - div3d.offsetLeft) / div3d.offsetWidth) * 2 - 1;
\r
250 y = -((event.clientY - div3d.offsetTop) / div3d.offsetHeight) * 2 + 1;
\r
253 var vector = new THREE.Vector3(x, y, z);
\r
254 projector.unprojectVector(vector, camera);
\r
256 var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());
\r
257 var intersects = ray.intersectObjects(objects);
\r
259 if (intersects.length > 0) {
\r
260 return intersects[0];
\r
266 // display some info of the node under the mouse
\r
267 function displayNodeInfo(e) {
\r
268 obj = findNodeUnderMouse(e);
\r
270 infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + obj.object.uid;
\r
274 // select/unselect nodes
\r
275 function toggleNode(obj) {
\r
276 var nodeId = obj.object.name;
\r
277 var index = selectedNodes.indexOf(nodeId);
\r
280 selectedNodes.push(nodeId);
\r
282 selectedNodes.splice(index, 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 != 'mousedown') 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