Main Page | Class Hierarchy | Class List | Directories | File List | Class Members

main.cpp

00001 
00006 #include <iostream>
00007 #include <glui.h>
00008 #include <glut.h>
00009 #include <sstream>
00010 
00011 #include "LifeVariables.h"
00012 
00013 using namespace std;
00014 
00015 
00016 /*
00017  * Section: Init
00018  *
00019  *    This section initalise all globals that are defined as extern in 
00020  *    LifeVariables.h
00021  *
00022  */
00023 
00025 int xResolution = X_RES;
00026 
00028 int yResolution = Y_RES;
00029 
00031 int mainWindow = 0;
00032 
00034 RawReader *reader = NULL;;
00035 
00037 MenuBar *menuBar = NULL;;
00038 
00040 StateBar *stateBar = NULL;;
00041 
00043 FileDialog *fileDialog = NULL;; 
00044 
00046 OptionPanel *optionPanel = NULL;
00047 
00049 Histogram *histogram = NULL;
00050 
00052 ViewPort *mainViewPort = NULL;
00053 
00055 int mouseBtn = -1;
00056 
00059 ColorCubePanel *colorSelector = NULL;
00060 
00063 ProgramState currentProgramState = START;
00064 
00067 bool debugMode = DEBUG_MODE;
00068 
00070 CVolVoxels GVolVoxels;
00071 
00073 CDensities GDensities;
00074 
00076 CTex GTex;
00077 
00079 CScanner    GScanner;
00080 
00081 
00082 
00084 bool refresh = true;
00085 
00086 /*
00087  * Section: Implementation
00088  *
00089  *    This gives an implementation to the extern functions 
00090  *    defined in LifeVariables.h
00091  *
00092  *
00093  */
00094 
00095 
00098 void showGlDebugMessages() {    
00099     switch (glGetError()) {
00100         case GL_NO_ERROR: break;
00101         case GL_INVALID_ENUM: 
00102             cout << "GL_INVALID_ENUM: An unacceptable value is specified for an enumerated argument." << endl;
00103             break;
00104         case GL_INVALID_VALUE: 
00105             cout << "GL_INVALID_VALUE: A numeric argument is out of range." << endl;
00106             break;
00107         case GL_INVALID_OPERATION:
00108             cout << "GL_STACK_OVERFLOW: The specified operation is not allowed in the current state." << endl;
00109             break;
00110         case GL_STACK_OVERFLOW: 
00111             cout << "GL_STACK_OVERFLOW: This function would cause a stack overflow." << endl;
00112             break;
00113         case GL_STACK_UNDERFLOW:
00114             cout << "GL_STACK_UNDERFLOW: This function would cause a stack underflow." << endl;
00115             break;
00116         case GL_OUT_OF_MEMORY: 
00117             cout << "GL_OUT_OF_MEMORY: There is not enough memory left to execute the function." << endl;
00118             break;
00119         default: break;
00120     }     
00121 }
00122 
00123 
00126 void renderString(int x, int y, void *font, int nr) {
00127     string text="";
00128     ostringstream outStream;
00129     outStream << nr;
00130     text = outStream.str();
00131     renderString(x,y,font,text);
00132 }
00133 
00134 
00137 void renderString(int x, int y, void *font, string text) {
00138     glRasterPos2i(x, y);    
00139     for(int i = 0; i < text.length(); i++) {
00140        glutBitmapCharacter(font, text[i]);       
00141     }    
00142 }
00143 
00144 extern void RenderVolume();
00145 
00146 
00149 void display() {
00150   
00151     glMatrixMode(GL_MODELVIEW); 
00152     glLoadIdentity();
00153 
00154     // setup the background color
00155     glClearColor(0.0,0.0,0.0,0.0);
00156 
00157     // clear everything drawn so far
00158     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00159     
00160     glViewport(mainViewPort->x, 
00161                mainViewPort->y+HISTOGRAM_WND_HEIGHT/2,
00162                mainViewPort->w, 
00163                mainViewPort->h);
00164     
00165     // render crap with respect to the program state:    
00166     switch(currentProgramState) {
00167         // if in VOLUME_MODE, render the volume
00168         case VOLUME_MODE:
00169             
00170             // QQ:  RenderVolume should go here.... 
00171             //
00172             //
00173             colorSelector->render();
00174 
00175             histogram->render(mainViewPort->x, 
00176                               mainViewPort->y,
00177                               mainViewPort->w,
00178                               HISTOGRAM_WND_HEIGHT);
00179 
00180             GScanner.ScanVolume();
00181 
00182             GTex.RenderVolumeSubTexture();
00183                 // refresh false will make the texture disappear after rendering due to
00184                 // the swap buffers call at the end..
00185                 // swap buffers can not be removed -> there must be a second way
00186                 // of showing the texture without raycasting
00187                 //refresh = false;                
00188             
00189             break;
00190 
00191         // if in SLICE_MODE, render the slices
00192         case SLICE_MODE:           
00193             colorSelector->render();
00194 
00195             histogram->render(mainViewPort->x, 
00196                               mainViewPort->y,
00197                               mainViewPort->w,
00198                               HISTOGRAM_WND_HEIGHT);
00199 
00200             
00201             // process the image if possible            
00202             if(GVolVoxels.GetDimX()) {
00203                 GTex.RenderSubTexture();
00204             }            
00205             break;
00206 
00207         // if UNLOADING do not render anything, the pointers
00208         // to the dataset are not valid
00209         case UNLOADING:            
00210             break;
00211 
00212         // if LOADING do not render anything, the pointers
00213         // to the dataset are not valid yet
00214         case LOADING:
00215             break;
00216         
00217         // by default we are in state START, do not render:
00218         default:            
00219             break;
00220 
00221     }      
00222     // if the program is in debug mode, show verbose messages
00223     if(debugMode) {
00224         showGlDebugMessages();
00225     }
00226     // swap the buffers
00227     glutSwapBuffers(); 
00228 }
00229 
00230 
00231 
00234 void reshape(int x, int y) {
00235     GLUI_Master.get_viewport_area(&mainViewPort->x, 
00236                                   &mainViewPort->y,
00237                                   &mainViewPort->w,
00238                                   &mainViewPort->h);
00239 
00240     glViewport(mainViewPort->x, 
00241                mainViewPort->y+HISTOGRAM_WND_HEIGHT/2,
00242                mainViewPort->w, 
00243                mainViewPort->h);
00244 
00245     glMatrixMode(GL_PROJECTION);    
00246     glLoadIdentity();
00247 
00248     if (mainViewPort->w <= mainViewPort->h) {
00249         glOrtho(-2.0, 
00250                  2.0,
00251                 -2.0 * (GLfloat) mainViewPort->h / (GLfloat) mainViewPort->w, 
00252                  2.0 * (GLfloat) mainViewPort->h / (GLfloat) mainViewPort->w,  
00253                 -3.0, 
00254                  3.0);
00255     }
00256     else {
00257         glOrtho(-2.0 * (GLfloat) mainViewPort->w / (GLfloat) mainViewPort->h, 
00258                  2.0 * (GLfloat) mainViewPort->w / (GLfloat) mainViewPort->h,
00259                 -2.0,
00260                  2.0,
00261                 -3.0,
00262                  3.0);
00263     }
00264     
00265     colorSelector->refreshDragBounds(x, y);
00266     xResolution = x;
00267     yResolution = y;
00268     glutPostRedisplay();
00269     glMatrixMode(GL_MODELVIEW); 
00270     
00271 }
00272 
00273 
00276 void idle() {
00277   Sleep(10);
00278   glutSetWindow(mainWindow);
00279   GLUI_Master.sync_live_all();
00280 }
00281 
00282 
00284 void enterUnloadedMode() throw(Error) {   
00285     if(currentProgramState == SLICE_MODE) {       
00286         // prevent the rendering - set the state at first
00287         currentProgramState = UNLOADING;
00288         if(debugMode == true) cout << "currentProgramState = UNLOADING" << endl;
00289     
00290         // disable the mode selection and the option panel
00291         optionPanel->disable();                
00292                
00293 
00294         // clean up the slice pointers
00295         GTex.Shutdown();        
00296         GDensities.Shutdown();
00297         GVolVoxels.Shutdown();
00298 
00299         currentProgramState = UNLOADED;
00300         if(debugMode == true) cout << "currentProgramState = UNLOADED" << endl;
00301         return;
00302     }   
00303 
00304     else if(currentProgramState == VOLUME_MODE) {
00305         // prevent the rendering - set the state at first
00306         currentProgramState = UNLOADING;
00307         stateBar->updateRenderInfo("Unloading file");
00308         if(debugMode == true) cout << "currentProgramState = UNLOADING" << endl;
00309         
00310         // disable the mode selection and the option panel
00311         optionPanel->disable();
00312 
00313         //
00314         // QQ unload volume data
00315         //
00316 
00317         currentProgramState = UNLOADED;
00318         if(debugMode == true) cout << "currentProgramState = UNLOADED" << endl;
00319         stateBar->updateRenderInfo("Unloading complete");        
00320     }
00321     
00322     else if (currentProgramState == START ) {        
00323         return;
00324     }
00325 
00326     else {        
00327         throw Error("Can not unload data."); 
00328     }
00329 }
00330 
00331 
00333 void enterLoadedMode() throw (Error) {
00334     if((currentProgramState == START) || (currentProgramState == UNLOADED)) {
00335         currentProgramState = LOADING;
00336         stateBar->updateFileInfo("-");
00337         stateBar->updateRenderInfo("Loading File...");
00338         if(debugMode == true) cout << "currentProgramState = LOADING" << endl;
00339 
00340         // open the new file - throws the error if the file is
00341         reader->open(menuBar->selectedFile);
00342         currentProgramState = LOADED;
00343         if(debugMode == true) cout << "currentProgramState = LOADED" << endl;
00344         stateBar->updateRenderInfo("Loading complete");
00345         return;
00346     }
00347     else {
00348         throw Error("Can not load data.");
00349     }
00350 }
00351 
00352 
00354 void enterSlicingMode() throw (Error) { 
00355     
00356     if(currentProgramState == LOADED) {
00357         stateBar->updateRenderInfo("Preparing Data...");
00358         // init the texture thing
00359         GVolVoxels.Init(reader->voxelData, 
00360                        reader->dimX,
00361                        reader->dimY,
00362                        reader->dimZ);
00363 
00364         histogram->update(reader->voxelData, reader->size);
00365 
00366         // refresh the gui:
00367         // enable the mode selection
00368         optionPanel->enableModeSelection();
00369 
00370         // enable the option panel (will set the default visualisation mode)
00371         optionPanel->switchRenderMode(SLICE_VISUALISATION);
00372 
00373         // set the slice spinner to 0
00374         optionPanel->updateSliceMax(reader->dimX, reader->dimY, reader->dimZ);
00375 
00376         // update the statebar with information of other gui components
00377         stateBar->updateFileInfo(reader->fileInfoString);
00378         stateBar->updateRenderInfo("Slice Visualisation");
00379        
00380         currentProgramState = SLICE_MODE;
00381         if(debugMode == true) cout << "currentProgramState = SLICE_MODE" << endl;
00382     }
00383 
00384     else if(currentProgramState == VOLUME_MODE) {
00385         // destroy VOLUME_MODE mode to stop rendering
00386         currentProgramState = SWITCHING;
00387         if(debugMode == true) cout << "currentProgramState = SWITCHING" << endl;
00388 
00389         //
00390         // QQ unload the volume
00391         //
00392 
00393         // init the texture thing - some error :
00394         // might happen because reader->voxelData had been deleted
00395         // during the last shutdown ???
00396         // currently works when press open again
00397         /*
00398         GVolVoxels.Init(reader->voxelData, 
00399                         reader->dimX,
00400                         reader->dimY,
00401                         reader->dimZ);
00402         */
00403         optionPanel->switchRenderMode(SLICE_VISUALISATION);
00404         stateBar->updateRenderInfo("Slice Visualisation");
00405         
00406         currentProgramState = SLICE_MODE;
00407         if(debugMode == true) cout << "currentProgramState = SLICE_MODE" << endl;
00408     }
00409     else {
00410         throw Error("Can not enter Slice Mode.");
00411     }
00412 }
00413 
00414 
00416 void enterVolumeMode() throw (Error){
00417     if(currentProgramState == SLICE_MODE) {
00418         // destroy SLICE_MODE to stop rendering
00419         currentProgramState = SWITCHING;
00420         if(debugMode == true) cout << "currentProgramState = SWITCHING" << endl;
00421 
00422         optionPanel->switchRenderMode(VOLUME_VISUALISATION);
00423         stateBar->updateRenderInfo("Volume Visualisation");
00424 
00425         //QQ need to create a new texture, then shutdown this texture.
00426         // shutdown the slice mode pointer
00427         // GVolVoxels.Shutdown();
00428         // GDensities.Shutdown();
00429         // GTex.Shutdown();
00430 
00431         //
00432         // QQ init the volumevisualisation
00433         //
00434         // Need to get eye opsition and ray direction here, pass it to init.
00435         //
00436         //GScanner.direction = optionPanel->viewingDirection;
00437         //GScanner.Init();
00438         
00439         currentProgramState = VOLUME_MODE;
00440         if(debugMode == true) cout << "currentProgramState = VOLUME_MODE" << endl;
00441         eventListener(REFRESH_ID);
00442     }
00443     else {
00444         throw Error("Can not enter Volume Mode.");
00445     }    
00446 }
00447 
00448 
00449 
00453 void eventListener(int control) {
00454     
00455     ProgramState oldState = currentProgramState;
00456     
00457     switch(control) {
00458 
00459         // if the user push the refresh button
00460         case REFRESH_ID:
00461             //
00462             // QQ add here code that says: do new raycasting
00463             //  this code should use all parameters/globals
00464             //  and create a new image by this way
00465             //
00466             refresh = true;            
00467             GScanner.direction = optionPanel->viewingDirection;           
00468             GScanner.Init();
00469             cout << "REFRESH_ID" << endl;
00470             break;
00471 
00472         // if the user push the button beside the drop down list
00473         case OPEN_FILE_ID:            
00474             try {
00475                 enterUnloadedMode();
00476                 enterLoadedMode();    
00477                 enterSlicingMode();
00478             }
00479             catch (Error e){
00480                 cout << e.getErrorMsg() << endl;
00481                 currentProgramState = oldState;                
00482             }          
00483             break;
00484 
00485         // the the user switch the visualisation mode
00486         case MODESELECT_ID:            
00487             if(currentProgramState == SLICE_MODE) {
00488                  enterVolumeMode();
00489             }
00490             else {            
00491                  enterSlicingMode();
00492             }             
00493             break;
00494 
00495         // if the user switch the plane (slicing mode)
00496         case PLANESELECT_ID:
00497              optionPanel->updateSliceMax(reader->dimX, reader->dimY, reader->dimZ);
00498              break;
00499 
00500         // if the user switch the transferfunction
00501         case TXFUNCTIONSELECT_ID:            
00502             if(optionPanel->txFunction == XRAY) {
00503                 optionPanel->disableMipSpinners();
00504             }
00505             else if(optionPanel->txFunction == COMPOSITING) {                
00506                 optionPanel->disableMipSpinners();                
00507             }
00508             else if (optionPanel->txFunction == FIRST_HIT) {
00509                 optionPanel->enableMipSpinners();
00510             }
00511             else if (optionPanel->txFunction == MIP) {                             
00512                 optionPanel->disableMipSpinners();
00513             }
00514             break;
00515 
00516         // if the user change the selected slice
00517         //case SLICESELECT_ID:             
00518         //     break;
00519         case VIEWINGDIRECTION_ID:
00520             GScanner.direction = optionPanel->viewingDirection;
00521             cout << GScanner.direction << endl;
00522             break;
00523 
00524         // if the user wants to change the search path
00525         case SHOWOPENFILEDLG_ID:
00526              fileDialog->show();
00527              break;
00528 
00529         // if the user confirms the search path dialog
00530         case CONFIRMOPENFILEDLG_ID:
00531              fileDialog->confirm();
00532              try {                 
00533                  reader->openPath(fileDialog->path);
00534                  menuBar->updateFileList();
00535                  optionPanel->disable();                 
00536              }
00537              catch (Error e) {
00538                  fileDialog->show(e.getError());
00539              }
00540              break;
00541 
00542         // if the user cancel the search path dialog
00543         case CANCELOPENFILEDLG_ID:
00544              fileDialog->hide();
00545              break;
00546 
00547         // default just do nothing
00548         default: break;
00549     }
00550     glutSetWindow(mainWindow);
00551     GLUI_Master.sync_live_all();
00552   
00553     // call display will refresh immediatly and
00554     // switch to the idle function afterwards
00555     display();
00556 }
00557 
00558 
00559 
00561 void deInit() {
00562     delete fileDialog;
00563     delete optionPanel;
00564     delete stateBar;
00565     delete menuBar;
00566     delete reader;   
00567     delete histogram;
00568     delete mainViewPort;
00569 }
00570 
00571 
00575 void keyEvent(unsigned char key, int x, int y) {
00576         switch(key) {
00577             case 27:
00578             //deInit();
00579             exit(0);
00580         case 127:
00581             histogram->updating();
00582             histogram->removeControlPoint();
00583             histogram->enable();
00584             display();
00585             break;
00586         default: 
00587             cout << "Key '"<< key <<"' is not assigned! (Press Esc to quit)" << endl;
00588             break;
00589         }
00590     display();
00591 }
00592 
00593 
00600 void mouseEvent(int button, int state, int x, int y) {
00601   
00602     // flip y
00603     y = yResolution - y;
00604     
00605     if((button == GLUT_LEFT_BUTTON)&&(state == GLUT_DOWN)) {
00606         mouseBtn = GLUT_LEFT_BUTTON;
00607         histogram->onLeftMouseClick(x,y);
00608         // if the user pressed left button, the color gets
00609         // selected and the histogram gets enabled again
00610         if(colorSelector->onMouseDown(x,y)) {
00611             histogram->enable();
00612         }
00613         display();
00614     }
00615 
00616     else if((button == GLUT_RIGHT_BUTTON)&&(state == GLUT_DOWN)) {
00617         mouseBtn = GLUT_RIGHT_BUTTON;
00618         // if some point had been selected, the histogram
00619         // gets disabled and returns true
00620         if(histogram->onRightMouseClick(x,y)) {
00621             // flip y
00622             colorSelector->moveTo(x,y);
00623             // thus we enable the color selection cube
00624             colorSelector->enable();
00625             colorSelector->point = histogram->grabbedPoint;
00626         }
00627     }
00628     else if((button == GLUT_WHEEL_UP)&&(state != GLUT_DOWN)) {
00629         mouseBtn = GLUT_WHEEL_UP;
00630         if(currentProgramState == SLICE_MODE) {
00631             optionPanel->incSlice();  
00632         }
00633 
00634     }
00635 
00636     else if((button == GLUT_WHEEL_DOWN)&&(state != GLUT_DOWN)) {
00637         mouseBtn = GLUT_WHEEL_DOWN;
00638         if(currentProgramState == SLICE_MODE) {
00639             optionPanel->decSlice();  
00640         }
00641 
00642     }
00643 
00644     if(state == GLUT_UP) {
00645         mouseBtn = -1;
00646     }
00647     display();
00648 }
00649 
00650 
00651 void mouseMotionEvent(int x, int y) {
00652     // note do not forget to flip the coordinate
00653     if(mouseBtn == GLUT_LEFT_BUTTON) {
00654         // flip y
00655         y = yResolution - y;        
00656         histogram->onMouseDrag(x,y);
00657     }
00658     else if(mouseBtn == GLUT_RIGHT_BUTTON) {
00659         colorSelector->onMouseDrag(x,y);
00660     }    
00661     display();
00662 }
00663 
00664 
00670 void main(int argc, char* argv[]) {
00671     // setting up glut stuff
00672     glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
00673     glutInitWindowPosition(50, 50);
00674 
00675     glutInitWindowSize(xResolution, yResolution);
00676     mainWindow = glutCreateWindow("Volume Visualiser 0.2");
00677     glutDisplayFunc(display);
00678     glutReshapeFunc(reshape);
00679     glutKeyboardFunc(keyEvent);
00680     glutMotionFunc(mouseMotionEvent);
00681 
00682     GLUI_Master.set_glutReshapeFunc(reshape);
00683     GLUI_Master.set_glutKeyboardFunc(keyEvent);
00684     GLUI_Master.set_glutMouseFunc(mouseEvent);
00685     GLUI_Master.set_glutIdleFunc(idle);   
00686 
00687     glEnable(GL_DEPTH_TEST);
00688     glEnable(GL_TEXTURE_2D);
00689     glShadeModel(GL_SMOOTH);
00690     glEnable(GL_COLOR_MATERIAL);
00691     
00692     reader = new RawReader();        
00693     
00694     menuBar = new MenuBar(mainWindow,GLUI_SUBWINDOW_TOP);
00695     
00696     stateBar = new StateBar(mainWindow,GLUI_SUBWINDOW_BOTTOM);
00697     
00698     optionPanel = new OptionPanel(mainWindow,GLUI_SUBWINDOW_LEFT);
00699     
00700     mainViewPort = new ViewPort();
00701 
00702     histogram = new Histogram();
00703 
00704     fileDialog = new FileDialog();
00705     fileDialog->hide();
00706     
00707     colorSelector = new ColorCubePanel();
00708    
00709     glutMainLoop();
00710 }

Generated on Mon Dec 12 15:20:26 2005 for CCube by  doxygen 1.4.1