SpikeStream Application Library
0.2
|
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