Post on 02-Oct-2020
transcript
(5) Transformationen
VorlesungComputergrafik
T. Grosch
Wiederholung
Linien Clipping Cyrus-Beck
• Linie – konvexes Clip-Polygon Sutherland-Hodgman
• Polygon – konvexes Clip-Polygon
Heute Transformationen (3D)
• Translation, Rotation, Skalierung Umsetzung in OpenGL
T. Grosch - 2 -
Translation
x
y
)5.0,5.0( )5.0,5.0(
)5.0,5.0()5.0,5.0(
x
y
xt
x
y
yt
1
1
T. Grosch - 3 -
Translation
void Polygon2D::translate(Vector2D offset){
for (int i=0; i<mPoints.size(); i++) mPoints[i] += offset;
}
x
y
1
1
y
x
tt
t Wir haben einen „Verschiebevektor“ t, der auf alle Eckpunkte addiert wird.
tPP ii
'
T. Grosch - 4 -
Beispiel „Verschieben des
Objektmittelpunktes in den Ursprung“
Genauer: Translation eines Objektes, so dass sein Mittelpunkt in den Ursprung verschoben wird.
x
y
1
1
),( yx MM
translate(Vector2D(-Mx, -My));x
y
1
1
)0,0(
y
x
MM
MOt
T. Grosch - 5 -
N
iiP
NM
1
1
Skalierung
x
y
)5.0,5.0( )5.0,5.0(
)5.0,5.0()5.0,5.0(
x
y
xs
x
y
ys1
1
T. Grosch - 6 -
Skalierung
void Polygon2D::scale(float factor){
for (int i=0; i<mPoints.size(); i++) mPoints[i] *= factor;
} //Gesamtskalierung (uniform)
x
y
1
1
Wir haben „Skalierungsfaktoren“ sx und sy, mit denen die Eckpunkte skaliert werden.
yy
xx
y
x
psps
pp
''
T. Grosch - 7 -
Beispiel
x
y
1
1
2
2
3
3
Skalierung des kleinen Quadrats in das große …
T. Grosch - 8 -
1. Schritt
x
y
1
1
2
2
3
3x
y
1
1
2
2
3
3
Translation des Objektmittelpunktes in den Ursprung
translate( -1.5, -1.5);
T. Grosch - 9 -
2. Schritt
x
y
1
1
2
2
3
3x
y
1
1
2
2
3
3
Skalierung um den Faktor 3:
scale( 3);
T. Grosch - 10 -
3. Schritt
x
y
1
1
2
2
3
3
Translation zurück zum (alten) Objektmittelpunkt
translate(1.5, 1.5);
x
y
1
1
2
2
3
3
T. Grosch - 11 -
Die 3 Schritte
x
y
1
1
2
2
3
3
x
y
1
1
2
2
3
3
x
y
1
1
2
2
3
3
x
y
1
1
2
2
3
3
translate( -1.5, -1.5);
scale( 3);
translate( 1.5, 1.5);
5,15,1
''
y
x
y
x
pp
pp
5,435,43
'3'3
''''
y
x
y
x
y
x
pp
pp
pp
3333
5,15,1
''''
''''''
y
x
y
x
y
x
pp
pp
pp
T. Grosch - 12 -
2D-Rotation um Ursprung
x
y
P
P‘
r
0
rpx)cos(
rpy)sin(
rp x')cos(
rp y')sin(
sincoscossin)sin(sinsincoscos)cos(
cossin'
sincos'
yxy
yxx
ppp
ppp
T. Grosch - 13 -
Rotation void Polygon2D::rotate(float angle){
float tmp;for (int i=0 ; i<mPoints.size() ; i++)
{tmp = mPoints[i].x() * cos(angle) -
mPoints[i].y() * sin(angle);mPoints[i].setY( mPoints[i].x() * sin(angle) +
mPoints[i].y() * cos(angle));mPoints[i].setX(tmp);}
}
x
y
1
1
Rotation um den Winkel (hier: gegen den Uhrzeigersinn)
cossinsincos
''
yx
yx
y
x
pppp
pp
T. Grosch - 14 -
Beispiel I
x
y
1
1
2
2
Was passiert durch rotate(/2)?
cossinsincos
''
yx
yx
y
x
pppp
pp
12sin;02cos
x
y
y
x
pp
pp
''
(s. Berechnung der Normalen !)
px py p‘x p‘y1 1 -1 1
2 1 -1 2
2 2 -2 2
1 2 -2 1
2 1
Ergebnis 90
T. Grosch - 15 -
x
y
1
1
2
2
Rotation um den Mittelpunkt des Objektes.
Beispiel 2
translate(-1.5,-1.5);
rotate(/4);
translate(1.5,1.5);
x
y
1
1
2
2
x
y
1
1
2
2
x
y
1
1
2
2
x
y
1
1
2
2
T. Grosch - 16 -
Beispiel 3
x
y
1
1
2
2
Rotation um eine Ecke des Objektes.
translate(-1,-1);
rotate(/4);
translate(1,1);
T. Grosch - 17 -
Fazit Rotation und Skalierung
beziehen sich auf den Ursprung
Rotation/Skalierung in Bezug auf einen beliebigen Punkt A passiert in 3 Schritten: Translation: A in Urspung Rotation/Skalierung Translation: zurück nach A
Dieses Beispiel zeigt: Transformationen werden oft miteinander „verkettet“
Die gezeigte Vorgehensweise (Transformationen der Reihe nach auf die Punkte anwenden) ist keine gute Lösung: Originalpunkte werden
verändert, was nach einiger Zeit zu Rundungsfehlern führt.
Effizienter wäre alle Transformationen zu konkatenieren und jedesmal auf die Originalpunkte anzuwenden.
Also: Rechnen mit Matrizen
'..'...''''......''
......'
pppppp
T. Grosch - 18 -
Matrizenrechnung
22
32
22
12
232221 cbbb
aaaMatrix-Multiplikation
Transponierte Matrix
333231
232221
131211
aaaaaaaaa
A
332313
322212
312111
aaaaaaaaa
AT
zzyyxx
z
y
x
zyx
T
babababbb
aaa
baba
Beispiel: Skalarprodukt:
T. Grosch - 19 -
N
kkjikij bac
1
Matrizen und Vektoren
y
x
y
x
pp
pp
cossinsincos
''
cossinsincos
'' yxyx pppp
Pre-Multiplikation (Links-Multiplikation) mit Zeilenvektor
Post-Multiplikation (Rechts-Multiplikation) mit Spaltenvektor (heute „Standard“)
y
x
y
x
pp
App
''
Tyxyx Apppp ''
Beispiel:
TTT ABBA
T. Grosch - 20 -
Determinanten2D-Matrizen
yy
xx
baba
A
a
b
xyyxyy
xx babababa
A
Im 2D entspricht die Determinante der (vorzeichenbehafteten) Flächedes ParallelogrammsBemerkung: Kreuzprodukt liefert Vektor, dessen Länge gleich dem aufgespannten Parallelogramm ist.
T. Grosch - 21 -
Determinanten3D-Matrizen
zzz
yyy
xxx
cbacbacba
A
a
b
Im 3D entspricht die Determinante dem (vorzeichenbehafteten) Volumendes Parallelepipeds
c
yy
xxz
zz
xxy
zz
yyx
zzz
yyy
xxx
cbcb
acbcb
acbcb
a
cbacbacba
A
cba
T. Grosch - 22 -
Inverse Matrix
333231
232221
1312111 1
AAAAAAAAA
AA
100010001
E EAAAA 11
;; 2111zz
yy
zz
yy
caca
Acbcb
A
zzz
yyy
xxx
cbacbacba
A
T. Grosch - 23 -
Matrixmultiplikation
Die Matrix-Multiplikation ist… assoziativ,
aber nicht kommutativ,
D.h. die Reihenfolge der Transformationen spielt eine große Rolle und darf nicht vertauscht werden !
CBACBA
ABBA
T. Grosch - 24 -
Affine Transformation (3D)
„Parallele Objekte bleiben parallel“
„Die Verhältnisse von Längen, Flächen und Volumen bleiben unverändert“
Rotation um x-Achse (Rechtssystem)
x
z
y
0
rpy)cos(
rpz)sin(
rp y')cos(
rp z')sin(
sincoscossin)sin(sinsincoscos)cos(
cossin'
sincos''
zyz
zyy
xx
ppp
ppppp
z
y
x
z
y
x
ppp
ppp
cossin0sincos0001
'''
P
P‘
r
T. Grosch - 26 -
Rotation um y-Achse (Rechtssystem)
x
z
y
0
rpz)cos(
rpx)sin(
rp z')cos(
rp x')sin(
sincoscossin)sin(sinsincoscos)cos(
sincos'
'cossin'
xzz
yy
xzx
ppp
ppppp
z
y
x
z
y
x
ppp
ppp
cos0sin010
sin0cos
'''
PP‘
r
T. Grosch - 27 -
Rotation um z-Achse (Rechtssystem)
x
z
y
0
rpx)cos(
rpy)sin(
rp x')cos(
rp y')sin(
sincoscossin)sin(sinsincoscos)cos(
zz
yxy
yxx
pp
ppp
ppp
'
cossin'
sincos'
z
y
x
z
y
x
ppp
ppp
1000cossin0sincos
'''
P
P‘
r
T. Grosch - 28 -
Skalierung
zz
yy
xx
z
y
x
z
y
x
z
y
x
pspsps
ppp
ss
s
ppp
000000
'''
x
z
y
0
P‘
x
z
y
0
P‘
x
z
y
0
P
2;2 yx ss2xs
T. Grosch - 29 -
Translation
Gesucht ist eine Matrix, so dass…
Dies ist mit einer 3D-Matrix leider nicht möglich! Man braucht eine weitere Dimension…
zz
yy
xx
z
y
x
z
y
x
tptptp
ppp
ppp
?????????
'''
T. Grosch - 30 -
Translation
Eine Möglichkeit: 3x4 Matrix
In der Regel aber 4x4 Matrizen (Begr. s. später)
zz
yy
xx
z
y
x
z
y
x
z
y
x
tptptp
ppp
ttt
ppp
1100010001
'''
111000100010001
1'''
zz
yy
xx
z
y
x
z
y
x
z
y
x
tptptp
ppp
ttt
ppp
T. Grosch - 31 -
Translation: Punkt oder Richtung
x
z
y
0
P
d
x
z
y
0
P‘
d
zyx ttt ,,Translation um
Der Ortsvektor von P verändert sich, während der Richtungsvektor von d unverändert bleibt
T. Grosch - 32 -
Translation
111000100010001
1'''
zz
yy
xx
z
y
x
z
y
x
z
y
x
tptptp
ppp
ttt
ppp
Punkt:
001000100010001
0'''
z
y
x
z
y
x
z
y
x
z
y
x
ddd
ddd
ttt
ddd
Richtung:
„Ein Punkt hat keine Richtung“
T. Grosch - 33 -
Affine Transformationen und Inverse
10000cossin00sincos00001
)(
xR
10000cos0sin00100sin0cos
)(
yR
1000010000cossin00sincos
)(
zR
1000000000000
),,(z
y
x
zyx ss
s
sssS
1000100010001
),,(z
y
x
zyx ttt
tttT
)();();( zyx RRR
),,();1,1,1( zyxzyx
tttTsss
S
Inverse:
Inversion bei Skalierungsfaktor 0 nicht möglich
T. Grosch - 34 -
Transformationsmatrix
1000z
y
x
tihgtfedtcba
TranslationSkalierung Rotationen
T. Grosch - 35 -
Hintereinanderausführung von Transformationen
1
3
2
1
''''''''
'
nn
n pMp
pMppMp
pMp
pMMMp nn
12ergibt durch Einsetzen:
Da in der Regel nicht nur ein Punkt transformiert wird, ist der Rechenaufwand erheblich geringer, wenn erst die kombinierte Matrix berechnet wird.
123
123
MMMMMMMMM
n
n
Matrixmultiplikation ist assoziativ:
…aber nicht kommutativ ! 2112 MMMM
Reihenfolge derAusführungen
T. Grosch - 36 -
Beispiel
x
y
1
1
2
2
3
3
Skalierung des kleinen Würfels in den großen …z
C
T. Grosch - 37 -
translate( -cx, -cy, -cz);
scale( s, s, s);
translate( cx, cy, cz);
1000100010001
z
y
x
ccc
1000100100100
ss
s
1000100010001
z
y
x
ccc
Bsp.: Matrizen
T. Grosch - 38 -
Bsp.: Transformation
1000100010001
1000000000000
1000100010001
z
y
x
z
y
x
ccc
ss
s
ccc
M
1000100010001
100000
0000
z
y
x
z
y
x
ccc
cscscs
M
100000
0000
1000100010001
z
y
x
z
y
x
csscsscss
ccc
M
1000)1(00)1(00)1(00
scsscsscs
Mz
y
x
(Assoziativität)
T. Grosch - 39 -
Bsp.: Einsetzen der Werte
1000)1(00)1(00)1(00
scsscsscs
Mz
y
x 5.1,5.1,5.1C3s
1333333
11000330030303003
1'''
z
y
x
z
y
x
z
y
x
ppp
ppp
ppp
Gleiches Ergebnis wie im 2D (s. Bsp. weiter vorne).Unterschied: hier wird eine „globale“ Matrix bestimmt/akkumuliert und dann die Punkte darauf angewendet (Aufwand pro Punkt dann unabhängig von Anzahl der Transformationen, sobald Matrix bestimmt).
T. Grosch - 40 -
Implementierung
Es gibt eine 4x4-Matrix als „globale Variable“ Es gibt eine Methode zum „Zurücksetzen“ der Matrix,
wobei sie mit der Einheitsmatrix gefüllt wird. Jeder Aufruf von translate, rotate, scale multipliziert
eine entsprechende Matrix an die „globale“ Matrix. In der Zeichen-Routine wird jeder Eckpunkt
transformiert bevor er gezeichnet wird.
T. Grosch - 41 -
Transformationen in OpenGL
OpenGL Namenstypisierung
von vielen Befehlen gibt es Varianten für verschiedene Parametertypen
glRotate{fd}( TYPE angle, x, y, z );bedeutet daß es zwei Varianten gibt:
glRotatef( float angle, float x, float y, float z );glRotated( double angle, double x, double y, double z );
T. Grosch - 43 -
Einfache Bewegungen
Einfache Befehle zur Objekttransformation: glRotate{fd}( TYPE angle, x, y, z );
rotiert um angle Grad um die angegeben Achse glScale{fd}( TYPE x,y,z );
skaliert um die angegebenen Faktoren glTranslate{fd}( TYPE x,y,z );
verschiebt (transferiert) um den angegebenen Betrag
für ein neues Bild muß die Szene vom Programm neu gezeichnet werden
Ungewöhnlich: Winkel in Grad!
T. Grosch - 44 -
Matrizen Es gibt eine „globale“ Matrix „MODELVIEW“, die anfangs
mit der Einheitsmatrix besetzt ist Jeder Aufruf von glRotate, glScale etc. resultiert in der
Multiplikation der entsprechenden Matrix mit der „globalen“ Matrix von rechts, z.B.
glScalef(sx,sy,sz) <=>
glTranslatef(tx,ty,tz) <=>
1000000000000
z
y
x
MODELVIEW ss
s
M
1000100010001
z
y
x
MODELVIEW ttt
M
T. Grosch - 45 -
Die umgekehrte Reihenfolge…
OGLnnn
OGL
OGL
OGL
MMM
MMMMMMMMM
1
3
2
1
''''''''
'
1
3
2
1
''''''''
'
nn
n pMp
pMppMp
pMp
pMMMp nn
12
Reihenfolge derAusführungen
OGLnOGLOGLn MMMMM 21
Reihenfolge derAusführungen
Reihenfolge derOpenGL Kommandos
T. Grosch - 46 -
Transformationsordnung
Die Anordnung entspringt aus dem Programmablauf Konzeptionell kann man es sich wie folgt vorstellen:
glScalef(1.5,1,1);glTranslatef(.2,0,0);glRotatef(30,0,0,1);glutWireTeapot(...);
„Die Geometrie wandert rückwärts durch das Programm und sammeltdie Transformationen ein“
„OpenGL Programme werden von unten nach oben gelesen…“
T. Grosch - 47 -
Transformationsordnung bei OpenGL
Anwendung passiert nach „letztes Kommando zuerst“, also in der umgekehrten angegebenen Reihenfolge
glTranslatef(.2,0,0);glRotatef(30,0,0,1);
glRotatef(30,0,0,1);glTranslatef(.2,0,0);
T. Grosch - 48 -
Nate Robin
transformation.exe
T. Grosch - 49 -
Direkte Matrizenspezifizierung
Man kann auch direkt Matrizen angeben glMultMatrix{fd}( TYPE * m );
multipliziert die Matrix auf die aktuelle Matrix glLoadMatrix{fd}( TYPE * m );
ersetzt die aktuelle Matrix durch die angegebene
Matrixabfrage glGetFloatv( GL_MODELVIEW_MATRIX, float * m );
Spezialfall: EinheitsmatrixglLoadIdentity(); Modelview Matrix immer am Anfang zurücksetzen (denn:
State Machine!)
T. Grosch - 50 -
Matrizen
werden spaltenweise abgelegt, nicht wie in C üblich zeilenweise!
<=>
GLfloat matrix[] = {1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,tx, ty, tz, 1 };
1000100010001
z
y
x
ttt
T. Grosch - 51 -
Polygone und Flächen in OpenGL
Primitivtypen in OpenGL
5.
3.
4. 2.
1.
GL_POINTS
5.
3.
4. 2.
1.
GL_LINE_STRIP
5.
3.
4. 2.
1.
GL_LINE_LOOP
5.
3.
4. 2.
1.
GL_POLYGON
1.
3.
2.4.
5.
GL_LINES
6.
1.
3.
4.2.
5.
GL_QUADS
8.
1.
2.
3.4.
6.
GL_TRIANGLES
5.
6.
7.
Mehrfachprimitive
T. Grosch - 53 -
Füllmuster
Analog zu den Linien: glPolygonStipple( GLuchar * pattern );
muß auch aktiviert werden glEnable(GL_POLYGON_STIPPLE);
feste Größe: 32x32 abgelegt als Bitmuster von links unten nach rechts
oben
T. Grosch - 54 -
Zusätzliche Eckpunktattribute
State machine: an jedem Eckpunkt wird der aktuelle Zustand verwendet, d.h. erst muß die Farbe etc. definiert werden, dann der Eckpunkt
glBegin(GL_POLYGON);glColor3f(1,0,0);glVertex3f(0,0,0);glVertex3f(1,0,0);glVertex3f(.5,1,0);glEnd();
T. Grosch - 55 -
Zusätzliche Eckpunktattribute
Änderungen pro Eckpunkt möglich
glBegin(GL_POLYGON);glColor3f(0,0,1);glVertex3f(0,0,0);glColor3f(0,0,1);glVertex3f(1,0,0);glColor3f(1,0,0);glVertex3f(.5,1,0);glEnd();
T. Grosch - 56 -
Farbinterpolation
Die Farbe muß nicht interpoliert werden glShadeModel( {GL_FLAT,GL_SMOOTH} ); bestimmt,
ob interpoliert wird bei GL_FLAT bestimmt die Farbe des letzten
Eckpunktes (Ausnahme GL_POLYGON: erster)
1.
5.
4.3.
2.
6.
1.
5.
4.3.
2.
6.
GL_FLATGL_SMOOTH
T. Grosch - 57 -
Polygone…. … werden in Dreiecke zerlegt
und als Dreiecke dargestellt. Bi-lineare Interpolation nicht
mehr eindeutig Abhängig davon, wie die
Dreieckskante verläuftr g r g
rgrgv1 v2 v1
v4 v3 v4
v2
v3
DrawPolygon(v1,v2,v3,v4)
DrawPolygon(v2,v3,v4,v1)
T. Grosch - 58 -
GLUT: Tastatur Callbackvoid keyboard( unsigned char key, int x, int y){
switch (key) {
case '1':show = 1;glutPostRedisplay();break;
case '2':show = 2;glutPostRedisplay();break;
default:break;
}}
key liefert die gedrückte Taste x, y die aktuelle Mausposition
T. Grosch - 59 -
GLUT: Idle und Special Funktionvoid main(…){…
glutIdleFunc(idle);glutSpecialFunc(special);
}
IDLE Funktion Wird immer aufgerufen,
wenn der Windowmanager „nichts zu tun hat“.
Gute Verwendung: automatische Objektbewegung
SPECIAL Funktion Sondertasten wie z.B. Pfeil-
/Cursortasten.
void special( int key, int x, int y){
switch (key) {case GLUT_KEY_UP :
speed += 0.001f; break;
case GLUT_KEY_DOWN : speed -= 0.001f; break;
}}
void idle( void){
beta += 5.0; glutPostRedisplay();
}
T. Grosch - 60 -
Front-/Backbuffer
Erlaubt flackerfreie Animationen
zeichnen
swap
zeichnen
Statt wie bisher:glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);…glFlush();
Benötigt man:glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);…glutSwapBuffers();
T. Grosch - 61 -
Tiefen-Puffer Für jedes Pixel: finde/zeichne
das vorderste Polygon … kann direkt mit Hilfe der z-
Koordinate entschieden werden
Für jedes Pixel (x,y) gibt es einen Farbeintrag im
Framebuffer gibt es einen z-Eintrag im Z-
Buffer
Vorgehen Initialisiere anfangs Z-Buffer
mit größtem, maximalen Wert
Schreibe rgb-Wert in Framebuffer und z-Wert in Z-Buffer für (x,y) nur, wenn aktueller z-Wert kleiner ist, als der für das Pixel bereits Eingetragene
function setpixel( int x, int y, rgb c, float z)if (z < z-buffer[x, y]){z-buffer[x, y]= z;screen[x, y] = c;
}
T. Grosch - 62 -
Tiefen-Puffer in OpenGL
Glut-Fenster anmeldenglutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
EinschaltenglEnable(GL_DEPTH_TEST);
Wichtig: nicht nur Bildspeicher, sondern auch Tiefenpuffer löschenglClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
T. Grosch - 63 -
Zusammenfassung
Transformationen Translation, Skalierung, Rotation Matrizen OpenGL
Nächste Woche View Transformationen (Kamerakoordinaten)
T. Grosch - 64 -