Kamera (3)

Aus DGL Wiki
Version vom 15. Oktober 2005, 15:51 Uhr von Andyh (Diskussion | Beiträge)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Ich habe einfach alle unktionen meiner Toolsammlung hierhin kopiert. Ich wollte jetzt nicht offline etwas weglöschen was vielleicht benötigt wird. Ihr findet also hier einen ganzen Wust von Funktionen, der zum Betrieb der Kamera nicht benötigt wird. Vielleicht könnt Ihr das eine oder andere aber brauchen...


unit OpenGLUtil;

interface

uses DglOpenGL, Math, Windows, Graphics, SysUtils, Dialogs;

type

 TProjection=(Frustum, Orthographic, Perspective);
 TGLPlace=packed record
   X,Y,Z: glFloat;
 end;
 TScale=packed record
   X,Y,Z: glFloat;
 end;
 TGLPosition=packed record
   X,Y,Z,W: glFloat;
 end;
 TPosition = packed record
   X,Y,Z,W: GLdouble;
 end;
 TGLVector = packed record
   X,Y,Z: GLfloat;
 end;
 TGLVectorArray = array of TGLvector;
 TGLfloatArray = array of TGLfloat;
 TGKVector = packed record
   X,Y,Z: GLfloat;
 end;
 TAngle = packed record
   X,Y,Z: GLdouble;
 end;
 TGLColor=record
   red,green,blue,alpha: GLclampf;
 end;
 TRotation = packed record
   angle, x, y, z: GLfloat;
 end;
 TTextureInfo = packed record
   BitmapName: string;
   TextureNum: GLUint;
 end;
 TTextureList = array of TTextureInfo;
 TMatrix = array [0..3,0..3] of TGLFloat;
 TArrMatrix = array [0..15] of TGLFloat;
 TFrustum = array [0..5,0..3] of TGLFloat;
 TArrVector = array [0..3] of TGLFloat;
 function Multiply (Color: TGLcolor; mult: TGLdouble): TGLcolor;
 procedure MatrixMultiply(M1, M2:TArrMatrix; var M3: TArrMatrix);
 function MakeVector(X,Y,Z:TGLFloat):TArrVector;overload;
 function MakeVector(X,Y,Z,W:TGLFloat):TArrVector;overload;
 procedure Normalize(aVector:TArrVector;var RVec:TArrVector);overload;
 procedure Normalize(aVector:TGLVector;var RVec:TGLVector);overload;
 function GetIdentity:TMatrix;
 function GetArrIdentity:TArrMatrix;
 function MatrixTranspose(const M:TMatrix):TMatrix;register;
 function VectorRotateX(v:TArrVector;a:TGLFloat):TArrVector;overload;
 function VectorRotateY(v:TArrVector;a:TGLFloat):TArrVector;overload;
 function VectorRotateZ(v:TArrVector;a:TGLFloat):TArrVector;overload;
 function VectorRotateX(v:TGLVector;a:TGLFloat):TGLVector;overload;
 function VectorRotateY(v:TGLVector;a:TGLFloat):TGLVector;overload;
 function VectorRotateZ(v:TGLVector;a:TGLFloat):TGLVector;overload;
 function GL2GKVector (V: TGLVector): TGKVector;
 function GK2GLVector (V: TGKVector): TGLVector;
 function GL2WinColor (GLcol: TGLcolor): TColor;
 function Win2GLColor (WinCol: Tcolor): TGLcolor;
 function CalcNormale (V1, V2, V3: TGLVector): TGLVector;
 function CrossProduct(V1, V2: TGLVector): TGLVector;
 function DotProduct (V1, V2: TGLVector): GLdouble;
 function LoadTexture(Filename: String; var Texture: GLuint): Boolean;
 function Magnitude(V1 : TGLVector) : GLfloat;
 function MultiplyVektor (V1, V2: TGLVector): TGLVector;
 function ScalarProduct (V1, V2: TGLVector): GLdouble;
 function SubtractVector (Vec1, Vec2: TGLVector): TGLVector;overload;
 function SubtractVector (Vec: TGLVector; X, Y, Z: TGLdouble): TGLVector;overload;
 function AddVector (Vec1, Vec2: TGLVector): TGLVector;overload;
 function AddVector (Vec: TGLVector; X, Y, Z: TGLdouble): TGLVector;overload;
 procedure CopyVector (FromVektor: TGLVector; var ToVektor: TGLVector);
 procedure InitVector (var V1: TGLVector; x, y, z: TGLdouble);overload;
 procedure InitVector (var V1: TGKVector; x, y, z: TGLdouble);overload;
 procedure InitVector (var V1: TArrVector; x, y, z: TGLdouble);overload;
 procedure InitScale (var S1: TScale; x, y, z: TGLdouble);
 procedure LoadBitmap(Filename: String;
                      out Width: Cardinal;
                      out Height: Cardinal;
                      out pData: Pointer);
 procedure GetRotation (V1, V2: TGLVector;
                        var Rotation: TRotation;
                        var normale: TGLVector);
 function MakeTextureFromBitmap (Bitmap: string; var BitmapList: TTextureList): GLenum;
 procedure EnableTexture (Texture: GLenum; TextureTiled: boolean);
 procedure DisableTexture;
 function TextToGLVector (VTxt: string): TGLVector;
 function TextToGKVector (VTxt: string): TGKVector;
 function GKVectorToText (V1: TGKVector): string;
 function GLVectorToText (V1: TGLVector): string;
 function MyCone (Start, Ende: TGLVector;
                  RadiusStart, RadiusEnde: TGLfloat;
                  Slices: Integer): boolean;
 function InvertMatrix (src: TArrMatrix; var inverse: TArrMatrix): boolean;

