<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
		<id>https://wiki.delphigl.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=TAK2004</id>
		<title>DGL Wiki - Benutzerbeiträge [de]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.delphigl.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=TAK2004"/>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php/Spezial:Beitr%C3%A4ge/TAK2004"/>
		<updated>2026-04-17T17:04:46Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.27.4</generator>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Zeichenkontext&amp;diff=24129</id>
		<title>Tutorial OpenGL3 Zeichenkontext</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Zeichenkontext&amp;diff=24129"/>
				<updated>2009-08-16T13:45:27Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Erstellung eines OpenGL3.x GC */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Der Grafikcontext==&lt;br /&gt;
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht.&lt;br /&gt;
Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten, dabei werden Identifier(ID) verwendet, um Resourcen nach außen Verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt.&lt;br /&gt;
Neben den ID-Listen werden noch sogenannte States, Informationen für die Bildausgabe und diverse unbekannte treiberspezifische Daten gespeichert.&lt;br /&gt;
&lt;br /&gt;
===Profil===&lt;br /&gt;
Um die einzelnen Befehlssätze zu Verwalten hat man sogenannte Profile eingeführt.&lt;br /&gt;
OpenGL3 ist z.B. ein Profil, es gibt noch weitere Profile wie z.B. OpenGL3.1 oder OpenGL3.1 Debug.&lt;br /&gt;
Die Profile werden vom ARB fest gelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als &amp;quot;deprecated&amp;quot; eingestuft wurden, und einmal mit diesen.&lt;br /&gt;
&lt;br /&gt;
===Forward compatible context und Full context===&lt;br /&gt;
Es gibt 2 Varianten eines Context, der Full context ist enthält alle Funktionen, auch die als deprecated maktierten. Der Forward compatible context enthält nur die nicht als deprecated markierten Funktionen des OpenGL Kerns. Bis zur Version 3.1 gab es immer eine abwärts Kompatibilität und der Treiber hatte entschieden, welche OpenGL Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine abwärts Kompatibilität mehr und man kann festlegen, was für ein GC man haben möchte.&lt;br /&gt;
&lt;br /&gt;
===Verwaltung der veralteten und neuen Funktionen===&lt;br /&gt;
Das hinzukommen und das entfernen von OpenGL Funktionen unterliegt dem Deprecation und Extension Mechanismus.&lt;br /&gt;
Diese funktionieren wie folgt.&lt;br /&gt;
&lt;br /&gt;
'''Deprecation Path''': Core-&amp;gt;ARB-&amp;gt;Vendor/Extension&lt;br /&gt;
&lt;br /&gt;
Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur verfügung gestellt.&lt;br /&gt;
Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt.&lt;br /&gt;
Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet.&lt;br /&gt;
&lt;br /&gt;
'''Extension Path''': Vendor/Extension-&amp;gt;ARB-&amp;gt;Core&lt;br /&gt;
&lt;br /&gt;
Wenn eine Extension, von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen.&lt;br /&gt;
Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL Version in den Kern aufgenommen.&lt;br /&gt;
&lt;br /&gt;
OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiter Entwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. Transform Feedback, Instancing oder GLSlang 1.4 .&lt;br /&gt;
&lt;br /&gt;
=Der erste Schritt (OpenGL Context)=&lt;br /&gt;
Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen, vom Desktop Manager, welche Möglichkeiten wir überhaupt zur Auswahl haben. Es wird ein Double Buffer benötigt und man muss die Farbtiefe sowie Tiefenpuffer Genauigkeit festlegen. Dies wird von den Desktop Managern unterschiedlich gehandhabt, so hat Windows z.B. ein DeviceContext und ein Pixelformat und X11 nennt dies VisualInfo bzw. GLXFBConfig.&lt;br /&gt;
Ist dieser Schritt getan kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen.&lt;br /&gt;
&lt;br /&gt;
==Erstellung eines OpenGL3.x GC==&lt;br /&gt;
Um ein GC ertellen zu können wird eine weitere API benötigt, welche plattformabhängig und durch wgl[Funktionsname]/glX[Funktionsname] erkennbar ist. Mit diesen Befehlen kann man mit den Windows und X11 Desktop Manager zusammen arbeiten. So werden Funktionen für das erstellen, wechseln, zerstören eines GC, laden von Extension, wechseln des Fensterpuffern und Synchronisieren von CPU und GPU ermöglicht. Bisher gibt es noch keine Möglichkeit einen OpenGL3 fähigen GC zu erstellen, ohne dafür eine Funktion vom ARB zu verwenden. Der Nachteil von ARB Funktionen sind, dass man einen gültigen GC benötigt den Zeiger auf diese zu erhalten. Um einen OpenGL 3.0 oder 3.1 GC zu erstellen benötigt man einen OpenGL1-2 GC und die Kernfunktion [[wglGetProcAddress]]/[[glxGetProcAddress]]. Einen gültigen OpenGL1 bzw. OpenGL2 GC bekommt man über den Befehl [[wglCreateContext]]/[[glxCreateContext]] und zwischen mehreren GC kann man mit dem Befehl [[wglMakeCurrent]]/[[glxMakeCurrent]] wechseln.&lt;br /&gt;
Der Befehl für die Erstellung eines OpenGL3 fähigen GC heisst [[wglCreateContextAttribsARB]]/[[glxCreateContextAttribsARB]].&lt;br /&gt;
Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, in dem man die noch jetzige ARB Funktion in den OpenGL-Kern mit aufnimmt und somit das erfragen der ARB Funktion, über ein OpenGL1-2GC, unnötig macht.&lt;br /&gt;
&lt;br /&gt;
'''Windows'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void CreateOpenGL3Context()&lt;br /&gt;
{&lt;br /&gt;
  HGLRC TempContext=wglCreateContext(DeviceContext);//erstellt ein alten OpenGL Context&lt;br /&gt;
  if (TempContext==NULL)&lt;br /&gt;
  {&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;//beenden&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,TempContext);//setzt den erstellten GC als aktuellen GC&lt;br /&gt;
&lt;br /&gt;
  //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
  typedef HGLRC (APIENTRY * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int *attribList);&lt;br /&gt;
&lt;br /&gt;
  PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;&lt;br /&gt;
&lt;br /&gt;
  //abfragen, ob die Funktion existiert&lt;br /&gt;
  wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(&amp;quot;wglCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if(wglCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
  {&lt;br /&gt;
    wglDeleteContext(TempContext);&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int attribs[]={WGL_CONTEXT_MAJOR_VERSION_ARB,3,WGL_CONTEXT_MINOR_VERSION_ARB,1,WGL_CONTEXT_FLAGS_ARB,WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
&lt;br /&gt;
  if (!(Context=wglCreateContextAttribsARB(DeviceContext,0, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen&lt;br /&gt;
  {&lt;br /&gt;
    //Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  &lt;br /&gt;
    attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
    if (!(Context=wglCreateContextAttribsARB(Win-&amp;gt;GetDeviceContext(),0, attribs)))&lt;br /&gt;
    {&lt;br /&gt;
      //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
      wglDeleteContext(TempContext);//aufräumen und beenden&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,Context);//wechsel auf den OpenGL3.x context&lt;br /&gt;
  wglDeleteContext(TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mac OS erlaubt die nachträgliche Installation von X11 und kann somit über die folgenden Code ebenfalls ein OpenGL Context erstellen. Alternativ bietet Mac OS mehrere OpenGL Schnittstellen, welche sich in der Einfachheit der API unterscheiden. Wenn man nicht den Nutzer zwingen will X11 zu installieren, dann sollte man zu den entsprechenden Schnittstellen AGL, CGL oder NSOpenGL greifen.&lt;br /&gt;
&lt;br /&gt;
'''X11(Linux/Mac OS)'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;  bool OpenGLWindow::CreateOpenGL3Context()&lt;br /&gt;
  {&lt;br /&gt;
    GLXContext TempContext=glXCreateContext(m_Display,m_VisualInfo,0,GL_TRUE);//erstellt ein alten OpenGL Context&lt;br /&gt;
    if(TempContext==0)&lt;br /&gt;
    {&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
    glXMakeCurrent(m_Display,m_Window,TempContext);&lt;br /&gt;
&lt;br /&gt;
    //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
    typedef GLXContext (* GLXCREATECONTEXTATTRIBSARBPROC)(Display *dpy,GLXFBConfig config,GLXContext share_context,Bool direct,const int *attrib_list);&lt;br /&gt;
    //abfragen, ob die Funktion existiert&lt;br /&gt;
    GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*)&amp;quot;glXCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if(glXCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
    {&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
    int minor=0;&lt;br /&gt;
    int major=0;&lt;br /&gt;
    glGetIntegerv(GL_MAJOR_VERSION,&amp;amp;major);&lt;br /&gt;
    glGetIntegerv(GL_MINOR_VERSION,&amp;amp;minor);&lt;br /&gt;
    int attribs[]={GLX_CONTEXT_MAJOR_VERSION_ARB,major,GLX_CONTEXT_MINOR_VERSION_ARB,minor,GLX_CONTEXT_FLAGS_ARB,GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
    for (int i=minor; i&amp;gt;=0;i--)&lt;br /&gt;
    {&lt;br /&gt;
      attribs[3]=i;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
      m_Context=glXCreateContextAttribsARB(m_Display, m_FBConfig[0], NULL, true, attribs);&lt;br /&gt;
      if (!m_Context)//versuche ein OpenGL3.i fähigen Context zu erstellen&lt;br /&gt;
      {&lt;br /&gt;
        if (i&amp;gt;0)&lt;br /&gt;
        {&lt;br /&gt;
          //Entweder hat der Treiber noch keinen OpenGL3.i support oder die Grafikkarte beherrscht kein OpenGL3.i.&lt;br /&gt;
          cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.&amp;quot;&amp;lt;&amp;lt;i&amp;lt;&amp;lt;&amp;quot; context. Try now OpenGL3.&amp;quot;&amp;lt;&amp;lt;i-1&amp;lt;&amp;lt;&amp;quot; context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
          continue;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
          //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
          glXDestroyContext(m_Display,TempContext);//aufräumen und beenden&lt;br /&gt;
          cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
    glXMakeCurrent(m_Display,m_Window,m_Context);//wechsel auf den OpenGL3.x context&lt;br /&gt;
    glXDestroyContext(m_Display,TempContext);&lt;br /&gt;
    return true;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24128</id>
		<title>Tutorial OpenGL3 Das Objekt System von OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24128"/>
				<updated>2009-08-16T13:28:43Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seit OpenGL3 sind alle verwendbaren Daten in Objekten verpackt.&lt;br /&gt;
Die OpenGL3 Bibliothek ist in c geschrieben und kennt daher keine Klassen, daher werden sogenannte ID's zur Assoziation verwendet.&lt;br /&gt;
Wenn man also eine der Funktionen aufruft, die zur Erstellung eines Objektes zuständig ist, dann bekommt man eine 32Bit große, Vorzeichenlose Nummer zurück.&lt;br /&gt;
Diese sind nicht zwingend aufsteigend Nummeriert, sondern können vom Treiber frei gewählt werden. Die einzige Bedingung die gestellt wird, ist das die ID 0 nicht vergeben wird, denn diese wird vom Treiber automatisch am Start reserviert und ein Null-Objekt erzeugt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:OpenGL3_Objekte.png]]&lt;br /&gt;
&lt;br /&gt;
glBind[Objekttyp](...) Aufruf:&lt;br /&gt;
&lt;br /&gt;
1.) Zuerst wird die Übergebene ID in einer Tabelle gesucht, diese Tabelle wird vom OpenGL Treiber verwaltet und wird vor dem Programmierer versteckt.&lt;br /&gt;
&lt;br /&gt;
2.) Sollte die ID nicht existieren wird die Adresse(Pointer) des Null-Objekt gewählt sonnst der gefundene Pointer. Dieser wird nun in eine Variable gespeichert, welche ebenfalls vom OpenGL Treiber verwaltet wird.&lt;br /&gt;
&lt;br /&gt;
3.) Abhängig von dem Ausgeführten Befehl, kann es sein, dass die ID direkt Übergeben wird(z.B. glGen[Objekttyp]s(...) ), ohne vorher die Ressource Binden zu müssen. Hierzu wird der 1.) Schritt ausgeführt und dann der Pointer verwendet um direkt auf den Speicherbereich, auf der Grafikkarte(VideoRAM) zu arbeiten.&lt;br /&gt;
&lt;br /&gt;
glTexImage2D(...), ... Aufruf:&lt;br /&gt;
&lt;br /&gt;
4.) Die meisten OpenGL Befehle arbeiten über die in Schritt 2.) kennen gelernte Variable, um nicht jedes mal die ID in der Tabelle suchen zu müssen und somit Schneller den Befehl abarbeiten zu können(Schritt 3.) ).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von Objekten Teilt sich in 4 Bereiche, Erstellung, Verändern, Verwenden und Vernichtung.&lt;br /&gt;
Da es verschiedene Typen von Objekten gibt, müssen diese auch Unterschieden werden können und unterschiedlich anwendbar sein.&lt;br /&gt;
Es gibt in OpenGL3 folgende Objekte:&lt;br /&gt;
*Buffer(auch als VBO bekannt)&lt;br /&gt;
*VertexArray&lt;br /&gt;
*Query&lt;br /&gt;
*Textur&lt;br /&gt;
*FrameBuffer(auch als FBO bekannt)&lt;br /&gt;
*Shader&lt;br /&gt;
*Program&lt;br /&gt;
&lt;br /&gt;
Für jeden Objekttyp gibt es eigene Funktionssammlungen für die 4 oben erwähnten Bereiche.&lt;br /&gt;
Durch eine Namenskonvention sind diese recht einfach zu erkennen.&lt;br /&gt;
So werden alle Befehle, zum erzeugen der Objekte wie folgt aufgebaut.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glGen[Objekttyp]s(Anzahl,Pointer auf ID-Array);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glGenTextures(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Zerstörung und das aktivieren eines Objektes wird auch über Namenskonventionen erleichtert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glBind[Objekttyp](...,ID);//Anzahl und Typ der Parameter sind Unterschiedlich.&lt;br /&gt;
glDelete[Objekttyp]s(Anzahl,Pointer auf ID-Array);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glBindTexture(GL_TEXTURE_2D,TextureID);&lt;br /&gt;
glDeleteTexture(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald man ein Objekt, mit der zu den Objekttyp passenden Generierungs-Funktion erstellt, erhält man eine ID und diese kann man nun verwenden um z.B. ab zu fragen was das Objekt für ein Typ ist und ob es Aktiv ist.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;bool glIs[Objekttyp](ID);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;if (glIsTexture(TextureID))&lt;br /&gt;
{...}//Objekt ist eine Textur.&lt;br /&gt;
else&lt;br /&gt;
{...}//Objekt ist keine Textur.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn nun statt einer erhaltenen ID die 0 bei einer OpenGL Funktion übergeben wird, dann zeigt man also auf das Null-Objekt, welches bei allen Objekt-Bind Befehlen zufolge hat, dass dieser Buffertyp als deaktiviert gilt.&lt;br /&gt;
Möchte man z.B. FrameBuffer abschalten, weil man diesen nicht mehr braucht, dann benutzt man den passenden Bind Befehl und setzt als ID die 0 ein.&lt;br /&gt;
&lt;br /&gt;
Um das ein bischen zu festigen kommt nun mal ein kleines Beispiel.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellung&lt;br /&gt;
GLuint TextureID=0;&lt;br /&gt;
glGenTextures(1,&amp;amp;TextureID);//Es wird ein Objekt erzeugt und die ID dieses Objektes in die TextureID Variable geschrieben.&lt;br /&gt;
//Weise Daten dem Objekt zu.&lt;br /&gt;
//...&lt;br /&gt;
//Zeichenroutine(Verwendung)&lt;br /&gt;
if (glIsTexture(TextureID))&lt;br /&gt;
{&lt;br /&gt;
  glEnable(GL_TEXTURE_2D);&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,TextureID);//Bindet das Objekt als OpenGL 2D-Textur.&lt;br /&gt;
  //...&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,0);&lt;br /&gt;
  glDisable(GL_TEXTURE_2D);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
//Aufräumen&lt;br /&gt;
glDeleteTextures(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Objekt bleibt solange Aktiv und/oder gebunden, bis ein anderes gebunden bzw. der Objektyp deaktiviert wurde.&lt;br /&gt;
Durch das ständige Binden,Aktivieren und Deaktivieren geht sehr viel Zeit verloren, die sich auf die Programmgeschwindigkeit auswirkt.&lt;br /&gt;
OpenGL war Ursprünglich eine Statemachiene, also etwas galt solange, bis es verändert wurden, dann galt der neue Zustand.&lt;br /&gt;
Dieses ist in OpenGL3 immer noch der Fall, allerdings in einer wesentlich abgeschwächten Form, da die meisten States schon entfernt werden konnten.&lt;br /&gt;
Das gleiche System findet auch bei der Objektverwaltung seinen Platz, was heute allerdings wenig Sinn macht.&lt;br /&gt;
Früher hat man beim Binden eine Hashtable verwendet, um aus der ID die dazugehörige Speicheradresse, der Objektdaten, auf im VideoRam zu ermitteln und im entsprechendem Globalen Variable zu setzen.&lt;br /&gt;
Dies hat die Leistung in den früheren OpenGL Versionen erhöht, da die Art, wie man gezeichnet hat eine ganz andere war, als wie heute.&lt;br /&gt;
Durch die generischen Buffer und der vom Entwickler bestimmten Shaderpipeline ist dieses ständige Binden zu dem Flaschenhals in der OpenGL3 Programmierung geworden.&lt;br /&gt;
Die ID's, die man von OpenGL bekommt sind allerdings nur 32Bit groß und die Speicheraddressen, passen nicht in die 32Bit.&lt;br /&gt;
Deshalb ist es bis jetzt noch nicht möglich, über die gegebene API das Problem zu lösen.&lt;br /&gt;
Man müsste also mit jeder Speicherbus Erweiterung, die eine Grafikkarte mit sich bringt, auch die API anpassen, was etwas Aufwand ist.&lt;br /&gt;
Der Grafikkartenhersteller Nvidia hat allerdings eine Erweiterung für OpenGL2 und Aufwärts zur verfügung gestellt, welche erlaubt die Speicheraddressen von den OpenGL Objekten ab zu fragen und diese in einen BuffeObjekt zu hinterlegen.&lt;br /&gt;
Wenn man nun alle logisch zusammengehörenden Objektaddressen in jeweils einen Buffer hinterlegt, dann kann man mit Hilfe dieses alle Bind Befehle auf einen einzigen reduzieren und somit den Flaschenhals auf ein anderen Bereich verschieben.&lt;br /&gt;
Dies ist allerdings noch eine Extension, wird aber wohl aufgrund seiner Einfachheit recht schnell in die ARB und dann in den OpenGL-Kern finden.&lt;br /&gt;
Bis dahin muss der Programmierer versuchen das Problem so stark wie möglich zu reduzieren.&lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt, ist OpenGL3 immer noch Statebasiert, was man sich zu nutze machen kann.&lt;br /&gt;
Wenn man z.B. alle genutzen Daten nach bestimmten Kriterien sortiert, kann man somit die Anzahl der Bindings und Stateänderungen reduzieren.&lt;br /&gt;
Im Laufe der einzelnen Artikel wird man noch die ein oder andere Möglichkeit sehen, weitere Optimierungen vor zu nehmen.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:OpenGL3_Objekte.png&amp;diff=24127</id>
		<title>Datei:OpenGL3 Objekte.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:OpenGL3_Objekte.png&amp;diff=24127"/>
				<updated>2009-08-16T12:59:17Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24126</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24126"/>
				<updated>2009-08-14T15:08:35Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Artikelreihe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Diese Artikel Reihe richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Inhaltsverzeichnis==&lt;br /&gt;
===Grundlagen===&lt;br /&gt;
Artikel in diesem Bereich sind für OpenGL wichtig aber haben nicht direkt mit OpenGL zu tun.&lt;br /&gt;
&lt;br /&gt;
Man kann diese Artikel überspringen und später bei aufkommenden Fragen in diese hinein lesen.&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_Lineare_Algebra|Lineare Algebra]]&lt;br /&gt;
===Artikelreihe===&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Vorschau auf das kommende]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_Zeichenkontext|Erstellen eines Grafik Kontext]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3|Das Objekt System von OpenGL3]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Vertex Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Verfügbare Geometrie]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|GLSLang]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Geometryshader]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Transform Feedback]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Texturen]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Frame Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Scissor/Clipping]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Instancing]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Oclussion Query]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Conditional Rendering]]&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24125</id>
		<title>Tutorial OpenGL3 Das Objekt System von OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24125"/>
				<updated>2009-08-14T15:03:09Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seit OpenGL3 sind alle verwendbaren Daten in Objekten verpackt.&lt;br /&gt;
