OpenGL: Unabhängige Rotation mehrerer Objekte
-
Hallo,
ich habe in meinem C Programm mehrere Objekte erstellt, die ich unabhängig voneinander rotieren und verschieben will. Wenn ich aber ein Objekt rotiere/verschiebe, wird die Operation auf ALLE Objekte angewandt. Kann mir jemand erklären, wie ich das vermeiden kann?
static void drawObject1() { int size = 5; if (lineMode == 0) glBegin(GL_POLYGON); else glBegin(GL_LINE_STRIP); glEdgeFlag(GL_TRUE); glVertex2f(-2*size, 0.0); glEdgeFlag(GL_TRUE); glVertex2f(-4*size, 3*size); glEdgeFlag(GL_TRUE); glVertex2f(5*size, 0.0); glEnd(); glFlush(); } static void drawObject2() { int size = 5; if (lineMode == 0) glBegin(GL_POLYGON); else glBegin(GL_LINE_STRIP); glEdgeFlag(GL_TRUE); glVertex2f(0.0*size, 0.0); glEdgeFlag(GL_TRUE); glVertex2f(2.0*size, 0.0); glEdgeFlag(GL_TRUE); glVertex2f(4.0*size, -2.0); glEnd(); glFlush(); } static void object1() { glTranslatef(center[0]+100.0, center[1]+100.0, 0.0); glRotatef(0.5, 0.0, 0.0, 1.0); glTranslatef(0.5, 0.0, 0.0); drawObject1(); glTranslatef(-center[0]-100.0, -center[1]-100.0, 0.0); } static void object2() { glTranslatef(center[0], center[1], 0.0); if (steer != 0.0) glRotatef(steer, 0.0, 0.0, 1.0); if (velocity != 0.0) glTranslatef( velocity, 0.0, 0.0); drawObject2(); glTranslatef(-center[0], -center[1], 0.0); } void DisplayFunc() { glClearColor(0.0F, 0.0F, 0.0F, 0.0F); glClear(GL_COLOR_BUFFER_BIT); object1(); object2(); }
-
Speichere dir die aktuelle modelviewmatrix auf dem matrix stack um nach dem zeichen (inklusive transformieren) den alten Zustand wiederherzustellen. In deinem Beispiel sähe das so aus:
void DisplayFunc() { glClearColor(0.0F, 0.0F, 0.0F, 0.0F); glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); object1(); glPopMatrix(); glPushMatrix(); object2(); glPopMatrix(); }
-
megaweber schrieb:
Speichere dir die aktuelle modelviewmatrix auf dem matrix stack um nach dem zeichen (inklusive transformieren) den alten Zustand wiederherzustellen.
Danke!
Diese Methode hat das Problem, dass sich mein Objekt damit nicht mehr rotieren lässt. Z.B. wird object1 im Beispielprogramm in der Methode object1() rotiert. Diese Rotation kommt jetzt nicht mehr zu Stande.static void object1() { glTranslatef(center[0], center[1], 0.0); if (steer != 0.0) glRotatef(steer, 0.0, 0.0, 1.0); if (velocity != 0.0) glTranslatef( velocity, 0.0, 0.0); drawObject1(); glTranslatef(-center[0], -center[1], 0.0); }
Oder meinst du es liegt an etwas anderem / ist die Ursache so offensichtlich ? Ich stehe hier gerade echt auf dem Schlauch
-
Ich weiß nicht genau, ob das was zur Sache tut, aber was ist mit
glLoadIdentity();
?
dadurch wird doch die Rotation etc. zurückgesetzt ...Gruß Simon
-
Wenn ich ein glLoadIdentity() dazwüschen setze (egal an welcher Position) wird plötzlich gar nichts mehr gezeichnet
-
Du wirst nicht drumherum kommen, ein geeignetes Tutorial durchzuarbeiten denn das Verstaendnis von Transformationen sind fuer den Umganist mit einer 3D-API essentiell.
-
Ja, habe mir mittlerweile das RedBook zugelegt. Dieses Problem ist beseitigt. Ich hätte aber doch noch eine andere Frage:
In meinem Code wird ein Dreieck gezeichnet, das sich über die Pfeiltasten steuern lässt (Beschleunigung/Richtung). Bei der Drehung rotiert das Objekt immer um den Mittelpunkt des Bildes. Es sollte sich aber um seinen eigenen Mittelpunkt drehen.
glTranslatef(x, y, 0.0); glRotatef(steer, 0.0, 0.0, 1.0);
Zuerst transformiere ich an den Punkt [x,y], welcher ständig geupdated wird; und danach wird eine Rotation um den Winkel steer durchgeführt. [x,y] ist der Objekt-Mittelpunkt, um den sich das Objekt drehen sollte.
Laut meinem Buch und versch. online-tuts müsste sich das Dreieck um seinen eigenen Mittelpunkt drehen. Kann mir jemand erklären, wieso es das nicht tut? Hier noch ein kleines Testprogramm in C, das mein Problem simuliert:
#include <stdlib.h> #include <GL/gl.h> #include <GL/glut.h> #include <sys/stat.h> #include <stdio.h> #include <math.h> #include <string.h> float steer = 0.0; float acc = 0.0; float vel = 0.0; float center[2]; static float degToRad(float deg) { return (deg / 180) * 3.14159; } static void drawTriangle() { int size = 10; glColor3f(0.0, 0.0, 1.0); glBegin(GL_POLYGON); glEdgeFlag(GL_TRUE); glVertex2f(-2*size, 2.0*size); glEdgeFlag(GL_TRUE); glVertex2f(-2*size, -2*size); glEdgeFlag(GL_TRUE); glVertex2f(2*size, 0.0); glEnd(); glFlush(); } static void triangle() { vel += acc; float x = center[0] + cos(degToRad(steer))*vel; float y = center[1] + sin(degToRad(steer))*vel; glTranslatef(x, y, 0.0); glRotatef(steer, 0.0, 0.0, 1.0); drawTriangle(); } static void rotate(int direction) { if (direction == 0) { steer += 8.0; } if (direction == 1) { steer -= 8.0; } if (steer > 360.0) { steer = steer - 360.0; } if (steer < -360.0) { steer = steer + 360.0; } glutPostRedisplay(); } static void init() { glClearColor(0.0F, 0.0F, 0.0F, 0.0F); } void DisplayFunc() { glClearColor(0.0F, 0.0F, 0.0F, 0.0F); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); triangle(); glPopMatrix(); glutSwapBuffers(); } void KeyboardFunc(unsigned char key, int x, int y) { switch(key) { case 27: exit(0); break; } } void SpecialFunc( int key, int x, int y ) { switch(key) { case GLUT_KEY_LEFT: rotate(0); //rotate left break; case GLUT_KEY_RIGHT: rotate(1); //rotate right break; case GLUT_KEY_UP: acc = acc + 0.1; break; case GLUT_KEY_DOWN: acc = acc - 0.1; break; } } void ReshapeFunc( int x, int y ) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( 0.0, x, 0.0, y, 1.0, -1.0 ); } void IdleFunc() { glutPostRedisplay(); } int main (int argc, char **argv) { center[0] = 640.0 / 2.0; center[1] = 480.0 / 2.0; glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(200, 0); glutInitWindowSize(640, 480); glutCreateWindow("Blank GL window"); init(); glutDisplayFunc(DisplayFunc); glutIdleFunc(IdleFunc); glutKeyboardFunc(KeyboardFunc); glutSpecialFunc(SpecialFunc); glutReshapeFunc(ReshapeFunc); glutMainLoop(); return 0; }
-
Du musst das Objekt zuerst auf den Nullpunkt verschieben, dann rotieren und dann an die Position verschieben, an der es stehen soll. Da sich dein Objekt so wie ich das sehe am Nullpunkt befidnet, musst du also zuerst rotieren, und dann verschieben.
-
otze schrieb:
Du musst das Objekt zuerst auf den Nullpunkt verschieben, dann rotieren und dann an die Position verschieben, an der es stehen soll. Da sich dein Objekt so wie ich das sehe am Nullpunkt befidnet, musst du also zuerst rotieren, und dann verschieben.
Das hatte ich auch schon ausprobiert:
glRotatef(steer, 0.0, 0.0, 1.0); glTranslatef(x, y, 0.0);
Das Resultat ist anders, aber nicht so wie es sein soll. Das Objekt dreht sich immer noch nicht um seinen Mittelpunkt.
Edit: Gleiches Problem mit:
glRotatef(steer, 0.0, 0.0, 1.0); glTranslatef(center[0]+vel, center[1], 0.0);
-
Du machst das schon richtig, erst Translate, dann Rotate, dann Zeichnen.
Kann mir jemand erklären, wieso es das nicht tut?
Ich habe gerade keinen Compiler zur Hand. Kannst du beschreiben was das Dreieck stattdessen tut?
-
joomoo schrieb:
Du machst das schon richtig, erst Translate, dann Rotate, dann Zeichnen.
Kann mir jemand erklären, wieso es das nicht tut?
Ich habe gerade keinen Compiler zur Hand. Kannst du beschreiben was das Dreieck stattdessen tut?
Danke für deine Antwort! Das Problem ist mittlerweile gelöst:
Mit dem geposteten Code rotiert das Dreieck immer um den Center-Punkt (center[0], center[1]). Ich musste diesen Punkt ständig anpassen, damit das Objekt um seinen eigenen Mittelpunkt rotiert.
Dieses Problem war mir lange nicht klar, denn das Objekt wurde ja an der Richtigen Position gezeichnet. Das Verschieben hatte geklappt, aber die Rotation nicht.