OpenGL: Bewegung zwischen zwei Punkten
-
Hallo,
ich möchte das sich ein 3D-Objekt von einem Punkt P1 zu einem Punkt P2 bewegt. Die Punkte P1 und P2 muss ich doch mit glTranslate setzten oder? Bisher habe ich es hinbekommen das er sich in einem Intervall hin und her bewegt:
void sphere(void){ glTranslatef(-1,1,-4); //überprüfen ob das Objekt sich nach rechts entlang der x.Achse bewegen kann if(xDir==1 && xTrans<5.0f) //stellt ein wie viele einheiten entlang der x-Achse erlaubt { xTrans+=0.1f;//xTrans erhöhen } else//wenn das Objekt das rechte ende erreicht { xDir=0;//Richtung ändern } //überprüfen ob das Objekt sich nach links entlang der x.Achse bewegen kann if(xDir==0 && xTrans>-5.0f) { xTrans-=0.1f;//xTrans verringern } else//wenn das Objekt das linke ende erreicht { xDir=1;//Richtung ändern } //translate along the x-axis glTranslatef(xTrans,0.0f,0.0f); //glTranslatef(-1,1,-angle); //glRotatef(angle,1,0,0); //glRotatef(angle,0,1,0); //glRotatef(angle,0,0,1); // Set the current OpenGL color to red //glColor4f(1.0, 0.0, 0.0, 1.0); glColor3f(0, 0.66, 0); //Grid farbe?? // Draw a wire sphere glutWireSphere(0.3, 30, 3000); }
Aber wie bekomme ich die Punkt zu Punkt bewegung hin?
Frage zu glTranslate: Wenn ich das benutze um die Kugel zu platzieren, bleibt doch das Koordinatensystem fest? Oder verschiebt sich damit das Koordinatensystem und die Kugel ist in Wirklichkeit im Ursprung?Noch ne Frage: Ich setzte in meinem Code zu Beginn glTranslatef(-1,1,-4), und dann erfolgt die Überprüfung ob er sich noch im Intervall befindet. Diese Funktion Sphere wird doch immer wieder aufgerufen, also müsste sich doch die Kugel auch wieder auf die Position (-1,1,-4)begeben, und er müsste hin und her sprigen. Passiert aber nicht. Warum?
Hoffe ihr könnt mir weiterhelfen. Hier nochmal der Komplette Code, damit ihr es auch mal Testen könnt:
#include "gridroom.h" #include <math.h> #include <stdio.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> void init(void) { /***********************************/ /* Hier werden ganz zu Anfang ein */ /* paar Sachen angeschaltet. */ /* Kümmert euch nicht :-) */ /***********************************/ //Hintergrund ist schwarz glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glEnable(GL_DEPTH_TEST); //es werde Licht GLfloat light0_pos[]={1.0, 5.0, 3.0, 1.0}; /*Position der Lichtquelle*/ glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } /**************************************** * Zeichnet einen Grid Boden * ****************************************/ void grid(void){ glDisable(GL_LIGHTING); /* * glTranslate(a,b,c) verschiebt den Koordinatenursprung * des aktuellen Koordinatensystems * um a Einheiten in die Richtung der X-Achse, um b * Einheiten in die Richtung der Y-Achse und um c Einheiten in die Richtung der Z-Achse. */ //glPushMatrix(); //glTranslatef(1,-1,-1); //glTranslatef(0,0,0); /* * glRotate(w,x,y,z) rotiert das * Koordinatensystem um w Grad um die Rotationsachse * welche durch (0,0,0) und (x,y,z) verläuft. glRotate * richtet also die Achsen neu aus. (Die Richtung der Achsen * ist z.B. wichtig für glTranslate) */ glRotatef(0,0,1,0); //glScalef(0.9,0.5,0.5); glBegin(GL_LINES); glColor3f(0, 0.66, 0); for(int i=-30;i<=30;++i) { //if(i!=0){ //um im Ursprung nichts zu zeichen glVertex3f(i,0,-30); glVertex3f(i,0,30); glVertex3f(30,0,i); glVertex3f(-30,0,i); //} } glEnd(); /******************************************** * Einzeichen der Kordinaten Achsen in Farbe* * x:weiß, y:rot, z: blau * ********************************************/ glBegin(GL_LINES); //glLineWidth (5.0); glColor3f (1.0, 1.0, 1.0); // Green for x axis glVertex3f(-3,0,0); glVertex3f(30,0,0); glColor3f(1.0,0.0,0.0); // Red for y axis glVertex3f(0,-3,0); glVertex3f(0,30,0); glColor3f(0.0,0.0,1.0); // Blue for z axis glVertex3f(0,0,-3); glVertex3f(0,0,30); glEnd(); glEnable(GL_LIGHTING); //glPopMatrix(); } //bool klein = true; GLfloat angle=0.0; void spin(void) { angle+=1; //klein = angle <= 10; // if(angle<=3){ // angle+=0.5; // } // if((angle==2.5)&&(angle==3)){ // angle= angle-1; // } glutPostRedisplay(); } float xTrans = 0.0f;//keeps track of X translation int xDir = 1;//1-rechts,0-links float zTrans = 0.0f; //zeichnet die Kugel in die Szene void sphere(void){ /*************************************** * Lineare Bewegung entlang der x-Achse* ****************************************/ //glTranslatef(-1,1,-2); glTranslatef(-1,1,-4); //überprüfen ob das Objekt sich nach rechts entlang der x.Achse bewegen kann if(xDir==1 && xTrans<5.0f) //stellt ein wie viele einheiten entlang der x-Achse erlaubt { xTrans+=0.1f;//xTrans erhöhen } else//wenn das Objekt das rechte ende erreicht { xDir=0;//Richtung ändern } //überprüfen ob das Objekt sich nach links entlang der x.Achse bewegen kann if(xDir==0 && xTrans>-5.0f) { xTrans-=0.1f;//xTrans verringern } else//wenn das Objekt das linke ende erreicht { xDir=1;//Richtung ändern } //translate along the x-axis glTranslatef(xTrans,0.0f,0.0f); //glTranslatef(-1,1,-angle); //glRotatef(angle,1,0,0); //glRotatef(angle,0,1,0); //glRotatef(angle,0,0,1); // Set the current OpenGL color to red //glColor4f(1.0, 0.0, 0.0, 1.0); glColor3f(0, 0.66, 0); //Grid farbe?? // Draw a wire sphere glutWireSphere(0.3, 30, 3000); /**************************************** * Orbitale Bewegung entlang der y-Achse* ****************************************/ /* //glPushMatrix(); // Push on a new matrix scope glRotatef(angle, 0, 1.0, 0); // Rotate the sphere around the origin (the sun) glTranslatef(-1,2,-3); //kleinerer Orbit; einstellbar durch den z wert //glTranslatef(-1,1,-5); //größerer Orbit einstellbar durch den z wert glRotatef(angle, 0, 1.0, 0); // Rotate the sphere to make it spin //gluSphere(pObj, 0.2f, 20, 20); // Draw the sphere with a radius of 0.2 so it's smaller than the sun glColor3f(0, 0.66, 0); //Grid farbe?? // Draw a wire sphere glutWireSphere(0.3, 30, 3000); //glPopMatrix(); */ } void zeichenfunktion(void) { glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); //glLoadIdentity(); // Reset The matrix /* gluLookAt: * We make our position a bit high and back to view the whole scene * Position View Up Vector */ //gluLookAt(0, 5,10, 0, 0, 1, 0, 1, 0); gluLookAt(12, 12,12, 0, 0, 0, 0, 1, 0); // This determines where the camera's position and view is // LookAt Parms (Eye_X, Eye_Y, Eye_Z, View_X, View_Y, View_Z, Up_X, Up_Y, UpZ) //und los geht es mit dem ZEICHNEN! grid(); sphere(); //das hier damit wir nochmal bei (0,0,0) anfangen können glLoadIdentity(); glutSwapBuffers(); } /// \brief Called when the screen gets resized /// \param w - the new width /// \param h - the new height /// void reshape(int w, int h) { // prevent divide by 0 error when minimised if(w==0) h = 1; glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,(float)w/h,0.1,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char** argv) { //Hier werden die elementaren Dinge eingestellt glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH); //wie z.B. das Fenster //hier die Größe glutInitWindowSize (640, 480); //der Ort wo das Fenster erscheinen soll glutInitWindowPosition (100, 100); //und der Titel des Fensters glutCreateWindow ("3Droom"); init (); //Hier wird angegeben welche Funktion die Befehlen fürs Zeichnen enthält //wir haben sie "zeichenfunktion" genannt glutDisplayFunc(zeichenfunktion); glutReshapeFunc(reshape); glutIdleFunc(spin); glutMainLoop(); return 0; }
Der Post ist jetzt ziemlich lang geworden
Vielen Dank im Voraus.
-
Die Punkte der Kugel sind ja in ihrem eigenen, lokalen Koordinatensystem definiert. glTranslate ist nicht mehr als eine Transformationsmatrix, die alle Punkte, auf die sie wirkt, verschiebt. Wenn du also glTranslatef( x, y, z ) aufrufst, kommt es mit dem Gedanken gleich, dass du alle lokale Koordinatensysteme, zu denen die im folgenden gezeichneten Punkte gehören, um diese Betrag gegenüber einem sie einbettenden Koordinatensystem verschoben werden. In den überwiegenden Fällen bettet man die Koordinatensysteme dann solange ein, bis alle, nach den auf sie wirkenden Transformationsketten, in dem selben Koordinatensystem (oft Welktkoordinatensystem gennant) gegeben sind (um sie anschließend in "Kamera"koordinaten zu bringen).
Alle OpenGL transformations-Helfer-Funktionen (Denn du könntest auch manuell die Transformationsmatrizen verändern) multiplizieren die Matrizen, die ihre Transformation darstellen, mit dem obersten Element des OpenGL-Matrizenstacks.
Wenn du folglich im Code stehen hast:glTranslatef( ... ); // Mt1 glTranslatef( ... ); // Mt2
und zuvor eine Matrix M auf dem Stack stand, so steht nun
M*Mt1*Mt2 auf dem Stack. Alle im anschluss spezifizierten Punkte v (Ortsvektoren) werden nun mit dieser Matrix multipliziert:v' = (M*Mt1*Mt2)*v = M*(Mt1*(Mt2*v))
womit klar ist, dass v zuerst um Mt2 verschoben wird, dann um Mt1 und anschließend mit M transformiert wird. Wegen der Assoziativität des Matrixprodukts kann man die Matrizen aber alle zusammenfassen, ohne das Ergebnis zu verändern, so dass ein Punkt immer nur mit einer einzigen Gesamtmatrix transformiert werden muss, die alle Einzeltransformationen in sich zusammenfasst.
Viele Grüße,
MichaelPS: Ich verzichte aus gutem Grund auf eine genaue Lösung deines Problems, weil es oberste Wichtigkeit besitzt, dass es für dich selber Klick macht. Das zählt zu den wichtigsten Grundlagen.
-
Dank dir für deine Erklärung. Denke ich hab es jetzt verstanden.