const

 C_X = 0;
 C_Y = 1;
 C_Z = 2;
 C_W = 3;
 C_EPS:TGLFloat=0.01;
 C_DEGTORAD:TGLFloat=3.1412/180;
 C_RADTODEG:TGLFloat=180/3.1412;
 C_LAMBDA_INCREMENT:TGLFloat=0.01;


implementation

function MyPower (Base: extended; Exp: integer): extended; // ist nicht ausprogrammiert, funktioniert nur für eine // einfache zweierpotenz begin

 result := Base * Base;

end;

procedure CopyVector (FromVektor: TGLVector; var ToVektor: TGLVector); begin

 ToVektor.X := FromVektor.X;
 ToVektor.Y := FromVektor.Y;
 ToVektor.Z := FromVektor.Z;

end;

function SubtractVector (Vec1, Vec2: TGLVector): TGLVector; // subtrahiert Vec2 von vec1 und gibt das ergebnis in vec3 zurück var

 Vec3: TGLVector;

begin

 Vec3 .X := Vec1.X - Vec2.X;
 Vec3 .Y := Vec1.Y - Vec2.Y;
 Vec3 .Z := Vec1.Z - Vec2.Z;
 result := Vec3;

end;

function SubtractVector (Vec: TGLVector; X, Y, Z: TGLdouble): TGLVector; // subtrahiert X, Y, Z von vec.x, vec.y, vec.z und gibt das // ergebnis zurück begin

 Vec .X := Vec.X - X;
 Vec .Y := Vec.Y - Y;
 Vec .Z := Vec.Z - Z;
 result := Vec;

end;

function AddVector (Vec1, Vec2: TGLVector): TGLVector; // addiert Vec2 auf vec1 und gibt das ergebnis in vec3 zurück var

 Vec3: TGLVector;

begin

 Vec3 .X := Vec1.X + Vec2.X;
 Vec3 .Y := Vec1.Y + Vec2.Y;
 Vec3 .Z := Vec1.Z + Vec2.Z;
 result := Vec3;

end;

