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,
    Michael

    PS: 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.


Anmelden zum Antworten