Grafikprogrammierung
3D Transformationen
Thorsten Thormählen
04. November 2022
Teil 5, Kapitel 2
Thorsten Thormählen
04. November 2022
Teil 5, Kapitel 2
Dies ist die Druck-Ansicht.
Weiterschalten der Folien durch die → Taste oder
durch das Klicken auf den rechten Folienrand.
Das Weiterschalten der Folien kann ebenfalls durch das Klicken auf den rechten bzw. linken Folienrand erfolgen.
| Typ | Schriftart | Beispiele |
|---|---|---|
| Variablen (Skalare) | kursiv | $a, b, x, y$ |
| Funktionen | aufrecht | $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$ |
| Vektoren | fett, Elemente zeilenweise | $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$ |
| Matrizen | Schreibmaschine | $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$ |
| Mengen | kalligrafisch | $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$ |
| Zahlenbereiche, Koordinatenräume | doppelt gestrichen | $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$ |
GLfloat T[16];
GL_MODELVIEW Matrix verantwortlich.glMatrixMode(GL_MODELVIEW);
glLoadIdentity, glLoadMatrix, glMultMatrix
glRotate, glScale, glTranslate, glPushMatrix, glPopMatrix werden dann auf der GL_MODELVIEW Matrix ausgeführt.
GL_MODELVIEW Matrix beeinflusst die Transformation der Objekte nur dann,
wenn diese gezeichnet werden (OpenGL als Zustandsmaschine)glLoadIdentity setzt die aktuelle GL_MODELVIEW Matrix gleich einer $4 \times 4$ Einheitmatrix:
glMultMatrix, glRotate, glScale, glTranslate, erzeugen intern eine $4 \times 4$ Matrix, die
von rechts auf die aktuelle GL_MODELVIEW Matrix multipliziert wird
Beispiel:
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(...); glRotatef(...); glScalef(..);
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t\,\mathtt{T}_r$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t\,\mathtt{T}_r\,\mathtt{T}_s $
$\underline{\tilde{\mathbf{P}}} = \mathtt{T}_{\mathrm{\small modelview}} \, \underline{\mathbf{P}}$
// rotate around z glRotatef(rot1, 0.0, 0.0, 1.0); // rotate around y glRotatef(rot2, 0.0, 1.0, 0.0); // rotate around x glRotatef(rot3, 1.0, 0.0, 0.0);
class Renderer {
public:
float rot1;
float rot2;
float rot3;
public:
Renderer() : rot1(0.0), rot2(0.0), rot3(0.0) {}
public:
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// view scene from the side
glTranslatef(0.0,0.0,-3.0);
glRotatef( -45.0f, 0.0, 0.0, 1.0);
glRotatef( -45.0f, 0.0, 1.0, 0.0);
glRotatef( 135.0f, 1.0, 0.0, 0.0);
// rotate around z
glRotatef(rot1, 0.0, 0.0, 1.0);
glColor3f(0.0f, 0.0f, 1.0f);
drawCoordinateAxisZ();
// rotate around local y
glRotatef(rot2, 0.0, 1.0, 0.0);
glColor3f(0.0f, 1.0f, 0.0f);
drawCoordinateAxisY();
// rotate around local x
glRotatef(rot3, 1.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 0.0f);
drawCoordinateAxisX();
// draw the plane in the local coordinate system
drawToyPlane();
}
private:
void drawCoordinateAxisZ() {
glBegin(GL_LINE_LOOP); // circle in x-y plane
for(int a=0; a<360; a+=10) {
float angle = M_PI / 180.0f * a;
glVertex3f(cos(angle), sin(angle), 0.0);
}
glEnd();
glBegin(GL_LINES);
glVertex3f(0.9f, 0.0f, 0.0f); // x-axis
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.9f, 0.0f); // y-axis
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f,-1.0f); // z-axis
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
glBegin(GL_TRIANGLES); // z-axis tip
glVertex3f(0.0f,-0.1f, 0.9f);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.1f, 0.9f);
glEnd();
}
void drawCoordinateAxisX() {
glPushMatrix();
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
drawCoordinateAxisZ();
glPopMatrix();
}
void drawCoordinateAxisY() {
glPushMatrix();
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
drawCoordinateAxisZ();
glPopMatrix();
}
...
};
mit $\mathbf{v}_n = (\mathbf{v}^\top \mathbf{n})\, \mathbf{n}$ gilt $\tilde{\mathbf{v}} = \mathbf{v}_n + (\mathbf{v} - \mathbf{v}_n) \cos \alpha + (\mathbf{n} \times \mathbf{v}) \sin \alpha$
mit $\mathbf{v}_n = (\mathbf{v}^\top \mathbf{n})\, \mathbf{n} = (\mathbf{n}^\top \mathbf{v} )\, \mathbf{n} = (\mathbf{n} \mathbf{n}^\top) \mathbf{v}$ gilt:
$\begin{align} \tilde{\mathbf{v}} &= \mathbf{v}_n + (\mathbf{v} - \mathbf{v}_n) \cos \alpha + (\mathbf{n} \times \mathbf{v}) \sin \alpha\\ \tilde{\mathbf{v}} &= (\mathbf{n} \mathbf{n}^\top) \mathbf{v} + (\mathbf{v} - (\mathbf{n}\mathbf{n}^\top ) \mathbf{v}) \cos \alpha + ([\mathbf{n}]_\times \mathbf{v}) \sin \alpha\\ \tilde{\mathbf{v}} &= \mathtt{R} \mathbf{v} \end{align}$
wobei die resultierende $3 \times 3$ Rotationsmatrix eine Funktion von $\mathbf{n}$ und $\alpha$ ist, die sich berechnen lässt durch
$ \mathtt{R} = (\mathbf{n} \mathbf{n}^\top) + (\cos \alpha) (\mathbf{I}_{3\times 3} - (\mathbf{n} \mathbf{n}^\top)) + (\sin \alpha)
[\mathbf{n}]_\times$
Die Rotationsmatrix hat also 4 Freiheitsgrade $\mathbf{n}=(n_x, n_y, n_z)$ und $\alpha$. Beziehungsweise, da gilt $|\mathbf{n}|=1$, gibt es eigentlich nur 3 Freiheitsgrade (äquivalent der Repräsentation mit Eulerwinkeln)
$\mathbf{q} = \begin{pmatrix}q_1\\q_2\\ q_3\\ q_4\end{pmatrix} = \begin{pmatrix}s \\v_x \\ v_y \\ v_z\end{pmatrix} = (s, \mathbf{v}^\top)^\top$
Quaternion fastmul(Quaternion ql, Quaternion qr) {
double s[9], t;
s[0] = (ql.vz-ql.vy)*(qr.vy-qr.vz); s[1] = (ql.s +ql.vx)*(qr.s +qr.vx);
s[2] = (ql.s -ql.vx)*(qr.vy+qr.vz); s[3] = (ql.vz+ql.vy)*(qr.s -qr.vx);
s[4] = (ql.vz-ql.vx)*(qr.vx-qr.vy); s[5] = (ql.vz+ql.vx)*(qr.vx+qr.vy);
s[6] = (ql.s +ql.vy)*(qr.s -qr.vz); s[7] = (ql.s -ql.vy)*(qr.s +qr.vz);
s[8] = s[5]+s[6]+s[7];
t = (s[4]+s[8])*0.5;
return Quaternion(s[0]+t-s[5], s[1]+t-s[8], s[2]+t-s[7], s[3]+t-s[6]);
}
class Renderer {
public:
Renderer() : t(0.0) {}
public:
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// view scene from the side
glTranslatef(0.0,0.0,-3.0);
glRotatef( -45.0f, 0.0, 0.0, 1.0);
glRotatef( -45.0f, 0.0, 1.0, 0.0);
glRotatef( 135.0f, 1.0, 0.0, 0.0);
if(true) {
// interpolate rotation matrices, which is wrong
float r0[16];
float r1[16];
float rt[16];
glPushMatrix(); // save for later use
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, r0);
glRotatef(180.0f, 0.0, 0.0, 1.0); // rotate around z
glGetFloatv(GL_MODELVIEW_MATRIX, r1);
glPopMatrix(); // restore
for(unsigned i=0; i < 16; i++) {
rt[i] = (1-t) * r0[i] + t * r1[i]; //interpolate
}
glMultMatrixf(rt); // apply matrix
}else{
// interpolate rotation angle, which is correct
glRotatef(t*180.0f, 0.0, 0.0, 1.0); // rotate around z
}
glColor3f(0.0f, 0.0f, 1.0f);
drawCoordinateAxisZ();
glColor3f(0.0f, 1.0f, 0.0f);
drawCoordinateAxisY();
glColor3f(1.0f, 0.0f, 0.0f);
drawCoordinateAxisX();
}
...
};
Anregungen oder Verbesserungsvorschläge können auch gerne per E-mail an mich gesendet werden: Kontakt