function AddVector (Vec: TGLVector; X, Y, Z: TGLdouble): TGLVector; // addiert X, Y, Z auf vec.x, vec.y, vec.z und gibt das // ergebnis zurück begin

 Vec .X := Vec.X + X;
 Vec .Y := Vec.Y + Y;
 Vec .Z := Vec.Z + Z;
 result := Vec;

end;

function Magnitude(V1 : TGLVector) : GLfloat; var

 Ergebnis: GLdouble;

begin // gibt die länge des vektors zurück

 Ergebnis := MyPower(V1.X,2)+MyPower(V1.Y,2)+MyPower(V1.Z,2);
 try
   result := sqrt(Ergebnis);
 except
   result := 0;
 end;

end;

function DotProduct (V1, V2: TGLVector): GLdouble; var

 len1, len2: GLdouble;
 Ergebnis: GLdouble;

begin

 len1 := Magnitude (V1);
 len2 := Magnitude (V2);
 Ergebnis := ScalarProduct (V1, V2);
 Ergebnis := arccos (Ergebnis / (len1 * len2));
 result := radtodeg (Ergebnis) * 2.0;

end;

function CrossProduct(V1, V2: TGLVector): TGLVector; var

 CrossVec: TGLVector;

begin

 CrossVec.X := ((V1.Y*V2.Z) - (V1.Z*V2.Y));
 CrossVec.Y := ((V1.Z*V2.X) - (V1.X*V2.Z));

CrossVec.Z := ((V1.X*V2.Y) - (V1.Y*V2.X));

 result := CrossVec;
end;

function CalcNormale (V1, V2, V3: TGLVector): TGLVector; var

 Kreuz: TGLvector;
 V1V2, V1V3: TGLvector;

begin

 // gibt die normale von 3 vektoren zurück (die senkrechte auf die
 // durch die drei vektoren gebildete ebene)
 V1V2 := SubtractVector (V2, V1);
 V1V3 := SubtractVector (V3, V1);
 Kreuz := CrossProduct (V1V2, V1V3);
 Normalize (Kreuz, result);

end;

procedure InitVector (var V1: TGLVector; x, y, z: TGLdouble); begin

 V1.x := x;
 V1.y := y;
 V1.z := z;

end;

procedure InitVector (var V1: TGKVector; x, y, z: TGLdouble); begin

 V1.x := x;
 V1.y := y;
 V1.z := z;

end;

procedure InitVector (var V1: TArrVector; x, y, z: TGLdouble); begin

 V1[C_X] := x;
 V1[C_Y] := y;
 V1[C_Z] := z;

end;

procedure InitScale (var S1: TScale; x, y, z: TGLdouble); begin

 S1.x := x;
 S1.y := y;
 S1.z := z;

end;

function MultiplyVektor (V1, V2: TGLVector): TGLVector; var

 multVec: TGLVector;

begin // zwei vektoren miteinander multiplizieren

 multVec.X := V1.X * V2.X;
 multVec.Y := V1.Y * V2.Y;
 multVec.Z := V1.Z * V2.Z;
 result := multvec;

end;

function ScalarProduct (V1, V2: TGLVector): GLdouble; begin // die summe der potenzen der einzelnen achsen von zwei vektoren errechnen

 result := (V1.X*V2.X +
            V1.Y*V2.Y +
            V1.Z*V2.Z);

end;

function LoadTexture(Filename: String; var Texture: GLuint): Boolean; var

 pData: Pointer;
 Width: Cardinal;
 Height: Cardinal;

begin

 pData :=nil;
 LoadBitmap(Filename, Width, Height, pData);
 if (Assigned(pData)) then
   Result := True
 else
 begin
   Result := False;
   MessageBox(0, PChar('Unable to load ' + filename), 'Loading Textures', MB_OK);
   Halt(1);
 end;
 glGenTextures(1, @Texture);
 glBindTexture(GL_TEXTURE_2D, Texture);
 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  {Texture blends with object background}
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { only first two can be used }
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); { all of the above can be used }
 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData);

