/*------------------------------------------------------------- * Dies ist ein Beispiel vom "The Inventor Mentor" * (Kapitel 10, 2. Beispiel), welches von Stephan Siemen * geaendert wurde um mit Coin und SoQt zu kompileren. * * Der Code kann mit * g++ SoQtDraw.cpp -o SoQtDraw -lCoin -lSoQt -I$QTDIR/include * uebersetzt werden. * *-----------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include // Timer Sensor - global definiert // Rotiert 90 Grad/Sekunde und wird 30 mal/Sekunde ausgefuehrt SoTimerSensor *ticker; #define ROTATION_WINKEL M_PI/60.0 #define UPDATE_RATE 1.0/30.0 void Projektion(SoQtRenderArea *renderFlaeche,int mausX,int mausY,SbVec3f &schnittpunkt) { // Nimm die x un y position der maus und normalise diese zu [0,1] SbVec2s groesse = renderFlaeche->getSize(); float x = float(mausX) / groesse[0]; float y = float(groesse[1] - mausY) / groesse[1]; // Erhalte einen Zeiger zur Kamera und erhalte das Kamera-Volumen SoGroup *wurzel = (SoGroup *) renderFlaeche->getSceneGraph(); SoCamera *kamera = (SoCamera *) wurzel->getChild(0); SbViewVolume kameraVolumen; kameraVolumen = kamera->getViewVolume(); // Erhalte den Anfangs- und Endpunkt der Linie die durch das // Kameravolumen geht und den Pfad des Mauszeiger durch die // Szene darstellt. SbVec3f p0, p1; kameraVolumen.projectPointToLine(SbVec2f(x,y), p0, p1); // Mittelpunkt dieser Linie dient als Punkt zum zeichnen schnittpunkt = (p0 + p1) / 2.0; } void neuerPunkt(SoQtRenderArea *renderFlaeche, const SbVec3f point) { // Zeiger auf die Elemente im Szenegraphen die veraendert werden soll SoGroup *wurzel = (SoGroup *) renderFlaeche->getSceneGraph(); SoCoordinate3 *PunktKoordinaten = (SoCoordinate3 *) wurzel->getChild(2); SoPointSet *punkte = (SoPointSet *) wurzel->getChild(3); // der neue Punkt wird in die Liste eingefuegt PunktKoordinaten->point.set1Value(PunktKoordinaten->point.getNum(), point); punkte->numPoints.setValue(PunktKoordinaten->point.getNum()); } void loeschePunkte(SoQtRenderArea *renderFlaeche) { // Zeiger auf die Elemente im Szenegraphen die veraendert werden soll SoGroup *wurzel = (SoGroup *) renderFlaeche->getSceneGraph(); SoCoordinate3 *PunktKoordinaten = (SoCoordinate3 *) wurzel->getChild(2); SoPointSet *punkte = (SoPointSet *) wurzel->getChild(3); // Loesche alle Werte vom ersten Wert (Index=0) PunktKoordinaten->point.deleteValues(0); punkte->numPoints.setValue(0); } void tickerCallback(void *userData, SoSensor *) { SoCamera *Kamera = (SoCamera *) userData; SbRotation rot; SbMatrix mtx; SbVec3f pos; // Rotieren der Kamera pos = Kamera->position.getValue(); rot = SbRotation(SbVec3f(0,1,0), ROTATION_WINKEL); mtx.setRotate(rot); mtx.multVecMatrix(pos, pos); Kamera->position.setValue(pos); // Korrektur der Ausrichtung der Kamera Kamera->orientation.setValue(Kamera->orientation.getValue() * rot); } SbBool ereignisHandler(void *userData, QEvent *einEreignis) { SoQtRenderArea *renderFlaeche = (SoQtRenderArea *) userData; QMouseEvent *MausEvent; SbVec3f vektor; SbBool handled = TRUE; switch(einEreignis->type()){ // falls Maustaste gedrueckt wurde ... case QEvent::MouseButtonPress: MausEvent = (QMouseEvent *) einEreignis; if(MausEvent->button() == Qt::LeftButton) { Projektion(renderFlaeche,MausEvent->x(), MausEvent->y(), vektor); neuerPunkt(renderFlaeche, vektor); } else if(MausEvent->button() == Qt::MidButton) { ticker->schedule(); // start das rotieren der Kamera } else if(MausEvent->button() == Qt::RightButton) { loeschePunkte(renderFlaeche); // loesche alle Punkte } break; // falls Maustaste losgelassen wurde ... case QEvent::MouseButtonRelease: MausEvent = (QMouseEvent *) einEreignis; if(MausEvent->button() == Qt::MidButton) { ticker->unschedule(); // stoppen das rotieren der Kamera } break; // falls die Maus bewegt wurde ... case QEvent::MouseMove: MausEvent = (QMouseEvent *) einEreignis; if( MausEvent->state()){ Projektion(renderFlaeche,MausEvent->x(), MausEvent->y(), vektor); neuerPunkt(renderFlaeche, vektor); } break; default: handled = FALSE; break; }// Ende des switch return handled; } // Hauptfunktion // -> erzeugt den Szenengraphen und den Betrachter int main(int argc, char **argv) { printf("Benutzung von SoQtDraw:\n"); printf("\tLinke Maustaste: fuegt Punkte hinzu.\n"); printf("\tMittlere Maustaste: rotiert die Szene\n"); printf("\tRechte Maustaste: loescht alle Punkte\n"); // Initialisierung von Coin (Open Inventor) und SoQt QWidget *HauptFenster = SoQt::init(argv[0]); if(HauptFenster == NULL) exit(1); // Erzeugen der Wurzel des Szenengraphen SoSeparator *wurzel = new SoSeparator; wurzel->ref(); // Hinzufuegen einer Kamera SoPerspectiveCamera *kamera = new SoPerspectiveCamera; wurzel->addChild(kamera); // Knoten 0 // Hinzufuegen eines einfachen Lichtmodels SoLightModel *licht = new SoLightModel; licht->model = SoLightModel::BASE_COLOR; wurzel->addChild(licht); // Knoten 1 // Setup der Kamera kamera->position.setValue(0, 0, 4); kamera->nearDistance.setValue(1.0); kamera->farDistance.setValue(7.0); kamera->heightAngle.setValue(M_PI/3.0); // Knoten um 3D Koordinaten zu speichern SoCoordinate3 *punktKoordinaten = new SoCoordinate3; // Geometrieknoten um Punkte zu zeichnen SoPointSet *punkte = new SoPointSet; wurzel->addChild(punktKoordinaten); // Knoten 2 wurzel->addChild(punkte); // Knoten 3 // Timer Sensor um Zeitimpulse an die Kamera zu geben waehrend // die mittlere Maustaste gedrueckt ist ticker = new SoTimerSensor(tickerCallback, kamera); ticker->setInterval(UPDATE_RATE); // Erstellen einer render area for viewing the scene SoQtExaminerViewer *renderFlaeche = new SoQtExaminerViewer(HauptFenster); renderFlaeche->setSceneGraph(wurzel); renderFlaeche->setTitle("SoQtDraw"); // Setzen des Ereignisbehandlung renderFlaeche->setEventCallback(ereignisHandler, renderFlaeche); // Anzeigen des Hauptfenster renderFlaeche->show(); SoQt::show(HauptFenster); // Endlos-Schleife zur Ereignisbehandlung SoQt::mainLoop(); return 0; }