Die OpenGL3 Bibliothek ist in c geschrieben und kennt daher keine Klassen, daher werden sogenannte ID's zur Assoziation verwendet.&lt;br /&gt;
Wenn man also eine der Funktionen aufruft, die zur Erstellung eines Objektes zuständig ist, dann bekommt man eine 32Bit große, Vorzeichenlose Nummer zurück.&lt;br /&gt;
Diese sind nicht zwingend aufsteigend Nummeriert, sondern können vom Treiber frei gewählt werden. Die einzige Bedingung die gestellt wird, ist das die ID 0 nicht vergeben wird, denn diese wird vom Treiber automatisch am Start reserviert und ein Null-Objekt erzeugt.&lt;br /&gt;
Die Verwendung von Objekten Teilt sich in 4 Bereiche, Erstellung, Verändern, Verwenden und Vernichtung.&lt;br /&gt;
Da es verschiedene Typen von Objekten gibt, müssen diese auch Unterschieden werden können und unterschiedlich anwendbar sein.&lt;br /&gt;
Es gibt in OpenGL3 folgende Objekte:&lt;br /&gt;
*Buffer(auch als VBO bekannt)&lt;br /&gt;
*VertexArray&lt;br /&gt;
*Query&lt;br /&gt;
*Textur&lt;br /&gt;
*FrameBuffer(auch als FBO bekannt)&lt;br /&gt;
*Shader&lt;br /&gt;
*Program&lt;br /&gt;
&lt;br /&gt;
Für jeden Objekttyp gibt es eigene Funktionssammlungen für die 4 oben erwähnten Bereiche.&lt;br /&gt;
Durch eine Namenskonvention sind diese recht einfach zu erkennen.&lt;br /&gt;
So werden alle Befehle, zum erzeugen der Objekte wie folgt aufgebaut.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glGen[Objekttyp]s(Anzahl,Pointer auf ID-Array);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glGenTextures(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Zerstörung und das aktivieren eines Objektes wird auch über Namenskonventionen erleichtert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glBind[Objekttyp](...,ID);//Anzahl und Typ der Parameter sind Unterschiedlich.&lt;br /&gt;
glDelete[Objekttyp]s(Anzahl,Pointer auf ID-Array);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;glBindTexture(GL_TEXTURE_2D,TextureID);&lt;br /&gt;
glDeleteTexture(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald man ein Objekt, mit der zu den Objekttyp passenden Generierungs-Funktion erstellt, erhält man eine ID und diese kann man nun verwenden um z.B. ab zu fragen was das Objekt für ein Typ ist und ob es Aktiv ist.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;bool glIs[Objekttyp](ID);&amp;lt;/source&amp;gt;&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;if (glIsTexture(TextureID))&lt;br /&gt;
{...}//Objekt ist eine Textur.&lt;br /&gt;
else&lt;br /&gt;
{...}//Objekt ist keine Textur.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn nun statt einer erhaltenen ID die 0 bei einer OpenGL Funktion übergeben wird, dann zeigt man also auf das Null-Objekt, welches bei allen Objekt-Bind Befehlen zufolge hat, dass dieser Buffertyp als deaktiviert gilt.&lt;br /&gt;
Möchte man z.B. FrameBuffer abschalten, weil man diesen nicht mehr braucht, dann benutzt man den passenden Bind Befehl und setzt als ID die 0 ein.&lt;br /&gt;
&lt;br /&gt;
Um das ein bischen zu festigen kommt nun mal ein kleines Beispiel.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellung&lt;br /&gt;
GLuint TextureID=0;&lt;br /&gt;
glGenTextures(1,&amp;amp;TextureID);//Es wird ein Objekt erzeugt und die ID dieses Objektes in die TextureID Variable geschrieben.&lt;br /&gt;
//Weise Daten dem Objekt zu.&lt;br /&gt;
//...&lt;br /&gt;
//Zeichenroutine(Verwendung)&lt;br /&gt;
if (glIsTexture(TextureID))&lt;br /&gt;
{&lt;br /&gt;
  glEnable(GL_TEXTURE_2D);&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,TextureID);//Bindet das Objekt als OpenGL 2D-Textur.&lt;br /&gt;
  //...&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,0);&lt;br /&gt;
  glDisable(GL_TEXTURE_2D);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
//Aufräumen&lt;br /&gt;
glDeleteTextures(1,&amp;amp;TextureID);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Objekt bleibt solange Aktiv und/oder gebunden, bis ein anderes gebunden bzw. der Objektyp deaktiviert wurde.&lt;br /&gt;
Durch das ständige Binden,Aktivieren und Deaktivieren geht sehr viel Zeit verloren, die sich auf die Programmgeschwindigkeit auswirkt.&lt;br /&gt;
OpenGL war Ursprünglich eine Statemachiene, also etwas galt solange, bis es verändert wurden, dann galt der neue Zustand.&lt;br /&gt;
Dieses ist in OpenGL3 immer noch der Fall, allerdings in einer wesentlich abgeschwächten Form, da die meisten States schon entfernt werden konnten.&lt;br /&gt;
Das gleiche System findet auch bei der Objektverwaltung seinen Platz, was heute allerdings wenig Sinn macht.&lt;br /&gt;
Früher hat man beim Binden eine Hashtable verwendet, um aus der ID die dazugehörige Speicheradresse, der Objektdaten, auf im VideoRam zu ermitteln und im entsprechendem Globalen Variable zu setzen.&lt;br /&gt;
Dies hat die Leistung in den früheren OpenGL Versionen erhöht, da die Art, wie man gezeichnet hat eine ganz andere war, als wie heute.&lt;br /&gt;
Durch die generischen Buffer und der vom Entwickler bestimmten Shaderpipeline ist dieses ständige Binden zu dem Flaschenhals in der OpenGL3 Programmierung geworden.&lt;br /&gt;
Die ID's, die man von OpenGL bekommt sind allerdings nur 32Bit groß und die Speicheraddressen, passen nicht in die 32Bit.&lt;br /&gt;
Deshalb ist es bis jetzt noch nicht möglich, über die gegebene API das Problem zu lösen.&lt;br /&gt;
Man müsste also mit jeder Speicherbus Erweiterung, die eine Grafikkarte mit sich bringt, auch die API anpassen, was etwas Aufwand ist.&lt;br /&gt;
Der Grafikkartenhersteller Nvidia hat allerdings eine Erweiterung für OpenGL2 und Aufwärts zur verfügung gestellt, welche erlaubt die Speicheraddressen von den OpenGL Objekten ab zu fragen und diese in einen BuffeObjekt zu hinterlegen.&lt;br /&gt;
Wenn man nun alle logisch zusammengehörenden Objektaddressen in jeweils einen Buffer hinterlegt, dann kann man mit Hilfe dieses alle Bind Befehle auf einen einzigen reduzieren und somit den Flaschenhals auf ein anderen Bereich verschieben.&lt;br /&gt;
Dies ist allerdings noch eine Extension, wird aber wohl aufgrund seiner Einfachheit recht schnell in die ARB und dann in den OpenGL-Kern finden.&lt;br /&gt;
Bis dahin muss der Programmierer versuchen das Problem so stark wie möglich zu reduzieren.&lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt, ist OpenGL3 immer noch Statebasiert, was man sich zu nutze machen kann.&lt;br /&gt;
Wenn man z.B. alle genutzen Daten nach bestimmten Kriterien sortiert, kann man somit die Anzahl der Bindings und Stateänderungen reduzieren.&lt;br /&gt;
Im Laufe der einzelnen Artikel wird man noch die ein oder andere Möglichkeit sehen, weitere Optimierungen vor zu nehmen.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24124</id>
		<title>Tutorial OpenGL3 Das Objekt System von OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3&amp;diff=24124"/>
				<updated>2009-08-14T15:00:57Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: Die Seite wurde neu angelegt: „Seit OpenGL3 sind alle verwendbaren Daten in Objekten verpackt. Die OpenGL3 Bibliothek ist in c geschrieben und kennt daher keine Klassen, daher werden sogenannte…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seit OpenGL3 sind alle verwendbaren Daten in Objekten verpackt.&lt;br /&gt;
Die OpenGL3 Bibliothek ist in c geschrieben und kennt daher keine Klassen, daher werden sogenannte ID's zur Assoziation verwendet.&lt;br /&gt;
Wenn man also eine der Funktionen aufruft, die zur Erstellung eines Objektes zuständig ist, dann bekommt man eine 32Bit große, Vorzeichenlose Nummer zurück.&lt;br /&gt;
Diese sind nicht zwingend aufsteigend Nummeriert, sondern können vom Treiber frei gewählt werden. Die einzige Bedingung die gestellt wird, ist das die ID 0 nicht vergeben wird, denn diese wird vom Treiber automatisch am Start reserviert und ein Null-Objekt erzeugt.&lt;br /&gt;
Die Verwendung von Objekten Teilt sich in 4 Bereiche, Erstellung, Verändern, Verwenden und Vernichtung.&lt;br /&gt;
Da es verschiedene Typen von Objekten gibt, müssen diese auch Unterschieden werden können und unterschiedlich anwendbar sein.&lt;br /&gt;
Es gibt in OpenGL3 folgende Objekte:&lt;br /&gt;
*Buffer(auch als VBO bekannt)&lt;br /&gt;
*VertexArray&lt;br /&gt;
*Query&lt;br /&gt;
*Textur&lt;br /&gt;
*FrameBuffer(auch als FBO bekannt)&lt;br /&gt;
*Shader&lt;br /&gt;
*Program&lt;br /&gt;
&lt;br /&gt;
Für jeden Objekttyp gibt es eigene Funktionssammlungen für die 4 oben erwähnten Bereiche.&lt;br /&gt;
Durch eine Namenskonvention sind diese recht einfach zu erkennen.&lt;br /&gt;
So werden alle Befehle, zum erzeugen der Objekte wie folgt aufgebaut.&lt;br /&gt;
glGen[Objekttyp]s(Anzahl,Pointer auf ID-Array);&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
glGenTextures(1,&amp;amp;TextureID);&lt;br /&gt;
Die Zerstörung und das aktivieren eines Objektes wird auch über Namenskonventionen erleichtert.&lt;br /&gt;
glBind[Objekttyp](...,ID);//Anzahl und Typ der Parameter sind Unterschiedlich.&lt;br /&gt;
glDelete[Objekttyp]s(Anzahl,Pointer auf ID-Array);&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
glBindTexture(GL_TEXTURE_2D,TextureID);&lt;br /&gt;
glDeleteTexture(1,&amp;amp;TextureID);&lt;br /&gt;
&lt;br /&gt;
Sobald man ein Objekt, mit der zu den Objekttyp passenden Generierungs-Funktion erstellt, erhält man eine ID und diese kann man nun verwenden um z.B. ab zu fragen was das Objekt für ein Typ ist und ob es Aktiv ist.&lt;br /&gt;
bool glIs[Objekttyp](ID);&lt;br /&gt;
Als Beispiel folgendes:&lt;br /&gt;
if (glIsTexture(TextureID))&lt;br /&gt;
{...}//Objekt ist eine Textur.&lt;br /&gt;
else&lt;br /&gt;
{...}//Objekt ist keine Textur.&lt;br /&gt;
&lt;br /&gt;
Wenn nun statt einer erhaltenen ID die 0 bei einer OpenGL Funktion übergeben wird, dann zeigt man also auf das Null-Objekt, welches bei allen Objekt-Bind Befehlen zufolge hat, dass dieser Buffertyp als deaktiviert gilt.&lt;br /&gt;
Möchte man z.B. FrameBuffer abschalten, weil man diesen nicht mehr braucht, dann benutzt man den passenden Bind Befehl und setzt als ID die 0 ein.&lt;br /&gt;
&lt;br /&gt;
Um das ein bischen zu festigen kommt nun mal ein kleines Beispiel.&lt;br /&gt;
//Erstellung&lt;br /&gt;
GLuint TextureID=0;&lt;br /&gt;
glGenTextures(1,&amp;amp;TextureID);//Es wird ein Objekt erzeugt und die ID dieses Objektes in die TextureID Variable geschrieben.&lt;br /&gt;
//Weise Daten dem Objekt zu.&lt;br /&gt;
//...&lt;br /&gt;
//Zeichenroutine(Verwendung)&lt;br /&gt;
if (glIsTexture(TextureID))&lt;br /&gt;
{&lt;br /&gt;
  glEnable(GL_TEXTURE_2D);&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,TextureID);//Bindet das Objekt als OpenGL 2D-Textur.&lt;br /&gt;
  //...&lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D,0);&lt;br /&gt;
  glDisable(GL_TEXTURE_2D);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
//Aufräumen&lt;br /&gt;
glDeleteTextures(1,&amp;amp;TextureID);&lt;br /&gt;
&lt;br /&gt;
Ein Objekt bleibt solange Aktiv und/oder gebunden, bis ein anderes gebunden bzw. der Objektyp deaktiviert wurde.&lt;br /&gt;
Durch das ständige Binden,Aktivieren und Deaktivieren geht sehr viel Zeit verloren, die sich auf die Programmgeschwindigkeit auswirkt.&lt;br /&gt;
OpenGL war Ursprünglich eine Statemachiene, also etwas galt solange, bis es verändert wurden, dann galt der neue Zustand.&lt;br /&gt;
Dieses ist in OpenGL3 immer noch der Fall, allerdings in einer wesentlich abgeschwächten Form, da die meisten States schon entfernt werden konnten.&lt;br /&gt;
Das gleiche System findet auch bei der Objektverwaltung seinen Platz, was heute allerdings wenig Sinn macht.&lt;br /&gt;
Früher hat man beim Binden eine Hashtable verwendet, um aus der ID die dazugehörige Speicheradresse, der Objektdaten, auf im VideoRam zu ermitteln und im entsprechendem Globalen Variable zu setzen.&lt;br /&gt;
Dies hat die Leistung in den früheren OpenGL Versionen erhöht, da die Art, wie man gezeichnet hat eine ganz andere war, als wie heute.&lt;br /&gt;
Durch die generischen Buffer und der vom Entwickler bestimmten Shaderpipeline ist dieses ständige Binden zu dem Flaschenhals in der OpenGL3 Programmierung geworden.&lt;br /&gt;
Die ID's, die man von OpenGL bekommt sind allerdings nur 32Bit groß und die Speicheraddressen, passen nicht in die 32Bit.&lt;br /&gt;
Deshalb ist es bis jetzt noch nicht möglich, über die gegebene API das Problem zu lösen.&lt;br /&gt;
Man müsste also mit jeder Speicherbus Erweiterung, die eine Grafikkarte mit sich bringt, auch die API anpassen, was etwas Aufwand ist.&lt;br /&gt;
Der Grafikkartenhersteller Nvidia hat allerdings eine Erweiterung für OpenGL2 und Aufwärts zur verfügung gestellt, welche erlaubt die Speicheraddressen von den OpenGL Objekten ab zu fragen und diese in einen BuffeObjekt zu hinterlegen.&lt;br /&gt;
Wenn man nun alle logisch zusammengehörenden Objektaddressen in jeweils einen Buffer hinterlegt, dann kann man mit Hilfe dieses alle Bind Befehle auf einen einzigen reduzieren und somit den Flaschenhals auf ein anderen Bereich verschieben.&lt;br /&gt;
Dies ist allerdings noch eine Extension, wird aber wohl aufgrund seiner Einfachheit recht schnell in die ARB und dann in den OpenGL-Kern finden.&lt;br /&gt;
Bis dahin muss der Programmierer versuchen das Problem so stark wie möglich zu reduzieren.&lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt, ist OpenGL3 immer noch Statebasiert, was man sich zu nutze machen kann.&lt;br /&gt;
Wenn man z.B. alle genutzen Daten nach bestimmten Kriterien sortiert, kann man somit die Anzahl der Bindings und Stateänderungen reduzieren.&lt;br /&gt;
Im Laufe der einzelnen Artikel wird man noch die ein oder andere Möglichkeit sehen, weitere Optimierungen vor zu nehmen.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24117</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24117"/>
				<updated>2009-08-13T14:28:04Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    float m_Vec[4];&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Addition(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Subtraktion(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
float Betrag(){&lt;br /&gt;
  float len=0.0;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
float Skalarprodukt(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  float alpha=0.0;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector4Float Kreuzprodukt(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
  {&lt;br /&gt;
    if (i==0)&lt;br /&gt;
      prev=3;&lt;br /&gt;
    else&lt;br /&gt;
      prev=i-1;&lt;br /&gt;
    next=i+1 % 4;//i+1 Modulog 4&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Normalisieren(){&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Betrag();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    TVector4Float m_Matrix[4]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    float m_Array[16]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    TVector4Float&amp;amp; Vektor(int Index)//Gibt eine Referenz vom Vektor zurück, was wie ein Pointer ist aber 100% auf ein Speicher zeigt, der existiert.&lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    T* GetMatrix1DArray()//Liefert den Pointer von der m_Array variable zurück.&lt;br /&gt;
    { &lt;br /&gt;
      //Überträgt die Daten von den einzelnen Vektoren in die OpenGL kompatible Matrix(m_Array).&lt;br /&gt;
      for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],16);&lt;br /&gt;
      return &amp;amp;m_Array[0];//Gibt den Pointer auf m_Array zurück.&lt;br /&gt;
    }&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
void Transponieren()&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix.Vektor(0).m_Vec[1],m_Matrix.Vektor(1).m_Vec[0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix.Vektor(0).m_Vec[2],m_Matrix.Vektor(2).m_Vec[0]); &lt;br /&gt;
  swap(m_Matrix.Vektor(0).m_Vec[3],m_Matrix.Vektor(3).m_Vec[0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix.Vektor(1).m_Vec[2],m_Matrix.Vektor(2).m_Vec[1]); &lt;br /&gt;
  swap(m_Matrix.Vektor(1).m_Vec[3],m_Matrix.Vektor(3).m_Vec[1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix.Vektor(2).m_Vec[3],m_Matrix.Vektor(3).m_Vec[2]); &lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Multipliziere(TVector4Float V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector4Float v=m_Matrix.Vektor(0)*V.m_Vec[0]+m_Matrix.Vektor(1)*V.m_Vec[1]+m_Matrix.Vektor(2)*V.m_Vec[2]+m_Matrix.Vektor(3)*V.m_Vec[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
TMatrix4x4Float Multiplikation(TMatrix4x4Float M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix4x4Float M1((*this)*M.Vektor(0)), (*this)*M.Vektor(1), (*this)*M.Vektor(2), (*this)*M.Vektor(3)); &lt;br /&gt;
  return M1;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
static TVector4Float Identity[4];//Statische Variable, welche nur einmal existiert.&lt;br /&gt;
&lt;br /&gt;
void LadeIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix.Vektor(i)=Identity.m_Vec[i];&lt;br /&gt;
}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
TVector4Float TMatrix4x4Float::Identity[4]={TVector4Float(1.0,0.0,0.0,0.0),TVector4Float(0.0,1.0,0.0,0.0),TVector4Float(0.0,0.0,1.0,0.0),TVector4Float(0.0,0.0,0.0,1.0)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
void Translate(float x,float y,float z)&lt;br /&gt;
{&lt;br /&gt;
  TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
  m.Vektor(3).m_Vec[0]=x;&lt;br /&gt;
  m.Vektor(3).m_Vec[1]=y;&lt;br /&gt;
  m.Vektor(3).m_Vec[2]=z;&lt;br /&gt;
  (*this)*=m;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;x = cos(ß)&lt;br /&gt;
y = sin(ß)&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;x = -sin(ß)&lt;br /&gt;
y = cos(ß)&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TMatrix4x4Float&lt;br /&gt;
{ &lt;br /&gt;
//...&lt;br /&gt;
void Rotiere(float w,float x,float y,float z)&lt;br /&gt;
{&lt;br /&gt;
  TMatrix4Float m;&lt;br /&gt;
  float rad=DegToRad(w);&lt;br /&gt;
  float c=cos(rad);&lt;br /&gt;
  float ic=1.0-c;&lt;br /&gt;
  float s=sin(rad);&lt;br /&gt;
  TVector4Float v(x,y,z,0.0);&lt;br /&gt;
  float mag=sqrt((v*v).Summe());&lt;br /&gt;
&lt;br /&gt;
  if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
    return;&lt;br /&gt;
&lt;br /&gt;
  v.m_Vec[0]=x/mag;&lt;br /&gt;
  v.m_Vec[1]=y/mag;&lt;br /&gt;
  v.m_Vec[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
  m.Vektor(0).m_Vec[0]=(v.m_Vec[0]*v.m_Vec[0]*ic)+c;&lt;br /&gt;
  m.Vektor(0).m_Vec[1]=(v.m_Vec[0]*v.m_Vec[1]*ic)+(v.m_Vec[2]*s);&lt;br /&gt;
  m.Vektor(0).m_Vec[2]=(v.m_Vec[0]*v.m_Vec[2]*ic)-(v.m_Vec[1]*s);&lt;br /&gt;
&lt;br /&gt;
  m.Vektor(1).m_Vec[0]=(v.m_Vec[0]*v.m_Vec[1]*ic)-(v.m_Vec[2]*s);&lt;br /&gt;
  m.Vektor(1).m_Vec[1]=(v.m_Vec[1]*v.m_Vec[1]*ic)+c;&lt;br /&gt;
  m.Vektor(1).m_Vec[2]=(v.m_Vec[1]*v.m_Vec[2]*ic)+(v.m_Vec[0]*s);&lt;br /&gt;
&lt;br /&gt;
  m.Vektor(2).m_Vec[0]=(v.m_Vec[0]*v.m_Vec[2]*ic)+(v.m_Vec[1]*s);&lt;br /&gt;
  m.Vektor(2).m_Vec[1]=(v.m_Vec[1]*v.m_Vec[2]*ic)-(v.m_Vec[0]*s);&lt;br /&gt;
  m.Vektor(2).m_Vec[2]=(v.m_Vec[2]*v.m_Vec[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
  *this*=m;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Im rechten Bild kann man 2 aufeinander folgende Befehlsketten sehen, die Transformationen auf ein Objekt ausführen. Dieses Bild soll nocheinmal verdeutlichen, dass das Anwenden von Befehlen, auf eine Modelview Matrix nicht Kommultativ(a*b ist nicht das gleiche wie b*a) ist.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
Die Projektions Matrix oder auch Projectionview genannt ist die 2. wichtige Matrix in der Renderpipeline.&lt;br /&gt;
Diese Matrix macht den ganzen Zauber, der Umwandlung von 3D in 2D erst möglich.&lt;br /&gt;
Wenn die Vertice mit der Modelview Matrix multipliziert wurden, wird nun das Ergebnis mit der Projektions Matrix multipliziert und wir erhalten Vektoren, dessen X und Y Komponente den Bildischrmpunkten entsprechen. Die 2 am häufigsten genutzten Matrizen sind die Perspektivische- und die Orthogonale Ansicht.&lt;br /&gt;
&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Perspektivische Ansicht ist eine drei Dimmensional wirkende Ansicht, welche durch mehrere Faktoren beeinflusst wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
aspect steht für aspect ratio und beschreibt das Bildverhältnis von Höhe und Breite.&lt;br /&gt;
Diese ist sehr leicht herraus zu finden, man dividiert einfach die Breite durch die Höhe, wenn man die Renderausgabe von der Bildschirmbreite abhängig machen möchte oder umgekerht, für die Bildschirmhöhe.&lt;br /&gt;
f kann durch folgende Formel berechnet werden und bestimmt den Blickwinkel, welcher alle x und y Koordinaten zusammen staucht oder auseinander zieht. Dies erkennt man recht schnell, wenn man sich an die Skalierungsmatrix erinnert und das eine Multiplikation mit einem Vektor die x und y Komponenten skaliert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:sichtwinkel.png]]&lt;br /&gt;
&lt;br /&gt;
zNear und zFar sind die Abstände, der Near- und Far-Clipping Plane, zur Kamera. Alle Objekte, die den Raum, zwischen beiden Ebenen nicht schneidet, wird verworfen und der rest durchläuft die restliche Renderpipeline. Die Thematik wird in einem späterem Artikel näher erläutet.&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Orthogonale Ansicht ist eine zwei Dimmensionale Ansicht, welche wie die gewöhnlichen Desktopsysteme wirkt.&lt;br /&gt;
Hierbei werden die Z Koordinaten nicht zur Verschiebung der Bildpunkte, in der Tiefe verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen.&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Multiplikation(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;class TVector4Float&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector4Float Division(TVector4Float b)&lt;br /&gt;
{&lt;br /&gt;
  TVector4Float c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24102</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24102"/>
				<updated>2009-08-08T11:11:34Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Inhaltsverzeichnis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Diese Artikel Reihe richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Inhaltsverzeichnis==&lt;br /&gt;
===Grundlagen===&lt;br /&gt;
Artikel in diesem Bereich sind für OpenGL wichtig aber haben nicht direkt mit OpenGL zu tun.&lt;br /&gt;
&lt;br /&gt;
Man kann diese Artikel überspringen und später bei aufkommenden Fragen in diese hinein lesen.&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_Lineare_Algebra|Lineare Algebra]]&lt;br /&gt;
===Artikelreihe===&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Vorschau auf das kommende]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_Zeichenkontext|Erstellen eines Grafik Kontext]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Das Objekt System von OpenGL3]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Vertex Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Verfügbare Geometrie]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|GLSLang]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Geometryshader]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Transform Feedback]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Texturen]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Frame Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Scissor/Clipping]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Instancing]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Oclussion Query]]&lt;br /&gt;
&lt;br /&gt;
[[Tutorial_OpenGL3_dead|Conditional Rendering]]&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24100</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24100"/>
				<updated>2009-08-07T22:49:09Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Im rechten Bild kann man 2 aufeinander folgende Befehlsketten sehen, die Transformationen auf ein Objekt ausführen. Dieses Bild soll nocheinmal verdeutlichen, dass das Anwenden von Befehlen, auf eine Modelview Matrix nicht Kommultativ(a*b ist nicht das gleiche wie b*a) ist.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
Die Projektions Matrix oder auch Projectionview genannt ist die 2. wichtige Matrix in der Renderpipeline.&lt;br /&gt;
Diese Matrix macht den ganzen Zauber, der Umwandlung von 3D in 2D erst möglich.&lt;br /&gt;
Wenn die Vertice mit der Modelview Matrix multipliziert wurden, wird nun das Ergebnis mit der Projektions Matrix multipliziert und wir erhalten Vektoren, dessen X und Y Komponente den Bildischrmpunkten entsprechen. Die 2 am häufigsten genutzten Matrizen sind die Perspektivische- und die Orthogonale Ansicht.&lt;br /&gt;
&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Perspektivische Ansicht ist eine drei Dimmensional wirkende Ansicht, welche durch mehrere Faktoren beeinflusst wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
aspect steht für aspect ratio und beschreibt das Bildverhältnis von Höhe und Breite.&lt;br /&gt;
Diese ist sehr leicht herraus zu finden, man dividiert einfach die Breite durch die Höhe, wenn man die Renderausgabe von der Bildschirmbreite abhängig machen möchte oder umgekerht, für die Bildschirmhöhe.&lt;br /&gt;
f kann durch folgende Formel berechnet werden und bestimmt den Blickwinkel, welcher alle x und y Koordinaten zusammen staucht oder auseinander zieht. Dies erkennt man recht schnell, wenn man sich an die Skalierungsmatrix erinnert und das eine Multiplikation mit einem Vektor die x und y Komponenten skaliert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:sichtwinkel.png]]&lt;br /&gt;
&lt;br /&gt;
zNear und zFar sind die Abstände, der Near- und Far-Clipping Plane, zur Kamera. Alle Objekte, die den Raum, zwischen beiden Ebenen nicht schneidet, wird verworfen und der rest durchläuft die restliche Renderpipeline. Die Thematik wird in einem späterem Artikel näher erläutet.&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Orthogonale Ansicht ist eine zwei Dimmensionale Ansicht, welche wie die gewöhnlichen Desktopsysteme wirkt.&lt;br /&gt;
Hierbei werden die Z Koordinaten nicht zur Verschiebung der Bildpunkte, in der Tiefe verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen.&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24099</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24099"/>
				<updated>2009-08-07T22:44:23Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Projectionview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Im rechten Bild kann man 2 aufeinander folgende Befehlsketten sehen, die Transformationen auf ein Objekt ausführen. Dieses Bild soll nocheinmal verdeutlichen, dass das Anwenden von Befehlen, auf eine Modelview Matrix nicht Kommultativ(a*b ist nicht das gleiche wie b*a) ist.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