end;

procedure LoadBitmap(Filename: String;

                    out Width: Cardinal;
                    out Height: Cardinal;
                    out pData: Pointer);

var

 FileHeader: BITMAPFILEHEADER;
 InfoHeader: BITMAPINFOHEADER;
 Palette: array of RGBQUAD;
 BitmapFile: THandle;
 BitmapLength: Cardinal;
 PaletteLength: Cardinal;
 ReadBytes: Cardinal;
 Front: ^Byte;
 Back: ^Byte;
 Temp: Byte;
 I : Cardinal;

begin

 BitmapFile := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 if (BitmapFile = INVALID_HANDLE_VALUE) then begin
   MessageBox(0, PChar('Error opening "' + Filename), PChar('BMP Unit'), MB_OK);
   Exit;
 end;
 // Get header information
 ReadFile(BitmapFile, FileHeader, SizeOf(FileHeader), ReadBytes, nil);
 ReadFile(BitmapFile, InfoHeader, SizeOf(InfoHeader), ReadBytes, nil);
 // Get palette
 PaletteLength := InfoHeader.biClrUsed;
 SetLength(Palette, PaletteLength);
 ReadFile(BitmapFile, Palette, PaletteLength, ReadBytes, nil);
 if (ReadBytes <> PaletteLength) then begin
   MessageBox(0, PChar('Error reading palette'), PChar('BMP Unit'), MB_OK);
   Exit;
 end;
 Width := InfoHeader.biWidth;
 Height := InfoHeader.biHeight;
 BitmapLength := InfoHeader.biSizeImage;
 if BitmapLength = 0 then
   BitmapLength := Width * Height * InfoHeader.biBitCount Div 8;
 // Get the actual pixel data
 GetMem(pData, BitmapLength);
 ReadFile(BitmapFile, pData^, BitmapLength, ReadBytes, nil);
 if (ReadBytes <> BitmapLength) then begin
   MessageBox(0, PChar('Error reading bitmap data'), PChar('BMP Unit'), MB_OK);
   Exit;
 end;
 CloseHandle(BitmapFile);
 // Bitmaps are stored BGR and not RGB, so swap the R and B bytes.
 for I :=0 to Width * Height - 1 do
 begin
   Front := Pointer(Cardinal(pData) + I*3);
   Back := Pointer(Cardinal(pData) + I*3 + 2);
   Temp := Front^;
   Front^ := Back^;
   Back^ := Temp;
 end;

end;

function GK2GLVector (V: TGKVector): TGLVector; // ändert Gauss-Krüger Koordinaten in OpenGL Koordinaten um begin

 result.X := V.X;
 result.Y := V.Z;
 result.Z := V.Y;

end;

function GL2GKVector (V: TGLVector): TGKVector; // ändert OpenGL Koordinaten in Gauss-Krüger Koordinaten um begin

 result.X := V.X;
 result.Y := V.Z;
 result.Z := V.Y;

end;

function Win2GLColor (WinCol: TColor): TGLcolor; begin

 result.Red := GetRValue (WinCol);
 result.Green := GetGValue (WinCol);
 result.Blue := GetBValue (WinCol);
 result.Alpha := 1.0;

end;

function GL2WinColor (GLcol: TGLcolor): TColor; begin

 result := Rgb (StrToInt (FloatToStr (int (GLcol.Red))),
                StrToInt (FloatToStr (int (GLcol.Green))),
                StrToInt (FloatToStr (int (GLcol.Blue))));

end;

procedure GetRotation (V1, V2: TGLVector;

                      var Rotation: TRotation;
                      var normale: TGLVector);

var

 tmpCyl, tmpZiel, nullVec: TGLVector;
 ResultLen: TGLVector;
 VectorLength: GLfloat;

