📄 mm3d.pas
字号:
begin
x := s1.x + s2.x;
y := s1.y + s2.y;
z := s1.z + s2.z;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorSubtract(const s1, s2: TMM3DVector): TMM3DVector;
begin
with Result do
begin
x := s1.x - s2.x;
y := s1.y - s2.y;
z := s1.z - s2.z;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorReflect(const ray, normal: TMM3DVector): TMM3DVector;
begin
Result := MM3DVectorRotate(ray,normal,Pi);
end;
{-----------------------------------------------------------------------------}
function MM3DVectorCrossProduct(const s1, s2: TMM3DVector): TMM3DVector;
begin
with Result do
begin
X := (s1.Y*s2.Z)-(s1.Z*s2.Y);
Y := (s1.Z*s2.X)-(s1.X*s2.Z);
Z := (s1.X*s2.Y)-(s1.Y*s2.X);
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorDotProduct(const s1, s2: TMM3DVector): TMM3DValue;
begin
Result := (s1.X * s2.X) + (s1.Y * s2.Y) + (s1.Z * s2.Z);
end;
{-----------------------------------------------------------------------------}
function MM3DVectorNormalize(const v: TMM3DVector): TMM3DVector;
var
M: TMM3DValue;
begin
M := MM3DVectorModulus(v);
if M = 0 then
{ TODO: Should be resource id }
raise EMM3DError.Create('Zero-length vector passed to normalize');
with Result do
begin
X := v.X/M;
Y := v.Y/M;
Z := v.Z/M;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorNormalise(const v: TMM3DVector): TMM3DVector;
begin
Result := MM3DVectorNormalize(v);
end;
{-----------------------------------------------------------------------------}
function MM3DVectorModulus(const v: TMM3DVector): TMM3DValue;
begin
Result := Sqrt(Sqr(v.x)+Sqr(v.y)+Sqr(v.z));
end;
{-----------------------------------------------------------------------------}
function MM3DVectorRotate(const v, axis: TMM3DVector; theta: TMM3DValue): TMM3DVector;
var
M: TMM3DMatrix4D;
begin
M := MM3DMatrixFromRotation(axis,theta);
Result := MM3DVector3D(MM3DVectorTransform(v,M));
end;
{-----------------------------------------------------------------------------}
function MM3DVectorScale(const s: TMM3DVector; factor: TMM3DValue): TMM3DVector;
begin
with Result do
begin
X := s.X*factor;
Y := s.Y*factor;
Z := s.Z*factor;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorRandom: TMM3DVector;
begin
with Result do
begin
X := Random(MaxInt)-(MaxInt div 2);
Y := Random(MaxInt)-(MaxInt div 2);
Z := Random(MaxInt)-(MaxInt div 2);
end;
Result := MM3DVectorNormalize(Result);
end;
{-----------------------------------------------------------------------------}
function MM3DQuaternionFromRotation(const v: TMM3DVector; theta: TMM3DValue): TMM3DQuaternion;
var
ht: TMM3DValue;
ch, sh: TMM3DValue;
ax: TMM3DVector;
begin
ax := MM3DVectorNormalize(v);
ht := theta/2;
ch := cos(ht);
sh := sin(ht);
Result.v.x := ax.x*sh;
Result.v.y := ax.y*sh;
Result.v.z := ax.z*sh;
Result.s := ch;
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixFromQuaternion(const q: TMM3DQuaternion): TMM3DMatrix4D;
var
xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz: TMM3DValue;
begin
xs := 2*q.v.x;
ys := 2*q.v.y;
zs := 2*q.v.z;
wx := q.s*xs;
wy := q.s*ys;
wz := q.s*zs;
xx := q.v.x*xs;
xy := q.v.x*ys;
xz := q.v.x*zs;
yy := q.v.y*ys;
yz := q.v.y*zs;
zz := q.v.z*zs;
Result := Identity;
Result[0,0] := 1 - (yy + zz);
Result[0,1] := xy - wz;
Result[0,2] := xz + wy;
Result[1,0] := xy + wz;
Result[1,1] := 1 - (xx + zz);
Result[1,2] := yz - wx;
Result[2,0] := xz - wy;
Result[2,1] := yz + wx;
Result[2,2] := 1 - (xx + yy);
end;
{-----------------------------------------------------------------------------}
function MM3DVector(x, y, z: TMM3DValue): TMM3DVector;
begin
Result.x := x;
Result.y := y;
Result.z := z;
end;
{-----------------------------------------------------------------------------}
function MM3DVectorRotateQ(const v: TMM3DVector; const q: TMM3DQuaternion): TMM3DVector;
begin
Result := MM3DVector3D(MM3DVectorTransform(v,MM3DMatrixFromQuaternion(q)));
end;
{-----------------------------------------------------------------------------}
function MM3DVectorTransform(const v: TMM3DVector; const Mat: TMM3DMatrix4D): TMM3DVector4D;
begin
with v do
begin
Result.x := x * mat[0,0] + y * mat[0,1] + z * mat[0,2] + 1 * mat[0,3];
Result.y := x * mat[1,0] + y * mat[1,1] + z * mat[1,2] + 1 * mat[1,3];
Result.z := x * mat[2,0] + y * mat[2,1] + z * mat[2,2] + 1 * mat[2,3];
Result.w := x * mat[3,0] + y * mat[3,1] + z * mat[3,2] + 1 * mat[3,3];
end;
end;
{-----------------------------------------------------------------------------}
function MM3DCreateViewportMatrix(Front: TMM3DValue; Proj: TMM3DProjectionType): TMM3DMatrix4D;
begin
FillChar(Result,SizeOf(Result),0);
if Proj = ptPerspective then
begin
Result[0,0] := Front;
Result[1,1] := Front;
Result[2,2] := 1;
Result[3,2] := 1;
end
else
begin
Result[0,0] := 1;
Result[1,1] := 1;
Result[2,3] := Front;
Result[3,3] := 1;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DVector3D(const v: TMM3DVector4D): TMM3DVector;
begin
with v do
begin
Result.X := X/W;
Result.Y := Y/W;
Result.Z := Z/W;
end;
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixMul(const M1, M2: TMM3DMatrix4D): TMM3DMatrix4D;
var
i, j: Integer;
begin
for i := 0 to 3 do
for j := 0 to 3 do
Result[j,i] := M1[0,i] * M2[j,0] + M1[1,i] * M2[j,1] + M1[2,i] * M2[j,2] + M1[3,i] * M2[j,3];
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixFromTranslation(const T: TMM3DVector): TMM3DMatrix4D;
begin
FillChar(Result,SizeOf(Result),0);
Result[0,3] := T.x;
Result[1,3] := T.y;
Result[2,3] := T.z;
Result[0,0] := 1;
Result[1,1] := 1;
Result[2,2] := 1;
Result[3,3] := 1;
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixFromScaling(const T: TMM3DVector): TMM3DMatrix4D;
begin
FillChar(Result,SizeOf(Result),0);
Result[0,0] := T.x;
Result[1,1] := T.y;
Result[2,2] := T.z;
Result[3,3] := 1;
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixFromRotation(const Axis: TMM3DVector; Angle: TMM3DValue): TMM3DMatrix4D;
var
Q: TMM3DQuaternion;
begin
if Angle = 0 then
Result := Identity
else
begin
Q := MM3DQuaternionFromRotation(Axis,Angle);
Result := MM3DMatrixFromQuaternion(Q);
end;
end;
{-----------------------------------------------------------------------------}
function MM3DMatrixFromRotationTo(const Dest: TMM3DVector): TMM3DMatrix4D;
type
PVect = ^TVect;
TVect = array[0..2] of TMM3DValue;
var
N, T, W, U, V: TMM3DVector;
function GetMinorAxis(const V: TMM3DVector): Integer;
begin
Result := 0;
if V.X > V.Y then
Result := 1;
if V.Z < PVect(@V)[Result] then
Result := 2;
end;
begin
N := MM3DVectorNormalize(Dest);
T := N;
W := N;
PVect(@T)[GetMinorAxis(W)] := 1.0;
U := MM3DVectorNormalize(MM3DVectorCrossProduct(T,W));
V := MM3DVectorCrossProduct(W,U);
Result := Identity;
Result[0,0] := U.X;
Result[0,1] := U.Y;
Result[0,2] := U.Z;
Result[1,0] := V.X;
Result[1,1] := V.Y;
Result[1,2] := V.Z;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -