Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

19.06.2010, 19:36

Rotationsmatrix Irrlicht

Hallo!
Hab mal ne Frage zu Rotationsmatrizen:
Ich hab den Vektor myVct(1,1,0) und möchte ihn an der x-Achse um 90 Grad drehen. Der resultierende Vektor müsste ja eigentlich myVct(1,0,1) sein, oder täuscht mich da irgendwas?

Ich hab das nämlich mal mit Irrlicht ausprobiert. Hier ist mein Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
using namespace std;

int main(int argc, char** argv)
{
    CMatrix4<float> myMat;
    vector3d<float> myVct(1.0,1.0,0.0); // Ausgangsvektor

    myMat.makeIdentity(); // Wir gehen von der Identitätsmatrix aus...
    myMat.setRotationDegrees(vector3d<float>(90.0,0.0,0.0)); // ...und erzeugen eine Rotationsmatrix, die den Vektor um 90 Grad an der x-Achse dreht
    myMat.rotateVect(myVct); // jetzt wird der Vektor gedreht

    cout << myVct.X << "   " << myVct.Y << "   " << myVct.Z << "\n"; // ... und angezeigt
    return 0;
}

Nun war ich überrascht, als die Ausgabe des Programms folgendes zeigte:

1 -4.37114e-008 1

Die x- und z-Komponenten stimmen meines Erachtens. Aber was ist mit der y-Komponente?? Die müsste doch 0 sein, oder hab ich da nen Denkfehler?

Gruß, Paul

2

19.06.2010, 20:34

Hey,

also -4.3 * 10^-8 ist -0.000000043 was ja schonma sogut wie null entspricht. ;)

Deine Zeile 18 würde ich mal wie folgt ändern:

C-/C++-Quelltext

1
 myMat.setRotationDegrees(vector3d<f32>(90.0f,0.0f,0.0f));


oder

C-/C++-Quelltext

1
 myMat.setRotationDegrees(vector3df(90,0,0));


Bin leider kein Irrlicht Experte, daher ist das nur so eine Idee, weiß nicht ob das funktioniert - probiers einfach mal aus.

Gruß
SaRu_

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »SaRu« (19.06.2010, 20:41)


3

19.06.2010, 21:16

also -4.3 * 10^-8 ist -0.000000043 was ja schonma sogut wie null entspricht. ;)
Da hast du wohl recht. ;)
Deine Zeile 18 würde ich mal wie folgt ändern:

C-/C++-Quelltext

1
myMat.setRotationDegrees(vector3d(90.0f,0.0f,0.0f));

oder

C-/C++-Quelltext

1
myMat.setRotationDegrees(vector3df(90,0,0));


Bin leider kein Irrlicht Experte, daher ist das nur so eine Idee, weiß nicht ob das funktioniert - probiers einfach mal aus.
Hab ich beides ausprobiert, hat aber nix geändert. Im Bogenmaß entspricht 90 grad doch PI oder? Dann würde ich mal die Methode setRotationRadians ausprobieren, aber ansonsten wird man das in einem Spiel wahrscheinlich nicht erkennen, wenn die Position nur FAST 0 ist oder? ;) Und bei der Kollisionserkennung später wird das wahrscheinlich auch keinen sichtbaren Unterschied machen oder? Wichtig ist dann ja eigentlich nur, dass ich wieder den SELBEN Vektor habe wenn ich ihn 4 mal um 90 Grad gedreht habe, damit ein sich drehendes Objekt nicht ganz langsam immer weiter nach oben rutscht :D

Gruß, Paul

4

19.06.2010, 21:35

PI/2

5

19.06.2010, 22:57

Im Bogenmaß entspricht 90 grad doch PI oder?
Siehe Beitrag von Genion: 90° -> PI/2

Zitat

aber ansonsten wird man das in einem Spiel wahrscheinlich nicht erkennen, wenn die Position nur FAST 0 ist oder? ;) Und bei der Kollisionserkennung später wird das wahrscheinlich auch keinen sichtbaren Unterschied machen oder?
Richtig, das wirst du nicht merken. Denk mal an die Koordinaten eines Objekts, gibst du die auch auf 8 Dezimalstellen an? Wohl kaum oder? Also wird das auch bei der Kollisionserkennung keinen Unterschied machen, denk ich mal. Ich erinner mich an dieser Stelle auch an eine Situation die David Scherfgen in seinem Buch beschreibt. Um sicherzugehn, dass es nicht zu einer Division durch null kommt, addiert man zum Divisor (im Bruch der Nenner) einen sehr, sehr kleinen Betrag. Dies ist schneller als eine if-Bedingung die überprüft, ob der Divisor null ist. Man kann also mit verschwindend geringen Ungenauigkeiten sehr gut leben, da sie meist an irgendeiner stelle eh wieder verschwinden. Wenn z.B. gerundet wird oder in integer gecastet wird. ;)