begin

 // temporäre vektoren initialisieren
 InitVector (nullVec, 0,0,0);
 InitVector (tmpCyl, 0,0,0);
 // länge des zu drehenden objekts ermitteln
 ResultLen := SubtractVector (V2, V1);
 VectorLength := Magnitude (ResultLen);
 // vektoren zur bildung der dreiecksfläche bilden.
 // die schenkel schneiden sich im nullpunkt
 // der Cylinder läuft immer entlang der Z-Achse
 tmpCyl.Z := VectorLength;
 tmpZiel := SubtractVector (V2, V1);
 tmpZiel.Z := tmpZiel.Z + VectorLength;
 // senkrechte zu den beiden vektoren bilden
 // (um diese achse soll nachher gedreht werden)
 // drehachse für späteren gebrauch speichern
 normale := CalcNormale (tmpCyl, tmpZiel, nullVec);
 // um "Angle" Grad soll nachher gedreht werden
 Rotation.Angle := DotProduct(tmpCyl, tmpZiel);
 Rotation.X     := normale.X;
 Rotation.Y     := normale.Y;
 Rotation.Z     := normale.Z;

end;

function MakeTextureFromBitmap (Bitmap: string; var BitmapList: TTextureList): GLenum; // die funktion lädt die in Bitmap übergebene Grafik und gibt die Textturnummer // zurück. ist das bitmap schon im array BitmapList enthalten, wird die bereits // vergeben nummer zurückgegeben. var

 i, Laenge: integer;

begin

 result := 0;
 if length (trim (Bitmap)) = 0 then
   exit;
 Bitmap := trim (uppercase (Bitmap));
 // suchen, ob die textur schon geladen wurde
 Laenge := length (BitmapList);
 if Laenge > 0 then
   for i := 0 to Laenge-1 do
   begin
     if (BitmapList[i].BitmapName = Bitmap) and
        (BitmapList[i].TextureNum > 0) then
       result := BitmapList[i].TextureNum;
   end;
 if (result = 0) then
 begin
   setlength (BitmapList, Laenge+1);
   BitmapList[Laenge].BitmapName := Bitmap;
   BitmapList[Laenge].TextureNum := 0;
   if LoadTexture (Bitmap, BitmapList[Laenge].TextureNum) then
     result := BitmapList[Laenge].TextureNum;
 end;

end;

procedure EnableTexture (Texture: GLenum; TextureTiled: boolean); begin

 glEnable(GL_TEXTURE_2D);
 glBindTexture(GL_TEXTURE_2D, Texture);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 if TextureTiled then
 begin
   glTexparameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   glTexparameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 end
 else
 begin
   glTexparameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexparameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 end;

end;

procedure DisableTexture; begin

 glDisable(GL_TEXTURE_2D);

end;

function TextToGLVector (VTxt: string): TGLVector; const

 subdelim: char = '/';

var

 posi: integer;
 V1: TGLVector;

begin

 InitVector (V1,0,0,0);
 posi := pos (subdelim, VTxt);
 if posi > 0 then
 begin
   V1.X := StrToFloat (copy (VTxt, 1, posi-1));
   VTxt := copy (VTxt, posi+1, length (VTxt));
   posi := pos (subdelim, VTxt);
 end;
 if posi > 0 then
 begin
   V1.Y := StrToFloat (copy (VTxt, 1, posi-1));
   VTxt := copy (VTxt, posi+1, length (VTxt));
 end;
 if length (VTxt) > 0 then V1.Z := StrToFloat (VTxt);
 result := V1;

end;

function TextToGKVector (VTxt: string): TGKVector; const

 subdelim: char = '/';

var

 posi: integer;
 V1: TGKVector;

