#include "BaseWin.h" #include "IGLoop.h" #include "Cmd.h" // Konstruktor BaseWin::BaseWin(int w, int h){ // Werte, bzw. Default-Werte setzen if(name == NULL) name = "IGL"; width=w>0?w:1; height=h>0?h:1; markerSize=0.02; wireMode=false; drawingMode = Immediate; for ( int i=0; i<3; i++ ) backColor[i]=DfltBackCol[i]; setAxis(-1,1,-1,1,-1,1); // Beim ersten Fenster ('Dummy-Fenster'), wird die Event-Loop hochgefahren if(!IGLoop::initialized) initializeGlut(); else { newObjectsQueue.push(this); } IGL_DEBUG("created Window" << this << endl); } // Destruktor BaseWin::~BaseWin(){ } // wird nur beim Erzeugen des Dummy-Fensters aufgerufen void BaseWin::initializeGlut() { IGLoop::initialized = true; char *dummy = "IGL"; int argc =1; IGL_DEBUG ("initializing glut..." << endl); glutInit(&argc,&dummy); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE); IGL_DEBUG("glut initialized!" << endl); registerGlut(1); // Dummy-Fenster unsichtbar machen glutHideWindow(); // EventLoop fuer Fensteraktionen (open, close, clear, redisplay) starten glutTimerFunc(0,st_windowEvents, 0); } // setzt in GLUT den current-window-Zeiger auf die zugehoerige GUI-Komponente void BaseWin::setCurrentWindow(){ glutSetWindow(windowID); } // setzt das logische Koordinatensystem void BaseWin::setAxis(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax){ axis[0] = xmin; axis[1] = xmax; axis[2] = ymin; axis[3] = ymax; axis[4] = zmin; axis[5] = zmax; sendToCmdQueue(new CmdWin(Res), Exec ); } // haengt eine Window-Operation an die Warteschlange an void BaseWin::sendToCmdQueue(CmdWin *cmd, MessType T){ IGL_DEBUG("############################################################################" << endl << "sending " << cmd->type << " to cmdQueue of window " << windowID << endl); cmdQueue.push(cmd); } // haengt einen Zeichenbefehl an die Warteschlange an void BaseWin::sendToDrawQueue(IGLCmd *drawCmd, MessType T){ IGL_DEBUG("sending " << drawCmd << " to drawQueue" << endl); // ggf. RDP in die drawQueue einfuegen redisplay(); drawQueue.push(drawCmd); } // gibt den Befehl zum Oeffnen ab (geoeffnet wird in st_windowEvents()) void BaseWin::open() { IGL_DEBUG("opening Window " << this << "(windowID=" << windowID << ")" << endl); open_it = true; } // schliesst das Fenster void BaseWin::close(){ open_it = false; isOpen = false; IGL_DEBUG("closing window Nr. " << windowID << endl); glutSetWindow(windowID); glutHideWindow(); } // loescht die Zeichen-Warteschlange und loescht damit den Fensterinhalt void BaseWin::clear(){ IGL_DEBUG("clearing drawQueue" << endl); // drawQueue leeren while(!drawQueue.empty()) drawQueue.pop(); } // wird nach jeder Fenster-Operation (siehe Cmd.cpp) ausgefuehrt void BaseWin::redisplay(){ // Falls nicht schon ein Redisplay-Befehl in der Cmd-Queue haengt, Befehl // anhaengen IGL_DEBUG("testing for Rdp" << endl); if(cmdQueue.empty() || cmdQueue.back()->type != Rdp){ IGL_DEBUG("pushing Rdp" << endl); sendToCmdQueue(new CmdWin(Rdp), Exec ); } } // die callbacks muessen als statische Funktionen realisiert werden // (member-Funktionen haben eine zu C inkompatible Signatur), bei denen // die 'current Window'-Variable als Schluessel wirkt. void BaseWin::st_windowEvents(int null){ // sind neue Fenster-Objekte erzeugt worden, die noch nicht beim GLUT // angemeldet sind? while(!newObjectsQueue.empty()){ newObjectsQueue.front()->registerGlut(0); newObjectsQueue.pop(); } // Fensterliste durchgehen und fuer jedes Fenster die Fenster-Operationen // durchfuehren for(map::iterator it = windowList.begin(); it != windowList.end(); it++){ BaseWin *win = (*it).second; IGL_DEBUG("windowEvents called for window Nr. " << win->windowID <windowID); // open, close, clear, etc. (->Cmd.cpp) win->issueWindowCmds(); // Ist dabei der Befehl zum Oeffnen eingegangen? if(win->open_it && !win->isOpen){ glutShowWindow(); win->isOpen = true; } } // naechster Aufruf von st_windowEvents glutTimerFunc(WINDOW_REFRESH_TIME,st_windowEvents, 0); } // cmdQueue abarbeiten void BaseWin::issueWindowCmds(){ IGL_DEBUG("--------" << endl << "cmdQueue has " << cmdQueue.size() << " elements" << endl); while(!cmdQueue.empty()){ CmdWin *cmd = cmdQueue.front(); cmdQueue.pop(); IGL_DEBUG("executing " << cmd->type << endl); cmd->Exec(*this); } IGL_DEBUG("now cmdQueue has " << cmdQueue.size() << " elements" << endl << "--------" << endl); } // Fenstergroesse hat sich geaendert (GLUT-Callback) void BaseWin::st_reshape(int w, int h){ windowList[glutGetWindow()]->_reshape(w,h); } // Fenster wird neugezeichnet (GLUT-Callback) void BaseWin::st_display(){ windowList[glutGetWindow()]->_display(); } // Anmeldung des Fensters bei GLUT // diese Methode darf nur in Synchronisation mit glutMainLoop() // aufgerufen werden, da GLUT ansonsten abstuerzt, daher als Callback // ueber st_windowEvents() void BaseWin::registerGlut(int dummyWindow){ glutInitWindowSize(width, height); windowID = glutCreateWindow(name); IGL_DEBUG("registering Window " << this << " windowID = " << windowID << endl); glutSetWindow(windowID); glutSetWindowTitle(name); glutSetIconTitle(name); // Eintragen in die Liste windowList[windowID] = this; // Callbacks: statische Funktionen, die mittels windowID = glutgetCurrent() // an die entsprechenden Member-Funktionen weitergegeben werden glutDisplayFunc(st_display); glutReshapeFunc(st_reshape); //glutIdleFunc(st_windowEvents); // expliziter open-Befehl notwendig zum Oeffnen if(!open_it) glutHideWindow(); } // wird durch st_reshape() aufgerufen void BaseWin::_reshape(int w, int h){ IGL_DEBUG("_reshape called for window Nr."<< windowID << " with w = " << w << ", h = " << h << endl); setCurrentWindow(); glViewport (0, 0, width = w, height = h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); IGL_DEBUG( "setting axis[] " << axis[0] << " " << axis[1] << " " << axis[2] << " " << axis[3] << " " << axis[4] << " " << axis[5] << " " << endl); glOrtho (axis[0], axis[1], axis[2], axis[3], axis[4], axis[5]); glMatrixMode(GL_MODELVIEW); IGL_DEBUG("done"<< endl); } // wird durch st_display() aufgerufen void BaseWin::_display(){ IGL_DEBUG("_display called for window Nr. " << windowID << endl); if(!isOpen){ IGL_DEBUG("Not open!!!!!" << endl); return; } setCurrentWindow(); // GL-Grundeinstellungen glEnable (GL_DEPTH_TEST); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glLightfv (GL_LIGHT0, GL_POSITION, DfltLightPos); glShadeModel (GL_SMOOTH); glColor4fv (DfltColor); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, DfltColor); glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, DfltColor); glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20); glClearColor (backColor[0], backColor[1], backColor[2], 0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Befehle in drawQueue abarbeiten (Queue wird nur bei einem Clr geloescht) //glNewList(1,GL_COMPILE_AND_EXECUTE); DrawQueueCL workQueue = drawQueue; while(!workQueue.empty()){ IGLCmd *drawCmd = workQueue.front(); drawCmd->Exec(*this); workQueue.pop(); } //glEndList(); glutSwapBuffers(); IGL_DEBUG("done." << endl); } /* int main(int argc, char** argv){ new BaseWin(100,200); new BaseWin(120,200); new BaseWin(130,200); new BaseWin(140,200); new BaseWin(150,200); glutMainLoop(); return 0; } */