SpikeStream Application Library  0.2
NetworkViewer.cpp
Go to the documentation of this file.
00001 //SpikeStream includes
00002 #include "EventRouter.h"
00003 #include "Globals.h"
00004 #include "GlobalVariables.h"
00005 #include "NetworkViewer.h"
00006 #include "SpikeStreamException.h"
00007 #include "Util.h"
00008 using namespace spikestream;
00009 
00010 //Qt includes
00011 #include <QDebug>
00012 #include <QMouseEvent>
00013 
00014 //Other includes
00015 #include <iostream>
00016 using namespace std;
00017 
00018 //Outputs debugging information when enabled
00019 //#define DEBUG
00020 
00021 //Defines for OpenGL
00023 #define GL_PI 3.1415f
00024 
00025 /* gltools macro to convert degrees to radians and vice versa. */
00026 #define GLT_PI_DIV_180 0.017453292519943296
00027 #define GLT_INV_PI_DIV_180 57.2957795130823229
00028 #define gltDegToRad(x)  ((x)*GLT_PI_DIV_180)
00029 #define gltRadToDeg(x)  ((x)*GLT_INV_PI_DIV_180)
00030 
00031 /* Light and material Data. */
00032 GLfloat fNoLight[] = { 0.0f, 0.0f, 0.0f, 0.0f };
00033 GLfloat fLowLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
00034 GLfloat fDiffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
00035 GLfloat fBrightLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00036 GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00037 
00038 
00040 NetworkViewer::NetworkViewer(QWidget* parent) : QGLWidget(parent) {
00041         //Connect refresh to changes in the display of network or archive
00042         connect(Globals::getEventRouter(), SIGNAL(networkDisplayChangedSignal()), this, SLOT(refresh()), Qt::QueuedConnection);
00043         connect(Globals::getEventRouter(), SIGNAL(neuronGroupDisplayChangedSignal()), this, SLOT(refreshNeurons()), Qt::QueuedConnection);
00044         connect(Globals::getEventRouter(), SIGNAL(weightsChangedSignal()), this, SLOT(refreshConnections()), Qt::QueuedConnection);
00045 
00046         //Connect reset to changes in the network
00047         connect(Globals::getEventRouter(), SIGNAL(networkChangedSignal()), this, SLOT(reset()), Qt::QueuedConnection);
00048         connect(Globals::getEventRouter(), SIGNAL(reloadSignal()), this, SLOT(reset()), Qt::QueuedConnection);
00049 
00050         //Initialize variables
00051         paintGLSkipped = false;
00052         resizeGLSkipped = false;
00053         useAxesDisplayList = false;
00054         useNeuronsDisplayList = false;
00055         useConnectionsDisplayList = false;
00056         perspective_angle = 46.0f;
00057         perspective_near = 1.0f;
00058         perspective_far = 100000.0f;//Set this to a large number so everything will be visible
00059 
00060         //Connect up signals to navigate around 3D environment
00061         connect(Globals::getEventRouter(), SIGNAL(moveUpSignal()), this, SLOT(moveUp()), Qt::QueuedConnection);
00062         connect(Globals::getEventRouter(), SIGNAL(moveDownSignal()), this, SLOT(moveDown()), Qt::QueuedConnection);
00063         connect(Globals::getEventRouter(), SIGNAL(moveLeftSignal()), this, SLOT(moveLeft()), Qt::QueuedConnection);
00064         connect(Globals::getEventRouter(), SIGNAL(moveRightSignal()), this, SLOT(moveRight()), Qt::QueuedConnection);
00065         connect(Globals::getEventRouter(), SIGNAL(moveBackwardSignal()), this, SLOT(moveBackward()), Qt::QueuedConnection);
00066         connect(Globals::getEventRouter(), SIGNAL(moveForwardSignal()), this, SLOT(moveForward()), Qt::QueuedConnection);
00067         connect(Globals::getEventRouter(), SIGNAL(resetViewSignal()), this, SLOT(resetView()), Qt::QueuedConnection);
00068         connect(Globals::getEventRouter(), SIGNAL(rotateUpSignal()), this, SLOT(rotateUp()), Qt::QueuedConnection);
00069         connect(Globals::getEventRouter(), SIGNAL(rotateDownSignal()), this, SLOT(rotateDown()), Qt::QueuedConnection);
00070         connect(Globals::getEventRouter(), SIGNAL(rotateLeftSignal()), this, SLOT(rotateLeft()), Qt::QueuedConnection);
00071         connect(Globals::getEventRouter(), SIGNAL(rotateRightSignal()), this, SLOT(rotateRight()), Qt::QueuedConnection);
00072 
00073         //Set size of widget
00074         setMinimumSize(200, 60);
00075         setBaseSize(700, 60);
00076 
00077         //Set display to initial state
00078         //reset();
00079 }
00080 
00081 
00083 NetworkViewer::~NetworkViewer(){
00084 }
00085 
00086 
00087 /*----------------------------------------------------------*/
00088 /*-----                PROTECTED METHODS               -----*/
00089 /*----------------------------------------------------------*/
00090 
00092 void NetworkViewer::initializeGL(){
00093         //White background
00094         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
00095 
00096         //Create IDs for display lists
00097         axesDisplayList = glGenLists(1);
00098         sphereDisplayList =  glGenLists(1);
00099         neuronsDisplayList =  glGenLists(1);
00100         connectionsDisplayList =  glGenLists(1);
00101 
00102         //Create objects
00103         gluSphereObj = gluNewQuadric();
00104         gluConeObj = gluNewQuadric();
00105         gluQuadricDrawStyle(gluSphereObj, GLU_FILL);
00106         gluQuadricNormals(gluSphereObj, GLU_SMOOTH);
00107 
00108         //Build sphere display list
00109         glNewList(sphereDisplayList, GL_COMPILE);
00110                 gluSphere(
00111                         gluSphereObj,
00112                         Globals::getNetworkDisplay()->getSphereRadius(),
00113                         Globals::getNetworkDisplay()->getSphereQuality()*2,
00114                         Globals::getNetworkDisplay()->getSphereQuality()
00115                 );
00116         glEndList();
00117 }
00118 
00119 
00121 void NetworkViewer::paintGL(){
00122         //If we are already painting, skip further calls to this method triggered by accelerator keys
00123         if(Globals::isRendering()){
00124                 paintGLSkipped = true;
00125                 return;
00126         }
00127 
00128         paintGLSkipped = false;
00129         cancelRender = false;
00130 
00131         //Record that rendering is in progress to filter out accelerator keys */
00132         Globals::setRendering(true);
00133 
00134         // Clear the window with current clearing color
00135         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00136 
00137         //Store current matrix state
00138         glPushMatrix();
00139 
00140         //Set zoom level
00141         setZoomLevel();
00142 
00143         //Position the camera appropriately
00144         positionCamera();
00145 
00146         //Lock network display whilst rendering is taking place
00147         //FIXME: MIGHT WANT TO LOCK NETWORK AS WELL
00148         Globals::getNetworkDisplay()->lockMutex();
00149 
00150         //Draw the connections before the neurons in full render mode
00151         if(Globals::getNetworkDisplay()->isFullRenderMode())
00152                 this->initialiseFullRender();
00153         else
00154                 this->disableFullRender();
00155 
00156         //Draw axes, connections and neurons
00157         drawAxes();
00158         drawConnections();
00159         drawNeurons();
00160 
00161         //Restore the original state of the matrix
00162         glPopMatrix();
00163 
00164         //Unlock network display
00165         Globals::getNetworkDisplay()->unlockMutex();
00166 
00167         //Check for OpenGL errors
00168         checkOpenGLErrors();
00169 
00170         //Render has stopped
00171         Globals::setRendering(false);
00172 
00173         /* If during the render, start render or resize were called and
00174                 filtered out, need to re-render. */
00175         if(resizeGLSkipped){
00176                 resizeGL(newTempScreenWidth, newTempScreenHeight);
00177                 paintGLSkipped = true;
00178         }
00179         if(paintGLSkipped){
00180                 paintGL();
00181         }
00182 }
00183 
00184 
00186 void NetworkViewer::resizeGL(int screenWidth, int screenHeight){
00187         if(Globals::isRendering()){
00188                 resizeGLSkipped = true;
00189 
00190                 //Store new screen width and height
00191                 newTempScreenWidth = screenWidth;
00192                 newTempScreenHeight = screenHeight;
00193                 return;
00194         }
00195 
00196         //Reset resizeSkipped
00197         resizeGLSkipped = false;
00198 
00199         // Prevent a divide by zero, when window is too short (you cant make a window of zero width).
00200         if(screenHeight == 0)
00201                 screenHeight = 1;
00202 
00203         glViewport(0, 0, screenWidth, screenHeight);
00204 
00205         // Reset the coordinate system before modifying
00206         glMatrixMode(GL_PROJECTION);
00207         glLoadIdentity();
00208 
00209         // Set the clipping volume
00210         GLfloat aspectRatio = (GLfloat)screenWidth / (GLfloat)screenHeight;
00211         gluPerspective(perspective_angle, aspectRatio, perspective_near, perspective_far);
00212 
00213         glMatrixMode(GL_MODELVIEW);
00214         glLoadIdentity();
00215 
00216         //Check for errors
00217         checkOpenGLErrors();
00218 }
00219 
00220 
00222 void NetworkViewer::mouseDoubleClickEvent (QMouseEvent* event){
00223         //Window coordinates in OpenGL start in the bottom left, so have to subtract the window height
00224         int mouseYPos = height() - event->y();
00225         int mouseXPos = event->x();
00226 
00227         //Determine if control button is down
00228         bool ctrlBtnDown = false;
00229         if(event->modifiers() & Qt::ControlModifier){
00230                 ctrlBtnDown = true;
00231         }
00232 
00233         //Create the select buffer
00234         int SELECT_BUFFER_SIZE = 512;
00235         GLuint selectBuffer[SELECT_BUFFER_SIZE];
00236         glSelectBuffer(SELECT_BUFFER_SIZE,selectBuffer);
00237 
00238         //Get the current viewport
00239         GLint viewport[4];
00240         glGetIntegerv(GL_VIEWPORT,viewport);
00241 
00242         //Start picking
00243         glRenderMode(GL_SELECT);
00244         glMatrixMode(GL_PROJECTION);
00245         glPushMatrix();
00246         glLoadIdentity();
00247         gluPickMatrix(mouseXPos, mouseYPos, 15, 15, viewport);
00248 
00249         float ratio = (float)viewport[2] / (float)viewport[3];
00250         gluPerspective(45, ratio, 0.1, 1000);
00251         glMatrixMode(GL_MODELVIEW);
00252 
00253         //Render neurons with names
00254         //Store current matrix state
00255         glPushMatrix();
00256 
00257         //Set zoom level
00258         setZoomLevel();
00259 
00260         //Position the camera appropriately
00261         positionCamera();
00262 
00263         //Draw the neurons
00264         drawNeurons();
00265 
00266         //Restore the matrix state
00267         glPopMatrix();
00268 
00269         // returning to normal rendering mode
00270         int hitCount = glRenderMode(GL_RENDER);
00271 
00272         if(hitCount != 0){//Neuron selected
00273                 unsigned int selectedNeuronID = getSelectedNeuron(selectBuffer, hitCount, SELECT_BUFFER_SIZE);
00274                 Globals::getNetworkDisplay()->setSelectedNeuronID(selectedNeuronID, ctrlBtnDown);
00275         }
00276         else{
00277                 Globals::getNetworkDisplay()->setSelectedNeuronID(0);
00278         }
00279 
00280         //Restore render mode and the original projection matrix
00281         glMatrixMode(GL_PROJECTION);
00282         glPopMatrix();
00283         glMatrixMode(GL_MODELVIEW);
00284         glFlush();
00285 }
00286 
00287 
00288 /*----------------------------------------------------------*/
00289 /*-----                PRIVATE SLOTS                   -----*/
00290 /*----------------------------------------------------------*/
00291 
00293 void NetworkViewer::moveUp(){
00294         cameraMatrix[12] += cameraMatrix[8];
00295         cameraMatrix[13] += cameraMatrix[9];
00296         cameraMatrix[14] += cameraMatrix[10];
00297         updateGL();
00298 }
00299 
00301 void NetworkViewer::moveDown(){
00302         cameraMatrix[12] -= cameraMatrix[8];
00303         cameraMatrix[13] -= cameraMatrix[9];
00304         cameraMatrix[14] -= cameraMatrix[10];
00305         updateGL();
00306 }
00307 
00308 
00310 void NetworkViewer::moveLeft(){
00311         cameraMatrix[12] -= cameraMatrix[0];
00312         cameraMatrix[13] -= cameraMatrix[1];
00313         cameraMatrix[14] -= cameraMatrix[2];
00314         updateGL();
00315 }
00316 
00317 
00319 void NetworkViewer::moveRight(){
00320         cameraMatrix[12] += cameraMatrix[0];
00321         cameraMatrix[13] += cameraMatrix[1];
00322         cameraMatrix[14] += cameraMatrix[2];
00323         updateGL();
00324 }
00325 
00326 
00328 void NetworkViewer::moveForward(){
00329         cameraMatrix[12] += cameraMatrix[4];
00330         cameraMatrix[13] += cameraMatrix[5];
00331         cameraMatrix[14] += cameraMatrix[6];
00332         updateGL();
00333 }
00334 
00335 
00337 void NetworkViewer::moveBackward(){
00338         cameraMatrix[12] -= cameraMatrix[4];
00339         cameraMatrix[13] -= cameraMatrix[5];
00340         cameraMatrix[14] -= cameraMatrix[6];
00341         updateGL();
00342 }
00343 
00344 
00346 void NetworkViewer::resetView(){
00347         viewClippingVolume_Horizontal(defaultClippingVol);
00348         updateGL();
00349 }
00350 
00351 
00353 void NetworkViewer::rotateUp(){
00354         sceneRotateX += 2.5f;
00355         updateGL();
00356 }
00357 
00358 
00360 void NetworkViewer::rotateDown(){
00361         sceneRotateX -= 2.5f;
00362         updateGL();
00363 }
00364 
00365 
00367 void NetworkViewer::rotateLeft(){
00368         sceneRotateZ += 2.5f;
00369         updateGL();
00370 }
00371 
00372 
00374 void NetworkViewer::rotateRight(){
00375         sceneRotateZ -= 2.5f;
00376         updateGL();
00377 }
00378 
00379 
00381 void NetworkViewer::refresh(){
00382         useNeuronsDisplayList = false;
00383         useConnectionsDisplayList = false;
00384         updateGL();
00385 }
00386 
00387 
00389 void NetworkViewer::refreshNeurons(){
00390         useNeuronsDisplayList = false;
00391         updateGL();
00392 }
00393 
00394 
00396 void NetworkViewer::refreshConnections(){
00397         useConnectionsDisplayList = false;
00398         updateGL();
00399 }
00400 
00401 
00403 void NetworkViewer::reset(){
00404         //Load up the volume enclosing the entire network
00405         loadDefaultClippingVolume();
00406 
00407         //Look at this network horizontally
00408         viewClippingVolume_Horizontal(defaultClippingVol);
00409 
00410         //Network has changed so need to re-render the display list
00411         useNeuronsDisplayList = false;
00412         useConnectionsDisplayList = false;
00413 
00414         //Re-draw
00415         updateGL();
00416 }
00417 
00418 
00419 
00420 /*----------------------------------------------------------*/
00421 /*-----                PRIVATE METHODS                 -----*/
00422 /*----------------------------------------------------------*/
00423 
00425 void NetworkViewer::checkOpenGLErrors(){
00426         //Check to see if error has occurred
00427         GLenum err = glGetError();
00428         if(err != GL_NO_ERROR){
00429                 //May be more than one error message, so add them all to the error string if there is an error
00430                 QString errMsg = "OpenGL ERROR(S): ";
00431                 while(err != GL_NO_ERROR){
00432                         errMsg += QString("'") + (const char *)gluErrorString(err) + "'; ";
00433                         err = glGetError();
00434                 }
00435 
00436                 //Flag error to user
00437                 qCritical()<<errMsg;
00438         }
00439 }
00440 
00441 
00444 void NetworkViewer::drawAxes(void){
00445         //Do nothing if drawAxes is set to false
00446         if(!Globals::getNetworkDisplay()->isDrawAxes())
00447                 return;
00448 
00449         //Use existing axes display list
00450         if(useAxesDisplayList){
00451                 glCallList(axesDisplayList);
00452         }
00453         //Create new display list with axes
00454         else{
00455                 glNewList(axesDisplayList, GL_COMPILE_AND_EXECUTE);
00456 
00457                 //Set the drawing colour to red
00458                 glColor3f(1.0f, 0.0f, 0.0f);
00459 
00460                 //Store current line width
00461                 glPushAttrib(GL_LINE_BIT);
00462 
00463                 //Set wide line
00464                 glLineWidth(2.0f);
00465 
00466                 //Draw the axes, extending extraLength beyond clipping volume
00467                 GLfloat extraLength = 20.0f;
00468 
00469                 //Draw the main axes
00470                 glBegin(GL_LINES);
00471                 //X Axis
00472                 glVertex3f(defaultClippingVol.x1 - extraLength, 0.0f, 0.0f);
00473                 glVertex3f(defaultClippingVol.x2 + extraLength, 0.0f, 0.0f);
00474                 //Y Axis
00475                 glVertex3f(0.0f, defaultClippingVol.y1 - extraLength, 0.0f);
00476                 glVertex3f(0.0f, defaultClippingVol.y2 + extraLength, 0.0f);
00477                 //Z Axis
00478                 glVertex3f(0.0f, 0.0f, defaultClippingVol.z1 - extraLength);
00479                 glVertex3f(0.0f, 0.0f, defaultClippingVol.z2 + extraLength);
00480                 glEnd();
00481 
00482                 //Work along axes, marking every point with a point
00483                 GLfloat scaleMarkSpacing = 5.0f;
00484 
00485                 //Set colour and point size
00486                 glColor3f(0.0f, 0.0f, 1.0f);
00487                 glPointSize(3.0f);
00488 
00489                 //Draw markings on X axis
00490                 for(float i=defaultClippingVol.x1 - extraLength; i < defaultClippingVol.x2 + extraLength; i += scaleMarkSpacing){
00491                         glBegin(GL_POINTS);
00492                                 glVertex3f(i, 0.0f, 0.0f);
00493                         glEnd();
00494                 }
00495 
00496                 //Draw markings on Y axis
00497                 for(float i=defaultClippingVol.y1 - extraLength; i < defaultClippingVol.y2 + extraLength; i += scaleMarkSpacing){
00498                         glBegin(GL_POINTS);
00499                                 glVertex3f(0.0f, i, 0.0f);
00500                         glEnd();
00501                 }
00502 
00503                 //Draw markings on Z axis
00504                 for(float i=defaultClippingVol.z1 - extraLength; i < defaultClippingVol.z2 + extraLength; i += scaleMarkSpacing){
00505                         glBegin(GL_POINTS);
00506                                 glVertex3f(0.0f, 0.0f, i);
00507                         glEnd();
00508                 }
00509 
00510                 //Reset line width to original value
00511                 glPopAttrib();
00512 
00513                 //Finish recording display list with axes
00514                 glEndList();
00515                 useAxesDisplayList = true;
00516         }
00517 }
00518 
00519 
00521 void NetworkViewer::drawConnections(){
00522         //Nothing to do if no network is loaded
00523         if(!Globals::networkLoaded())
00524                 return;
00525 
00526         //Use existing display list
00527         if(useConnectionsDisplayList){
00528                 glCallList(connectionsDisplayList);
00529         }
00530         //Create new display list with connections
00531         else{
00532                 glNewList(connectionsDisplayList, GL_COMPILE_AND_EXECUTE);
00533 
00534                 //Local variables declared once here to save processing. These point to the points stored in the neurons
00535                 Point3D* fromNeuronPoint;
00536                 Point3D* toNeuronPoint;
00537 
00538                 //Get pointer to network that is to be drawn and its associated display
00539                 Network* network = Globals::getNetwork();
00540                 NetworkDisplay* netDisplay = Globals::getNetworkDisplay();
00541                 bool fullRender = netDisplay->isFullRenderMode();
00542 
00543                 //Get information about rendering connections
00544                 unsigned weightRenderMode = netDisplay->getWeightRenderMode();
00545                 float weight = 0.0f;//Declare here to save declaring it all the time.
00546                 weightRadiusFactor = netDisplay->getWeightRadiusFactor();
00547                 minimumConnectionRadius = netDisplay->getMinimumConnectionRadius();
00548                 connectionQuality = netDisplay->getConnectionQuality();
00549 
00550                 //Default neuron colour
00551                 RGBColor positiveConnectionColor = *netDisplay->getPositiveConnectionColor();
00552                 RGBColor negativeConnectionColor = *netDisplay->getNegativeConnectionColor();
00553 
00554                 //Sort out the connection mode
00555                 unsigned int singleNeuronID=0, toNeuronID=0;
00556                 unsigned int connectionMode = netDisplay->getConnectionMode();
00557                 QList<Connection*>& visConList = netDisplay->getVisibleConnectionsList();
00558                 if(connectionMode & CONNECTION_MODE_ENABLED){
00559                         connectedNeuronMap.clear();
00560                         singleNeuronID = netDisplay->getSingleNeuronID();
00561                         if(connectionMode & SHOW_BETWEEN_CONNECTIONS)
00562                                 toNeuronID = netDisplay->getToNeuronID();
00563 
00564                         //Rebuild list of visible connections
00565                         visConList.clear();
00566                 }
00567 
00568                 //Work through the connection groups listed in the network display
00569                 bool drawConnection;
00570                 int thinningThreshold = Globals::getNetworkDisplay()->getConnectionThinningThreshold();
00571                 unsigned ignoreConCnt = 0;
00572                 QList<unsigned int> conGrpIDs = Globals::getNetworkDisplay()->getVisibleConnectionGroupIDs();
00573                 for(QList<unsigned int>::iterator conGrpIter = conGrpIDs.begin(); conGrpIter != conGrpIDs.end(); ++conGrpIter){
00574 
00575                         //Pointer to connection group
00576                         ConnectionGroup* conGrp = network->getConnectionGroup(*conGrpIter);
00577                         int numCons = conGrp->size();
00578                         int drawingThreshold = 0;
00579                         if(numCons > thinningThreshold){
00580                                 drawingThreshold = Util::rInt(RAND_MAX * ( (double)thinningThreshold/(double)numCons));
00581                         }
00582 
00583                         //Get neuron groups for extracting the position information
00584                         NeuronGroup* fromNeuronGroup = network->getNeuronGroup(conGrp->getFromNeuronGroupID());
00585                         NeuronGroup* toNeuronGroup = network->getNeuronGroup(conGrp->getToNeuronGroupID());
00586 
00587                         //Draw all the connections in the group
00588                         ConnectionIterator endConGrp = conGrp->end();
00589                         for(ConnectionIterator conIter = conGrp->begin(); conIter != endConGrp; ++ conIter){
00590                                 //Get the weight
00591                                 weight = conIter->getWeight();
00592                                 if( (weightRenderMode & WEIGHT_RENDER_ENABLED) && (weightRenderMode & RENDER_TEMP_WEIGHTS) )
00593                                         weight = conIter->getTempWeight();
00594 
00595                                 //Decide if connection should be drawn, depending on the connection mode and neuron id
00596                                 drawConnection = true;
00597                                 if(connectionMode & CONNECTION_MODE_ENABLED){
00598                                         //Single neuron mode
00599                                         if( !(connectionMode & SHOW_BETWEEN_CONNECTIONS) ){
00600                                                 //Show only connections from a single neuron
00601                                                 if(connectionMode & SHOW_FROM_CONNECTIONS){
00602                                                         if( conIter->getFromNeuronID() != singleNeuronID){
00603                                                                 drawConnection = false;
00604                                                         }
00605                                                         else{
00606                                                                 connectedNeuronMap[conIter->getToNeuronID()] = weight;
00607                                                         }
00608                                                 }
00609                                                 //Show only connections to a single neuron
00610                                                 else if(connectionMode & SHOW_TO_CONNECTIONS){
00611                                                         if( conIter->getToNeuronID() != singleNeuronID){
00612                                                                 drawConnection = false;
00613                                                         }
00614                                                         else{
00615                                                                 connectedNeuronMap[conIter->getFromNeuronID()] = weight;//Positive connection
00616                                                         }
00617                                                 }
00618                                                 //Show from and to connections to a single neuron
00619                                                 else {
00620                                                         if( (conIter->getFromNeuronID() != singleNeuronID) && (conIter->getToNeuronID() != singleNeuronID) ){
00621                                                                 drawConnection = false;
00622                                                         }
00623                                                         else {//Highlight connected neurons
00624                                                                 if( conIter->getFromNeuronID() == singleNeuronID){
00625                                                                         connectedNeuronMap[conIter->getToNeuronID()] = weight;//Positive connection
00626                                                                 }
00627                                                                 else if( conIter->getToNeuronID() == singleNeuronID){
00628                                                                         connectedNeuronMap[conIter->getFromNeuronID()] = weight;//Positive connection
00629                                                                 }
00630                                                         }
00631                                                 }
00632                                         }
00633                                         //Between neuron mode
00634                                         else{
00635                                                 //Only show connections from first neuron to second
00636                                                 if( conIter->getFromNeuronID() != singleNeuronID || conIter->getToNeuronID() != toNeuronID)
00637                                                         drawConnection = false;
00638                                         }
00639 
00640                                         //Decide whether to draw connection based on its weight
00641                                         if( weight < 0 && (connectionMode & SHOW_POSITIVE_CONNECTIONS) )
00642                                                 drawConnection = false;
00643                                         if( weight >= 0 && (connectionMode & SHOW_NEGATIVE_CONNECTIONS))
00644                                                 drawConnection = false;
00645 
00646                                         //Add connection to list of visible connections
00647                                         if(drawConnection)
00648                                                 visConList.append(&(*conIter));
00649 
00650                                 }
00651                                 //Draw all connections, potentially thinned
00652                                 else if(drawingThreshold && (rand() > drawingThreshold)){
00653                                         drawConnection = false;
00654                                         ++ignoreConCnt;
00655                                 }
00656 
00657                                 //Draw the connection
00658                                 if(drawConnection){
00659                                         //Get the position of the from and to neurons
00660                                         fromNeuronPoint = &fromNeuronGroup->getNeuronLocation(conIter->getFromNeuronID());
00661                                         toNeuronPoint = &toNeuronGroup->getNeuronLocation(conIter->getToNeuronID());
00662 
00663                                         //Set the colour
00664                                         if(weight > 0)
00665                                                 glColor3f(positiveConnectionColor.red, positiveConnectionColor.green, positiveConnectionColor.blue);
00666                                         else if(weight < 0)
00667                                                 glColor3f(negativeConnectionColor.red, negativeConnectionColor.green, negativeConnectionColor.blue);
00668                                         else
00669                                                 glColor3f(0.0f, 0.0f, 0.0f);
00670 
00671                                         //Draw the connection
00672                                         if(fullRender && (weightRenderMode & WEIGHT_RENDER_ENABLED) ){
00673                                                 drawWeightedConnection(
00674                                                                 fromNeuronPoint->getXPos(),
00675                                                                 fromNeuronPoint->getYPos(),
00676                                                                 fromNeuronPoint->getZPos(),
00677                                                                 toNeuronPoint->getXPos(),
00678                                                                 toNeuronPoint->getYPos(),
00679                                                                 toNeuronPoint->getZPos(),
00680                                                                 weight
00681                                                 );
00682                                         }
00683                                         else{
00684                                                 //Start drawing lines
00685                                                 glBegin(GL_LINES);
00686                                                         glVertex3f(fromNeuronPoint->getXPos(), fromNeuronPoint->getYPos(), fromNeuronPoint->getZPos());
00687                                                         glVertex3f(toNeuronPoint->getXPos(), toNeuronPoint->getYPos(), toNeuronPoint->getZPos());
00688                                                 glEnd();//End of line drawing
00689                                         }
00690 
00691                                 }
00692                         }
00693                 }
00694 
00695                 //Inform other classes that the list of visible connections has changed.
00696                 if(connectionMode & CONNECTION_MODE_ENABLED){
00697                         Globals::getEventRouter()->visibleConnectionsChangedSlot();
00698                 }
00699 
00700                 #ifdef DEBUG
00701                         qDebug()<<"Number of ignored connections = "<<ignoreConCnt;
00702                 #endif//DEBUG
00703 
00704                 //Finished creating connection display list
00705                 glEndList();
00706                 useConnectionsDisplayList = true;
00707         }
00708 }
00709 
00710 
00712 void NetworkViewer::drawNeurons(){
00713         //Nothing to do if no network is loaded
00714         if(!Globals::networkLoaded())
00715                 return;
00716 
00717         //Use existing display list
00718         if(useNeuronsDisplayList){
00719                 glCallList(neuronsDisplayList);
00720         }
00721         //Create new display list with connections
00722         else{
00723                 glNewList(neuronsDisplayList, GL_COMPILE_AND_EXECUTE);
00724 
00725                 //Local variables
00726                 RGBColor *tmpColor, tmpColor2;
00727                 float weight;
00728 
00729                 //Get pointer to network that is to be drawn and its associated display
00730                 Network* network = Globals::getNetwork();
00731                 NetworkDisplay* netDisplay = Globals::getNetworkDisplay();
00732 
00733                 //Connection mode
00734                 unsigned int connectionMode = netDisplay->getConnectionMode();
00735 
00736                 //Default neuron colour
00737                 RGBColor defaultNeuronColor;
00738                 bool fullRenderMode = netDisplay->isFullRenderMode();//Local copy for speed
00739                 if(fullRenderMode){
00740                         defaultNeuronColor = *netDisplay->getDefaultNeuronColorFullRender();
00741                 }
00742                 else{
00743                         defaultNeuronColor = *netDisplay->getDefaultNeuronColor();
00744                         glPointSize(netDisplay->getVertexSize());//Set the size of points in OpenGL
00745                 }
00746                 float neuronAlpha = netDisplay->getNeuronTransparency();
00747 
00748                 //Get map with colours of neurons
00749                 QHash<unsigned int, RGBColor*> neuronColorMap = netDisplay->getNeuronColorMap();
00750 
00751                 //Initialize list of names for clicking on neurons
00752                 glInitNames();
00753 
00754                 //Work through the neuron groups listed in the view vector
00755                 QList<unsigned int> neuronGrpIDs = Globals::getNetworkDisplay()->getVisibleNeuronGroupIDs();
00756                 for(QList<unsigned int>::iterator neurGrpIter = neuronGrpIDs.begin(); neurGrpIter != neuronGrpIDs.end(); ++neurGrpIter){
00757                         //Get the map of neurons associated with this group
00758                         NeuronMap* neuronMap = network->getNeuronGroup(*neurGrpIter)->getNeuronMap();
00759 
00760                         //Draw the neurons in the map
00761                         NeuronMap::iterator neurMapEnd = neuronMap->end();
00762                         for(NeuronMap::iterator neurIter = neuronMap->begin(); neurIter != neurMapEnd; ++neurIter){
00763 
00764                                 //Set the color of the neuron
00765                                 if(connectionMode & CONNECTION_MODE_ENABLED){
00766                                         if(netDisplay->getSingleNeuronID() == (*neurIter)->getID() ){//Single selected neuron
00767                                                 tmpColor2 = netDisplay->getSingleNeuronColor();
00768                                                 glColor4f(tmpColor2.red, tmpColor2.green, tmpColor2.blue, neuronAlpha);
00769                                         }
00770                                         else if(netDisplay->getToNeuronID() == (*neurIter)->getID() ){//To neuron
00771                                                 tmpColor2 = netDisplay->getToNeuronColor();
00772                                                 glColor4f(tmpColor2.red, tmpColor2.green, tmpColor2.blue, neuronAlpha);
00773                                         }
00774                                         else if(connectedNeuronMap.contains((*neurIter)->getID())){//A connected neuron
00775                                                 weight = connectedNeuronMap[(*neurIter)->getID()];
00776                                                 if(weight > 0)//Positive connection
00777                                                         glColor4f(1.0f, 0.0f, 0.0f, neuronAlpha);
00778                                                 else if(weight < 0)
00779                                                         glColor4f(0.0f, 0.0f, 1.0f, neuronAlpha);
00780                                                 else
00781                                                         glColor4f(0.0f, 0.0f, 0.0f, neuronAlpha);
00782                                         }
00783                                         else{
00784                                                 glColor4f(defaultNeuronColor.red, defaultNeuronColor.green, defaultNeuronColor.blue, neuronAlpha);
00785                                         }
00786                                 }
00787                                 else if(neuronColorMap.contains(neurIter.key())){
00788                                         tmpColor = neuronColorMap[neurIter.key()];
00789                                         glColor4f(tmpColor->red, tmpColor->green, tmpColor->blue, neuronAlpha);
00790                                 }
00791                                 else{
00792                                         glColor4f(defaultNeuronColor.red, defaultNeuronColor.green, defaultNeuronColor.blue, neuronAlpha);
00793                                 }
00794 
00795                                 //Draw the neuron
00796                                 glPushName((*neurIter)->getID());
00797                                         if(!fullRenderMode){//Draw neurons as a vertex
00798                                                 glBegin(GL_POINTS);
00799                                                         glVertex3f(neurIter.value()->getXPos(), neurIter.value()->getYPos(), neurIter.value()->getZPos());
00800                                                 glEnd();
00801                                         }
00802                                         else{//Draw neurons as a sphere
00803                                                 drawSphere(neurIter.value()->getXPos(), neurIter.value()->getYPos(), neurIter.value()->getZPos());
00804                                         }
00805                                 glPopName();
00806                         }
00807                 }
00808 
00809                 //Finished creating neurons display list
00810                 glEndList();
00811                 useNeuronsDisplayList = true;
00812         }
00813 }
00814 
00815 
00817 void NetworkViewer::drawSphere(float xPos, float yPos, float zPos) {
00818         glPushMatrix();
00819         glTranslatef(xPos, yPos, zPos);//Translate to sphere position
00820 
00821         //Call display list to draw a sphere
00822         glCallList(sphereDisplayList);
00823 
00824         glPopMatrix();
00825 }
00826 
00827 
00829 void NetworkViewer::drawWeightedConnection(float x1, float y1, float z1, float x2, float y2, float z2, float weight){
00830         //Make sure weight is positive
00831         if(weight < 0.0f)
00832                 weight *= -1.0f;
00833 
00834         //Draw line if we are less than minimum connection weight
00835         if(weightRadiusFactor * weight < minimumConnectionRadius){
00836                 glBegin(GL_LINES);
00837                         glVertex3f(x1, y1, z1);
00838                         glVertex3f(x2, y2, z2);
00839                 glEnd();//End of line drawing
00840                 return;
00841         }
00842 
00843         //Calculate vector and angle with Z axis
00844         float conVect [] = { x2-x1, y2-y1, z2-z1 };
00845 
00846         //Some calculations
00847         float length = sqrt(pow(conVect[0], 2) + pow(conVect[1], 2) + pow(conVect[2], 2));
00848         float rotationAngle = GLT_INV_PI_DIV_180 * -1.0f * acos((conVect[2]) / length);//Angle with vertical z axis
00849 
00850         //Store matrix and move to first point
00851         glPushMatrix();
00852         glTranslatef(x1, y1, z1);
00853         glRotatef(rotationAngle, conVect[1], -conVect[0], 0.0f);//Rotate z vertical
00854         gluCylinder(gluConeObj, 0.0 , weightRadiusFactor * weight, length/2.0, 8, 8);
00855         glTranslatef(0.0, 0.0, length/2);//Half way up current Z axis
00856         gluCylinder(gluConeObj, weightRadiusFactor * weight, 0.0, length/2.0, 8, 8);
00857         glPopMatrix();
00858 }
00859 
00860 
00862 void NetworkViewer::initialiseFullRender(){
00863         // Cull backs of polygons
00864         glCullFace(GL_BACK);
00865         glFrontFace(GL_CCW);
00866         glEnable(GL_CULL_FACE);
00867         glEnable(GL_DEPTH_TEST);
00868 
00869         // Setup light parameters
00870         GLfloat fLightPos2[4]   = { defaultClippingVol.x1 + 0.5f * (defaultClippingVol.x2 - defaultClippingVol.x1), defaultClippingVol.y1, defaultClippingVol.z2, 1.0f };
00871         glLightfv(GL_LIGHT0, GL_POSITION, fLightPos2);
00872         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fLowLight);
00873         glLightfv(GL_LIGHT0, GL_AMBIENT, fLowLight);
00874         glLightfv(GL_LIGHT0, GL_DIFFUSE, fBrightLight);
00875         glLightfv(GL_LIGHT0, GL_SPECULAR, fBrightLight);
00876         glEnable(GL_LIGHTING);
00877         glEnable(GL_LIGHT0);
00878 
00879         // Mostly use material tracking
00880         glEnable(GL_COLOR_MATERIAL);
00881         glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
00882         glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
00883         glMateriali(GL_FRONT, GL_SHININESS, 128);
00884 
00885         //Transparency settings
00886         glEnable(GL_BLEND);
00887         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00888 }
00889 
00890 
00892 void NetworkViewer::disableFullRender(){
00893         glDisable(GL_CULL_FACE);
00894         glDisable(GL_DEPTH_TEST);
00895         glDisable(GL_LIGHTING);
00896         glDisable(GL_LIGHT0);
00897         glDisable(GL_COLOR_MATERIAL);
00898         glDisable(GL_BLEND);
00899 }
00900 
00901 
00903 void NetworkViewer::positionCamera(){    //
00904         gluLookAt(
00905                         //Location defined by fourth column of camera matrix
00906                         cameraMatrix[12], cameraMatrix[13], cameraMatrix[14],
00907                         //Forward is the Y axis so add this to position
00908                         (cameraMatrix[12] + cameraMatrix[4]), (cameraMatrix[13] + cameraMatrix[5]), (cameraMatrix[14] + cameraMatrix[6]),
00909                         //Up is the Z axis
00910                         cameraMatrix[8], cameraMatrix[9], cameraMatrix[10]
00911                         );
00912 
00913         //Rotate scene
00914         glRotatef(sceneRotateX, 1.0f, 0.0f, 0.0f);
00915         glRotatef(sceneRotateZ, 0.0f, 0.0f, 1.0f);
00916 }
00917 
00918 
00922 void NetworkViewer::fillRotationMatrix(float angle, float x, float y, float z){
00923         float vecLength, sinSave, cosSave, oneMinusCos;
00924         float xx, yy, zz, xy, yz, zx, xs, ys, zs;
00925 
00926         // If NULL vector passed in, this will blow up...
00927         if(x == 0.0f && y == 0.0f && z == 0.0f){
00928                 qCritical()<<"NetworkViewer: NULL MATRIX PASSED TO fillRotationMatrix.";
00929                 return;
00930         }
00931 
00932         // Scale vector
00933         vecLength = (float)sqrt( x*x + y*y + z*z );
00934 
00935         // Rotation matrix is normalized
00936         x /= vecLength;
00937         y /= vecLength;
00938         z /= vecLength;
00939 
00940         sinSave = (float)sin(angle);
00941         cosSave = (float)cos(angle);
00942         oneMinusCos = 1.0f - cosSave;
00943 
00944         xx = x * x;
00945         yy = y * y;
00946         zz = z * z;
00947         xy = x * y;
00948         yz = y * z;
00949         zx = z * x;
00950         xs = x * sinSave;
00951         ys = y * sinSave;
00952         zs = z * sinSave;
00953 
00954         rotationMatrix[0] = (oneMinusCos * xx) + cosSave;
00955         rotationMatrix[4] = (oneMinusCos * xy) - zs;
00956         rotationMatrix[8] = (oneMinusCos * zx) + ys;
00957         rotationMatrix[12] = 0.0f;
00958 
00959         rotationMatrix[1] = (oneMinusCos * xy) + zs;
00960         rotationMatrix[5] = (oneMinusCos * yy) + cosSave;
00961         rotationMatrix[9] = (oneMinusCos * yz) - xs;
00962         rotationMatrix[13] = 0.0f;
00963 
00964         rotationMatrix[2] = (oneMinusCos * zx) - ys;
00965         rotationMatrix[6] = (oneMinusCos * yz) + xs;
00966         rotationMatrix[10] = (oneMinusCos * zz) + cosSave;
00967         rotationMatrix[14] = 0.0f;
00968 
00969         rotationMatrix[3] = 0.0f;
00970         rotationMatrix[7] = 0.0f;
00971         rotationMatrix[11] = 0.0f;
00972         rotationMatrix[15] = 1.0f;
00973 }
00974 
00975 
00978 unsigned int NetworkViewer::getSelectedNeuron(GLuint selectBuffer[], int hitCount, int bufferSize){
00979         if(hitCount == 0)
00980                 return 0;
00981         if(hitCount * 4 > bufferSize)
00982                 throw SpikeStreamException("Hit data overflows buffer");
00983 
00984 
00985         GLuint nameCount, *ptr, minZ, minZName=0, currentMinZ, name;
00986         ptr = selectBuffer;
00987         minZ = 0xffffffff;
00988         for(int i=0; i<hitCount; ++i){
00989                 //First field is the number of names
00990                 nameCount = *ptr;
00991                 if(nameCount != 1)
00992                         throw SpikeStreamException("Unnamed object selected or multiple names associated with the same object.");
00993 
00994                 //Second field is minimum depth for this record
00995                 ++ptr;
00996                 currentMinZ = *ptr;
00997 
00998                 //Third field is the maximum depth for this record
00999                 ++ptr;
01000 
01001                 //Remaining field for this record is the name - should only be 1 name if we have got this far
01002                 ++ptr;
01003                 name = *ptr;
01004 
01005                 if(currentMinZ < minZ){
01006                         minZ = currentMinZ;
01007                         minZName = name;
01008                 }
01009 
01010                 //Increase pointer to the next hit if it exists
01011                 ++ptr;
01012         }
01013 
01014         //Return the name with the minimum z
01015         return minZName;
01016 }
01017 
01018 
01020 void NetworkViewer::initialiseCameraParameters(){
01021         //Scene rotate parameters are used to control the rotation of the scene
01022         sceneRotateX = 0.0f;
01023         sceneRotateZ = 0.0f;
01024 
01025         //Set up camera looking down positive Y direction with z axis pointing up and positive X to the right
01026         //X axis for camera frame of reference
01027         cameraMatrix[0] = 1.0f;
01028         cameraMatrix[1] = 0.0f;
01029         cameraMatrix[2] = 0.0f;
01030         cameraMatrix[3] = 0.0f;
01031 
01032         //Y axis for camera frame of reference
01033         cameraMatrix[4] = 0.0f;
01034         cameraMatrix[5] = 1.0f;
01035         cameraMatrix[6] = 0.0f;
01036         cameraMatrix[7] = 0.0f;
01037 
01038         //Z axis for camera frame of reference
01039         cameraMatrix[8] = 0.0f;
01040         cameraMatrix[9] = 0.0f;
01041         cameraMatrix[10] = 1.0f;
01042         cameraMatrix[11] = 0.0f;
01043 
01044         //Location for camera frame of reference
01045         cameraMatrix[12] = 0.0f;
01046         cameraMatrix[13] = -5.0f;
01047         cameraMatrix[14] = 0.0f;
01048 }
01049 
01050 
01052 void NetworkViewer::loadDefaultClippingVolume(){
01053         /*If the network is empty or contains no neurons.
01054         set up default clipping volume around origin */
01055         if(!Globals::networkLoaded() || Globals::getNetwork()->size() == 0){
01056                 defaultClippingVol.x1 = -100;
01057                 defaultClippingVol.x2 = 100;
01058                 defaultClippingVol.y1 = -100;
01059                 defaultClippingVol.y2 = 100;
01060                 defaultClippingVol.z1 = -100;
01061                 defaultClippingVol.z2 = 100;
01062                 return;
01063         }
01064 
01065         //Get box enclosing network
01066         defaultClippingVol = Globals::getNetwork()->getBoundingBox();
01067 
01068         //Want to include the origin in the starting clip volume
01069         if(defaultClippingVol.x1 > 0)
01070                 defaultClippingVol.x1 = 0;
01071         if(defaultClippingVol.x2 < 0)
01072                 defaultClippingVol.x2 =0;
01073         if(defaultClippingVol.y1 > 0)
01074                 defaultClippingVol.y1 = 0;
01075         if(defaultClippingVol.y2 < 0)
01076                 defaultClippingVol.y2 = 0;
01077         if(defaultClippingVol.z1 > 0)
01078                 defaultClippingVol.z1 = 0;
01079         if(defaultClippingVol.z2 < 0)
01080                 defaultClippingVol.z2 = 0;
01081 
01082         //Expand box by 20% to give a nice view
01083         defaultClippingVol.expand_percent(20);
01084 }
01085 
01086 
01089 void NetworkViewer::rotateVector(GLfloat x, GLfloat y, GLfloat z, GLfloat result[]){
01090         result[0] = rotationMatrix[0] * x + rotationMatrix[4] * y + rotationMatrix[8] *  z;
01091         result[1] = rotationMatrix[1] * x + rotationMatrix[5] * y + rotationMatrix[9] *  z;
01092         result[2] = rotationMatrix[2] * x + rotationMatrix[6] * y + rotationMatrix[10] * z;
01093 }
01094 
01095 
01097 void NetworkViewer::rotateXAxis(float angle){
01098         //Rotating around X axis so pass vector defining this axis for the camera to fillRotationMatrix
01099         fillRotationMatrix(angle, cameraMatrix[0], cameraMatrix[1], cameraMatrix[2]);
01100 
01101         //Create temporary array to hold result
01102         GLfloat resultArray[3];
01103 
01104         //First rotate the Y axis around X axis
01105         rotateVector(cameraMatrix[4], cameraMatrix[5], cameraMatrix[6], resultArray);
01106 
01107         //Copy result array into cameraMatrix. Could probably simplify this
01108         cameraMatrix[4] = resultArray[0];
01109         cameraMatrix[5] = resultArray[1];
01110         cameraMatrix[6] = resultArray[2];
01111 
01112         //Now rotate the Z axis around X axis
01113         rotateVector(cameraMatrix[8], cameraMatrix[9], cameraMatrix[10], resultArray);
01114 
01115         //Copy result array into cameraMatrix. Could probably simplify this
01116         cameraMatrix[8] = resultArray[0];
01117         cameraMatrix[9] = resultArray[1];
01118         cameraMatrix[10] = resultArray[2];
01119 }
01120 
01121 
01123 void NetworkViewer::rotateZAxis(float angle){
01124         //Rotating around Z axis, so pass vector defining this axis for the camera to fillRotationMatrix
01125         fillRotationMatrix(angle, cameraMatrix[8], cameraMatrix[9], cameraMatrix[10]);
01126 
01127         //Create temporary array to hold result
01128         GLfloat resultArray[3];
01129 
01130         //First rotate the X axis around Z axis
01131         rotateVector(cameraMatrix[0], cameraMatrix[1], cameraMatrix[2], resultArray);
01132 
01133         //Copy result array into cameraMatrix. Could probably simplify this
01134         cameraMatrix[0] = resultArray[0];
01135         cameraMatrix[1] = resultArray[1];
01136         cameraMatrix[2] = resultArray[2];
01137 
01138         //Now rotate the Y axis around Z axis
01139         rotateVector(cameraMatrix[4], cameraMatrix[5], cameraMatrix[6], resultArray);
01140 
01141         //Copy result array into cameraMatrix. Could probably simplify this
01142         cameraMatrix[4] = resultArray[0];
01143         cameraMatrix[5] = resultArray[1];
01144         cameraMatrix[6] = resultArray[2];
01145 }
01146 
01147 
01149 void NetworkViewer::viewClippingVolume_Horizontal(Box& clipVolume){
01150         //First set camera parameters to their starting values
01151         initialiseCameraParameters();
01152 
01153         //Now adjust these parameters to view the whole of the clipping volume
01154         //X location should be half way along the clipping volume
01155         cameraMatrix[12] = clipVolume.x1 + (clipVolume.x2 - clipVolume.x1)/2.0f;
01156 
01157 
01158         //Camera is looking down the Y axis. So need to move back far enough to see all of clipping volume within perspective
01159         //First find whether z or x direction is longest
01160         GLfloat backwardsDistance;
01161         if((clipVolume.x2 - clipVolume.x1) > (clipVolume.z2 - clipVolume.z1)){//X direction is longest
01162                 backwardsDistance = ((clipVolume.x2 - clipVolume.x1)/2.0f)/tan(gltDegToRad(perspective_angle)/2.0f);
01163         }
01164         else{//Z direction is longest
01165                 backwardsDistance = ((clipVolume.z2 - clipVolume.z1)/2.0f)/tan(gltDegToRad(perspective_angle)/2.0f);
01166         }
01167         //Now move camera back so that it can see everything in both directions
01168         //In this case this moves camera back along the negative y direction
01169         cameraMatrix[13] = -1 * backwardsDistance;
01170 
01171         //Z location should be half way up clipping volume
01172         cameraMatrix[14] = clipVolume.z1 + (clipVolume.z2 - clipVolume.z1)/2.0f;
01173 
01174         //Forward vector does not need to be calculated because camera is initilised looking along positive Y, which is correct for horizontal view
01175 }
01176 
01177 
01179 void NetworkViewer::viewClippingVolume_Vertical(Box& clipVolume){
01180         //First set camera parameters to their starting values
01181         initialiseCameraParameters();
01182 
01183         //X location should be half way along the clipping volume
01184         cameraMatrix[12] = clipVolume.x1 + (clipVolume.x2 - clipVolume.x1)/2.0f;
01185 
01186         //Camera is looking down the Z axis. So need to move back far enough to see all of clipping volume within perspective
01187         //First find whether y or x direction is longest
01188         GLfloat backwardsDistance;
01189         if((clipVolume.x2 - clipVolume.x1) > (clipVolume.y2 - clipVolume.y1)){//X direction is longest
01190                 backwardsDistance = ((clipVolume.x2 - clipVolume.x1)/2.0f)/tan(gltDegToRad(perspective_angle)/2.0f);
01191         }
01192         else{//Y direction is longest
01193                 backwardsDistance = ((clipVolume.y2 - clipVolume.y1)/2.0f)/tan(gltDegToRad(perspective_angle)/2.0f);
01194         }
01195 
01196         //Now move camera back so that it can see everything in both directions
01197         //To look above need to move up the positive direction of the Z axis
01198         cameraMatrix[14] = 1.1f*(backwardsDistance + clipVolume.z2);
01199 
01200         //Y location should be half way along clipping volume
01201         cameraMatrix[13] = clipVolume.y1 + (clipVolume.y2 - clipVolume.y1)/2.0f;
01202 
01203         //X axis stays the same
01204         //Change camera Y axis so that it is pointing down negative Z
01205         cameraMatrix[4] = 0.0f;
01206         cameraMatrix[5] = 0.0f;
01207         cameraMatrix[6] = -1.0f;
01208 
01209         //Change camera Z axis so that it points along positive Y
01210         cameraMatrix[8] = 0.0f;
01211         cameraMatrix[9] = 1.0f;
01212         cameraMatrix[10] = 0.0f;
01213 }
01214 
01215 
01217 void NetworkViewer::setZoomLevel(){
01218         if(Globals::getNetworkDisplay()->isZoomEnabled()){
01219                 unsigned int tmpZoomNeurGrpID = Globals::getNetworkDisplay()->getZoomNeuronGroupID();
01220                 if(tmpZoomNeurGrpID == 0)
01221                         zoomDefaultView();
01222                 else{
01223                         if(Globals::getNetworkDisplay()->getZoomStatus() == NetworkDisplay::ZOOM_SIDE)
01224                                 zoomToNeuronGroup(tmpZoomNeurGrpID);
01225                         else if (Globals::getNetworkDisplay()->getZoomStatus() == NetworkDisplay::ZOOM_ABOVE)
01226                                 zoomAboveNeuronGroup(tmpZoomNeurGrpID);
01227                 }
01228         }
01229 }
01230 
01231 
01233 void NetworkViewer::zoomDefaultView(){
01234         viewClippingVolume_Horizontal(defaultClippingVol);
01235 }
01236 
01237 
01241 void NetworkViewer::zoomAboveNeuronGroup(unsigned int neuronGroupID){
01242         if(!Globals::networkLoaded())
01243                 return;
01244         Box neurGrpBox = Globals::getNetwork()->getNeuronGroupBoundingBox(neuronGroupID);
01245         viewClippingVolume_Vertical(neurGrpBox);
01246 }
01247 
01248 
01252 void NetworkViewer::zoomToNeuronGroup(unsigned int neuronGroupID){
01253         if(!Globals::networkLoaded())
01254                 return;
01255         Box neurGrpBox = Globals::getNetwork()->getNeuronGroupBoundingBox(neuronGroupID);
01256         viewClippingVolume_Horizontal(neurGrpBox);
01257 }
01258 
01259 
 All Classes Files Functions Variables Typedefs Friends Defines