begin

 InitVector (V1,0,0,0);
 posi := pos (subdelim, VTxt);
 if posi > 0 then
 begin
   V1.X := StrToFloat (copy (VTxt, 1, posi-1));
   VTxt := copy (VTxt, posi+1, length (VTxt));
   posi := pos (subdelim, VTxt);
 end;
 if posi > 0 then
 begin
   V1.Y := StrToFloat (copy (VTxt, 1, posi-1));
   VTxt := copy (VTxt, posi+1, length (VTxt));
 end;
 if length (VTxt) > 0 then V1.Z := StrToFloat (VTxt);
 result := V1;

end;

function GKVectorToText (V1: TGKVector): string; const

 subdelim: char = '/';

var

 VTxt: string;

begin

 VTxt := FloatToStr (V1.X) + subdelim;
 VTxt := VTxt + FloatToStr (V1.Y) + subdelim;
 VTxt := VTxt + FloatToStr (V1.Z);
 result := VTxt;

end;

function GLVectorToText (V1: TGLVector): string; const

 subdelim: char = '/';

var

 VTxt: string;

begin

 VTxt := FloatToStr (V1.X) + subdelim;
 VTxt := VTxt + FloatToStr (V1.Y) + subdelim;
 VTxt := VTxt + FloatToStr (V1.Z);
 result := VTxt;

end;

function MyCone (Start, Ende: TGLVector;

                RadiusStart, RadiusEnde: TGLfloat;
                Slices: Integer): boolean;

var

 Slice: Integer;
 Laenge, xdelta, zdelta: TGLfloat;
 V1, V2, V3, V4: TGLvector;
 A, B: Single;
 tmpVec: TGLvector;

begin

 result := true;
 // laenge des kegels berechnen
 // hierbei wird davon ausgegangen, dass der kegel senkrecht steht
 // Laenge := Ende.y - Start.y;
 tmpVec := SubtractVector (Start, Ende);
 Laenge := Magnitude (tmpVec);
 // radiusdifferenz berechnen
 xdelta := Start.x - Ende.x;
 zdelta := Start.z - Ende.z;
 xdelta := -xdelta;
 //zdelta := zdelta;
 glBegin (GL_TRIANGLE_STRIP);
 // der kegel wird entlang der z-achse gezeichnet
 V1.z := 0;
 V2.z := 0;
 V3.z := Laenge;
 V4.z := Laenge;
 for Slice := 1 to Slices do begin
   A := 2 * PI * Slice / Slices;
   B := 2 * PI * (Slice+1) / Slices;
   V1.x := sin(A)*RadiusStart;
   V1.y := cos(A)*RadiusStart;
   V2.x := sin(B)*RadiusStart;
   V2.y := cos(B)*RadiusStart;
   // umsetzung von y nach z-achse
   V3.x := (sin(B)*RadiusEnde)+xdelta;
   V3.y := (cos(B)*RadiusEnde)+zdelta;
   V4.x := (sin(A)*RadiusEnde)+xdelta;
   V4.y := (cos(A)*RadiusEnde)+zdelta;
   //Normale := CalcNormale (V1, V3, V2);
   //glNormal3fv(@Normale);
   if Slice = 1 then
   begin
     glTexCoord2f(1,0); glVertex3fv(@V1);
     glTexCoord2f(1,1); glVertex3fv(@V4);
     glTexCoord2f(1-Slice/Slices,0); glVertex3fv(@V2);
     glTexCoord2f(1-Slice/Slices,1); glVertex3fv(@V3);
   end
   else
   begin
     glTexCoord2f(1-Slice/Slices,0); glVertex3fv(@V2);
     glTexCoord2f(1-Slice/Slices,1); glVertex3fv(@V3);
   end;
   // aktuellen und nächsten punkt des kreises (oben und unten)
   // nehmen und ein rechteck zeichnen. alle rechtecke zusammen sollten
   // einen geschlossenen kegel ergeben.
   //glBegin(GL_QUADS);
   //  glNormal3fv(@Normale);
   //  glTexCoord2f(0,0); glVertex3fv(@V2);
   //  glTexCoord2f(1,0); glVertex3fv(@V1);
   //  glTexCoord2f(1,1); glVertex3fv(@V4);
   //  glTexCoord2f(0,1); glVertex3fv(@V3);
   //glEnd;
 end;
 glEnd;  // (GL_TRIANGLE_STRIP)

