[OpenGL] "Textur" dreht sich ungewollt



  • Wenn beide wirklich so hintereinander stünden wie du das in Deinem ersten post darstellst, wäre es auch nicht das gleiche. Ich nehme mal an, da liegt evtl. das Missverständniss!?

    Nehmen wir doch mal an, zaxis wäre 1 und xaxis 0, dannn entstünde nach Deinem code von oben folgendes:

    glRotatef((float) xRoll, 0.0f, 0.0f, 1); 
        glRotatef((float) zRoll, 0.0f, 0.0f, 1);
    


  • Hä? wenn ich mir von xRoll und zRoll das verspreche was ich denke, dann wird bei jedem aufruf von glRotatef jedesmal das Objekt um xRoll/zRoll Grad gedreht, unzwar um die Achse (1,0,0) oder (0,0,1) - d.h. entweder x oder z Achse.
    bzw. wiki sagt dazu:

    glRotatef(angle: TGLdouble; x: TGLdouble; y: TGLdouble; z: TGLdouble);

    (ist das bei c++ anders, da es sich hierbei um Delphi handelt? eigentlich dürften sich die ogl funktionen intern nicht verändern....oder ist genau hier der Fehler?)



  • Sag mal, kommst du vllt. mit den Bezeichnungen durcheinander? 😕

    Die nächste Code-Zeile ist neu. glRotatef(Angle,Xvector,Yvector,Zvector) ist verantwortlich, um ein Objekt um eine Achse rotieren zu lassen. Sie werden diesen Befehl ziemlich häufig verwenden. Angle (=Winkel) ist eine Zahl (in der Regel in einer Variable gespeichert), die repräsentiert, wie weit das Objekt gedreht werden soll. Die Parameter Xvector, Yvector und Zvector präsentieren zusammen den Vektor um welchen die Rotation statt findet. Wenn Sie die Werte (1,0,0) verwenden, beschreiben Sie einen Vektor, der sich 1 Einheit entlängs der X-Achse nach rechts bewegt. Die Werte (-1,0,0) beschreiben einen Vektor der in die Richtung einer Einheit entlängs der X-Achse bewegt, aber diesmal nach links.

    D. Michael Traub: hat die obige Erklärung der Xvector, Yvector und Zvector Parameter geliefert.

    Um X, Y und Z-Rotation besser zu verstehen, werde ich sie anhand von Beispielen erklären...

    X-Achse - Sie arbeiten an einer Kreissäge. Der Stab der direkt durch die Mitte des Sägeblatts geht, verläuft von links nach rechts (wie die X-Achse in OpenGl). Die scharfen Zähne rotieren um die X-Achse (den Stabe, der durch die Mitte des Sägeblatts verläuft) und scheint sich auf Sie zu oder weg von Ihnen zu bewegen, je nachdem in welche Richtung das Sägeblatt rotiert. Wenn Sie etwas in OpenGL auf der X-Achse rotieren lassen, wird es genauso rotieren.

    Y-Achse - Stellen Sie sich vor, dass Sie inmitten eines Feldes stehen. Ein gewaltiger Tornado kommt direkt auf Sie zu. Das Zentrum des Tornados verläuft vom Himmel zum Boden (rauf und runter, genauso wie die Y-Achse in OpenGL). Der Schmutz und alles andere in dem Tornado rotiert um die Y-Achse (das Zentrum des Tornados) von links nach rechts oder von Rechts nach links. Wenn Sie etwas in OpenGL auf der Y-Achse rotieren lassen, wird es genauso rotieren.

    Z-Achse - Sie schauen direkt auf einen Fächer. Der Mittelpunkt des Fächers zeigt auf Sie und weg von Ihnen (wie die z-Achse in OpenGL). Die einzelnen Fächer des Fächers rotieren um die Z-Achse (Zentrum des Fächers) im Uhrzeigersinn oder gegen den Uhrzeigersinn. Wenn Sie etwas in OpenGL auf der Z-Achse rotieren lassen, wird es genauso rotieren.

    Demnach würde die folgende Code-Zeile, wenn rtri gleich 7 ist, eine Rotation um 7 auf der Y-Achse (links nach recht) tätigen. Sie können ein wenig mit dem Code herum experimentieren. Ändern Sie die 0.0f in 1.0f und die 1.0f in 0.0f um das Dreieck auf der X und Y Achse zur selben Zeit rotieren zu lassen.

    Es ist wichtig zu beachten, dass die Rotation in Grad vorgenommen wird. Wenn rtri einen Wert von 10 hat, würden wir um 10 Grad auf der Y-Achse rotieren.

    http://www.joachimrohde.com/cms/xoops/modules/articles/article.php?id=8



  • Stier X schrieb:

    Hä? wenn ich mir von xRoll und zRoll das verspreche was ich denke, dann wird bei jedem aufruf von glRotatef jedesmal das Objekt um xRoll/zRoll Grad gedreht, unzwar um die Achse (1,0,0) oder (0,0,1) - d.h. entweder x oder z Achse.

    Naja weiss nicht ob ich das richtig verstehe. Hier nochmal ein Ausschnitt aus dem Zitat von langeweile:

    glRotatef(Angle,Xvector,Yvector,Zvector) ist verantwortlich, um ein Objekt um eine Achse rotieren zu lassen. [..] Angle (=Winkel) ist eine Zahl (in der Regel in einer Variable gespeichert), die repräsentiert, wie weit das Objekt gedreht werden soll. Die Parameter Xvector, Yvector und Zvector präsentieren zusammen den Vektor um welchen die Rotation statt findet.

    Und jetzt versuchs doch einfach mal so:

    if(xaxis)
        glRotatef((float) xRoll, 1.0f, 0.0f, 0.0f);
    if(zaxis)
        glRotatef((float) zRoll, 0.0f, 0.0f, 1.0f);
    


  • Ich habe es jetzt so ausprobiert, konnte das Problem dadurch aber leider nicht beheben.
    Also die Bezeichnungen sind ja gleich. Der erste Parameter bestimmt den Drehwinkel. Der Bleibt solange auf 5 (oder wie schnell auch immer gedreht werden soll), bis xRoll oder zRoll % 90 == 0, d.h. der Würfel hat sich um 90 Grad letztedndlich gedreht. Da es sich hier um eine Funktion handelt, die immer wiederholt wird, wird der Zähler in xRoll z.B immer um 5 erhöht, wenn w oder s gedrücht wurden, bis eben xRoll%90 == 0 gilt. Dann wird xRoll wieder 0, so dass alles so bleibt, bis wieder eine Taste gedrückt wird.

    (xRoll beschreibt die Drehungen auf der z-Achse ; zRoll die Drehungen entlang der x Achse).

    Abgesehen davon dürfte xRoll (wenn =0) keine Auswirkung auf

    glRotatef((float) zRoll, 0.0f, 0.0f, 1);
    

    nehmen, da und anders herum dürfte zRoll keine Auswirkung auf

    glRotatef((float) xRoll, 1.0f, 0.0f, 0.0f);
    

    nehmen. Insofern dreht sich der Würfel immer nur um eine Achse, da xRoll oder zRoll immer nur solange auf 5 gesetzt werden, wie auch für die Drehung nötig ist, d.h. bei 90/5 = 18 bleibt xRoll z.B 18 mal auf 5, dann gilt xRoll%90 == 0 und xRoll wird auf 0 gesetzt.
    D.h. letztendlich wieder, dass ich eigentlich nicht auf xRoll oder zRoll überprüfen muss... aber wo kann dann der Fehler liegen. 😕 😕 (Es ist ja nicht so, dass ich nicht schon seit ein paar Stunden vor dem Problem sitze 😃 )



  • Dann versteh ich dein Problem i-wie nicht...



  • also ich hab das problem folgendermaßen verstanden:

    der würfel wird um 90° gedreht, je nach eingabe entweder um die z-Achse oder die x-Achse.
    Dabei ist wohl das Problem, dass sich die Achsen mitdrehen. D.h. dass bei der nächsten drehung die Achsen vertauscht sind.

    Nehmen wir an, wir drehen den Würfel um 90° im Uhrzeigersinn. Dann bleibt die Z-Achse gleich, aber die X- und die Y-Achse vertauschen sich. Solange man nur rechts und links drehen würde, wäre das ja kein problem.
    Nun will unser Stier aber auch nach vorne und nach hinten rotieren, was jetzt aber schwierig wird, da die Achsen ja vertauscht sind.

    glRotatef((float) zRoll, xaxis, 0.0f, zaxis); 
    glRotatef((float) xRoll, xaxis, 0.0f, zaxis);
    

    Anhand von xaxis und zaxis nehme ich an, dass du schon versucht hast, den Würfel jeweils relativ zu den Achsen zu drehen. Evtl. kannst du mal den code dafür posten...

    Ich glaube was hier gebraucht wird ist irgendwas, was die Mitrotation der Achsen verhindert.

    Ich selber hab da leider nich so viel ahnung von...

    .eraemaajaervi



  • Ja, da hab ich ja schon mehrere versionen ausprobiert. z.b. die nachfolgende:

    int RollCorrect(int zRoll)                             // fixing, around which axis the cube shall rotate
    {
        //signed int sign=zRoll / abs(zRoll);               // when pressen left or right (makes problems, needs to be fixed)
        if(abs(zRoll)== 360) 
        {
                             //zRoll=0; //1*(zRoll%360); 
        }
        if(zRoll >= 0) 
        {
             if(zRoll%270==0) setRollAxis(0,-1,0);  // needs to be negative when degree is negative
             if(zRoll%270!=0 && zRoll%180==0) setRollAxis(0,0,-1);
             if(zRoll%270!=0 && zRoll%180!=0 && zRoll%90==0) setRollAxis(0,1,0); // needs to be negative when degree is positive
             if(zRoll==0) setRollAxis(0,0,1); 
        }
        else 
        {
             if(zRoll%270==0) setRollAxis(0,1,0);  // needs to be negative when degree is negative
             if(zRoll%270!=0 && zRoll%180==0) setRollAxis(0,0, -1);
             if(zRoll%270!=0 && zRoll%180!=0 && zRoll%90==0) setRollAxis(0,-1,0); // needs to be negative when degree is positive
             if(zRoll%360==0 || zRoll==0) setRollAxis(0,0,1); 
        } 
        return 0; 
    }
    

    Der ganze Code prüft eigentlich nur, um welche Achse letztendlich gedreht werden soll, da sich die lokalen achsen ja mitdrehen und so eine drehung nur um x und z achse zu definieren zu rotationsfehlern führen müsste.
    Es gibt noch einen ähnlichen code (etwas ausführlicher), aber der funktioniert genauso wenig.



  • Guck dir mal glPop/PushMatrix an... 😕



  • Oder du versuchst absolut zu drehen und machst vor dem Rendern ein GLLoadIdentity().



  • Mach mal ein Video per Screencapturing, dass man sich auch vorstellen kann, was du meinst 😉



  • leider funktioniert das mit screen capturing unter vista nicht richtig, daher hab ich mal 3 screenshots gemacht, die sollten ausreichen:
    Bild_1
    Bild_2
    Bild_3

    Wie man sieht dreht die textur sich einfach so zurück als wenn nichts passiert ist (die verschiebung bleibt bestehen). und es ist ja auch nicht so, dass ich den winkel, um den gedreht wurde, zurücksetzte...



  • Um es mal etwas konkreter zu machen:
    Download

    Das Problem will einfach nicht weg. Verstehen tu ich das schon lang nicht mehr 😡. An den Variablen kanns nicht mehr liegen, habe jede einzeld überprüft...war ne menge Arbeit. Ich hoffe, jemnad weis noch eine Lösung.

    edit:

    q: runter
    w: vorwärts
    e: rauf
    a: links
    s: zurück
    d: rechts

    VK_UP: Würfel vorwärts
    VK_LEFT: Würfel links
    VK_DOWN: Würfel zurück
    VK_RIGHT: Würfel rechts



  • Stier X schrieb:

    VK_UP: Würfel vorwärts
    VK_LEFT: Würfel links
    VK_DOWN: Würfel zurück
    VK_RIGHT: Würfel rechts

    Liegt vllt in diesen Codestücken der Hund begraben?



  • glaub ich kaum. dennoch:

    if (keys[VK_UP] && keyup[VK_UP] && !RollWay.down && !RollWay.left && !RollWay.right) {
                            RollWay.up = true;
                            }
    keyup[VK_UP]=!keys[VK_UP];
    

    RollWay ist bool und sagt, ob und in welche richtung gedreht wird.
    Analog zu links, runter, rechts.

    if (RollWay.up==true){
                                  Cubeanglex -= IncCube;
                                  }
    

    Cubeanglex beschreibt die Drehung um die x-Achse. IncCube muss ein ganzzahliger Faktor von 90 sein.
    Analog zu links, runter, rechts - bei links und rechts wird mit Cubeanglez gearbeitet.

    if (Cubeanglex%90 == 0 && Cubeanglez%90 == 0 && (RollWay.up || RollWay.down || RollWay.left || RollWay.right)){
                                  RollWay.up = false;
                                  RollWay.down = false;
                                  RollWay.right = false;
                                  RollWay.left = false;
                                  if(Cubeanglex == 360 || Cubeanglex ==-360) Cubeanglex = 0;
                                  if(Cubeanglez == 360 || Cubeanglez ==-360) Cubeanglez = 0;
    

    Setzt alles zurück, wenn die Drehung beendet ist.

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		glLoadIdentity(); // ist dieses das LoadIdentity aus connans Beitrag?
                                // wenn ichs weg mache, ist alles schwarz...
    	glTranslatef(Camera.posx,Camera.posy,Camera.posz);	
           glTranslatef( 0.0f+xmove, 0.0f+ymove,-5.0f+zmove);
        if(RollWay.up || RollWay.down) {glRotatef(Cubeanglex, 1.0f, 0.0f, 0.0f);}
        if(RollWay.left || RollWay.right) {glRotatef(Cubeanglez, 0.0f, 0.0f, 1.0f);}
        DrawCube();
    	return TRUE;					
    }
    


  • So, habe jetzt glaube ich herausgefunden, warum es zu dieser Drehung kommt:

    Ich hatte nie beachtet, dass es einen Unterschied macht, erst um 90° um die x, 90° um die z und wieder 90° um die x-Achse zu drehen anstelle wie es fälschlicherweise in meinem Programm ist, dass um 180° um die x und dann 90° um die z-Achse gedreht wird.
    Das kommt daher, weil ich ja durch GLLoadIdentity() die Modelviewmatrix zurücksetzte. Jetzt muss erstmal um die 90x-90z-90x gedreht werden um dann weiter fortzufahren. Da aber in den Variablen xRoll und zRoll nur vermerkt wurde, dass um 180° insgesamt um die x und 90° insgesamt um die z-Ache gedreht werden soll, kam es eben manchmal zu unterschieden. Jetzt ist natürlich die Frage, wie ich dieses Problem umgehe.

    Bisher habe ich versucht, durch glGetDoublev (GL_MODELVIEW_MATRIX, Wuerfelmatrix) die Matrix nach dem Zeichnen des Würfels abzuspeichern und anschließend wieder nach glLoadIdentity() zu laden aber anscheinend funktioniert das (immer noch) nicht, denn alles bleibt wie vorher.
    Gibt es da auch noch eine andere Möglichkeit (am besten gleich etwas code, bitte 😃 ).



  • *Push*

    Sry für den Trippelpost aber iwie hatte ich nen doppelpost ganz unbeabsichtigt...


Anmelden zum Antworten