www.pudn.com > 1000y.rar > D3DUtils.pas, change:2006-03-07,size:23921b

```unit D3DUtils;

interface

uses
Windows, Math,
{\$IfDef StandardDX}
DirectDraw, Direct3D;
{\$Else}
DirectX;
{\$EndIf}

const
g_PI       =  3.14159265358979323846; // Pi
g_Uhel       =  g_PI / 180  ;
g_2_PI     =  6.28318530717958623200; // 2 * Pi
g_PI_DIV_2 =  1.57079632679489655800; // Pi / 2
g_PI_DIV_4 =  0.78539816339744827900; // Pi / 4
g_INV_PI   =  0.31830988618379069122; // 1 / Pi
g_HUGE     =  1.0e+38;                // Huge number for FLOAT
g_EPSILON  =  1.0e-5;                 // Tolerance for FLOATs

function ProjectionMatrix( near_plane, far_plane,  fov_horiz,  fov_vert:real): TD3DMatrix ;
function MakeD3DVector(x, y, z: TD3DValue): TD3DVector;
function MakeD3DVertex(hv, nv: TD3DVector; tu, tv: TD3DValue): TD3DVertex;

function D3DMath_IsZero(a: Double; fTol: Double{ = g_EPSILON}): Boolean;
procedure D3DMath_MatrixMultiply(var q: TD3DMatrix; const a, b: TD3DMatrix);
function D3DMath_MatrixInvert(var q: TD3DMatrix; const a: TD3DMatrix): HResult;
function D3DMath_VectorMatrixMultiply(var vDest: TD3DVector; const vSrc: TD3DVector;
const mat: TD3DMatrix): HResult;
function D3DMath_VertexMatrixMultiply(var vDest: TD3DVertex; const vSrc: TD3DVertex;
const mat: TD3DMatrix): HResult;
procedure D3DMath_QuaternionFromRotation(var x, y, z, w: Double;
const v: TD3DVector; fTheta: Double);
procedure D3DMath_RotationFromQuaternion(var v: TD3DVector; var fTheta: Double;
x, y, z, w: Double);
procedure D3DMath_QuaternionFromAngles(var x, y, z, w: Double; fYaw, fPitch, fRoll: Double);
procedure D3DMath_MatrixFromQuaternion(var mat: TD3DMatrix; x, y, z, w: Double);
procedure D3DMath_QuaternionFromMatrix(var x, y, z, w: Double; var mat: TD3DMatrix);
procedure D3DMath_QuaternionMultiply(var Qx, Qy, Qz, Qw: Double;
Ax, Ay, Az, Aw, Bx, By, Bz, Bw: Double);
procedure D3DMath_QuaternionSlerp(var Qx, Qy, Qz, Qw: Double;
Ax, Ay, Az, Aw, Bx, By, Bz, Bw, fAlpha: Double);

procedure D3DUtil_InitSurfaceDesc(var ddsd: TDDSurfaceDesc2; dwFlags, dwCaps: DWORD);
procedure D3DUtil_InitMaterial(var mtrl: TD3DMaterial7; r, g, b, a: Double);
procedure D3DUtil_InitLight(var light: TD3DLight7; ltType: TD3DLightType; x, y, z: Double);
procedure D3DUtil_SetIdentityMatrix(var m: TD3DMatrix);
function D3DUtil_SetViewMatrix(var mat: TD3DMatrix;  const vFrom, vAt, vWorldUp: TD3DVector): HResult;
function D3DUtil_SetProjectionMatrix(var mat: TD3DMatrix; fFOV, fAspect, fNearPlane, fFarPlane: Double): HResult;
procedure D3DUtil_SetRotateXMatrix(var mat: TD3DMatrix; fRads: Double);
procedure D3DUtil_SetRotateYMatrix(var mat: TD3DMatrix; fRads: Double);
procedure D3DUtil_SetRotateZMatrix(var mat: TD3DMatrix; fRads: Double);
procedure D3DUtil_SetRotationMatrix(var mat: TD3DMatrix; var vDir: TD3DVector; fRads: Double);

implementation

function MakeD3DVector(x, y, z: TD3DValue): TD3DVector;
begin
Result.x := x;
Result.y := y;
Result.z := z;
end;

function MakeD3DVertex(hv, nv: TD3DVector; tu, tv: TD3DValue): TD3DVertex;
begin
Result.x := hv.x;
Result.y := hv.y;
Result.z := hv.z;
Result.nx := nv.x;
Result.ny := nv.y;
Result.nz := nv.z;
Result.tu := tu;
Result.tv := tv;
end;

function ProjectionMatrix( near_plane,     // distance to near clipping plane
far_plane,     // distance to far clipping plane
fov_horiz,     // horizontal field of view angle, in radians
fov_vert:real): TD3DMatrix ;    // vertical field of view angle, in radians
var h,w,Q:real;
begin
Fov_horiz:=g_Uhel * Fov_horiz;
Fov_Vert:=g_Uhel * Fov_Vert;

w := cotan(fov_horiz*0.5);
h := cotan(fov_vert*0.5);
Q := far_plane/(far_plane - near_plane);

result._11 := w;
result._22 := h;
result._33 := Q;
result._43 := -Q*near_plane;
result._34 := 1;
end;
// end of ProjectionMatrix()

//-----------------------------------------------------------------------------
// File: D3DMath.cpp
//
// Desc: Shortcut macros and functions for using DX objects
//
//-----------------------------------------------------------------------------

function D3DMath_IsZero(a: Double; fTol: Double{ = g_EPSILON}): Boolean;
begin
if a<0 then
Result := a>=-fTol
else
Result := a<=fTol;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_MatrixMultiply()
// Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
//       this operation was changed from the previous version of the DXSDK.
//-----------------------------------------------------------------------------
procedure D3DMath_MatrixMultiply(var q: TD3DMatrix; const a, b: TD3DMatrix);
type
PArrayD3DValue = ^TArrayD3DValue;
TArrayD3DValue = array[0..15] of TD3DValue;
var
pA, pB, pQ: PArrayD3DValue;
i, j, k: Integer;
begin
FillChar(q, SizeOf(q), 0);

pA := @a;
pB := @b;
pQ := @q;
for i:=0 to 3 do
for j:=0 to 3 do
for k:=0 to 3 do
pQ[4*i+j] := pQ[4*i+j] + pA[4*i+k] * pB[4*k+j];
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_MatrixInvert()
// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
//       works for matrices with [0 0 0 1] for the 4th column.
//-----------------------------------------------------------------------------
function D3DMath_MatrixInvert(var q: TD3DMatrix; const a: TD3DMatrix): HResult;
var
fDetInv: Double;
begin
if (abs(a._44-1.0)>0.001) or (abs(a._14) > 0.001) or (abs(a._24) > 0.001) or (abs(a._34) > 0.001) then
begin
Result := E_INVALIDARG;
Exit;
end;

fDetInv := 1.0 / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) -
a._12 * ( a._21 * a._33 - a._23 * a._31 ) +
a._13 * ( a._21 * a._32 - a._22 * a._31 ) );

q._11 :=  fDetInv * ( a._22 * a._33 - a._23 * a._32 );
q._12 := -fDetInv * ( a._12 * a._33 - a._13 * a._32 );
q._13 :=  fDetInv * ( a._12 * a._23 - a._13 * a._22 );
q._14 := 0.0;

q._21 := -fDetInv * ( a._21 * a._33 - a._23 * a._31 );
q._22 :=  fDetInv * ( a._11 * a._33 - a._13 * a._31 );
q._23 := -fDetInv * ( a._11 * a._23 - a._13 * a._21 );
q._24 := 0.0;

q._31 :=  fDetInv * ( a._21 * a._32 - a._22 * a._31 );
q._32 := -fDetInv * ( a._11 * a._32 - a._12 * a._31 );
q._33 :=  fDetInv * ( a._11 * a._22 - a._12 * a._21 );
q._34 := 0.0;

q._41 := -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 );
q._42 := -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 );
q._43 := -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 );
q._44 := 1.0;

Result := S_OK;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_VectorMatrixMultiply()
// Desc: Multiplies a vector by a matrix
//-----------------------------------------------------------------------------
function D3DMath_VectorMatrixMultiply(var vDest: TD3DVector; const vSrc: TD3DVector;
const mat: TD3DMatrix): HResult;
var
x, y, z, w: Double;
begin
x := vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
y := vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
z := vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
w := vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;

if abs(w) < g_EPSILON then
begin
Result := E_INVALIDARG;
Exit;
end;

vDest.x := x/w;
vDest.y := y/w;
vDest.z := z/w;

Result := S_OK;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_VertexMatrixMultiply()
// Desc: Multiplies a vertex by a matrix
//-----------------------------------------------------------------------------
function D3DMath_VertexMatrixMultiply(var vDest: TD3DVertex; const vSrc: TD3DVertex;
const mat: TD3DMatrix): HResult;
var
pSrcVec, pDestVec: PD3DVector;
begin
pSrcVec := @vSrc.x;
pDestVec := @vDest.x;

Result := D3DMath_VectorMatrixMultiply(pDestVec^, pSrcVec^, mat);
if SUCCEEDED(Result) then
begin
pSrcVec  := @vSrc.nx;
pDestVec := @vDest.nx;
Result := D3DMath_VectorMatrixMultiply(pDestVec^, pSrcVec^, mat);
end;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_QuaternionFromRotation()
// Desc: Converts a normalized axis and angle to a unit quaternion.
//-----------------------------------------------------------------------------
procedure D3DMath_QuaternionFromRotation(var x, y, z, w: Double;
const v: TD3DVector; fTheta: Double);
begin
x := sin( fTheta/2.0 ) * v.x;
y := sin( fTheta/2.0 ) * v.y;
z := sin( fTheta/2.0 ) * v.z;
w := cos( fTheta/2.0 );
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_RotationFromQuaternion()
// Desc: Converts a normalized axis and angle to a unit quaternion.
//-----------------------------------------------------------------------------
procedure D3DMath_RotationFromQuaternion(var v: TD3DVector; var fTheta: Double;
x, y, z, w: Double);
begin
fTheta := arccos(w) * 2.0;
v.x    := x / sin( fTheta/2.0 );
v.y    := y / sin( fTheta/2.0 );
v.z    := z / sin( fTheta/2.0 );
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_QuaternionFromAngles()
// Desc: Converts euler angles to a unit quaternion.
//-----------------------------------------------------------------------------
procedure D3DMath_QuaternionFromAngles(var x, y, z, w: Double; fYaw, fPitch, fRoll: Double);
var
fSinYaw, fSinPitch, fSinRoll, fCosYaw, fCosPitch, fCosRoll: Double;
begin
fSinYaw   := sin( fYaw/2.0 );
fSinPitch := sin( fPitch/2.0 );
fSinRoll  := sin( fRoll/2.0 );
fCosYaw   := cos( fYaw/2.0 );
fCosPitch := cos( fPitch/2.0 );
fCosRoll  := cos( fRoll/2.0 );

x := fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
y := fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
z := fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
w := fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_MatrixFromQuaternion()
// Desc: Converts a unit quaternion into a rotation matrix.
//-----------------------------------------------------------------------------
procedure D3DMath_MatrixFromQuaternion(var mat: TD3DMatrix; x, y, z, w: Double);
var
xx, yy, zz, xy, xz, yz, wx, wy, wz: Double;
begin
xx := x*x; yy := y*y; zz := z*z;
xy := x*y; xz := x*z; yz := y*z;
wx := w*x; wy := w*y; wz := w*z;

mat._11 := 1 - 2 * ( yy + zz );
mat._12 :=     2 * ( xy - wz );
mat._13 :=     2 * ( xz + wy );

mat._21 :=     2 * ( xy + wz );
mat._22 := 1 - 2 * ( xx + zz );
mat._23 :=     2 * ( yz - wx );

mat._31 :=     2 * ( xz - wy );
mat._32 :=     2 * ( yz + wx );
mat._33 := 1 - 2 * ( xx + yy );

mat._14 := 0.0; mat._24 := 0.0; mat._34 := 0.0;
mat._41 := 0.0; mat._42 := 0.0; mat._43 := 0.0;
mat._44 := 1.0;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_QuaternionFromMatrix()
// Desc: Converts a rotation matrix into a unit quaternion.
//-----------------------------------------------------------------------------
procedure D3DMath_QuaternionFromMatrix(var x, y, z, w: Double; var mat: TD3DMatrix);
var
s: Double;
xx, yy, zz, xy, xz, yz, wx, wy, wz: Double;
begin
if( mat._11 + mat._22 + mat._33 > 0.0 )then
begin
s := sqrt( mat._11 + mat._22 + mat._33 + mat._44 );

x := (mat._23-mat._32) / (2*s);
y := (mat._31-mat._13) / (2*s);
z := (mat._12-mat._21) / (2*s);
w := 0.5 * s;
end;

xx := x*x; yy := y*y; zz := z*z;
xy := x*y; xz := x*z; yz := y*z;
wx := w*x; wy := w*y; wz := w*z;

mat._11 := 1 - 2 * ( yy + zz );
mat._12 :=     2 * ( xy - wz );
mat._13 :=     2 * ( xz + wy );

mat._21 :=     2 * ( xy + wz );
mat._22 := 1 - 2 * ( xx + zz );
mat._23 :=     2 * ( yz - wx );

mat._31 :=     2 * ( xz - wy );
mat._32 :=     2 * ( yz + wx );
mat._33 := 1 - 2 * ( xx + yy );

mat._14 := 0.0; mat._24 := 0.0; mat._34 := 0.0;
mat._41 := 0.0; mat._42 := 0.0; mat._43 := 0.0;
mat._44 := 1.0;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_QuaternionMultiply()
// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
//-----------------------------------------------------------------------------
procedure D3DMath_QuaternionMultiply(var Qx, Qy, Qz, Qw: Double;
Ax, Ay, Az, Aw, Bx, By, Bz, Bw: Double);
var
Dx, Dy, Dz, Dw: Double;
begin
Dx :=  Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
Dy := -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
Dz :=  Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
Dw := -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;

Qx := Dx; Qy := Dy; Qz := Dz; Qw := Dw;
end;

//-----------------------------------------------------------------------------
// Name: D3DMath_SlerpQuaternions()
// Desc: Compute a quaternion which is the spherical linear interpolation
//       between two other quaternions by dvFraction.
//-----------------------------------------------------------------------------
procedure D3DMath_QuaternionSlerp(var Qx, Qy, Qz, Qw: Double;
Ax, Ay, Az, Aw, Bx, By, Bz, Bw, fAlpha: Double);
var
fCosTheta: Double;
fBeta: Double;
fTheta: Double;
begin
// Compute dot product (equal to cosine of the angle between quaternions)
fCosTheta := Ax*Bx + Ay*By + Az*Bz + Aw*Bw;

// Check angle to see if quaternions are in opposite hemispheres
if fCosTheta < 0.0 then
begin
// If so, flip one of the quaterions
fCosTheta := -fCosTheta;
Bx := -Bx; By := -By; Bz := -Bz; Bw := -Bw;
end;

// Set factors to do linear interpolation, as a special case where the
// quaternions are close together.
fBeta := 1.0 - fAlpha;

// If the quaternions aren't close, proceed with spherical interpolation
if 1.0 - fCosTheta > 0.001 then
begin
fTheta := arccos( fCosTheta );

fBeta  := sin( fTheta*fBeta ) / sin( fTheta);
fAlpha := sin( fTheta*fAlpha ) / sin( fTheta);
end;

// Do the interpolation
Qx := fBeta*Ax + fAlpha*Bx;
Qy := fBeta*Ay + fAlpha*By;
Qz := fBeta*Az + fAlpha*Bz;
Qw := fBeta*Aw + fAlpha*Bw;
end;

//-----------------------------------------------------------------------------
// File: D3DUtil.cpp
//
// Desc: Shortcut macros and functions for using DX objects
//
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Name: D3DUtil_InitSurfaceDesc()
// Desc: Helper function called to build a DDSURFACEDESC2 structure,
//       typically before calling CreateSurface() or GetSurfaceDesc()
//-----------------------------------------------------------------------------
procedure D3DUtil_InitSurfaceDesc(var ddsd: TDDSurfaceDesc2; dwFlags, dwCaps: DWORD);
begin
FillChar(ddsd, SizeOf(ddsd), 0);
ddsd.dwSize                 := SizeOf(ddsd);
ddsd.dwFlags                := dwFlags;
ddsd.ddsCaps.dwCaps         := dwCaps;
ddsd.ddpfPixelFormat.dwSize := SizeOf(ddsd.ddpfPixelFormat);
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_InitMaterial()
// Desc: Helper function called to build a D3DMATERIAL7 structure
//-----------------------------------------------------------------------------
procedure D3DUtil_InitMaterial(var mtrl: TD3DMaterial7; r, g, b, a: Double);
begin
FillChar(mtrl, SizeOf(mtrl), 0);
mtrl.dcvDiffuse.r := r; mtrl.dcvAmbient.r := r;
mtrl.dcvDiffuse.g := g; mtrl.dcvAmbient.g := g;
mtrl.dcvDiffuse.b := b; mtrl.dcvAmbient.b := b;
mtrl.dcvDiffuse.a := a; mtrl.dcvAmbient.a := a;
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_InitLight()
// Desc: Initializes a D3DLIGHT7 structure
//-----------------------------------------------------------------------------
procedure D3DUtil_InitLight(var light: TD3DLight7; ltType: TD3DLightType; x, y, z: Double);
begin
FillChar(light, SizeOf(light), 0);
light.dltType        := ltType;
light.dcvDiffuse.r   := 1.0;
light.dcvDiffuse.g   := 1.0;
light.dcvDiffuse.b   := 1.0;
light.dcvSpecular    := light.dcvDiffuse;
light.dvPosition.x   := x; light.dvDirection.x := x;
light.dvPosition.y   := y; light.dvDirection.y := y;
light.dvPosition.z   := z; light.dvDirection.z := z;
light.dvAttenuation0 := 1.0;
light.dvRange        := D3DLIGHT_RANGE_MAX;
end;

procedure D3DUtil_SetIdentityMatrix(var m: TD3DMatrix);
begin
m._12 := 0; m._13 := 0; m._14 := 0; m._21 := 0; m._23 := 0; m._24 := 0;
m._31 := 0; m._32 := 0; m._34 := 0; m._41 := 0; m._42 := 0; m._43 := 0;
m._11 := 1; m._22 := 1; m._33 := 1; m._44 := 1;
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetViewMatrix()
// Desc: Given an eye point, a lookat point, and an up vector, this
//       function builds a 4x4 view matrix.
//-----------------------------------------------------------------------------
function D3DUtil_SetViewMatrix(var mat: TD3DMatrix;  const vFrom, vAt, vWorldUp: TD3DVector): HResult;
var
vView: TD3DVector;
fLength: Double;
fDotProduct: Double;
vUp: TD3DVector;
vRight: TD3DVector;
begin
// Get the z basis vector, which points straight ahead. This is the
// difference from the eyepoint to the lookat point.
vView := VectorSub(vAt, vFrom);

fLength := VectorMagnitude( vView );
if fLength < 0.1e-6 then
begin
Result := E_INVALIDARG;
Exit;
end;

// Normalize the z basis vector
vView := VectorDivS(vView, fLength);

// Get the dot product, and calculate the projection of the z basis
// vector onto the up vector. The projection is the y basis vector.
fDotProduct :=VectorDotProduct( vWorldUp, vView );

vUp := VectorSub(vWorldUp, VectorMulS(vView, fDotProduct));

// If this vector has near-zero length because the input specified a
// bogus up vector, let's try a default up vector
fLength := VectorMagnitude(vUp);
if 1e-6 > fLength then
begin
vUp := VectorSub(MakeD3DVector(0, 1, 0), VectorMulS(vView, vView.y));

// If we still have near-zero length, resort to a different axis.
fLength := VectorMagnitude(vUp);
if 1e-6 > fLength then
begin
vUp := VectorSub(MakeD3DVector(0, 0, 1), VectorMulS(vView, vView.z));

fLength := VectorMagnitude(vUp);
if  1e-6 > fLength then
begin
Result := E_INVALIDARG;
Exit;
end;
end;
end;

// Normalize the y basis vector
vUp := VectorDivS(vUp, fLength);

// The x basis vector is found simply with the cross product of the y
// and z basis vectors
vRight := VectorCrossProduct( vUp, vView );

// Start building the matrix. The first three rows contains the basis
// vectors used to rotate the view to point at the lookat point
D3DUtil_SetIdentityMatrix( mat );
mat._11 := vRight.x;    mat._12 := vUp.x;    mat._13 := vView.x;
mat._21 := vRight.y;    mat._22 := vUp.y;    mat._23 := vView.y;
mat._31 := vRight.z;    mat._32 := vUp.z;    mat._33 := vView.z;

// Do the translation values (rotations are still about the eyepoint)
mat._41 := - VectorDotProduct( vFrom, vRight );
mat._42 := - VectorDotProduct( vFrom, vUp );
mat._43 := - VectorDotProduct( vFrom, vView );

Result := S_OK;
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetProjectionMatrix()
// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
//       from the field-of-view (fov, in y), aspect ratio, near plane (D),
//       and far plane (F). Note that the projection matrix is normalized for
//       element [3][4] to be 1.0. This is performed so that W-based range fog
//       will work correctly.
//-----------------------------------------------------------------------------
function D3DUtil_SetProjectionMatrix(var mat: TD3DMatrix; fFOV, fAspect, fNearPlane, fFarPlane: Double): HResult;
var
w, h, Q: Double;
begin
if (abs(fFarPlane-fNearPlane)<0.01) or (abs(sin(fFOV/2))<0.01) then
begin
Result := E_INVALIDARG;
Exit;
end;

w := fAspect * ( cos(fFOV/2)/sin(fFOV/2) );
h :=   1.0   * ( cos(fFOV/2)/sin(fFOV/2) );
Q := fFarPlane / ( fFarPlane - fNearPlane );

FillChar(mat, SizeOf(mat), 0);
mat._11 := w;
mat._22 := h;
mat._33 := Q;
mat._34 := 1.0;
mat._43 := -Q*fNearPlane;

Result := S_OK;
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateXMatrix()
// Desc: Create Rotation matrix about X axis
//-----------------------------------------------------------------------------
procedure D3DUtil_SetRotateXMatrix(var mat: TD3DMatrix; fRads: Double);
begin
D3DUtil_SetIdentityMatrix( mat );
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateYMatrix()
// Desc: Create Rotation matrix about Y axis
//-----------------------------------------------------------------------------
procedure D3DUtil_SetRotateYMatrix(var mat: TD3DMatrix; fRads: Double);
begin
D3DUtil_SetIdentityMatrix( mat );
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateZMatrix()
// Desc: Create Rotation matrix about Z axis
//-----------------------------------------------------------------------------
procedure D3DUtil_SetRotateZMatrix(var mat: TD3DMatrix; fRads: Double);
begin
D3DUtil_SetIdentityMatrix( mat );
end;

//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotationMatrix
// Desc: Create a Rotation matrix about vector direction
//-----------------------------------------------------------------------------
procedure D3DUtil_SetRotationMatrix(var mat: TD3DMatrix; var vDir: TD3DVector; fRads: Double);
var
fCos, fSin: Double;
v: TD3DVector;
begin
v    := VectorNormalize( vDir );

mat._11 := ( v.x * v.x ) * ( 1.0 - fCos ) + fCos;
mat._12 := ( v.x * v.y ) * ( 1.0 - fCos ) - (v.z * fSin);
mat._13 := ( v.x * v.z ) * ( 1.0 - fCos ) + (v.y * fSin);

mat._21 := ( v.y * v.x ) * ( 1.0 - fCos ) + (v.z * fSin);
mat._22 := ( v.y * v.y ) * ( 1.0 - fCos ) + fCos ;
mat._23 := ( v.y * v.z ) * ( 1.0 - fCos ) - (v.x * fSin);

mat._31 := ( v.z * v.x ) * ( 1.0 - fCos ) - (v.y * fSin);
mat._32 := ( v.z * v.y ) * ( 1.0 - fCos ) + (v.x * fSin);
mat._33 := ( v.z * v.z ) * ( 1.0 - fCos ) + fCos;

mat._14 := 0; mat._24 := 0; mat._34 := 0;
mat._41 := 0; mat._42 := 0; mat._43 := 0;
mat._44 := 1.0;
end;

end.```