Kamera (3)
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.