end;

{-----------------------------------------------------------------------------} {----------------------------- für TRUVCamera --------------------------------} {-----------------------------------------------------------------------------}

procedure MatrixMultiply(M1, M2: TArrMatrix; var M3: TArrMatrix); // multiplies two 4x4 matrices begin

 glPushMatrix();
 glLoadMatrixf(@M1);
 glMultMatrixf(@M2);
 glGetFloatv(GL_MODELVIEW_MATRIX,@M3);
 glPopMatrix();

end;

function MakeVector(X,Y,Z:TGLFloat):TArrVector; begin

 result[0]:=x;
 result[1]:=y;
 result[2]:=z;

end;

function MakeVector(X,Y,Z,W:TGLFloat):TArrVector; begin

 result[0]:=x;
 result[1]:=y;
 result[2]:=z;
 result[3]:=w;

end;

procedure Normalize(aVector:TArrVector;var RVec:TArrVector); var

  d:double;

begin

 InitVector (RVec,1,1,1);
 d:=Sqrt(Sqr(aVector[C_X])+Sqr(aVector[C_Y])+Sqr(aVector[C_Z]));
 if d=0 then
 begin
   //raise exception.Create('Zero length vector(Normalize 1)');
   exit;
 end;
 RVec[C_X]:=aVector[C_X]/d;
 RVec[C_Y]:=aVector[C_Y]/d;
 RVec[C_Z]:=aVector[C_Z]/d;

end;

procedure Normalize(aVector:TGLVector; var RVec:TGLVector); var

  d:double;

begin

 InitVector (RVec,1,1,1);
 d:=Sqrt(Sqr(aVector.X)+Sqr(aVector.Y)+Sqr(aVector.Z));
 if d=0 then
 begin
   //raise exception.Create('Zero length vector(Normalize 2)');
   exit;
 end;
 RVec.X:=aVector.X/d;
 RVec.Y:=aVector.Y/d;
 RVec.Z:=aVector.Z/d;

end;

function GetIdentity:TMatrix; begin

 result[0,0]:=1.0;result[0,1]:=0.0;result[0,2]:=0.0;result[0,3]:=0.0;
 result[1,0]:=0.0;result[1,1]:=1.0;result[1,2]:=0.0;result[1,3]:=0.0;
 result[2,0]:=0.0;result[2,1]:=0.0;result[2,2]:=1.0;result[2,3]:=0.0;
 result[3,0]:=0.0;result[3,1]:=0.0;result[3,2]:=0.0;result[3,3]:=1.0;

end;

function GetArrIdentity:TArrMatrix; begin

 result[0]:=1.0;result[1]:=0.0;result[2]:=0.0;result[3]:=0.0;
 result[4]:=0.0;result[5]:=1.0;result[6]:=0.0;result[7]:=0.0;
 result[8]:=0.0;result[9]:=0.0;result[10]:=1.0;result[11]:=0.0;
 result[12]:=0.0;result[13]:=0.0;result[14]:=0.0;result[15]:=1.0;

end;

function MatrixTranspose(const M:TMatrix):TMatrix;register; var

  i,j:integer;

begin

    for i:=0 to 3 do
        for j:=0 to 3 do
            result[i,j]:=M[j,i];

end;

function VectorRotateX(v:TArrVector;a:TGLFloat):TArrVector; var

  temp: TArrVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp[C_X] := v[C_x];
    temp[C_Y] := (v[C_Y] * cosine) + (v[C_Z] * -sine);
    temp[C_Z] := (v[C_Y] * sine) + (v[C_Z] * cosine);
    result := temp;

end;

