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

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

1

01.09.2011, 16:14

Bisschen Matrizenrechnung

Hi,

ich versuche gerade glTranslate, rotate, scale, lookat, perspective usw. in mein Matrix struct mit einzubauen, da die Funktionen ja depraved sind.
translate und scale funktionieren so weit, ich vergleich das dann immer mit dem was OpenGL liefert (auch mit meheren Funktionsaufrufen mit unterschiedlichen Werten hintereinander). Jetzt hab ich nur das Problem das ich nicht genau weiß wie man z.B. rotate umsetzt, dazu habe ich das gefunden. Ich hab das dann 1:1 nachgebaut, also:

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
void rotate(float angle, float x, float y, float z){
        mat4 m;
        float co, si, x2, y2, z2;
        
        angle = angle*(PI/180);
        co = cos(angle);
        si = sin(angle);
        x2 = x*x;
        y2 = y*y;
        z2 = z*z;
 
        m.values[0] = x2*(1-co)+co;
        m.values[1] = y*x*(1-co)+z*si;
        m.values[2] = x*z*(1-co)-y*si;
        m.values[3]= 0;
 
        m.values[4] = x*y*(1-co)-z*si;
        m.values[5] = y2*(1-co)+co;
        m.values[6] = y*z*(1-co)+x*si;
        m.values[7]= 0;
 
        m.values[8] = x*z*(1-co)+y*si;
        m.values[9] = y*z*(1-co)-x*si;
        m.values[10]= z2*(1-co)+co;
        m.values[11]= 0;
 
        m.values[12] = 0;
        m.values[13] = 0;
        m.values[14]= 0;
        m.values[15]= 1;
        
        *this *= m;
    }


Gestest wird dann so:

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
float m[16];
    mat4 m2;

    glPushMatrix();
        glLoadIdentity();

        glRotatef(32, 1, 1, 0);

        glGetFloatv(GL_MODELVIEW_MATRIX, m);
    glPopMatrix();
    
    m2.setIdentity();
    m2.rotate(32, 1, 1, 0);

    for(int r = 0; r < 4; r++){
        for(int c = 0; c < 4; c++){
            if(m[r*4+c] != m2[r*4+c]){
                cout<<r*4+c<<":   "<<m[r*4+c]<<" = "<<m2[r*4+c]<<endl;
            }
        }
    }
    cout<<endl;


Aber: es kommt nicht die gleiche Matrix bei raus! Aber warum? Wenn ich nur um eine Achse drehe (x, y, z) funktionierts. Ich hab mir dazu auch schon den Wiki Artikel durchgelesen und dachte eigentlich das diese Rechung für einen Rotationsvektor da ist.

Kann mir das einer erklären, oder zweigen wie ich rechnen muss?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

01.09.2011, 16:45

Deine Rotationsachse ist nicht normalisiert.

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

3

01.09.2011, 16:48

Die Rotationsachse muss normalisiert sein.
Edit: ... too slow.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

4

01.09.2011, 16:54

Ah ok, das hat schonmal geholfen, allerdings passt es nur fast, z.B. so:

(Index 0) 0,92 gibt OpenGL, bei mir ist es genau 1.

Muss ich das Quadrat noch normalisieren?

[EDIT]

Habs probiert, Zahlen liegen immer noch ein wenig daneben, ich willst aber so genau wie möglich:

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
axis = vec3(x, y, z);
        axis.normalize();

        axis2 = axis;
        axis2 *= axis2;
        axis2.normalize();

        angle = angle*(PI/180);
        co = cos(angle);
        si = sin(angle);
        x2 = axis2.x;
        y2 = axis2.y;
        z2 = axis2.z;
 
        m.values[0] = x2*(1-co)+co;
        m.values[1] = axis.y*axis.x*(1-co)+axis.z*si;
        m.values[2] = axis.x*axis.z*(1-co)-axis.y*si;
        m.values[3]= 0;
 
        m.values[4] = axis.x*axis.y*(1-co)-axis.z*si;
        m.values[5] = y2*(1-co)+co;
        m.values[6] = axis.y*axis.z*(1-co)+axis.x*si;
        m.values[7]= 0;
 
        m.values[8] = axis.x*axis.z*(1-co)+axis.y*si;
        m.values[9] = axis.y*axis.z*(1-co)-axis.x*si;
        m.values[10]= z2*(1-co)+co;
        m.values[11]= 0;
 
        m.values[12] = 0;
        m.values[13] = 0;
        m.values[14]= 0;
        m.values[15]= 1;

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

01.09.2011, 17:04

Warum solltest du axis2 normalisieren!?

6

01.09.2011, 17:05

Ich würde die Variablen x2,y2 und z2 generell weglassen, da du sowiso nur einmal das Quadrat rechnest.

der erste Block würde dann so ausschaun:

C-/C++-Quelltext