Die Projektions Matrix oder auch Projectionview genannt ist die 2. wichtige Matrix in der Renderpipeline.&lt;br /&gt;
Diese Matrix macht den ganzen Zauber, der Umwandlung von 3D in 2D erst möglich.&lt;br /&gt;
Wenn die Vertice mit der Modelview Matrix multipliziert wurden, wird nun das Ergebnis mit der Projektions Matrix multipliziert und wir erhalten Vektoren, dessen X und Y Komponente den Bildischrmpunkten entsprechen. Die 2 am häufigsten genutzten Matrizen sind die Perspektivische- und die Orthogonale Ansicht.&lt;br /&gt;
&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Perspektivische Ansicht ist eine drei Dimmensional wirkende Ansicht, welche durch mehrere Faktoren beeinflusst wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
aspect steht für aspect ratio und beschreibt das Bildverhältnis von Höhe und Breite.&lt;br /&gt;
Diese ist sehr leicht herraus zu finden, man dividiert einfach die Breite durch die Höhe, wenn man die Renderausgabe von der Bildschirmbreite abhängig machen möchte oder umgekerht, für die Bildschirmhöhe.&lt;br /&gt;
f kann durch folgende Formel berechnet werden und bestimmt den Blickwinkel, welcher alle x und y Koordinaten zusammen staucht oder auseinander zieht. Dies erkennt man recht schnell, wenn man sich an die Skalierungsmatrix erinnert und das eine Multiplikation mit einem Vektor die x und y Komponenten skaliert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:sichtwinkel.png]]&lt;br /&gt;
&lt;br /&gt;
zNear und zFar sind die Abstände, der Near- und Far-Clipping Plane, zur Kamera. Alle Objekte, die den Raum, zwischen beiden Ebenen nicht schneidet, wird verworfen und der rest durchläuft die restliche Renderpipeline. Die Thematik wird in einem späterem Artikel näher erläutet.&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Orthogonale Ansicht ist eine zwei Dimmensionale Ansicht, welche wie die gewöhnlichen Desktopsysteme wirkt.&lt;br /&gt;
Hierbei werden die Z Koordinaten nicht zur Verschiebung der Bildpunkte, in der Tiefe verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen.&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24098</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24098"/>
				<updated>2009-08-07T22:43:44Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: Änderung 24097 von TAK2004 (Diskussion) wurde rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Im rechten Bild kann man 2 aufeinander folgende Befehlsketten sehen, die Transformationen auf ein Objekt ausführen. Dieses Bild soll nocheinmal verdeutlichen, dass das Anwenden von Befehlen, auf eine Modelview Matrix nicht Kommultativ(a*b ist nicht das gleiche wie b*a) ist.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24097</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24097"/>
				<updated>2009-08-07T22:43:13Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Projectionview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Projectionview==&lt;br /&gt;
Die Projektions Matrix oder auch Projectionview genannt ist die 2. wichtige Matrix in der Renderpipeline.&lt;br /&gt;
Diese Matrix macht den ganzen Zauber, der Umwandlung von 3D in 2D erst möglich.&lt;br /&gt;
Wenn die Vertice mit der Modelview Matrix multipliziert wurden, wird nun das Ergebnis mit der Projektions Matrix multipliziert und wir erhalten Vektoren, dessen X und Y Komponente den Bildischrmpunkten entsprechen. Die 2 am häufigsten genutzten Matrizen sind die Perspektivische- und die Orthogonale Ansicht.&lt;br /&gt;
&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Perspektivische Ansicht ist eine drei Dimmensional wirkende Ansicht, welche durch mehrere Faktoren beeinflusst wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
aspect steht für aspect ratio und beschreibt das Bildverhältnis von Höhe und Breite.&lt;br /&gt;
Diese ist sehr leicht herraus zu finden, man dividiert einfach die Breite durch die Höhe, wenn man die Renderausgabe von der Bildschirmbreite abhängig machen möchte oder umgekerht, für die Bildschirmhöhe.&lt;br /&gt;
f kann durch folgende Formel berechnet werden und bestimmt den Blickwinkel, welcher alle x und y Koordinaten zusammen staucht oder auseinander zieht. Dies erkennt man recht schnell, wenn man sich an die Skalierungsmatrix erinnert und das eine Multiplikation mit einem Vektor die x und y Komponenten skaliert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:sichtwinkel.png]]&lt;br /&gt;
&lt;br /&gt;
zNear und zFar sind die Abstände, der Near- und Far-Clipping Plane, zur Kamera. Alle Objekte, die den Raum, zwischen beiden Ebenen nicht schneidet, wird verworfen und der rest durchläuft die restliche Renderpipeline. Die Thematik wird in einem späterem Artikel näher erläutet.&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Orthogonale Ansicht ist eine zwei Dimmensionale Ansicht, welche wie die gewöhnlichen Desktopsysteme wirkt.&lt;br /&gt;
Hierbei werden die Z Koordinaten nicht zur Verschiebung der Bildpunkte, in der Tiefe verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:sichtwinkel.png&amp;diff=24096</id>
		<title>Datei:sichtwinkel.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:sichtwinkel.png&amp;diff=24096"/>
				<updated>2009-08-07T22:31:47Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24095</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24095"/>
				<updated>2009-08-07T19:57:06Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Modelview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Im rechten Bild kann man 2 aufeinander folgende Befehlsketten sehen, die Transformationen auf ein Objekt ausführen. Dieses Bild soll nocheinmal verdeutlichen, dass das Anwenden von Befehlen, auf eine Modelview Matrix nicht Kommultativ(a*b ist nicht das gleiche wie b*a) ist.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24094</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24094"/>
				<updated>2009-08-07T19:53:25Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Modelview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
=Vom Vektor zur Bildschirmkoordinate=&lt;br /&gt;
Auf in den Endspurt!&lt;br /&gt;
Alle Mathematischen Formeln und Funktionen benötigen wir um die letzten 2 Punkte behandeln zu können.&lt;br /&gt;
Die Rede ist von der Umwandlung eines Vektors im 3D Raum in den 2D Raum, auf dem Bildschirm.&lt;br /&gt;
In Rahmen dieses Artikel wird nur auf die Transformation der Vektoren eingegangen und in einem späterem Artikel dann die weiteren Zwischenschritte zum Zeichnen einer Geometrie.&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
Die Modelview kann man sich wie ein 3D Unterraum vorstellen oder einer Transformation des Raumes. Die Modelview sorgt dafür, dass alle Vektoren, die mit dieser Multipliziert werden zu dieser Modelview ausgerichtet werden und die Modelview ist relativ zur Welt ausgerichtet. Dies bedeutet, wenn man für jedes Objekt eine Modelview erzeugt, dann kann dieses Objekt relativ zur Welt ausgerichtet werden, sobald man die Vektoren des Objektes mit der Modelview multipliziert. Wieso richtet man die Vektoren nicht gleich zur Welt aus, statt den Umweg über die Modelview Matrix zu gehen ? Die Antwort ist schlicht &amp;quot;Optimierung&amp;quot;. Es wäre zu langsam, wenn man jeden Renderdurchgang jedes einzelne Vertex im Speicher lesen müsste, die neue Position berechnen, im Speicher updaten und in der Pipeline weiter zu arbeiten. Es ist auch Speichereffizienter, da z.B. gleiche Objekte nur einmal in den Speicher abgelegt werden müssen und nur 2 unterschiedliche Modelview Matrizen benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Während vor OpenGL3 die Modelview Matrix von den OpenGL Treibern verwaltet wurde, muss dies ab OpenGL3 vom User gemacht werden und auch das aktualisieren in der Renderpipeline muss nun vom Entwickler übernommen werden, wie dies funktioniert wird in einem späteren Artikel erklärt. Es ist nur noch wichtig zu sagen, dass die GPU diese Matrix mit jeden Vertex multipliziert, der durch dir Renderpipeline geschickt wird.&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24093</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24093"/>
				<updated>2009-08-07T19:25:55Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Scale */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Skalierung ist eine sehr einfache Matrix, in der für die 1, des Einheitsvektors, der entsprechende Skalierungsfaktor angegeben wird. Wenn man die Matrix mit einem Vektor multipliziert, dann werden X,Y und Z des Vektors mit den x,y und z Werten in der Skalierungsmatrix multipliziert und damit skaliert. Wenn man etwas größer machen will, dann wird der Wert entsprechend über 1.0 gewählt, z.B. 2.0 wäre doppelte größe und für verkleinern würde man ein Wert zwischen 1.0 und 0.0 wählen. Der Wert 0.5 würde z.B. eine Division durch 2 bedeuten, also 3*0.5=1.5. Der 4. Einheitsvektor wird belassen, da wir diesen nur als Kompatibilität zu den 4Komponenten Vektoren benötigen.&lt;br /&gt;
