⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mm3d.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    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 + -