1
2
3
4
        m.values[0] = axis.x*axis.x*(1-co)+co;
        m.values[1] = axis.y*axis.x*(1-co)+axis.z*si;
        m.values[2] = axis.x*axis.z*(1-co)-axis.y*si;
        m.values[3]= 0;

Zitat

Basically, there are only 10 types of people in the world. Those who know binary, and those who don't.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

7

01.09.2011, 17:29

Stellt sich mir nurnoch die Frage wo diese geringfügige Ungenauigkeit her kommt? Rechnet OpenGL intern vielleicht mit double? Aber ich denke das ist genau genug. Hier noch einmal die Unterschiede:


(Link)


So jetzt hab ich nurnoch Probleme mit lookAt, ortho und frustum die ich mir nicht erklären kann:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
void lookAt(float x, float y, float z, float xlook, float ylook, float zlook, float xup, float yup, float zup){
        mat4 mat1, mat2;
        vec3 dir, right, up;
 
        up.x = xup;    
        up.y = yup;    
        up.z = zup;
 
        dir.x = (xlook-x);
        dir.y = (xlook-y);
        dir.z = (xlook-z);
        dir.normalize();
 
        right.cross(dir, up);
        right.normalize();
 
        up.cross(right, dir);
        up.normalize();
 
        mat1.values[0] = right.x;
        mat1.values[4] = right.y;
        mat1.values[8] = right.z;
        mat1.values[12] = 0;
 
        mat1.values[1] = up.x;
        mat1.values[5] = up.y;
        mat1.values[9] = up.z;
        mat1.values[13] = 0;
 
        mat1.values[2] = -dir.x;
        mat1.values[6] = -dir.y;
        mat1.values[10] = -dir.z;
        mat1.values[14] =  0;
 
        mat1.values[3] = 0;
        mat1.values[7] = 0;
        mat1.values[11] = 0;
        mat1.values[15] = 1;
 
        mat2.setIdentity();
        mat2.values[12] = -x;
        mat2.values[13] = -y;
        mat2.values[14] = -z;

        *this *= mat1;
        *this *= mat2;
    }

    void ortho(float left, float right, float bottom, float top, float nearp, float farp){
        mat4 m;
        
        m.setIdentity();

        m.values[0] = 2/(right-left);
        m.values[5] = 2/(top-bottom);
        m.values[10] = -2/(farp-nearp);
        m.values[3] = -(right+left)/(right-left);
        m.values[7] = -(top+bottom)/(top-bottom);
        m.values[11] = -(farp+nearp)/(farp-nearp);

        *this *= m;
    }

    void frustum(float left, float right, float bottom, float top, float nearp, float farp){
        mat4 m;
 
        m.setIdentity();
 
        m.values[0] = 2*nearp/(right-left);
        m.values[5] = 2*nearp/(top-bottom);
        m.values[8] = (right+left)/(right-left);
        m.values[9] = (top+bottom)/(top-bottom);
        m.values[10] = -(farp+nearp)/(farp-nearp);
        m.values[11] = -1;
        m.values[14] = -2*farp*nearp/(farp-nearp);
        m.values[15] = 0;
 
        *this *= m;
    }


[EDIT]

Bei lookAt, kommt übrigens immer -1.#IND raus...

[EDIT 2]

perspective funktioniert...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »DeKugelschieber« (01.09.2011, 17:49)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

01.09.2011, 18:01

Stellt sich mir nurnoch die Frage wo diese geringfügige Ungenauigkeit her kommt?

Rundungsfehler

So jetzt hab ich nurnoch Probleme mit lookAt, ortho und frustum die ich mir nicht erklären kann:

Und wir sollen jetzt anhand des Code rausfinden, was genau für Probleme du damit hast?

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

9

01.09.2011, 18:50

Die Matrizen werden halt falsch aufgesetzt: Nicht genau das gleich Ergebnis wie bei OpenGL. Dabei halte ich mich eigentlich an die Angaben vom DGL Wiki, oder auch anderen Seiten...

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

01.09.2011, 18:59

Und wo genau liegen die Unterschiede. Stimmts überhaupt nicht? Stehen die richtigen Zahlen in den falschen Zellen? Stimmen nur manche Werte? Wenn ja welche?

Bei lookAt, kommt übrigens immer -1.#IND raus...

Dann würd ich mal meinen, einer deiner Vektoren hat Länge 0, was beim Normalisieren zu einer Division durch 0 führt. Außerdem hast du wohl übersehen, dass die View-Matrix eigentlich die Inverse von dem, was du da berechnest, sein sollte. Aufgrund der speziellen Form der View-Matrix ließe sich das aber überhaupt sehr viel effizienter berechnen:

Quellcode

1
2
3
4
right.x  right.y  right.z   -dot(right, eye)
  up.x     up.y     up.z     -dot(up, eye)
 -dir.x   -dir.y   -dir.z     dot(dir, eye)
   0        0        0              1

Wobei eye deine Kameraposition ist. Das normalize() von up kannst du außerdem sparen, da dir und right schon normalisiert und orthogonal sind.

Werbeanzeige