Gruß,
SaRu_

6

19.06.2010, 23:10

Ich denke dann kann ich die Matrizen guten Gewissens anwenden. Ich mach nur grad noch einen kleinen Test, in dem ich 100 mal 1000000 komplette Drehungen eines Objekts simuliere:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
using namespace std;

int main(int argc, char** argv)
{
    CMatrix4<double> myMat;
    vector3d<float> myVct(1.0,1.0,0.0);


    for(int y=0; y<100;y++)
    {
        for(int x = 0;  x<360*1000000 ;  x++)
        {
            myMat.makeIdentity();
            myMat.setRotationDegrees(vector3d<double>(1,0,0));
            myMat.rotateVect(myVct);
        }
    }




    cout << myVct.X << "   " << myVct.Y << "   " << myVct.Z << "\n";


    return 0;
}


Aber ich glaube, in diesem Maß ist das sowieso nicht mehr sehr realitäts nah oder? Interessiert mich trotzdem mal welcher Vektor dabei rauskommt. Das Programm läuft schon seit ca. 10 Minuten :D

Gruß, Paul


Edit: Ich habs übrigens geschafft, die Ungenauigkeiten noch etwas zu reduzieren, in dem ich eine double-Matrix anstatt einer float-Matrix verwende :)

7

19.06.2010, 23:15

In der Regel wird die Rotationsmatrix einmal, vielleicht auch ein paar Mal auf ein Objekt angewendet, aber dann erfolgt zunächst erst das Rendern etc. Dabei kann sich der Vektor eh wieder ändern. Das heißt, in der Realität werden wohl nicht so viele Drehungen nacheinander stattfinden. ;)

Aber poste doch mal dein Ergebnis, bin gespannt.

Gruß,
SaRu_

8

19.06.2010, 23:30

Okay Programm ist durchgelaufen, hier die Ausgabe:

1 1 -2.92702e-009

Process returned 0 (0x0) execution time : 2273.988 s
press any key to continue,

also stimmen x- und y- Koordinate und die z-Koordinaate stimmt FAST (nach so vielen umdrehungen)
Da kann ich ja dann mit SEHR gutem Gewissen rangehen :D und mein Prozessor hatte ca 37 minuten sinnlose Arbeit :D


Gruß Paul

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

9

20.06.2010, 11:25

und mein Prozessor hatte ca 37 minuten sinnlose Arbeit :D



Hättest dir vermutlich Zeit gespart wenn du fixe Operationen ausgelagert hättest:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
myMat.makeIdentity();
myMat.setRotationDegrees(vector3d<double>(1,0,0));

for(int x = 0;  x<360*1000000;  x++)
{
    for(int y = 0; y <100; y++)
        myMat.rotateVect(myVct);
}
@D13_Dreinig

10

20.06.2010, 15:43

Kombination von Transformationen

Is ja egal wie langs gedauert hat, war ja nur ein Test :D

Und jetzt hab ich gleich mal ne anderer Frage:

undzwar hab ich David Scherfgens Buch entnommen dass erst Skalierung, dann Rotation und dann Translation durchgeführt werden soll. So das hab ich dann auch mal probiert, undzwar zuerst auf dem Papier:

Vektor v(1,1,0) mit 2 Skalieren
(2,2,0) um 90 Grad an der x-Achse rotieren
(2,1,1) um (4,2,1) verschieben

Resultierender Vektor: (6,3,2)

So, und das dann im Programm umgesetzt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
using namespace std;

int main(int argc, char** argv)
{
    CMatrix4<double> mScale,mRotate,mTranslate,mTransform;
    vector3d<float> myVct(1.0,1.0,0.0);


    mScale.makeIdentity();
    mRotate.makeIdentity();
    mTranslate.makeIdentity();
    mTransform.makeIdentity();

    mScale.setScale(2);
    mRotate.setRotationDegrees(vector3d<double>(90,0,0));
    mTranslate.setTranslation(vector3d<double>(4,2,1));

    mTransform = mScale;
    mTransform*= mRotate;
    mTransform*= mTranslate;

    mTransform.transformVect(myVct);




    cout << myVct.X << "   " << myVct.Y << "   " << myVct.Z << "\n";


    return 0;
}



Die Ausgabe des Programms zeigt: (10,-2,6)

Ist jetzt meine Rechnung auf dem Papier falsch oder stimmt mit dem Code irgendwas nicht?

Grüße, Paul

Werbeanzeige