&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24092</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24092"/>
				<updated>2009-08-07T19:16:20Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Konstruieren von Matrizen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24091</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24091"/>
				<updated>2009-08-07T19:15:11Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: Änderung 24090 von TAK2004 (Diskussion) wurde rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24090</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24090"/>
				<updated>2009-08-07T19:13:40Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Rotate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Der Z-Achsen Einheitsvektor(3. Spalte=0.0, 0.0, 1.0, 0.0) bleibt bei der Rotation unverändert - man nehme einen Finger, deute damit nach vorne. Nun drehe man diesen Finger um seine eigene Achse, wohin zeigt er? In die selbe Richtung wie vor der Drehung? Damit entspricht Z-Achsen Einheitsvektor auch der vorletzen Spalte der Matrix: (0.0, 0.0, 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Der X-Achsen Einheitsvektor(1. Spalte=1.0, 0.0, 0.0 0.0) dreht sich hingegen mit. Trigonometrie findet der Lösung Spur. Ein Blick auf das Bild zum Einheitskreis zeigt, dass wir gerade das gleiche Problem für X und Y zu bewältigen haben: Die Rotationsachse ist in beiden Fällen die Z-Achse. Der Einheitsvektor, der gedreht wird, ist der X-Achsen Einheitsvektor also:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = cos(ß)&lt;br /&gt;
y = sin(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
womit der Inhalt der ersten Spalte der Matrix kennen: (cos(ß), sin(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Dies kann man auch auf den Y-Achsen Einheitsvektor(2. Spalte=0.0, 1.0, 0.0, 0.0) übertragen, man muss nur bedenken in welcher weise sich x und y vertauschen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
x = -sin(ß)&lt;br /&gt;
y = cos(ß)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So ergibt sich für die zweite Spalte: (-sin(ß), cos(ß), 0.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
Nun kann man die Rotationsmatrix für die Rotation auf der Z-Achse beschreiben, die Matrix findet man am Anfang des Abschnittes.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Die Berechnung der Matrix wird auf die gleiche weise ermittelt, wie bei der Berechnung der Z-Achsen Rotationsmatrix.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Rotation um alle Achsen mit einer Matrix===&lt;br /&gt;
&lt;br /&gt;
Es ist recht aufwändig für die CPU und für den Programmierer immer 3 Rotationen aus zu führen, deswegen hat man diese auch zu einer einzigen Operation zusammen gefasst. Die Matrizen werden einfach miteinander multipliziert und es kommt eine Rotationsmatrix herraus, welche 3 Eingabeparameter benötigt, alpha, beta und gamma sind dabei die Winkel für X-,Y- und Z-Achse.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix_3angle.png]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, um eine Rotationsmatrix zu erstellen, wäre das nutzen eines Richtungsvektors und einem Winkel. Hierbei wird der Winkel auf den Richtungsvektor angewendet, wenn also man als Vektor (1,0,0) verwendet dann hat man eine Rotation auf der X-Achse, (0,1,0) Y-Achse und (0,0,1) für die Z-Achse. Man kann nun auch Vektoren wie (1,1,1) angeben, wobei die Funktion diesen Vektor dann normalisieren wird, damit er noch auf das Einheitskreis System funktioniert. Dieser Vektor ist nicht equivalent mit dem Rotieren von X-,Y- und Z-Achse nacheinander. Der Vorteil hierbei liegt in der Kompaktheitund des Codes und man kann auf Algorithmen zurück greifen, die vor OpenGL3 entwickelt wurden, da der OpenGL Treiber früher die Rotation über diese Variante Implementiert hatte.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix_3angle.png&amp;diff=24089</id>
		<title>Datei:rotationsmatrix 3angle.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix_3angle.png&amp;diff=24089"/>
				<updated>2009-08-07T17:40:36Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24085</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24085"/>
				<updated>2009-08-06T16:08:25Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Diese Artikel Reihe richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Inhaltsverzeichnis==&lt;br /&gt;
1.OpenGL3 und die Vorgeschichte&lt;br /&gt;
&lt;br /&gt;
2.[[Tutorial_OpenGL3_Lineare_Algebra|Lineare Algebra]]&lt;br /&gt;
&lt;br /&gt;
3.[[Tutorial_OpenGL3_Zeichenkontext|Erstellen eines Grafik Kontext]]&lt;br /&gt;
&lt;br /&gt;
4.[[Tutorial_OpenGL3_dead|Das Objekt System von OpenGL3]]&lt;br /&gt;
&lt;br /&gt;
5.[[Tutorial_OpenGL3_dead|Vertex Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
6.[[Tutorial_OpenGL3_dead|Verfügbare Geometrie]]&lt;br /&gt;
&lt;br /&gt;
7.[[Tutorial_OpenGL3_dead|GLSLang]]&lt;br /&gt;
&lt;br /&gt;
8.[[Tutorial_OpenGL3_dead|Geometryshader]]&lt;br /&gt;
&lt;br /&gt;
9.[[Tutorial_OpenGL3_dead|Transform Feedback]]&lt;br /&gt;
&lt;br /&gt;
10.[[Tutorial_OpenGL3_dead|Texturen]]&lt;br /&gt;
&lt;br /&gt;
11.[[Tutorial_OpenGL3_dead|Frame Buffer Object]]&lt;br /&gt;
&lt;br /&gt;
12.[[Tutorial_OpenGL3_dead|Scissor/Clipping]]&lt;br /&gt;
&lt;br /&gt;
13.[[Tutorial_OpenGL3_dead|Instancing]]&lt;br /&gt;
&lt;br /&gt;
14.[[Tutorial_OpenGL3_dead|Oclussion Query]]&lt;br /&gt;
&lt;br /&gt;
15.[[Tutorial_OpenGL3_dead|Conditional Rendering]]&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Zeichenkontext&amp;diff=24084</id>
		<title>Tutorial OpenGL3 Zeichenkontext</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Zeichenkontext&amp;diff=24084"/>
				<updated>2009-08-06T16:00:36Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: Die Seite wurde neu angelegt: „==Der Grafikcontext== Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht. Im GC werden alle …“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Der Grafikcontext==&lt;br /&gt;
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht.&lt;br /&gt;
Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten, dabei werden Identifier(ID) verwendet, um Resourcen nach außen Verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt.&lt;br /&gt;
Neben den ID-Listen werden noch sogenannte States, Informationen für die Bildausgabe und diverse unbekannte treiberspezifische Daten gespeichert.&lt;br /&gt;
&lt;br /&gt;
===Profil===&lt;br /&gt;
Um die einzelnen Befehlssätze zu Verwalten hat man sogenannte Profile eingeführt.&lt;br /&gt;
OpenGL3 ist z.B. ein Profil, es gibt noch weitere Profile wie z.B. OpenGL3.1 oder OpenGL3.1 Debug.&lt;br /&gt;
Die Profile werden vom ARB fest gelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als &amp;quot;deprecated&amp;quot; eingestuft wurden, und einmal mit diesen.&lt;br /&gt;
&lt;br /&gt;
===Forward compatible context und Full context===&lt;br /&gt;
Es gibt 2 Varianten eines Context, der Full context ist enthält alle Funktionen, auch die als deprecated maktierten. Der Forward compatible context enthält nur die nicht als deprecated markierten Funktionen des OpenGL Kerns. Bis zur Version 3.1 gab es immer eine abwärts Kompatibilität und der Treiber hatte entschieden, welche OpenGL Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine abwärts Kompatibilität mehr und man kann festlegen, was für ein GC man haben möchte.&lt;br /&gt;
&lt;br /&gt;
===Verwaltung der veralteten und neuen Funktionen===&lt;br /&gt;
Das hinzukommen und das entfernen von OpenGL Funktionen unterliegt dem Deprecation und Extension Mechanismus.&lt;br /&gt;
Diese funktionieren wie folgt.&lt;br /&gt;
&lt;br /&gt;
'''Deprecation Path''': Core-&amp;gt;ARB-&amp;gt;Vendor/Extension&lt;br /&gt;
&lt;br /&gt;
Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur verfügung gestellt.&lt;br /&gt;
Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt.&lt;br /&gt;
Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet.&lt;br /&gt;
&lt;br /&gt;
'''Extension Path''': Vendor/Extension-&amp;gt;ARB-&amp;gt;Core&lt;br /&gt;
&lt;br /&gt;
Wenn eine Extension, von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen.&lt;br /&gt;
Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL Version in den Kern aufgenommen.&lt;br /&gt;
&lt;br /&gt;
OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiter Entwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. Transform Feedback, Instancing oder GLSlang 1.4 .&lt;br /&gt;
&lt;br /&gt;
=Der erste Schritt(Garphic Context)=&lt;br /&gt;
Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen, vom Desktop Manager, welche Möglichkeiten wir überhaupt zur Auswahl haben. Es wird ein Double Buffer benötigt und man muss die Farbtiefe sowie Tiefenpuffer Genauigkeit festlegen. Dies wird von den Desktop Managern unterschiedlich gehandhabt, so hat Windows z.B. ein DeviceContext und ein Pixelformat und X11 nennt dies VisualInfo bzw. GLXFBConfig.&lt;br /&gt;
Ist dieser Schritt getan kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen.&lt;br /&gt;
&lt;br /&gt;
==Erstellung eines OpenGL3.x GC==&lt;br /&gt;
Um ein GC ertellen zu können wird eine weitere API benötigt, welche plattformabhängig und durch wgl[Funktionsname]/glX[Funktionsname] erkennbar ist. Mit diesen Befehlen kann man mit den Windows und X11 Desktop Manager zusammen arbeiten. So werden Funktionen für das erstellen, wechseln, zerstören eines GC, laden von Extension, wechseln des Fensterpuffern und Synchronisieren von CPU und GPU ermöglicht. Bisher gibt es noch keine Möglichkeit einen OpenGL3 fähigen GC zu erstellen, ohne dafür eine Funktion vom ARB zu verwenden. Der Nachteil von ARB Funktionen sind, dass man einen gültigen GC benötigt den Zeiger auf diese zu erhalten. Um einen OpenGL 3.0 oder 3.1 GC zu erstellen benötigt man einen OpenGL1-2 GC und die Kernfunktion [[wglGetProcAddress]]/[[glxGetProcAddress]]. Einen gültigen OpenGL1 bzw. OpenGL2 GC bekommt man über den Befehl [[wglCreateContext]]/[[glxCreateContext]] und zwischen mehreren GC kann man mit dem Befehl [[wglMakeCurrent]]/[[glxMakeCurrent]] wechseln.&lt;br /&gt;
Der Befehl für die Erstellung eines OpenGL3 fähigen GC heisst [[wglCreateContextAttribsARB]]/[[glxCreateContextAttribsARB]].&lt;br /&gt;
Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, in dem man die noch jetzige ARB Funktion in den OpenGL-Kern mit aufnimmt und somit das erfragen der ARB Funktion, über ein OpenGL1-2GC, unnötig macht.&lt;br /&gt;
&lt;br /&gt;
'''Windows'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void CreateOpenGL3Context()&lt;br /&gt;
{&lt;br /&gt;
  HGLRC TempContext=wglCreateContext(DeviceContext);//erstellt ein alten OpenGL Context&lt;br /&gt;
  if (TempContext==NULL)&lt;br /&gt;
  {&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;//beenden&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,TempContext);//setzt den erstellten GC als aktuellen GC&lt;br /&gt;
&lt;br /&gt;
  //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
  typedef HGLRC (APIENTRY * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int *attribList);&lt;br /&gt;
&lt;br /&gt;
  PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;&lt;br /&gt;
&lt;br /&gt;
  //abfragen, ob die Funktion existiert&lt;br /&gt;
  wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(&amp;quot;wglCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if(wglCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
  {&lt;br /&gt;
    wglDeleteContext(TempContext);&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int attribs[]={WGL_CONTEXT_MAJOR_VERSION_ARB,3,WGL_CONTEXT_MINOR_VERSION_ARB,1,WGL_CONTEXT_FLAGS_ARB,WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
&lt;br /&gt;
  if (!(Context=wglCreateContextAttribsARB(DeviceContext,0, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen&lt;br /&gt;
  {&lt;br /&gt;
    //Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  &lt;br /&gt;
    attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
    if (!(Context=wglCreateContextAttribsARB(Win-&amp;gt;GetDeviceContext(),0, attribs)))&lt;br /&gt;
    {&lt;br /&gt;
      //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
      wglDeleteContext(TempContext);//aufräumen und beenden&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,Context);//wechsel auf den OpenGL3.x context&lt;br /&gt;
  wglDeleteContext(TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''X11(Linux/Mac OS)'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void CreateOpenGL3Context()&lt;br /&gt;
{&lt;br /&gt;
  GLXContex TempContext=glXCreateContext(Display,VisualInfo,NULL,true);//erstellt ein alten OpenGL Context&lt;br /&gt;
  if (TempContext==NULL)&lt;br /&gt;
  {&lt;br /&gt;
    cout&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
  glXMakeCurrent(Display,Handle,TempContext);//setzt den erstellten GC als aktuellen GC&lt;br /&gt;
&lt;br /&gt;
  //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
  typedef HGLRC (APIENTRY * PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display *dpy,GLXFBConfig config,GLXContext share_context,Bool direct,const int *attrib_list);&lt;br /&gt;
&lt;br /&gt;
  PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = NULL;&lt;br /&gt;
&lt;br /&gt;
  //abfragen, ob die Funktion existiert&lt;br /&gt;
  glXCreateContextAttribsARB=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(&amp;quot;glXCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if(glXCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
  {&lt;br /&gt;
    glXDeleteContext(TempContext);&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int attribs[]={GLX_CONTEXT_MAJOR_VERSION_ARB,3,GLX_CONTEXT_MINOR_VERSION_ARB,1,GLX_CONTEXT_FLAGS_ARB,GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
&lt;br /&gt;
  if (!(Context=glXCreateContextAttribsARB(Display, FBConfig, NULL, true, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen&lt;br /&gt;
  {&lt;br /&gt;
    //Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  &lt;br /&gt;
    attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
    if (!(Context=glXCreateContextAttribsARB(Display, FBConfig, NULL, true, attribs)))&lt;br /&gt;
    {&lt;br /&gt;
      //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
      glXDeleteContext(TempContext);//aufräumen und beenden&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  glXMakeCurrent(Display,Handle,TempContext);//wechsel auf den OpenGL3.x context&lt;br /&gt;
  glXDeleteContext(Display,TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24083</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24083"/>
				<updated>2009-08-06T16:00:19Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Der Grafikcontext */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Dieser Artikel richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
=Grundlagen=&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Die Render Pipeline==&lt;br /&gt;
{{Hinweis|Dieser Abschnitt ist für Erfahrende OpenGL Entwickler gedacht, die nochmal Nachschlagen wollen oder ein schnellen Einstieg in OpenGL3 suchen. Es wird ein hoher Grad an Vorwissen vorraus gesetzt, erklärt aber dafür wesentlich kompakter und tiefgehender die Funktionalität von OpenGL3. Wer noch keine oder wenig Erfahrung mit OpenGL hat, der sollte dieses Punkt überspringen und am Ende des Artikel dann hier rein schauen.}}&lt;br /&gt;
&lt;br /&gt;
OpenGL 3 sieht folgende Pipeline vor.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OGL3Pipeline.png]]&lt;br /&gt;
&lt;br /&gt;
Diese Darstellung ist noch weiter zerlegbar aber momentan reicht dieser Grad an Genauigkeit aus.&lt;br /&gt;
Am Anfang der Pipeline stehen die Vertexdaten, diese werden über ein Vertex Buffer Object(VBO) oder über ein Vertex Array(VA) übergeben.&lt;br /&gt;
Ein VBO ist ein Stück Speicher, in den Daten hinterlegt werden können, egal ob Vertice, Normalen oder Userdaten.&lt;br /&gt;
Man weist dann Teile des Buffers Variablen, im Vertex/Fragment Shader, zu und kann somit eine Interpretation der Daten realisieren.&lt;br /&gt;
Die zuweisung, auf ein Shader Attribut wird über VA realisiert, es bildet hierbei die Brücke.&lt;br /&gt;
Bei einem VBO gibt es 2 Typen, einmal Element und einmal Vertice, es kann nur ein Element Buffer verwendet werden aber mehrere Vertice Buffer.&lt;br /&gt;
Der Element Buffer enhält Indices und unterliegt im vergelich zum Vertex Buffer keiner besonderen Regel.&lt;br /&gt;
Die Vertex Buffer hingegen müssen die gleiche länge besitzen, was bedeutet, wenn im einen Vertex Buffer 4 Dateneinheiten stehen, dann müssen auch im anderen Buffer 4 Dateneinheiten vorhanden sein.&lt;br /&gt;
Dies lässt sich recht einfach erklären, denn man Geometrie zeichnen will, dann benötigt man N Punkte und zu jeden Punkt gibt es auch eine Normale, Farbinformation, Texturkoordinate und so weiter.&lt;br /&gt;
Wenn OpenGL also nun die Geometrie zeichnet, ruft es in allen gebundenen Buffern immer das I. Element auf und würde ein Vertex Buffer nicht entsprechend viele Elemente enthalten, dann gibt es Zeichenfehler.&lt;br /&gt;
&lt;br /&gt;
Es gibt noch Geometrie Shader, welche in der Abbildung nicht mit eingearbeitet sind, diese sind aktuell nicht im OpenGL Kern implementiert aber über ARB zugreifbar.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Pipeline erhalten wir die Pixelinformationen für das Endgültige Bild.&lt;br /&gt;
&lt;br /&gt;
==Viewport==&lt;br /&gt;
Da die Matrizen in OpenGL3 vom Entwickler verwaltet wird, hat man entsprechend nur noch wenig Einstellungen an OpenGL zu tätigen.&lt;br /&gt;
OpenGL benötigt Informationen über den Zeichenbereich, damit der Framebuffer korrekt verwaltet wird.&lt;br /&gt;
Um dies zu ermöglichen, stellt OpenGL die [[glViewport]] Funktion zur verfügung.&lt;br /&gt;
Diese Funktion wird z.B. verwendet, wenn man mehrere Ansichten einer Szene in einem Framebuffer zeichnen möchte(z.B 3D Grafik Tools wie Blender).&lt;br /&gt;
Wenn man z.B. glViewport(0,0,320,240); ausführt und eine Fenstergröße von 640x480 hat, dann wird die ganze Szene auf ein Bereich von 320x240 Pixel gezeichnet und an der Unteren, Linken Ecke des Fensters gezeichnet. Nun kann man noch mit glViewport(0,240,320,240); und noch einmal mit glViewport(320,0,320,480); die Szene zeichnen und wir hätten 3 mal die Szene auf unserem Fenster gezeichnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Scissor==&lt;br /&gt;
Neben dieser Funktion gibt es noch eine Scissor Funktionalität, welche den Rasterisierungsprozess beeinflusst.&lt;br /&gt;
Die Scissor Funktionalität wird durch [[glEnable]](GL_SCISSOR_TEST), [[glDisable]](GL_SCISSOR_TEST) und [[glScissor]](Links,Unten,Breite,Höhe) realisiert.&lt;br /&gt;
Dabei werden alle Pixel, die ausserhalb des Bereiches liegen, nicht gezeichnet. Hierzu ist zu sagen, dass nur der Shading Prozess abgebrochen wird aber nicht die davor liegende berechnung. Dies benötigt man z.B. bei dem zeichnen des User Interfaces und Schriften, damit diese nicht über ein Editfeld hinaus ragen oder Komponenten nicht ausserhalb einer Übergeordneten Komponente gezeichnet wird.&lt;br /&gt;
&lt;br /&gt;
=Der vierte Schritt(Zeichnen mit VertexBufferObjects und VertexArrayObject)=&lt;br /&gt;
Der Grafik Kontext ist erstellt und bereit seine Arbeit zu verrichten.&lt;br /&gt;
OpenGL3 benötigt zum zeichnen von Primitiven einen Defaultshader und die Primitivendaten.&lt;br /&gt;
Die Primitivendaten können über ein Vertex Buffer Object(VBO) oder Vertex Array Object(VAO) erzeugt und bereit gestellt werden.&lt;br /&gt;
VBO's sind sehr einfach zu handhaben, wie folgender Code zeigen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
glGenBuffers(1,&amp;amp;VBOID);//Erstelle ein Buffer Object.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);//Das Buffer Object soll als ein VBO gebunden werden.&lt;br /&gt;
glBufferData(GL_ARRAY_BUFFER,ElementCount*ElementSize,Data,GL_STATIC_DRAW);//Lade die Daten vom Data Pointer in den Grafikspeicher, dabei werden ElementSize*ElementCount Bytes kopiert.&lt;br /&gt;
&lt;br /&gt;
//Zeichenphase:&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);&lt;br /&gt;
glDrawArrays(GL_POINTS,0,ElementCount);//Zeichne aus dem aktuell gebundenen VBO ElementCount Punkte, von Element 0 beginnend.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,0);//Binde das Objekt mit der ID 0, welches immer als Leeres Objekt definiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies reicht allerdings noch nicht aus, um unsere Punkte zu zeichnen, da aktuell weder ein Vertexshader noch ein Fragmentshader gebunden ist, der die verarbeitung der Daten übernimmt.&lt;br /&gt;
In OpenGL 1 bis 2 gab es eine Fixed Function Pipeline bzw. später eine automatisch anpassende Render Pipeline, bestehend aus einen generierten Vertex- und Fragment-Shader sowie den Fixed Function Teil.&lt;br /&gt;
OpenGL3 geht keinen der beiden Wege, sondern beschreitet einen neuen und legt fest, dass der Entwickler diese beiden Shader selber liefern muss und stellt den rest über Fixed Function bereit.&lt;br /&gt;
Der Vertex- und Fragment-Shader werden über eine extra Shadersprache implementiert, welche sich OpenGL Shader Language oder kurz GLSL nennt.&lt;br /&gt;
OpenGL3.1 bietet die GLSL Version 1.4 an, die nähere Behandlung dieses Themas würde aber den Rahmen des Artikels sprengen und wäre auch nicht mehr Einsteigerfreundlich.&lt;br /&gt;
Ich will daher die API zum verwalten von Shader Objekten näher erläutern und einfach ein fertigen Shadercode liefern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
VSO=glCreateShader(GL_VERTEX_SHADER);//Erstellt ein Vertex Shader Objekt.&lt;br /&gt;
FSO=glCreateShader(GL_FRAGMENT_SHADER);//Erstellt ein Fragment Shader Objekt.&lt;br /&gt;
&lt;br /&gt;
glShaderSource(VSO,1,&amp;amp;VertexShaderSourcecode,0);//Man übergibt 1 Text, der den Shadercode enthält, mit dem letzten Parameter 0(alle übergebenen Strings sind 0 terminiert).&lt;br /&gt;
glShaderSource(FSO,1,&amp;amp;FragmentShaderSourcecode,0);&lt;br /&gt;
&lt;br /&gt;
glCompileShader(VSO);//Compiliert den Shadercode.&lt;br /&gt;
//glGetShaderiv(VSO,GL_COMPILE_STATUS,&amp;amp;compiled);//Sollte der Shadercode nicht korrekt sein, dann liefert compiled GL_FALSE zurück, sonnst GL_TRUE.&lt;br /&gt;
glCompileShader(FSO);&lt;br /&gt;
&lt;br /&gt;
ShaderID=glCreateProgram();//Erstellt ein Shader Programm Objekt, welches aus einen compilierten Vertex- und Fragment-Shader besteht.&lt;br /&gt;
glAttachShader(ShaderID,VSO);//Fügt den Vertexshader hinzu.&lt;br /&gt;
glAttachShader(ShaderID,FSO);//Fügt den Fragmentshader hinzu.&lt;br /&gt;
&lt;br /&gt;
glLinkProgram(ShaderID);//Wie bei einer Programmiersprache üblich, wird nach dem compilieren des Sourcode, die entstandenen Codesegmente zu einem Machienencode gelinkt und somit Referenzen aufgelöst.&lt;br /&gt;
//glGetProgramiv(ShaderID,GL_LINK_STATUS,&amp;amp;compiled);//Verhält sich wie bei den vorher compilierten Shader.&lt;br /&gt;
glEnableVertexAttribArray(glGetAttribLocation(ShaderID,Name));//Finde die Speicheradresse vom Attribute, mit entsprechendem Name und aktiviere das Attribute.&lt;br /&gt;
glVertexAttribPointer(glGetAttribLocation(ShaderID,Name),3,GL_FLOAT,GL_FALSE,0,0);//glVertexAttribPointer(Speicheradresse,Vektordimension,Vektortyp,Normalisieren,Datenoffset,Datenpointer)Wenn Datenpointer 0 ist, dann wird das aktuell gebundene Buffer Object verwendet, sonnst die Speicheradresse, auf die Datenpointer zeigt.&lt;br /&gt;
&lt;br /&gt;
Zeichenphase:&lt;br /&gt;
glUseProgram(ShaderID);//Binde das zuvor erstellte Programm als aktuell zu nutzendes Program.&lt;br /&gt;
glUniformMatrix4fv(glGetUniformLocation(ShaderID,VariableName),1,GL_FALSE,&amp;amp;ProjectionMatrix);//Sucht die Speicheradresse von VariableName, im Shader Program, übergibt diese dann einer weiteren Funktion, um an dieser Speicheradresse unsere ProjectionMatrix zu kopieren(2. Parameter gibt die Anzahl der Matrizen an und der 3. ob die Matrix Transponiert werden soll).&lt;br /&gt;
//zeichenaufruf&lt;br /&gt;
glUseProgram(0);//Binde das Program Objekt mit der ID 0, welches als Leerer Shader(kein Shader aktiv) implementiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
Wir müssen dem Shader die VBO Daten verfügbar machen, dies geschieht über die VertexAttrib Funktionen.&lt;br /&gt;
Als erste muss ein Attribut, im Shader, lokalisiert und aktiviert werden, dazu wird glGetAttribLocation und glEnableVertexAttribArray verwendet.&lt;br /&gt;
Der zweite Schritt wäre dann das binden von unserem VBO an dieses Attribut, indem glGetAttribLocation,glVertexAttribPointer sowie glBindBuffer verwendet wird.&lt;br /&gt;
Bevor man das VertexAttrib setzen kann, muss das entsprechende VBO vorher gebunden werden, da immer nur ein BO aktiv sein kann.&lt;br /&gt;
Wenn man mehrere VBO verwenden will, um z.B. noch Farben oder Texturkoordinaten zu binden, dann bindet man erst den ersten Buffer, setzt das VertexAttribut, bindet den zweiten Buffer, setzt das VertexAttribut und so weiter. Das ganze muss nicht jeden Renderdurchgang neu machen, sondern kann es nach dem erstellen der Resourcen einmal machen.&lt;br /&gt;
Allerdings sind IndexBuffer und/oder einer der Vertexbuffer zu binden, damit der Shader die richtigen Buffer Objects nutzt.&lt;br /&gt;
Das ganze kann noch weiter vereinfacht werden, indem man ein VAO verwendet, dabei wird ein VAO erstellt, gebunden, dann alle VBO's erstellt, die Vertex Attribute gesetzt und das VAO wieder ausgebunden. Wenn man nun statt der VBO's und so weiter das VAO bindet, wird dieses alle anderen Resourcen(VBO, Vertexbassierte Flags), automatisch binden und setzen.&lt;br /&gt;
&lt;br /&gt;
VertexShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
uniform mat4 ProjectionMatrix;&lt;br /&gt;
&lt;br /&gt;
in vec4 Vertex;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_Position=ProjectionMatrix*Vertex;&lt;br /&gt;
  gl_FrontColor=vec4(1.0f,0.0f,0.0f,1.0f);&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FragmentShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
out vec4 gl_FragColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_FragColor=gl_Color;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24082</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24082"/>
				<updated>2009-08-06T15:59:54Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Der erste Schritt(Garphic Context) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Dieser Artikel richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
=Grundlagen=&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Der Grafikcontext==&lt;br /&gt;
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht.&lt;br /&gt;
Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten, dabei werden Identifier(ID) verwendet, um Resourcen nach außen Verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt.&lt;br /&gt;
Neben den ID-Listen werden noch sogenannte States, Informationen für die Bildausgabe und diverse unbekannte treiberspezifische Daten gespeichert.&lt;br /&gt;
&lt;br /&gt;
===Profil===&lt;br /&gt;
Um die einzelnen Befehlssätze zu Verwalten hat man sogenannte Profile eingeführt.&lt;br /&gt;
OpenGL3 ist z.B. ein Profil, es gibt noch weitere Profile wie z.B. OpenGL3.1 oder OpenGL3.1 Debug.&lt;br /&gt;
Die Profile werden vom ARB fest gelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als &amp;quot;deprecated&amp;quot; eingestuft wurden, und einmal mit diesen.&lt;br /&gt;
&lt;br /&gt;
===Forward compatible context und Full context===&lt;br /&gt;
Es gibt 2 Varianten eines Context, der Full context ist enthält alle Funktionen, auch die als deprecated maktierten. Der Forward compatible context enthält nur die nicht als deprecated markierten Funktionen des OpenGL Kerns. Bis zur Version 3.1 gab es immer eine abwärts Kompatibilität und der Treiber hatte entschieden, welche OpenGL Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine abwärts Kompatibilität mehr und man kann festlegen, was für ein GC man haben möchte.&lt;br /&gt;
&lt;br /&gt;
===Verwaltung der veralteten und neuen Funktionen===&lt;br /&gt;
Das hinzukommen und das entfernen von OpenGL Funktionen unterliegt dem Deprecation und Extension Mechanismus.&lt;br /&gt;
Diese funktionieren wie folgt.&lt;br /&gt;
&lt;br /&gt;
'''Deprecation Path''': Core-&amp;gt;ARB-&amp;gt;Vendor/Extension&lt;br /&gt;
&lt;br /&gt;
Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur verfügung gestellt.&lt;br /&gt;
Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt.&lt;br /&gt;
Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet.&lt;br /&gt;
&lt;br /&gt;
'''Extension Path''': Vendor/Extension-&amp;gt;ARB-&amp;gt;Core&lt;br /&gt;
&lt;br /&gt;
Wenn eine Extension, von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen.&lt;br /&gt;
Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL Version in den Kern aufgenommen.&lt;br /&gt;
&lt;br /&gt;
OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiter Entwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. Transform Feedback, Instancing oder GLSlang 1.4 .&lt;br /&gt;
&lt;br /&gt;
==Die Render Pipeline==&lt;br /&gt;
{{Hinweis|Dieser Abschnitt ist für Erfahrende OpenGL Entwickler gedacht, die nochmal Nachschlagen wollen oder ein schnellen Einstieg in OpenGL3 suchen. Es wird ein hoher Grad an Vorwissen vorraus gesetzt, erklärt aber dafür wesentlich kompakter und tiefgehender die Funktionalität von OpenGL3. Wer noch keine oder wenig Erfahrung mit OpenGL hat, der sollte dieses Punkt überspringen und am Ende des Artikel dann hier rein schauen.}}&lt;br /&gt;
&lt;br /&gt;
OpenGL 3 sieht folgende Pipeline vor.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OGL3Pipeline.png]]&lt;br /&gt;
&lt;br /&gt;
Diese Darstellung ist noch weiter zerlegbar aber momentan reicht dieser Grad an Genauigkeit aus.&lt;br /&gt;
Am Anfang der Pipeline stehen die Vertexdaten, diese werden über ein Vertex Buffer Object(VBO) oder über ein Vertex Array(VA) übergeben.&lt;br /&gt;
Ein VBO ist ein Stück Speicher, in den Daten hinterlegt werden können, egal ob Vertice, Normalen oder Userdaten.&lt;br /&gt;
Man weist dann Teile des Buffers Variablen, im Vertex/Fragment Shader, zu und kann somit eine Interpretation der Daten realisieren.&lt;br /&gt;
Die zuweisung, auf ein Shader Attribut wird über VA realisiert, es bildet hierbei die Brücke.&lt;br /&gt;
Bei einem VBO gibt es 2 Typen, einmal Element und einmal Vertice, es kann nur ein Element Buffer verwendet werden aber mehrere Vertice Buffer.&lt;br /&gt;
Der Element Buffer enhält Indices und unterliegt im vergelich zum Vertex Buffer keiner besonderen Regel.&lt;br /&gt;
Die Vertex Buffer hingegen müssen die gleiche länge besitzen, was bedeutet, wenn im einen Vertex Buffer 4 Dateneinheiten stehen, dann müssen auch im anderen Buffer 4 Dateneinheiten vorhanden sein.&lt;br /&gt;
Dies lässt sich recht einfach erklären, denn man Geometrie zeichnen will, dann benötigt man N Punkte und zu jeden Punkt gibt es auch eine Normale, Farbinformation, Texturkoordinate und so weiter.&lt;br /&gt;
Wenn OpenGL also nun die Geometrie zeichnet, ruft es in allen gebundenen Buffern immer das I. Element auf und würde ein Vertex Buffer nicht entsprechend viele Elemente enthalten, dann gibt es Zeichenfehler.&lt;br /&gt;
&lt;br /&gt;
Es gibt noch Geometrie Shader, welche in der Abbildung nicht mit eingearbeitet sind, diese sind aktuell nicht im OpenGL Kern implementiert aber über ARB zugreifbar.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Pipeline erhalten wir die Pixelinformationen für das Endgültige Bild.&lt;br /&gt;
&lt;br /&gt;
==Viewport==&lt;br /&gt;
Da die Matrizen in OpenGL3 vom Entwickler verwaltet wird, hat man entsprechend nur noch wenig Einstellungen an OpenGL zu tätigen.&lt;br /&gt;
OpenGL benötigt Informationen über den Zeichenbereich, damit der Framebuffer korrekt verwaltet wird.&lt;br /&gt;
Um dies zu ermöglichen, stellt OpenGL die [[glViewport]] Funktion zur verfügung.&lt;br /&gt;
Diese Funktion wird z.B. verwendet, wenn man mehrere Ansichten einer Szene in einem Framebuffer zeichnen möchte(z.B 3D Grafik Tools wie Blender).&lt;br /&gt;
Wenn man z.B. glViewport(0,0,320,240); ausführt und eine Fenstergröße von 640x480 hat, dann wird die ganze Szene auf ein Bereich von 320x240 Pixel gezeichnet und an der Unteren, Linken Ecke des Fensters gezeichnet. Nun kann man noch mit glViewport(0,240,320,240); und noch einmal mit glViewport(320,0,320,480); die Szene zeichnen und wir hätten 3 mal die Szene auf unserem Fenster gezeichnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Scissor==&lt;br /&gt;
Neben dieser Funktion gibt es noch eine Scissor Funktionalität, welche den Rasterisierungsprozess beeinflusst.&lt;br /&gt;
Die Scissor Funktionalität wird durch [[glEnable]](GL_SCISSOR_TEST), [[glDisable]](GL_SCISSOR_TEST) und [[glScissor]](Links,Unten,Breite,Höhe) realisiert.&lt;br /&gt;
Dabei werden alle Pixel, die ausserhalb des Bereiches liegen, nicht gezeichnet. Hierzu ist zu sagen, dass nur der Shading Prozess abgebrochen wird aber nicht die davor liegende berechnung. Dies benötigt man z.B. bei dem zeichnen des User Interfaces und Schriften, damit diese nicht über ein Editfeld hinaus ragen oder Komponenten nicht ausserhalb einer Übergeordneten Komponente gezeichnet wird.&lt;br /&gt;
&lt;br /&gt;
=Der vierte Schritt(Zeichnen mit VertexBufferObjects und VertexArrayObject)=&lt;br /&gt;
Der Grafik Kontext ist erstellt und bereit seine Arbeit zu verrichten.&lt;br /&gt;
OpenGL3 benötigt zum zeichnen von Primitiven einen Defaultshader und die Primitivendaten.&lt;br /&gt;
Die Primitivendaten können über ein Vertex Buffer Object(VBO) oder Vertex Array Object(VAO) erzeugt und bereit gestellt werden.&lt;br /&gt;
VBO's sind sehr einfach zu handhaben, wie folgender Code zeigen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
glGenBuffers(1,&amp;amp;VBOID);//Erstelle ein Buffer Object.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);//Das Buffer Object soll als ein VBO gebunden werden.&lt;br /&gt;
glBufferData(GL_ARRAY_BUFFER,ElementCount*ElementSize,Data,GL_STATIC_DRAW);//Lade die Daten vom Data Pointer in den Grafikspeicher, dabei werden ElementSize*ElementCount Bytes kopiert.&lt;br /&gt;
&lt;br /&gt;
//Zeichenphase:&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);&lt;br /&gt;
glDrawArrays(GL_POINTS,0,ElementCount);//Zeichne aus dem aktuell gebundenen VBO ElementCount Punkte, von Element 0 beginnend.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,0);//Binde das Objekt mit der ID 0, welches immer als Leeres Objekt definiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies reicht allerdings noch nicht aus, um unsere Punkte zu zeichnen, da aktuell weder ein Vertexshader noch ein Fragmentshader gebunden ist, der die verarbeitung der Daten übernimmt.&lt;br /&gt;
In OpenGL 1 bis 2 gab es eine Fixed Function Pipeline bzw. später eine automatisch anpassende Render Pipeline, bestehend aus einen generierten Vertex- und Fragment-Shader sowie den Fixed Function Teil.&lt;br /&gt;
OpenGL3 geht keinen der beiden Wege, sondern beschreitet einen neuen und legt fest, dass der Entwickler diese beiden Shader selber liefern muss und stellt den rest über Fixed Function bereit.&lt;br /&gt;
Der Vertex- und Fragment-Shader werden über eine extra Shadersprache implementiert, welche sich OpenGL Shader Language oder kurz GLSL nennt.&lt;br /&gt;
OpenGL3.1 bietet die GLSL Version 1.4 an, die nähere Behandlung dieses Themas würde aber den Rahmen des Artikels sprengen und wäre auch nicht mehr Einsteigerfreundlich.&lt;br /&gt;
Ich will daher die API zum verwalten von Shader Objekten näher erläutern und einfach ein fertigen Shadercode liefern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
VSO=glCreateShader(GL_VERTEX_SHADER);//Erstellt ein Vertex Shader Objekt.&lt;br /&gt;
FSO=glCreateShader(GL_FRAGMENT_SHADER);//Erstellt ein Fragment Shader Objekt.&lt;br /&gt;
&lt;br /&gt;
glShaderSource(VSO,1,&amp;amp;VertexShaderSourcecode,0);//Man übergibt 1 Text, der den Shadercode enthält, mit dem letzten Parameter 0(alle übergebenen Strings sind 0 terminiert).&lt;br /&gt;
glShaderSource(FSO,1,&amp;amp;FragmentShaderSourcecode,0);&lt;br /&gt;
&lt;br /&gt;
glCompileShader(VSO);//Compiliert den Shadercode.&lt;br /&gt;
//glGetShaderiv(VSO,GL_COMPILE_STATUS,&amp;amp;compiled);//Sollte der Shadercode nicht korrekt sein, dann liefert compiled GL_FALSE zurück, sonnst GL_TRUE.&lt;br /&gt;
glCompileShader(FSO);&lt;br /&gt;
&lt;br /&gt;
ShaderID=glCreateProgram();//Erstellt ein Shader Programm Objekt, welches aus einen compilierten Vertex- und Fragment-Shader besteht.&lt;br /&gt;
glAttachShader(ShaderID,VSO);//Fügt den Vertexshader hinzu.&lt;br /&gt;
glAttachShader(ShaderID,FSO);//Fügt den Fragmentshader hinzu.&lt;br /&gt;
&lt;br /&gt;
glLinkProgram(ShaderID);//Wie bei einer Programmiersprache üblich, wird nach dem compilieren des Sourcode, die entstandenen Codesegmente zu einem Machienencode gelinkt und somit Referenzen aufgelöst.&lt;br /&gt;
//glGetProgramiv(ShaderID,GL_LINK_STATUS,&amp;amp;compiled);//Verhält sich wie bei den vorher compilierten Shader.&lt;br /&gt;
glEnableVertexAttribArray(glGetAttribLocation(ShaderID,Name));//Finde die Speicheradresse vom Attribute, mit entsprechendem Name und aktiviere das Attribute.&lt;br /&gt;
glVertexAttribPointer(glGetAttribLocation(ShaderID,Name),3,GL_FLOAT,GL_FALSE,0,0);//glVertexAttribPointer(Speicheradresse,Vektordimension,Vektortyp,Normalisieren,Datenoffset,Datenpointer)Wenn Datenpointer 0 ist, dann wird das aktuell gebundene Buffer Object verwendet, sonnst die Speicheradresse, auf die Datenpointer zeigt.&lt;br /&gt;
&lt;br /&gt;
Zeichenphase:&lt;br /&gt;
glUseProgram(ShaderID);//Binde das zuvor erstellte Programm als aktuell zu nutzendes Program.&lt;br /&gt;
glUniformMatrix4fv(glGetUniformLocation(ShaderID,VariableName),1,GL_FALSE,&amp;amp;ProjectionMatrix);//Sucht die Speicheradresse von VariableName, im Shader Program, übergibt diese dann einer weiteren Funktion, um an dieser Speicheradresse unsere ProjectionMatrix zu kopieren(2. Parameter gibt die Anzahl der Matrizen an und der 3. ob die Matrix Transponiert werden soll).&lt;br /&gt;
//zeichenaufruf&lt;br /&gt;
glUseProgram(0);//Binde das Program Objekt mit der ID 0, welches als Leerer Shader(kein Shader aktiv) implementiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
Wir müssen dem Shader die VBO Daten verfügbar machen, dies geschieht über die VertexAttrib Funktionen.&lt;br /&gt;
Als erste muss ein Attribut, im Shader, lokalisiert und aktiviert werden, dazu wird glGetAttribLocation und glEnableVertexAttribArray verwendet.&lt;br /&gt;
Der zweite Schritt wäre dann das binden von unserem VBO an dieses Attribut, indem glGetAttribLocation,glVertexAttribPointer sowie glBindBuffer verwendet wird.&lt;br /&gt;
Bevor man das VertexAttrib setzen kann, muss das entsprechende VBO vorher gebunden werden, da immer nur ein BO aktiv sein kann.&lt;br /&gt;
Wenn man mehrere VBO verwenden will, um z.B. noch Farben oder Texturkoordinaten zu binden, dann bindet man erst den ersten Buffer, setzt das VertexAttribut, bindet den zweiten Buffer, setzt das VertexAttribut und so weiter. Das ganze muss nicht jeden Renderdurchgang neu machen, sondern kann es nach dem erstellen der Resourcen einmal machen.&lt;br /&gt;
Allerdings sind IndexBuffer und/oder einer der Vertexbuffer zu binden, damit der Shader die richtigen Buffer Objects nutzt.&lt;br /&gt;
Das ganze kann noch weiter vereinfacht werden, indem man ein VAO verwendet, dabei wird ein VAO erstellt, gebunden, dann alle VBO's erstellt, die Vertex Attribute gesetzt und das VAO wieder ausgebunden. Wenn man nun statt der VBO's und so weiter das VAO bindet, wird dieses alle anderen Resourcen(VBO, Vertexbassierte Flags), automatisch binden und setzen.&lt;br /&gt;
&lt;br /&gt;
VertexShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
uniform mat4 ProjectionMatrix;&lt;br /&gt;
&lt;br /&gt;
in vec4 Vertex;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_Position=ProjectionMatrix*Vertex;&lt;br /&gt;
  gl_FrontColor=vec4(1.0f,0.0f,0.0f,1.0f);&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FragmentShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
out vec4 gl_FragColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_FragColor=gl_Color;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24081</id>
		<title>Tutorial OpenGL3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3&amp;diff=24081"/>
				<updated>2009-08-06T15:56:44Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Willkommen zur Einführung in OpenGL3.x.&lt;br /&gt;
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Dieser Artikel richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.&lt;br /&gt;
&lt;br /&gt;
=Grundlagen=&lt;br /&gt;
==OpenGL3 und die Vorgeschichte==&lt;br /&gt;
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt. &lt;br /&gt;
&lt;br /&gt;
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird. &lt;br /&gt;
&lt;br /&gt;
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.&lt;br /&gt;
&lt;br /&gt;
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.&lt;br /&gt;
&lt;br /&gt;
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.&lt;br /&gt;
&lt;br /&gt;
==Der Grafikcontext==&lt;br /&gt;
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht.&lt;br /&gt;
Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten, dabei werden Identifier(ID) verwendet, um Resourcen nach außen Verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt.&lt;br /&gt;
Neben den ID-Listen werden noch sogenannte States, Informationen für die Bildausgabe und diverse unbekannte treiberspezifische Daten gespeichert.&lt;br /&gt;
&lt;br /&gt;
===Profil===&lt;br /&gt;
Um die einzelnen Befehlssätze zu Verwalten hat man sogenannte Profile eingeführt.&lt;br /&gt;
OpenGL3 ist z.B. ein Profil, es gibt noch weitere Profile wie z.B. OpenGL3.1 oder OpenGL3.1 Debug.&lt;br /&gt;
Die Profile werden vom ARB fest gelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als &amp;quot;deprecated&amp;quot; eingestuft wurden, und einmal mit diesen.&lt;br /&gt;
&lt;br /&gt;
===Forward compatible context und Full context===&lt;br /&gt;
Es gibt 2 Varianten eines Context, der Full context ist enthält alle Funktionen, auch die als deprecated maktierten. Der Forward compatible context enthält nur die nicht als deprecated markierten Funktionen des OpenGL Kerns. Bis zur Version 3.1 gab es immer eine abwärts Kompatibilität und der Treiber hatte entschieden, welche OpenGL Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine abwärts Kompatibilität mehr und man kann festlegen, was für ein GC man haben möchte.&lt;br /&gt;
&lt;br /&gt;
===Verwaltung der veralteten und neuen Funktionen===&lt;br /&gt;
Das hinzukommen und das entfernen von OpenGL Funktionen unterliegt dem Deprecation und Extension Mechanismus.&lt;br /&gt;
Diese funktionieren wie folgt.&lt;br /&gt;
&lt;br /&gt;
'''Deprecation Path''': Core-&amp;gt;ARB-&amp;gt;Vendor/Extension&lt;br /&gt;
&lt;br /&gt;
Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur verfügung gestellt.&lt;br /&gt;
Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt.&lt;br /&gt;
Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet.&lt;br /&gt;
&lt;br /&gt;
'''Extension Path''': Vendor/Extension-&amp;gt;ARB-&amp;gt;Core&lt;br /&gt;
&lt;br /&gt;
Wenn eine Extension, von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen.&lt;br /&gt;
Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL Version in den Kern aufgenommen.&lt;br /&gt;
&lt;br /&gt;
OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiter Entwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. Transform Feedback, Instancing oder GLSlang 1.4 .&lt;br /&gt;
&lt;br /&gt;
==Die Render Pipeline==&lt;br /&gt;
{{Hinweis|Dieser Abschnitt ist für Erfahrende OpenGL Entwickler gedacht, die nochmal Nachschlagen wollen oder ein schnellen Einstieg in OpenGL3 suchen. Es wird ein hoher Grad an Vorwissen vorraus gesetzt, erklärt aber dafür wesentlich kompakter und tiefgehender die Funktionalität von OpenGL3. Wer noch keine oder wenig Erfahrung mit OpenGL hat, der sollte dieses Punkt überspringen und am Ende des Artikel dann hier rein schauen.}}&lt;br /&gt;
&lt;br /&gt;
OpenGL 3 sieht folgende Pipeline vor.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OGL3Pipeline.png]]&lt;br /&gt;
&lt;br /&gt;
Diese Darstellung ist noch weiter zerlegbar aber momentan reicht dieser Grad an Genauigkeit aus.&lt;br /&gt;
Am Anfang der Pipeline stehen die Vertexdaten, diese werden über ein Vertex Buffer Object(VBO) oder über ein Vertex Array(VA) übergeben.&lt;br /&gt;
Ein VBO ist ein Stück Speicher, in den Daten hinterlegt werden können, egal ob Vertice, Normalen oder Userdaten.&lt;br /&gt;
Man weist dann Teile des Buffers Variablen, im Vertex/Fragment Shader, zu und kann somit eine Interpretation der Daten realisieren.&lt;br /&gt;
Die zuweisung, auf ein Shader Attribut wird über VA realisiert, es bildet hierbei die Brücke.&lt;br /&gt;
Bei einem VBO gibt es 2 Typen, einmal Element und einmal Vertice, es kann nur ein Element Buffer verwendet werden aber mehrere Vertice Buffer.&lt;br /&gt;
Der Element Buffer enhält Indices und unterliegt im vergelich zum Vertex Buffer keiner besonderen Regel.&lt;br /&gt;
Die Vertex Buffer hingegen müssen die gleiche länge besitzen, was bedeutet, wenn im einen Vertex Buffer 4 Dateneinheiten stehen, dann müssen auch im anderen Buffer 4 Dateneinheiten vorhanden sein.&lt;br /&gt;
Dies lässt sich recht einfach erklären, denn man Geometrie zeichnen will, dann benötigt man N Punkte und zu jeden Punkt gibt es auch eine Normale, Farbinformation, Texturkoordinate und so weiter.&lt;br /&gt;
Wenn OpenGL also nun die Geometrie zeichnet, ruft es in allen gebundenen Buffern immer das I. Element auf und würde ein Vertex Buffer nicht entsprechend viele Elemente enthalten, dann gibt es Zeichenfehler.&lt;br /&gt;
&lt;br /&gt;
Es gibt noch Geometrie Shader, welche in der Abbildung nicht mit eingearbeitet sind, diese sind aktuell nicht im OpenGL Kern implementiert aber über ARB zugreifbar.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Pipeline erhalten wir die Pixelinformationen für das Endgültige Bild.&lt;br /&gt;
&lt;br /&gt;
=Der erste Schritt(Garphic Context)=&lt;br /&gt;
Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen, vom Desktop Manager, welche Möglichkeiten wir überhaupt zur Auswahl haben. Es wird ein Double Buffer benötigt und man muss die Farbtiefe sowie Tiefenpuffer Genauigkeit festlegen. Dies wird von den Desktop Managern unterschiedlich gehandhabt, so hat Windows z.B. ein DeviceContext und ein Pixelformat und X11 nennt dies VisualInfo bzw. GLXFBConfig.&lt;br /&gt;
Ist dieser Schritt getan kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen.&lt;br /&gt;
&lt;br /&gt;
==Erstellung eines OpenGL3.x GC==&lt;br /&gt;
Um ein GC ertellen zu können wird eine weitere API benötigt, welche plattformabhängig und durch wgl[Funktionsname]/glX[Funktionsname] erkennbar ist. Mit diesen Befehlen kann man mit den Windows und X11 Desktop Manager zusammen arbeiten. So werden Funktionen für das erstellen, wechseln, zerstören eines GC, laden von Extension, wechseln des Fensterpuffern und Synchronisieren von CPU und GPU ermöglicht. Bisher gibt es noch keine Möglichkeit einen OpenGL3 fähigen GC zu erstellen, ohne dafür eine Funktion vom ARB zu verwenden. Der Nachteil von ARB Funktionen sind, dass man einen gültigen GC benötigt den Zeiger auf diese zu erhalten. Um einen OpenGL 3.0 oder 3.1 GC zu erstellen benötigt man einen OpenGL1-2 GC und die Kernfunktion [[wglGetProcAddress]]/[[glxGetProcAddress]]. Einen gültigen OpenGL1 bzw. OpenGL2 GC bekommt man über den Befehl [[wglCreateContext]]/[[glxCreateContext]] und zwischen mehreren GC kann man mit dem Befehl [[wglMakeCurrent]]/[[glxMakeCurrent]] wechseln.&lt;br /&gt;
Der Befehl für die Erstellung eines OpenGL3 fähigen GC heisst [[wglCreateContextAttribsARB]]/[[glxCreateContextAttribsARB]].&lt;br /&gt;
Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, in dem man die noch jetzige ARB Funktion in den OpenGL-Kern mit aufnimmt und somit das erfragen der ARB Funktion, über ein OpenGL1-2GC, unnötig macht.&lt;br /&gt;
&lt;br /&gt;
'''Windows'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void CreateOpenGL3Context()&lt;br /&gt;
{&lt;br /&gt;
  HGLRC TempContext=wglCreateContext(DeviceContext);//erstellt ein alten OpenGL Context&lt;br /&gt;
  if (TempContext==NULL)&lt;br /&gt;
  {&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;//beenden&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,TempContext);//setzt den erstellten GC als aktuellen GC&lt;br /&gt;
&lt;br /&gt;
  //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
  typedef HGLRC (APIENTRY * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int *attribList);&lt;br /&gt;
&lt;br /&gt;
  PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;&lt;br /&gt;
&lt;br /&gt;
  //abfragen, ob die Funktion existiert&lt;br /&gt;
  wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(&amp;quot;wglCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if(wglCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
  {&lt;br /&gt;
    wglDeleteContext(TempContext);&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int attribs[]={WGL_CONTEXT_MAJOR_VERSION_ARB,3,WGL_CONTEXT_MINOR_VERSION_ARB,1,WGL_CONTEXT_FLAGS_ARB,WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
&lt;br /&gt;
  if (!(Context=wglCreateContextAttribsARB(DeviceContext,0, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen&lt;br /&gt;
  {&lt;br /&gt;
    //Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  &lt;br /&gt;
    attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
    if (!(Context=wglCreateContextAttribsARB(Win-&amp;gt;GetDeviceContext(),0, attribs)))&lt;br /&gt;
    {&lt;br /&gt;
      //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
      wglDeleteContext(TempContext);//aufräumen und beenden&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  wglMakeCurrent(DeviceContext,Context);//wechsel auf den OpenGL3.x context&lt;br /&gt;
  wglDeleteContext(TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''X11(Linux/Mac OS)'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void CreateOpenGL3Context()&lt;br /&gt;
{&lt;br /&gt;
  GLXContex TempContext=glXCreateContext(Display,VisualInfo,NULL,true);//erstellt ein alten OpenGL Context&lt;br /&gt;
  if (TempContext==NULL)&lt;br /&gt;
  {&lt;br /&gt;
    cout&amp;lt;&amp;lt;&amp;quot;Error: Could not create an OpenGL rendering context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
  glXMakeCurrent(Display,Handle,TempContext);//setzt den erstellten GC als aktuellen GC&lt;br /&gt;
&lt;br /&gt;
  //Typdefinition von wglCreateContextAttribsARB&lt;br /&gt;
  typedef HGLRC (APIENTRY * PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display *dpy,GLXFBConfig config,GLXContext share_context,Bool direct,const int *attrib_list);&lt;br /&gt;
&lt;br /&gt;
  PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = NULL;&lt;br /&gt;
&lt;br /&gt;
  //abfragen, ob die Funktion existiert&lt;br /&gt;
  glXCreateContextAttribsARB=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(&amp;quot;glXCreateContextAttribsARB&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if(glXCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der --&amp;gt;Treiber&amp;lt;-- keinen OpenGL3 support&lt;br /&gt;
  {&lt;br /&gt;
    glXDeleteContext(TempContext);&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: There is no OpenGL3 context support.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int attribs[]={GLX_CONTEXT_MAJOR_VERSION_ARB,3,GLX_CONTEXT_MINOR_VERSION_ARB,1,GLX_CONTEXT_FLAGS_ARB,GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};&lt;br /&gt;
&lt;br /&gt;
  if (!(Context=glXCreateContextAttribsARB(Display, FBConfig, NULL, true, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen&lt;br /&gt;
  {&lt;br /&gt;
    //Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.&lt;br /&gt;
    cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
    return;&lt;br /&gt;
  &lt;br /&gt;
    attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.&lt;br /&gt;
    if (!(Context=glXCreateContextAttribsARB(Display, FBConfig, NULL, true, attribs)))&lt;br /&gt;
    {&lt;br /&gt;
      //Die --&amp;gt;Grafikkarte&amp;lt;-- beherrscht kein OpenGL3.&lt;br /&gt;
      glXDeleteContext(TempContext);//aufräumen und beenden&lt;br /&gt;
      cerr&amp;lt;&amp;lt;&amp;quot;Error: Couldn't create OpenGL3 context.&amp;quot;&amp;lt;&amp;lt;endl;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  glXMakeCurrent(Display,Handle,TempContext);//wechsel auf den OpenGL3.x context&lt;br /&gt;
  glXDeleteContext(Display,TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Viewport==&lt;br /&gt;
Da die Matrizen in OpenGL3 vom Entwickler verwaltet wird, hat man entsprechend nur noch wenig Einstellungen an OpenGL zu tätigen.&lt;br /&gt;
OpenGL benötigt Informationen über den Zeichenbereich, damit der Framebuffer korrekt verwaltet wird.&lt;br /&gt;
Um dies zu ermöglichen, stellt OpenGL die [[glViewport]] Funktion zur verfügung.&lt;br /&gt;
Diese Funktion wird z.B. verwendet, wenn man mehrere Ansichten einer Szene in einem Framebuffer zeichnen möchte(z.B 3D Grafik Tools wie Blender).&lt;br /&gt;
Wenn man z.B. glViewport(0,0,320,240); ausführt und eine Fenstergröße von 640x480 hat, dann wird die ganze Szene auf ein Bereich von 320x240 Pixel gezeichnet und an der Unteren, Linken Ecke des Fensters gezeichnet. Nun kann man noch mit glViewport(0,240,320,240); und noch einmal mit glViewport(320,0,320,480); die Szene zeichnen und wir hätten 3 mal die Szene auf unserem Fenster gezeichnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Scissor==&lt;br /&gt;
Neben dieser Funktion gibt es noch eine Scissor Funktionalität, welche den Rasterisierungsprozess beeinflusst.&lt;br /&gt;
Die Scissor Funktionalität wird durch [[glEnable]](GL_SCISSOR_TEST), [[glDisable]](GL_SCISSOR_TEST) und [[glScissor]](Links,Unten,Breite,Höhe) realisiert.&lt;br /&gt;
Dabei werden alle Pixel, die ausserhalb des Bereiches liegen, nicht gezeichnet. Hierzu ist zu sagen, dass nur der Shading Prozess abgebrochen wird aber nicht die davor liegende berechnung. Dies benötigt man z.B. bei dem zeichnen des User Interfaces und Schriften, damit diese nicht über ein Editfeld hinaus ragen oder Komponenten nicht ausserhalb einer Übergeordneten Komponente gezeichnet wird.&lt;br /&gt;
&lt;br /&gt;
=Der vierte Schritt(Zeichnen mit VertexBufferObjects und VertexArrayObject)=&lt;br /&gt;
Der Grafik Kontext ist erstellt und bereit seine Arbeit zu verrichten.&lt;br /&gt;
OpenGL3 benötigt zum zeichnen von Primitiven einen Defaultshader und die Primitivendaten.&lt;br /&gt;
Die Primitivendaten können über ein Vertex Buffer Object(VBO) oder Vertex Array Object(VAO) erzeugt und bereit gestellt werden.&lt;br /&gt;
VBO's sind sehr einfach zu handhaben, wie folgender Code zeigen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
glGenBuffers(1,&amp;amp;VBOID);//Erstelle ein Buffer Object.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);//Das Buffer Object soll als ein VBO gebunden werden.&lt;br /&gt;
glBufferData(GL_ARRAY_BUFFER,ElementCount*ElementSize,Data,GL_STATIC_DRAW);//Lade die Daten vom Data Pointer in den Grafikspeicher, dabei werden ElementSize*ElementCount Bytes kopiert.&lt;br /&gt;
&lt;br /&gt;
//Zeichenphase:&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,VBOID);&lt;br /&gt;
glDrawArrays(GL_POINTS,0,ElementCount);//Zeichne aus dem aktuell gebundenen VBO ElementCount Punkte, von Element 0 beginnend.&lt;br /&gt;
glBindBuffer(GL_ARRAY_BUFFER,0);//Binde das Objekt mit der ID 0, welches immer als Leeres Objekt definiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies reicht allerdings noch nicht aus, um unsere Punkte zu zeichnen, da aktuell weder ein Vertexshader noch ein Fragmentshader gebunden ist, der die verarbeitung der Daten übernimmt.&lt;br /&gt;
In OpenGL 1 bis 2 gab es eine Fixed Function Pipeline bzw. später eine automatisch anpassende Render Pipeline, bestehend aus einen generierten Vertex- und Fragment-Shader sowie den Fixed Function Teil.&lt;br /&gt;
OpenGL3 geht keinen der beiden Wege, sondern beschreitet einen neuen und legt fest, dass der Entwickler diese beiden Shader selber liefern muss und stellt den rest über Fixed Function bereit.&lt;br /&gt;
Der Vertex- und Fragment-Shader werden über eine extra Shadersprache implementiert, welche sich OpenGL Shader Language oder kurz GLSL nennt.&lt;br /&gt;
OpenGL3.1 bietet die GLSL Version 1.4 an, die nähere Behandlung dieses Themas würde aber den Rahmen des Artikels sprengen und wäre auch nicht mehr Einsteigerfreundlich.&lt;br /&gt;
Ich will daher die API zum verwalten von Shader Objekten näher erläutern und einfach ein fertigen Shadercode liefern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;//Erstellungsphase:&lt;br /&gt;
VSO=glCreateShader(GL_VERTEX_SHADER);//Erstellt ein Vertex Shader Objekt.&lt;br /&gt;
FSO=glCreateShader(GL_FRAGMENT_SHADER);//Erstellt ein Fragment Shader Objekt.&lt;br /&gt;
&lt;br /&gt;
glShaderSource(VSO,1,&amp;amp;VertexShaderSourcecode,0);//Man übergibt 1 Text, der den Shadercode enthält, mit dem letzten Parameter 0(alle übergebenen Strings sind 0 terminiert).&lt;br /&gt;
glShaderSource(FSO,1,&amp;amp;FragmentShaderSourcecode,0);&lt;br /&gt;
&lt;br /&gt;
glCompileShader(VSO);//Compiliert den Shadercode.&lt;br /&gt;
//glGetShaderiv(VSO,GL_COMPILE_STATUS,&amp;amp;compiled);//Sollte der Shadercode nicht korrekt sein, dann liefert compiled GL_FALSE zurück, sonnst GL_TRUE.&lt;br /&gt;
glCompileShader(FSO);&lt;br /&gt;
&lt;br /&gt;
ShaderID=glCreateProgram();//Erstellt ein Shader Programm Objekt, welches aus einen compilierten Vertex- und Fragment-Shader besteht.&lt;br /&gt;
glAttachShader(ShaderID,VSO);//Fügt den Vertexshader hinzu.&lt;br /&gt;
glAttachShader(ShaderID,FSO);//Fügt den Fragmentshader hinzu.&lt;br /&gt;
&lt;br /&gt;
glLinkProgram(ShaderID);//Wie bei einer Programmiersprache üblich, wird nach dem compilieren des Sourcode, die entstandenen Codesegmente zu einem Machienencode gelinkt und somit Referenzen aufgelöst.&lt;br /&gt;
//glGetProgramiv(ShaderID,GL_LINK_STATUS,&amp;amp;compiled);//Verhält sich wie bei den vorher compilierten Shader.&lt;br /&gt;
glEnableVertexAttribArray(glGetAttribLocation(ShaderID,Name));//Finde die Speicheradresse vom Attribute, mit entsprechendem Name und aktiviere das Attribute.&lt;br /&gt;
glVertexAttribPointer(glGetAttribLocation(ShaderID,Name),3,GL_FLOAT,GL_FALSE,0,0);//glVertexAttribPointer(Speicheradresse,Vektordimension,Vektortyp,Normalisieren,Datenoffset,Datenpointer)Wenn Datenpointer 0 ist, dann wird das aktuell gebundene Buffer Object verwendet, sonnst die Speicheradresse, auf die Datenpointer zeigt.&lt;br /&gt;
&lt;br /&gt;
Zeichenphase:&lt;br /&gt;
glUseProgram(ShaderID);//Binde das zuvor erstellte Programm als aktuell zu nutzendes Program.&lt;br /&gt;
glUniformMatrix4fv(glGetUniformLocation(ShaderID,VariableName),1,GL_FALSE,&amp;amp;ProjectionMatrix);//Sucht die Speicheradresse von VariableName, im Shader Program, übergibt diese dann einer weiteren Funktion, um an dieser Speicheradresse unsere ProjectionMatrix zu kopieren(2. Parameter gibt die Anzahl der Matrizen an und der 3. ob die Matrix Transponiert werden soll).&lt;br /&gt;
//zeichenaufruf&lt;br /&gt;
glUseProgram(0);//Binde das Program Objekt mit der ID 0, welches als Leerer Shader(kein Shader aktiv) implementiert ist.&amp;lt;/source&amp;gt;&lt;br /&gt;
Wir müssen dem Shader die VBO Daten verfügbar machen, dies geschieht über die VertexAttrib Funktionen.&lt;br /&gt;
Als erste muss ein Attribut, im Shader, lokalisiert und aktiviert werden, dazu wird glGetAttribLocation und glEnableVertexAttribArray verwendet.&lt;br /&gt;
Der zweite Schritt wäre dann das binden von unserem VBO an dieses Attribut, indem glGetAttribLocation,glVertexAttribPointer sowie glBindBuffer verwendet wird.&lt;br /&gt;
Bevor man das VertexAttrib setzen kann, muss das entsprechende VBO vorher gebunden werden, da immer nur ein BO aktiv sein kann.&lt;br /&gt;
Wenn man mehrere VBO verwenden will, um z.B. noch Farben oder Texturkoordinaten zu binden, dann bindet man erst den ersten Buffer, setzt das VertexAttribut, bindet den zweiten Buffer, setzt das VertexAttribut und so weiter. Das ganze muss nicht jeden Renderdurchgang neu machen, sondern kann es nach dem erstellen der Resourcen einmal machen.&lt;br /&gt;
Allerdings sind IndexBuffer und/oder einer der Vertexbuffer zu binden, damit der Shader die richtigen Buffer Objects nutzt.&lt;br /&gt;
Das ganze kann noch weiter vereinfacht werden, indem man ein VAO verwendet, dabei wird ein VAO erstellt, gebunden, dann alle VBO's erstellt, die Vertex Attribute gesetzt und das VAO wieder ausgebunden. Wenn man nun statt der VBO's und so weiter das VAO bindet, wird dieses alle anderen Resourcen(VBO, Vertexbassierte Flags), automatisch binden und setzen.&lt;br /&gt;
&lt;br /&gt;
VertexShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
uniform mat4 ProjectionMatrix;&lt;br /&gt;
&lt;br /&gt;
in vec4 Vertex;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_Position=ProjectionMatrix*Vertex;&lt;br /&gt;
  gl_FrontColor=vec4(1.0f,0.0f,0.0f,1.0f);&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FragmentShader:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;#version 140&lt;br /&gt;
&lt;br /&gt;
out vec4 gl_FragColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_FragColor=gl_Color;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24080</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24080"/>
				<updated>2009-08-06T15:50:03Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Orthogonal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
Mit r, l, b, t, f und n sind der rechte, linke, untere und obere Rand, sowie Distanz der far und near clipping plane, des Bildschirmausschnittes, gemeint. Die far und near clipping plane sind parallel, zum Betrachter, ausgerichtete Ebenen. Alles was zwischen diesen beiden Ebenen liegt wird gezeichnet und alles außerhalb wird in der Pipeline verworfen. Für die Orthogonal Matrix ist dieses weniger von Bedeutung, da nur mit aktiven Tiefentest und unterschiedlichen z-Werten, eine Auswirkung vorliegt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24079</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24079"/>
				<updated>2009-08-06T14:17:39Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Scale */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
[[Bild:skalierungsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:skalierungsmatrix.png&amp;diff=24078</id>
		<title>Datei:skalierungsmatrix.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:skalierungsmatrix.png&amp;diff=24078"/>
				<updated>2009-08-06T14:17:06Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix.png&amp;diff=24077</id>
		<title>Datei:rotationsmatrix.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix.png&amp;diff=24077"/>
				<updated>2009-08-06T14:09:57Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: hat eine neue Version von „Datei:rotationsmatrix.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24076</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24076"/>
				<updated>2009-08-06T04:30:55Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Projectionview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GlOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24075</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24075"/>
				<updated>2009-08-06T04:29:39Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Konstruieren von Matrizen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
===Perspektive===&lt;br /&gt;
&lt;br /&gt;
[[Bild:GluPerspective.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLuPerspective_Quads_X.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Orthogonal===&lt;br /&gt;
[[Bild:GLOrtho_Matrix.png]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Orthomode_Quads.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24074</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24074"/>
				<updated>2009-08-06T04:18:38Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Modelview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
[[Bild:translation-vs-rotation.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24073</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24073"/>
				<updated>2009-08-06T04:17:00Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Modelview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
[[Bild:weltkoordinatensystem-vs-modellkoordinatensystem.png]]&lt;br /&gt;
&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24072</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24072"/>
				<updated>2009-08-06T04:13:21Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Rotate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
Man kann die Rotation, der einzelnen Achsen in einem Schritt oder in 3 einzelne Aufteilen. Um die Rotationsmatrix besser zu verstehen werden erst einmal alle Achsen einzeln betrachtet.&lt;br /&gt;
&lt;br /&gt;
===Drehen um die X-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotx.gif]][[Datei:Tutorial_Nachsitzen_RotXMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Y-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_roty.gif]][[Datei:Tutorial_Nachsitzen_RotYMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Drehen um die Z-Achse===&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_rotz.gif]][[Datei:Tutorial_Nachsitzen_RotZMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
===Alle drei zusammen===&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotationsmatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix.png&amp;diff=24071</id>
		<title>Datei:rotationsmatrix.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:rotationsmatrix.png&amp;diff=24071"/>
				<updated>2009-08-06T04:12:41Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24067</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24067"/>
				<updated>2009-08-06T03:39:19Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Trigonometrie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
Da später in der Linearen Algebra auf die Trigonometrie zurück gegriffen werden wird, soll als erstes die notwendigen Grundlagen in diesem Bereich beleuchtet werden.&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
Man unterscheidet bei der Darstellung eines Winkels zwischen Bogenmaß(rad) und Gradmaß(deg).&lt;br /&gt;
Das Bogenmaß wird durch die Konstante Pi beschrieben, wobei der Wertebereich von 0 bis 2*Pi geht.&lt;br /&gt;
Das Gradmaß ist eine Einteilung, welche von 0 bis 360° abgebildet wird.&lt;br /&gt;
0° sind 0, 90° sind 0.5*Pi, 180° sind Pi, 270° sind 2/3*Pi und 360° sind 2*Pi oder auch 0° und 0.&lt;br /&gt;
&lt;br /&gt;
Um vom Bogenmaß in Gradmaß um zu rechnen, kann man folgende Formel verwenden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Umwandlung von Bogenmaß in Gradmaß gilt diese Formel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Für das sinnvolle arbeiten mit Winkelfunktionen benötigen wir einen Einheitskreis.&lt;br /&gt;
Dieser ist ein Kreis, dessen Radius 1 ist und somit eine Reihe von Funktionen zu lässt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:einheitsvektor.png]] &lt;br /&gt;
&lt;br /&gt;
Der Einheitskreis ist wie folgt Beschriftet. In Blau sind die Bogenmaß Werte angegeben, in dunkelgrün die äquivalenten Werte der Kosinusfunktion und Orang ist der Winkel. Wenn man den Kosinus und Sinus von dem Winkel errechnet, dann erhält man den Hellgrünen x und Roten y Wert. Egal welchen Winkel man in der Sinus- und Kosinus-Funktion einsetzt, der Wert wird nie größer 1 oder kleiner -1 werden. Aber halt, wieso &lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
Durch das Umstellen der Gleichungen kann man die einzelnen Winkel oder Seiten, eines Dreiecks, erhalten. Hierzu werden entweder 2 Seiten und ein Winkel oder 2 Winkel und eine Seite benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Kosinussatz&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
ermöglicht es, entweder aus drei gegebenen Seiten die Winkel auszurechnen oder aus zwei Seiten und ihrem Zwischenwinkel die gegenüber liegende Seite.&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
Es kann hilfreich sein, eine Sinus Funktion in eine Kosinus Funktion umzuwandeln oder umgekehrt. Hierzu benötigt man die Komplementärformeln, welche wie folgt aussehen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
Um den Rückgabewert, der Sinus- oder Kosinus-Funktion in den Bogenmaß um zu wandeln, gibt es folgende Umkehrfunktionen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu beachten, dass diese den Bogenmaß zurück geben und diese für Gradmaß entsprechend umgerechnet werden müssen.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:einheitsvektor.png&amp;diff=24059</id>
		<title>Datei:einheitsvektor.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:einheitsvektor.png&amp;diff=24059"/>
				<updated>2009-08-06T02:59:18Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: hat eine neue Version von „Datei:einheitsvektor.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:einheitsvektor.png&amp;diff=24058</id>
		<title>Datei:einheitsvektor.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:einheitsvektor.png&amp;diff=24058"/>
				<updated>2009-08-06T02:58:17Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24055</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24055"/>
				<updated>2009-08-06T02:11:09Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Vorwort */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
=Trigonometrie=&lt;br /&gt;
==Bogenmaß und Gradmaß==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_rad2deg.png]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Lineare_Algebra_deg2rad.png]]&lt;br /&gt;
&lt;br /&gt;
==Trigonometrische Funktionen==&lt;br /&gt;
Einheitskreis&lt;br /&gt;
&lt;br /&gt;
==Trigonometrie im allgemeinen Dreieck==&lt;br /&gt;
Man unterscheidet in der Trigonometrie zwischen rechtwinkligen Dreiecken und allgemeinen Dreiecken.&lt;br /&gt;
Die allgemeinen Dreiecke sind allerdings für den weiteren Verlauf des Artikels wichtig und werden deswegen behandelt.&lt;br /&gt;
&lt;br /&gt;
===Sinus- und Kosinussatz===&lt;br /&gt;
Ein wichtige Gleichung, welche später wieder aufgegriffen werden wird, ist der Kosinutzsatz.&lt;br /&gt;
Doch zuvor sollte der Sinussatz genauer betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:sinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:kosinussatz.png]]&lt;br /&gt;
&lt;br /&gt;
===Eigenschaften und Formeln===&lt;br /&gt;
&lt;br /&gt;
[[Datei:costosin_sintocos.png]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:umkehrfunktion_sin_cos_tan.png]]&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:umkehrfunktion_sin_cos_tan.png&amp;diff=24054</id>
		<title>Datei:umkehrfunktion sin cos tan.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:umkehrfunktion_sin_cos_tan.png&amp;diff=24054"/>
				<updated>2009-08-06T02:02:26Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:costosin_sintocos.png&amp;diff=24053</id>
		<title>Datei:costosin sintocos.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:costosin_sintocos.png&amp;diff=24053"/>
				<updated>2009-08-06T02:01:44Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:kosinussatz.png&amp;diff=24052</id>
		<title>Datei:kosinussatz.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:kosinussatz.png&amp;diff=24052"/>
				<updated>2009-08-06T02:00:33Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:sinussatz.png&amp;diff=24051</id>
		<title>Datei:sinussatz.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:sinussatz.png&amp;diff=24051"/>
				<updated>2009-08-06T01:59:58Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24050</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24050"/>
				<updated>2009-08-05T23:21:00Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Identity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&amp;lt;/source&amp;gt;&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24049</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24049"/>
				<updated>2009-08-05T23:18:56Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Konstruieren von Matrizen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
&lt;br /&gt;
==Identity==&lt;br /&gt;
Die Identity Matrix ist die Initialisierungsmatrix, mit der alle Matrizen belegt werden.&lt;br /&gt;
Diese ist recht einfach und hat denn Sinn, dass bei einer Multiplikation immer der Wert herraus kommt, mit dem diese Multipliziert wurde.&lt;br /&gt;
Wer aufmerksam gelsen hat, der wird nun an Einheitsvektoren denken und liegt richtig.&lt;br /&gt;
Aufgrund der beschaffenheit einer Matrix benötigen wir in jeder Reihe und Spalte jeweils ein Element, welche den Wert 1 an nimmt und die restlichen nehmen den Wert 0 an. Die sieht dann wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_IdentityMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
Es ist nicht zwingend notwendig die Einheitsvektoren in dieser Reihenfolge zu verwenden, man könnte auch den ersten und dritten Vektor tauschen und es würde trotzdem das gleiche Ergebnis geben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;static TKar_Vector&amp;lt;T&amp;gt; Identity[4];&lt;br /&gt;
&lt;br /&gt;
void LoadIdentity()&lt;br /&gt;
{&lt;br /&gt;
  for (int i=0;i&amp;lt;4;i++)&lt;br /&gt;
    m_Matrix[i]=Identity[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt; TKar_Vector&amp;lt;T&amp;gt; TKar_Matrix&amp;lt;T&amp;gt;::Identity[4]={TKar_Vector&amp;lt;T&amp;gt;(1.0f,0.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,1.0f,0.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,1.0f,0.0f),TKar_Vector&amp;lt;T&amp;gt;(0.0f,0.0f,0.0f,1.0f)};&lt;br /&gt;
==Translate==&lt;br /&gt;
Wenn man ein Vektor oder Matrix in x,y,z bewegen möchte, dann kann man dies mit einer Transformationsmatrix erreichen.&lt;br /&gt;
Dazu erstellt man eine Matrix, füllt sie mit der Identity Matrix und setzt dann x,y,z in der Matrix mit den zu x,y,z Werten, um die man etwas verschieben möchte.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Tutorial_Nachsitzen_MoveMatrix.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Translate(T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      m[3][0]=x;&lt;br /&gt;
      m[3][1]=y;&lt;br /&gt;
      m[3][2]=z;&lt;br /&gt;
      (*this)*=m;&lt;br /&gt;
    }&lt;br /&gt;
==Rotate==&lt;br /&gt;
Das Bewegen auf den 3 Achsen ist allerdings oft nicht ausreichend und deswegen gibt es auch eine Rortations-Matrix.&lt;br /&gt;
Die Rotations-Matrix wird durch 3 Vektoren beschrieben, welche jeweils für die x,y und z Achse zuständig sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;    void Rotate(T w,T x,T y,T z)&lt;br /&gt;
    {&lt;br /&gt;
      TKar_Matrix&amp;lt;KAR_MATH_TYPE&amp;gt; m;&lt;br /&gt;
      T rad=TKar_Math&amp;lt;T&amp;gt;::DegToRad(w);&lt;br /&gt;
      T c=TKar_Math&amp;lt;T&amp;gt;::Cos(rad);&lt;br /&gt;
      T ic=1.0-c;&lt;br /&gt;
      T s=TKar_Math&amp;lt;T&amp;gt;::Sin(rad);&lt;br /&gt;
      TKar_Vector&amp;lt;T&amp;gt; v(x,y,z,0.0);&lt;br /&gt;
      T mag=TKar_Math&amp;lt;T&amp;gt;::Sqrt((v*v).Sum());&lt;br /&gt;
&lt;br /&gt;
      if (mag&amp;lt;=1.0e-4)&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
      v[0]=x/mag;&lt;br /&gt;
      v[1]=y/mag;&lt;br /&gt;
      v[2]=z/mag;&lt;br /&gt;
&lt;br /&gt;
      m[0][0]=(v[0]*v[0]*ic)+c;&lt;br /&gt;
      m[0][1]=(v[0]*v[1]*ic)+(v[2]*s);&lt;br /&gt;
      m[0][2]=(v[0]*v[2]*ic)-(v[1]*s);&lt;br /&gt;
&lt;br /&gt;
      m[1][0]=(v[0]*v[1]*ic)-(v[2]*s);&lt;br /&gt;
      m[1][1]=(v[1]*v[1]*ic)+c;&lt;br /&gt;
      m[1][2]=(v[1]*v[2]*ic)+(v[0]*s);&lt;br /&gt;
&lt;br /&gt;
      m[2][0]=(v[0]*v[2]*ic)+(v[1]*s);&lt;br /&gt;
      m[2][1]=(v[1]*v[2]*ic)-(v[0]*s);&lt;br /&gt;
      m[2][2]=(v[2]*v[2]*ic)+c;&lt;br /&gt;
&lt;br /&gt;
      *this*=m;&lt;br /&gt;
    }&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24048</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24048"/>
				<updated>2009-08-05T22:01:09Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Multiplikation mit einer Matrix */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Es sieht recht aufwändig aus allerdings kann man es dank der vorigen Matrix-Vektor Multiplikation auf eine recht übersichtliches Maß runter streichen. Man braucht dann nur noch die Matrix a jeweils mit einen der Vektoren von Matrix b multiplizieren und hat die Matrix-Matrix Multiplikation erledigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
==Identity==&lt;br /&gt;
==Translate==&lt;br /&gt;
==Rotate==&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24047</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24047"/>
				<updated>2009-08-05T21:58:28Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Multiplikation mit einem Vektor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Um eine Matrix mit einem Vektor zu multiplizieren, braucht man man nur den Vektor[n] von der Matrix mit der Komponente[n] von dem Vektor multiplizieren und die resultierenden Vektoren anschließend addieren. Hierbei wird also ein Vektor mit einer einzelnen Komponente multipliziert, was weiter oben, bei den Vektoren, erklärt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
==Identity==&lt;br /&gt;
==Translate==&lt;br /&gt;
==Rotate==&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24046</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24046"/>
				<updated>2009-08-05T21:50:42Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Matrix */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte, welcher als Modelview Matrix abgebildet wird.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
==Identity==&lt;br /&gt;
==Translate==&lt;br /&gt;
==Rotate==&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24045</id>
		<title>Tutorial OpenGL3 Lineare Algebra</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_OpenGL3_Lineare_Algebra&amp;diff=24045"/>
				<updated>2009-08-05T21:47:28Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: /* Kreuzprodukt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Vorwort=&lt;br /&gt;
Lineare Algebra ist ein Teilgebiet der Mathematik und beschäftigt sich mit Vektorräumen.&lt;br /&gt;
Die für OpenGL wichtigen Unterbereiche sind Vektoren und Matrizen.&lt;br /&gt;
Der größte Teil der 3D Programmierung beschäftigt sich mit Linearer Algebra, daher sollte auch diese Grundlage eine besondere Aufmerksamkeit gewidmet werden.&lt;br /&gt;
Sollte der Inhalt vieleicht zu viel für einmal sein, dann wäre es ratsam in mehreren Etappen zu bewältigen aber es sollte auf jedenfall vollständig verstanden werden, bevor man sich ernsthaft mit OpenGL auseinander setzen will.&lt;br /&gt;
&lt;br /&gt;
=Vektor=&lt;br /&gt;
Ein Vektor kann mit einem Array oder einer Liste vergleicht werden, wenn man z.B. einen 3-dimensionalen Vektor meint, dann wäre es ein Array mit 3 Elementen.&lt;br /&gt;
Die übliche Schreibweise eines Vektors sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generischer_vektor.png]]&lt;br /&gt;
&lt;br /&gt;
Eine entsprechende C++ Representation wäre z.B. folgende&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    T m_Vec[ DIMENSION];&lt;br /&gt;
};&lt;br /&gt;
//typedef Vec4 TVector&amp;lt;float,4&amp;gt;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet auf der Grafikkarte immer 4-dimensionale Vektoren, auch wenn nur 1 oder 3 benötigt werden. Die restlichen Elemente des Vektors werden dann mit 0 aufgefüllt. Vektoren werden in OpenGL in 2 Arten verwendet, als absoluter und als relativer Wert. Absolute Werte wären z.B. Positionen und Farbwerte wärend relative Werte z.B. eine Transformation wäre. Der OpenGL Vektor sieht wie folgt aus.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
==Einheitsvektor==&lt;br /&gt;
Ein besondere Form eines Vektors ist der Einheitsvektor, welcher immer eine Länge von 1 ergibt. Der Einheitsvektor wird normalerweise als klein e gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung eines Einheitsvektors wird später in der der Magnitude und Normalisierung Funktion näher erläutert. Einheitsvektoren sind als Normalen/Richtungsvektoren in OpenGL im Einsatz und ist die Basis für Rotationen.&lt;br /&gt;
&lt;br /&gt;
==Addition==&lt;br /&gt;
[[Datei:addition_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Addition wird Komponentenweise ausgeführt, was bedeutet, man kann sich eine Addition von Vektoren als eine Addition von jeden einzelnen Element mit dem entsprechenden Element im anderem Vektor Vorstellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:addition_vektor_visual.png]]&lt;br /&gt;
&lt;br /&gt;
Die Addition von Vektoren kann man sich sehr einfach Vorstellen, in dem man die einzelnen Vektoren als Bewegungsbefehle sieht. Wenn man also 2 schritte vorwärts,einen schritt seitwärts laufen soll und danach ein halben Schritt vorwärts und ein Schritt seitwärts, dann kann man diese beiden Befehle auch zu einem Befehl zusammen fassen. Laufe 2 1/2 Schritte vorwärts und 2 Schritte Seitwärts und wir stehen am gleichen Punkt und dieser Befehl wäre dann unser Ergebnis Vektor c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator+(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]+b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a+b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subtraktion==&lt;br /&gt;
[[Datei:subtraktion_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:subtraktion_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
Hier gilt gleiches, wie bei der Addition, nur das Komponentenweise Subtrahiert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Subtraktion_vektor_visual.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Subtraktion eines Vektors wendet man den ersten Befehl an und läuft z.B. 2 Schritte nach vorne und einen Seitwärts, dann wendet man den 2. Schritt an aber wechselt das Vorzeichen jeder einzelnen Komponente. Also wird ein positive Komponente zu einer negativen und eine negative zu einer Positiven. Wenn man also einen schritt seitwärts,nach links, laufen soll, dann läuft man ein Schritt seitwärts, nach rechts, sowie vorwärts statt rückwärts. Man kann eine Subtraktion über eine Addition realisieren, wenn man jede Subtraktion, den rechten Vektor zuvor invertiert und dann addiert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator-(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]-b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a-b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Betrag==&lt;br /&gt;
[[Datei:magnitude_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Magnitude ist der Englische Begriff für die Berechnung des Betrags eines Vektors oder auch die Länge.&lt;br /&gt;
Die Länge des Vektors wird benötigt, wenn man einen Vektor Normalisieren will oder fest stellen möchte ob ein Vektor ein Einheitsvektor ist. &lt;br /&gt;
&lt;br /&gt;
[[Datei:betrag_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Der Betrag eines Vektors kann über den Satz des Pytagoras ermittelt werden, welcher die Wurzel der Summe, der Quadrate, aller Komponenten ist.&lt;br /&gt;
Dies ist natürlich für wenige gut Vorstellbar und daher hier mal eine bessere Erklärung. Ein Vektor kann in n Komponenten zerlegt werden, der 4 Komponenten Vektor von OpenGL in 4 Komponenten. Jede Komponente stellt eine Dimension dar, welche x,y,z und w sind. Pytagoras lernt man in der Schule im 2 Dimensionalen Raum kennen, also wie es im Abbild über diesen Text dargestellt ist. Die Regel besagt, das der Flächeninhalt einer Seite der Summe der anderen entspricht, also l²=x²+y².&lt;br /&gt;
Diese Flächen sind Quadratisch also hat jede Seite der Fläche die gleiche Kantenlänge. Wenn man die Quadratwurzel von der Fläche zieht, bekommt man also die Kantenlänge. Wenn man nun die Flächen von x,y,z und w summiert erhält man die Fläche l². Zieht man von l² die Quadratwurzel, dann hat man die Kantenlänge l von dem 4Komponenten Vektor, welche als Betrag oder Länge bezeichnet wird. Da bei einem Vektor w=0.0 gesetzt wird, hat diese keinen Einfluss auf diese Operation und wird in den Formeln auch in der Regel nicht mit hin geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T Magnitude(){&lt;br /&gt;
  T len=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    len+=this-&amp;gt;m_Vec[i]*this-&amp;gt;m_Vec[i];&lt;br /&gt;
  return sqrt(len);&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a; float len; len=a.Magnitude();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Skalarprodukt==&lt;br /&gt;
[[Datei:skalarprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Skalarprodukt erlaubt uns die Berechnung, des Winkels, zwischen 2 Vektoren. Hierfür müssen allerdings beide Vektoren Normalisiert sein, also jeweils einen Betrag von 1 ergeben. Sonnst muss dies noch nachträglich getan werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:skalarprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn die 2 Vektoren a und b vorliegen, sollte man davon ausgehen, dass der Betrag beider Vektoren jeweils 1 ist. Sollte es nicht der Fall sein, so wie im Bild über diesen Text, dann muss dies durch die Normalisierung nachgeholt werden. Dies passiert, indem man den Betrag beider Vektoren errechnet und dann diesen Komponentenweise mit dem Vektor dividiert. Die oben stehende Formel wird aus dem Kosinussatz abgeleitet und Umgestellt. Darraus ergibt sich am Ende, dass die Summe, der Komponentenweise multiplizierten Vektoren a und b den Kosinus des Winkels ergibt. Es ist wichtig zu beachten, dass nicht der Winkel sondern der Kosinus des Winkels in c wieder zu finden ist. Wenn man den Winkel haben möchte, dann muss man den Arkuskosinus von c berechnen und das Ergebnis von Bogenmaß in Gradmaß umwandeln um den Winkel(als Delta makiert) zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
T DotProduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  T alpha=T(0);&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    alpha+=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b; float c; c=a.DotProduct(b);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kreuzprodukt==&lt;br /&gt;
[[Datei:kreuzprodukt_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Das Kreuzprodukt errechnet einen Vektor, der senkrecht zu den Vektoren a und b steht, wenn a und b den selben Ursprung haben. Dieses Verhalten wird genutz, um die Normale einer Fläche zu errechnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:kreuzprodukt_vektor1.png]]&lt;br /&gt;
&lt;br /&gt;
Der berechnete Vektor hat wie schon erwähnt die Eigenschaft, dass er senkrecht zu den Vektoren a und b ausgerichtet ist. Dies bedeutet, dass der Winkel zwischen dem Berechnetem Winkel und a oder b immer 90° beträgt. Wenn a und b 2 von den 3 Eckpunkten, eines Dreiecks ist, dann zeigt der Vektor c senkrecht zum Dreieck und bildet den Richtungsvektor des Dreiecks. Wenn man nun noch diesen Vektor normalisiert, dann erhält man die Flächenormale. Diese hat den Betrag 1 und wird für verschiedene Rendertechniken, sowie Physikberechnungen benötigt.&lt;br /&gt;
Wenn z.B. ein Lichtstrahl solch ein Dreieck schneidet, dann kann man mit Hilfe des Vektors(vom Lichstrahl) und der Normale(der Fläche) den Reflektionsvektor berechnen und somit sagen, in welche Richtung sich das Licht weiter bewegen würde.&lt;br /&gt;
Es ist zu beachten, dass die Reihenfolge, in der man beide Vektoren Multipliziert einen Einfluss auf die Richtung, in die c zeigt.&lt;br /&gt;
Wenn man a und b tauscht, dann wechseln die Vorzeichen aller Komponenten von c.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Crossproduct(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  unsigned int prev,next;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
  {&lt;br /&gt;
    prev=i==0?DIMENSION-1:i-1;&lt;br /&gt;
    next=i+1 % DIMENSION;&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[next]*b.m_Vec[prev]-this-&amp;gt;m_Vec[prev]*b.m_Vec[next];&lt;br /&gt;
  }&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalisieren==&lt;br /&gt;
[[Datei:normalisieren_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Normalisierung wird der Betrag eines Vektors mit dem Vektor dividiert und man erhält ein Vektor, der in die Gleiche Richtung zeigt aber auf eine Länge 1 skaliert ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; Normalize(){&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  c=(*this)/this-&amp;gt;Magnitude();&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,c; c=a.Normalize();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Matrix=&lt;br /&gt;
Eine Matrix kann man sich als 2-dimensionalen Array mit n und m Länge.&lt;br /&gt;
&lt;br /&gt;
[[Datei:generische_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
OpenGL verwendet 4x4 große Matrizen und kann aus 4 Vektoren mit einer Länge von 4 konstruiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,int DIMENSION&amp;gt; &lt;br /&gt;
class TMatrix &lt;br /&gt;
{ &lt;br /&gt;
  protected: &lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt; m_Matrix[DIMENSION]; //Erlaubt uns das nutzen von der eigenen Vektorklarsse.&lt;br /&gt;
    T m_Array[DIMENSION*DIMENSION]; //für die LoadMatrix Funktion von OpenGL&lt;br /&gt;
  public:&lt;br /&gt;
    Tvector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator [](const int Index) &lt;br /&gt;
    { &lt;br /&gt;
      return m_Matrix[Index]; &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const T* GetMatrix1DArray() &lt;br /&gt;
    { &lt;br /&gt;
      int size=sizeof(T)*DIEMNSION; &lt;br /&gt;
      for (int i=0;i&amp;lt;DIMENSION;i++)&lt;br /&gt;
        memcpy(&amp;amp;m_Array[i*4],&amp;amp;m_Matrix[i][0],size); &lt;br /&gt;
      return &amp;amp;m_Array[0]; &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
//typedef Mat Tmatrix&amp;lt;float,4&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Matrizen brauchen wir nicht so viele Funktionen wie bei Vektoren, um genau zu sagen brauchen wir 2 Operationen. Diese Operationen lauten Transponieren und Multiplikation.&lt;br /&gt;
Bei der Matrix benötigen wir einige Konstruktionsfunktionen und zwar Identity, Translate, Rotate  und Scale Matrix. Diese Matrizen machen die ganze Arbeit für uns, wenn man sich in einem 3D Raum bewegen möchte.&lt;br /&gt;
&lt;br /&gt;
==Transponieren==&lt;br /&gt;
[[Datei:transponieren_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
Transponieren wird durch ein großes T über der Matrix dargestellt. Diese Funktion tauscht die Werte einer Matrix miteinander aus, so das aus einer Spalten konstruierten Matrix eine Zeilenweise konstruierte Matrix wird. Diese Funktion kann Hilfreich sein, wenn man zwischen Direct3D und OpenGL Daten austauschen will, denn nicht jeder nutzt spalten orientierte Matrizen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:opengl_matrix.png‎]][[Datei:d3d_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;void Transpose() //Transponieren für 4x4 Matrizen&lt;br /&gt;
{ &lt;br /&gt;
  swap(m_Matrix[0][1],m_Matrix[1][0]); //swap kopiert b in tmp, kopiert a in b und tmp in a&lt;br /&gt;
  swap(m_Matrix[0][2],m_Matrix[2][0]); &lt;br /&gt;
  swap(m_Matrix[0][3],m_Matrix[3][0]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[1][2],m_Matrix[2][1]); &lt;br /&gt;
  swap(m_Matrix[1][3],m_Matrix[3][1]); &lt;br /&gt;
&lt;br /&gt;
  swap(m_Matrix[2][3],m_Matrix[3][2]); &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiplikation==&lt;br /&gt;
Multiplikation ist die wichtigste Operation bei Matrizen, wenn wir uns mit OpenGL beschäftigen.&lt;br /&gt;
Dies liegt daran, dass OpenGL 2 verschiedene Matrizen verwendet, um Vektoren in Bildschirmkoordinaten um zu wandeln. Damit dies Funktioniert muss jeder Vektor mit diesen Matrizen jeweils multipliziert werden. Um eine Matrix zu manipulieren wird diese mit einer Konstruierten Matrix multipliziert. Diese Operation die ist meist ausgeführte Operation sowohl in der OpenGL Pipeline als auch in einem Spiel. Seit OpenGL3 gibt es kein Matrizen support mehr, was bedeutet, dass man diese selber implementieren muss und dann die fertigen Matrizen an OpenGL übergibt. Die lässt viel Raum für Optimierung und kann somit ein OpenGL3 Programm schneller machen als ein OpenGL2 Programm, wenn man zuvor die glTranslate,glRotate und weiteren Funktionen verwendet hat. Es ist also ratsam sich eine sehr Performance Bibliothek zu laden oder mit einem Performance Analyzer bewaffnet den eigenen Code zu optimieren.&lt;br /&gt;
===Multiplikation mit einem Vektor===&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix_vektor1.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; V) &lt;br /&gt;
{ &lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; v=m_Matrix[0]*V[0]+m_Matrix[1]*V[1]+m_Matrix[2]*V[2]+m_Matrix[3]*V[3];&lt;br /&gt;
  return v; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multiplikation mit einer Matrix===&lt;br /&gt;
[[Datei:multiplikation_matrix.png‎]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:multiplikation_matrix1.png‎]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;Tmatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; operator *(TMatrix&amp;lt;T,DIMENSION&amp;gt;&amp;amp; M) &lt;br /&gt;
{ &lt;br /&gt;
  TMatrix&amp;lt;T,DIMENSION&amp;gt; M1((*this)*M[0]), (*this)*M[1], (*this)*M[2], (*this)*M[3]); &lt;br /&gt;
  return M1; &lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
=Konstruieren von Matrizen=&lt;br /&gt;
==Identity==&lt;br /&gt;
==Translate==&lt;br /&gt;
==Rotate==&lt;br /&gt;
==Scale==&lt;br /&gt;
==Modelview==&lt;br /&gt;
==Projectionview==&lt;br /&gt;
==Orthoview==&lt;br /&gt;
&lt;br /&gt;
=Exkurs in die Optimierung=&lt;br /&gt;
==Vektoren==&lt;br /&gt;
Man hat oft den Fall, dass man auf der CPU mehrere Werte multiplizieren, dividieren, addieren, subtrahieren muss z.B. bei Bildbearbeitung.&lt;br /&gt;
&lt;br /&gt;
Dieses kann man Optimieren, indem man Vektoren verwendet, dabei wird ein Pixel als Vektor interpretiert und nun kann man alle Farbkanäle mit einen einzigen Aufruf verarbeiten lassen, indem man die Vektoroperationen verwendet. Wenn die Vektoren mit einer CPU Extension wie SSE oder MMX implementiert wurden, dann werden die 4 Komponenten eines Vektors sogar gleichzeitig verarbeitet. Sollte man nur 2 oder 3 Komponenten verwenden, dann füllt man die restlichen Komponenten mit 0 auf bzw. ignoriert sie einfach beim auslesen der Komponenten.&lt;br /&gt;
===Multiplikation===&lt;br /&gt;
[[Datei:multiplikation_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Die Multiplikation von 2 Vektoren miteinander ist eigentlich nicht definiert, da es wenig Sinn macht aber wir haben nun einen Verwendungszweck gefunden und definieren ihn. Bei dieser Operation gilt das gleiches, wie bei der Addition und Subtraktion, nur mit einem Mulltiplikations Operator. Die Bildverarbeitung wird sich mit mehr Geschwindigkeit bedanken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator*(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]*b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a*b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Division===&lt;br /&gt;
[[Datei:division_vektor.png‎]]&lt;br /&gt;
&lt;br /&gt;
Bei der Division muss man aufpassen, dass keiner der Element im Divisor 0 ist, da sonnst eine Division mit 0 entsteht. Eine Division mit 0 hat ein Interrupt zufolge, welcher das Programm zum beenden bittet. Also sollte man dies Vorher überprüfen oder bei einer Division den Aufruf mit einer entsprechenden Routine den Fehler abfangen. Sonnst verhält es wie bei der Multiplikation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;template&amp;lt;typename T,unsigned int DIMENSION&amp;gt;&lt;br /&gt;
class TVector&lt;br /&gt;
{&lt;br /&gt;
//...&lt;br /&gt;
TVector&amp;lt;T,DIMENSION&amp;gt; operator/(const TVector&amp;lt;T,DIMENSION&amp;gt;&amp;amp; b)&lt;br /&gt;
{&lt;br /&gt;
  TVector&amp;lt;T,DIMENSION&amp;gt; c;&lt;br /&gt;
  for (unsigned int i=0;i&amp;lt;DIMENSION,i++)&lt;br /&gt;
    c.m_Vec[i]=this-&amp;gt;m_Vec[i]/b.m_Vec[i];&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
//...&lt;br /&gt;
};&lt;br /&gt;
//Vec4 a,b,c; c=a/b;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programmiersprache,Compiler und CPU Extension==&lt;br /&gt;
Die Optimierung ist von Programmiersprache und Compiler stark abhängig. Wärend Delphi, Freepascal und MS VSC++ Compiler man nur aufwändig SSE,MMX und weitere CPU Extension implementieren kann, hat der GCC eine Vektorextension und seit Version 4.x auch eine Funktionsoptimierung. Die Vektorextension von GCC ist ein Parser Erweiterung, welche einen Typ als ein bestimmten Vektortyp(z.B. Float Länge 4) bestimmt und dann entsprechend alle Operationen in SSE1-4 oder MMX Code umwandelt. Seit Version 4.x gibt es eine Funktionsoptimierung, welche erlaubt im Quellcode mehrere Optimierungen gleichzeitig zu nutzen. Die bedeutet, dass man eine Funktion, wie Vektor.Magnitude() mehrfach implementiert und dann jeweils eine andere Optimierungs Aktiviert. Also Vektor.Magnitude_sse(), Vektor.Magnitude_mmx(),... und dann die jeweilige Funktion mit SSE,MMX oder ohne Optimierung markiert. Der Compiler optimiert dann diese Funktion für die jeweilige CPU Extension und man kann dann im Programmcode entsprechend der gegebenen Hardware auf die beste Mögliche Funktion umlenken. Dies hat den Vorteil, dass man nur noch eine Binary hat und alle CPUs(mehr Kern, ein Kern, Intel Petium1-4, AMD Athlon und so weiter) der gleichen Architektur Optimiert  Unterstützen kann. Dies ist ist nützlich, wenn man alte CPUs unterstützen will. Es würde sich also lohnen, wenn man sich viel Ärger und Code sparen will, den Code in GCC als Bibliothek zu implementieren und statisch oder dynamisch zu linken.&lt;br /&gt;
&lt;br /&gt;
==Templates und Generics==&lt;br /&gt;
Eine Optimierung die sich bei C++ stark auswirkt sind Templates, da diese die Eigenschaft aufweisen vom Compiler generiert zu werden. Dies bedeutet je nach Qualität des Compilers kann dieser Code starke Performanceschübe bekommen, wenn man die Operationen in Templates verpackt, da der Compiler oft Optimierungen machen kann, die man selber nicht kennt oder gar nicht machen will(Kompatibilität und Übersichtlichkeit). Templates entrollen z.B. konstante For Schleifen und wie schon vorher in den Codeschnipseln zu sehen war, haben wir davon einige in den Vektor Operationen. Das Entrollen von Schleifen entfernt eine menge Balast(Counter,Prüfung,..) welche sich auf die Performance auswirkt. Templates reduziert den Codeaufwand, da man viele weitere Implementierungen einspart(Vektor von Typ float, int, unsigned short, unsigned int, double, ...).&lt;br /&gt;
&lt;br /&gt;
==Testen testen testen==&lt;br /&gt;
Wenn man Performance Test macht, dann sollte man verschiedene Test machen und einer der teilweise oft unterschätzt wird ist der Create und Free Test. Sobald man eine Klasse benutzt wird beim erstellen des Objektes immer ein Speicher alloziert und dann der Konstruktor aufgerufen, was  Zeit kostet. Man sollte also einmal ein Test durchführen, der Vektoren und Matrizen erstellt und zerstört. Die Operation Test sollten die Vektoren und Matrizen vorher erstellen und in der Schleife wiederverwendet werden und nach beenden des Performance Trackings erst zerstört werden.&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:kreuzprodukt_vektor1.png&amp;diff=24044</id>
		<title>Datei:kreuzprodukt vektor1.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:kreuzprodukt_vektor1.png&amp;diff=24044"/>
				<updated>2009-08-05T21:44:27Z</updated>
		
		<summary type="html">&lt;p&gt;TAK2004: hat eine neue Version von „Datei:kreuzprodukt vektor1.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TAK2004</name></author>	</entry>

	</feed>