function VectorRotateY(v: TArrVector;a:TGLFloat):TArrVector; var

  temp: TArrVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp[C_x] := (v[C_x] * cosine) + (v[C_z] * sine);
    temp[C_y] := v[C_y];
    temp[C_z] := (v[C_x] * -sine) + (v[C_z] * cosine);
    result := temp;

end;

function VectorRotateZ(v: TArrVector; a: TGLFloat):TArrVector; var

 temp: TArrVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp[C_x] := (v[C_x] * cosine) + (v[C_y] * -sine);
    temp[C_y] := (v[C_x] * sin(a)) + (v[C_y] * cosine);
    temp[C_z] := v[C_z];
    result := temp;

end;

function VectorRotateX(v:TGLVector;a:TGLFloat):TGLVector; var

  temp: TGLVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp.X := v.x;
    temp.Y := (v.Y * cosine) + (v.Z * -sine);
    temp.Z := (v.Y * sine) + (v.Z * cosine);
    result := temp;

end;

function VectorRotateY(v: TGLVector;a:TGLFloat):TGLVector; var

  temp: TGLVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp.x := (v.x * cosine) + (v.z * sine);
    temp.y := v.y;
    temp.z := (v.X * -sine) + (v.z * cosine);
    result := temp;

end;

function VectorRotateZ(v: TGLVector; a: TGLFloat):TGLVector; var

 temp: TGLVector;
  sine,cosine:TGLFloat;

begin

    a:=a*C_DEGTORAD;
    sine:=Sin(a);
    cosine:=Cos(a);
    temp.x := (v.x * cosine) + (v.y * -sine);
    temp.y := (v.x * sin(a)) + (v.y * cosine);
    temp.z := v.z;
    result := temp;

end;

{-----------------------------------------------------------------------------} {-------------------------------- allgemein ----------------------------------} {-----------------------------------------------------------------------------}

function InvertMatrix (src: TArrMatrix; var inverse: TArrMatrix): boolean; var

 t: TGLdouble;
 i, j, k, swap: integer;
 tmp: TMatrix;

begin

 result := false;
 inverse := GetArrIdentity;
 for i := 0 to 3 do
 begin
   for j := 0 to 3 do
   begin
     tmp[i][j] := src[i*4+j];
   end;
 end;
 for i := 0 to 3 do
 begin
   // look for largest element in column.
   swap := i;
   for j := i+1 to 3 do
   begin
     if abs(tmp[j][i]) > abs(tmp[i][i]) then
     begin
       swap := j;
     end;
   end;
   if not (swap = i) then
   begin
     // swap rows.
     for k := 0 to 3 do
     begin
       t := tmp[i][k];
       tmp[i][k] := tmp[swap][k];
       tmp[swap][k] := t;
       t := inverse[i*4+k];
       inverse[i*4+k] := inverse[swap*4+k];
       inverse[swap*4+k] := t;
     end;
   end;
   if tmp[i][i] = 0 then
   begin
   { no non-zero pivot.  the matrix is singular, which
     shouldn't happen.  This means the user gave us a bad
     matrix. }
     exit;
   end;
   t := tmp[i][i];
   for k := 0 to 3 do
   begin
     tmp[i][k] := tmp[i][k]/t;
     inverse[i*4+k] := inverse[i*4+k]/t;
   end;
   for j := 0 to 3 do
   begin
     if not (j = i) then
     begin
       t := tmp[j][i];
       for k := 0 to 3 do
       begin
         tmp[j][k] := tmp[j][k]-tmp[i][k]*t;
         inverse[j*4+k] := inverse[j*4+k]-inverse[i*4+k]*t;
       end;
     end;
   end;
 end;
 result := true;

end;

function Multiply (Color: TGLcolor; mult: TGLdouble): TGLcolor; begin

 Color.red := Color.red * mult;
 Color.green := Color.green * mult;
 Color.blue := Color.blue * mult;

end;

end.