- Status
- Offline
- Joined
- Apr 18, 2019
- Messages
- 202
- Reaction score
- 326
I think this code will need a very small number of coders, because using Delphi is rare in itself, but still.
Hope that at least someone will need it.
Hope that at least someone will need it.
Code:
type
FVector = packed record
X, Y, Z: Single;
class function Create(const x, y, z: Single): FVector; inline; static;
class operator Negative(const a: FVector): FVector; inline;
class operator Positive(const a: FVector): FVector; inline;
class operator Equal(const Left, Right: FVector): Boolean; inline;
class operator NotEqual(const Left, Right: FVector): Boolean; inline;
class operator Add(const Left, Right: FVector): FVector; inline;
class operator Subtract(const Left, Right: FVector): FVector; inline;
class operator Multiply(const Left, Right: FVector): FVector; inline;
class operator Divide(const Left, Right: FVector): FVector; inline;
function Size: Single;
function Size2D: Single;
function SizeSquared: Single;
function SizeSquared2D: Single;
function Dot(const v: FVector): Single;
function Normalize: FVector;
function Distance(const v: FVector): Single;
end;
type Vector3 = FVector;
type FMinimalViewInfo = packed record
Location: Vector3;
Rotation: Vector3;
FOV: Single;
OrthoWidth: Single;
OrthoNearClipPlane: Single;
OrthoFarClipPlane: Single;
AspectRatio: Single;
end;
type FCameraCacheEntry = packed record
TimeStamp: Single;
UnknownData00: array[1..$C]of Byte;
POV: FMinimalViewInfo;
end;
type Bones = (
Root,
pelvis,
spine_01,
spine_02,
spine_03,
neck_01,
Head,
face_root,
eyebrows_pos_root,
eyebrows_root,
eyebrows_r,
eyebrows_l,
eyebrow_l,
eyebrow_r,
forehead_root,
forehead,
jaw_pos_root,
jaw_root,
jaw,
mouth_down_pos_root,
mouth_down_root,
lip_bm_01,
lip_bm_02,
lip_br,
lip_bl,
jaw_01,
jaw_02,
cheek_pos_root,
cheek_root,
cheek_r,
cheek_l,
nose_side_root,
nose_side_r_01,
nose_side_r_02,
nose_side_l_01,
nose_side_l_02,
eye_pos_r_root,
eye_r_root,
eye_rot_r_root,
eye_lid_u_r,
eye_r,
eye_lid_b_r,
eye_pos_l_root,
eye_l_root,
eye_rot_l_root,
eye_lid_u_l,
eye_l,
eye_lid_b_l,
nose_pos_root,
nose,
mouth_up_pos_root,
mouth_up_root,
lip_ul,
lip_um_01,
lip_um_02,
lip_ur,
lip_l,
lip_r,
hair_root,
hair_b_01,
hair_b_02,
hair_l_01,
hair_l_02,
hair_r_01,
hair_r_02,
hair_f_02,
hair_f_01,
hair_b_pt_01,
hair_b_pt_02,
hair_b_pt_03,
hair_b_pt_04,
hair_b_pt_05,
camera_fpp,
GunReferencePoint,
GunRef,
breast_l,
breast_r,
clavicle_l,
upperarm_l,
lowerarm_l,
hand_l,
thumb_01_l,
thumb_02_l,
thumb_03_l,
thumb_04_l_MBONLY,
index_01_l,
index_02_l,
index_03_l,
index_04_l_MBONLY,
middle_01_l,
middle_02_l,
middle_03_l,
middle_04_l_MBONLY,
ring_01_l,
ring_02_l,
ring_03_l,
ring_04_l_MBONLY,
pinky_01_l,
pinky_02_l,
pinky_03_l,
pinky_04_l_MBONLY,
item_l,
lowerarm_twist_01_l,
upperarm_twist_01_l,
clavicle_r,
upperarm_r,
lowerarm_r,
hand_r,
thumb_01_r,
thumb_02_r,
thumb_03_r,
thumb_04_r_MBONLY,
index_01_r,
index_02_r,
index_03_r,
index_04_r_MBONLY,
middle_01_r,
middle_02_r,
middle_03_r,
middle_04_r_MBONLY,
ring_01_r,
ring_02_r,
ring_03_r,
ring_04_r_MBONLY,
pinky_01_r,
pinky_02_r,
pinky_03_r,
pinky_04_r_MBONLY,
item_r,
lowerarm_twist_01_r,
upperarm_twist_01_r,
BackPack,
backpack_01,
backpack_02,
Slot_Primary,
Slot_Secondary,
Slot_Melee,
slot_throwable,
coat_l_01,
coat_l_02,
coat_l_03,
coat_l_04,
coat_fl_01,
coat_fl_02,
coat_fl_03,
coat_fl_04,
coat_b_01,
coat_b_02,
coat_b_03,
coat_b_04,
coat_r_01,
coat_r_02,
coat_r_03,
coat_r_04,
coat_fr_01,
coat_fr_02,
coat_fr_03,
coat_fr_04,
thigh_l,
calf_l,
foot_l,
ball_l,
calf_twist_01_l,
thigh_twist_01_l,
thigh_r,
calf_r,
foot_r,
ball_r,
calf_twist_01_r,
thigh_twist_01_r,
Slot_SideArm,
skirt_l_01,
skirt_l_02,
skirt_l_03,
skirt_f_01,
skirt_f_02,
skirt_f_03,
skirt_b_01,
skirt_b_02,
skirt_b_03,
skirt_r_01,
skirt_r_02,
skirt_r_03,
ik_hand_root,
ik_hand_gun,
ik_hand_r,
ik_hand_l,
ik_aim_root,
ik_aim_l,
ik_aim_r,
ik_foot_root,
ik_foot_l,
ik_foot_r,
camera_tpp,
ik_target_root,
ik_target_l,
ik_target_r,
VB_spine_03_spine_03,
VB_upperarm_r_lowerarm_r
);
type FQuat = packed record
x, y, z, w: Single;
end;
type FTransform = packed record
rot: FQuat;
translation: Vector3;
pad: array[1..4]of Byte;
scale: Vector3;
pad1: array[1..4]of Byte;
function ToMatrixWithScale: D3DXMATRIX;
end;
implementation
class function FVector.Create(const x, y, z: Single): FVector;
begin
Result.X:= x;
Result.Y:= y;
Result.Z:= z;
end;
class operator FVector.Negative(const a: FVector): FVector;
begin
Result.x:= -a.x;
Result.y:= -a.y;
Result.z:= -a.z;
end;
class operator FVector.Positive(const a: FVector): FVector;
begin
Result:= a;
end;
class operator FVector.Equal(const Left, Right: FVector): Boolean;
begin
Result:= (Left.x = Right.x) and (Left.y = Right.y) and (Left.z = Right.z);
end;
class operator FVector.NotEqual(const Left, Right: FVector): Boolean;
begin
Result:= not((Left.x = Right.x) and (Left.y = Right.y) and (Left.z = Right.z));
end;
class operator FVector.Add(const Left, Right: FVector): FVector;
begin
Result.x:= Left.x + Right.x;
Result.y:= Left.y + Right.y;
Result.z:= Left.z + Right.z;
end;
class operator FVector.Subtract(const Left, Right: FVector): FVector;
begin
Result.x:= Left.x - Right.x;
Result.y:= Left.y - Right.y;
Result.z:= Left.z - Right.z;
end;
class operator FVector.Multiply(const Left, Right: FVector): FVector;
begin
Result.x:= Left.x * Right.x;
Result.y:= Left.y * Right.y;
Result.z:= Left.z * Right.z;
end;
class operator FVector.Divide(const Left, Right: FVector): FVector;
begin
Result.x:= Left.x / Right.x;
Result.y:= Left.y / Right.y;
Result.z:= Left.z / Right.z;
end;
function FVector.Size;
begin
Result:= sqrt(x*x + y*y + z*z);
end;
function FVector.Size2D;
begin
Result:= sqrt(x*x + y*y);
end;
function FVector.SizeSquared;
begin
Result:= x*x + y*y + z*z;
end;
function FVector.SizeSquared2D;
begin
Result:= x*x + y*y;
end;
function FVector.Dot(const v: FVector): Single;
begin
Result:= x * v.x + y * v.y + z * v.z;
end;
function FVector.Normalize;
var v: FVector;
len: Single;
begin
len:= Self.Size;
if (len <> 0) then
begin
v.X:= X / len;
v.Y:= Y / len;
v.Z:= Z / len;
end
else
begin
v.X:= 0;
v.Y:= 0;
v.Z:= 1;
end;
Result:= v;
end;
function FVector.Distance(const v: FVector): Single;
var v0: FVector;
begin
v0:= Self - v;
v0:= v0 * v0;
Result:= sqrt(v0.X + v0.Y + v0.Z);
end;
function FTransform.ToMatrixWithScale: D3DXMATRIX;
var m: D3DXMATRIX;
x2, y2, z2, xx2, yy2, zz2, yz2, wx2, xy2, wz2, xz2, wy2: Single;
begin
m._41:= translation.x;
m._42:= translation.y;
m._43:= translation.z;
x2:= rot.x + rot.x;
y2:= rot.y + rot.y;
z2:= rot.z + rot.z;
xx2:= rot.x * x2;
yy2:= rot.y * y2;
zz2:= rot.z * z2;
m._11:= (1 - (yy2 + zz2)) * scale.X;
m._22:= (1 - (xx2 + zz2)) * scale.Y;
m._33:= (1 - (xx2 + yy2)) * scale.Z;
yz2:= rot.y * z2;
wx2:= rot.w * x2;
m._32:= (yz2 - wx2) * scale.Z;
m._23:= (yz2 + wx2) * scale.Y;
xy2:= rot.x * y2;
wz2:= rot.w * z2;
m._21:= (xy2 - wz2) * scale.y;
m._12:= (xy2 + wz2) * scale.x;
xz2:= rot.x * z2;
wy2:= rot.w * y2;
m._31:= (xz2 + wy2) * scale.z;
m._13:= (xz2 - wy2) * scale.x;
m._14:= 0.0;
m._24:= 0.0;
m._34:= 0.0;
m._44:= 1.0;
Result:= m;
end;
Code:
const upper_part: array[0..2]of Bones = (Bones.neck_01, Bones.Head, Bones.forehead);
const right_arm: array[0..3]of Bones = (Bones.neck_01, Bones.upperarm_r, Bones.lowerarm_r, Bones.hand_r);
const left_arm: array[0..3]of Bones = (Bones.neck_01, Bones.upperarm_l, Bones.lowerarm_l, Bones.hand_l);
const spine: array[0..3]of Bones = (Bones.neck_01, Bones.spine_02, Bones.spine_01, Bones.pelvis);
const lower_right: array[0..3]of Bones = (Bones.pelvis, Bones.thigh_r, Bones.calf_r, Bones.foot_r);
const lower_left: array[0..3]of Bones = (Bones.pelvis, Bones.thigh_l, Bones.calf_l, Bones.foot_l);
var skeleton: array[0..5]of array of Bones;
function Matrix(const rot, origin: Vector3): D3DXMATRIX;
var radPitch, radYaw, radRoll, SP, CP, SY, CY, SR, CR: Single;
begin
radPitch:= rot.X * Pi / 180;
radYaw:= rot.Y * Pi / 180;
radRoll:= rot.Z * Pi/ 180;
SP:= sin(radPitch);
CP:= cos(radPitch);
SY:= sin(radYaw);
CY:= cos(radYaw);
SR:= sin(radRoll);
CR:= cos(radRoll);
Result.m[0][0]:= CP * CY;
Result.m[0][1]:= CP * SY;
Result.m[0][2]:= SP;
Result.m[0][3]:= 0;
Result.m[1][0]:= SR * SP * CY - CR * SY;
Result.m[1][1]:= SR * SP * SY + CR * CY;
Result.m[1][2]:= -SR * CP;
Result.m[1][3]:= 0;
Result.m[2][0]:= -(CR * SP * CY + SR * SY);
Result.m[2][1]:= CY * SR - CR * SP * SY;
Result.m[2][2]:= CR * CP;
Result.m[2][3]:= 0;
Result.m[3][0]:= origin.x;
Result.m[3][1]:= origin.y;
Result.m[3][2]:= origin.z;
Result.m[3][3]:= 1;
end;
function WorldToScreen(WorldLocation: Vector3; CameraCacheL: FCameraCacheEntry): Vector3;
var Screenlocation, Rotation, vDelta, vTransformed: Vector3;
POV: FMinimalViewInfo;
tempMatrix: D3DXMATRIX;
vAxisX, vAxisY, vAxisZ: Vector3;
ScreenCenterX, ScreenCenterY, FovAngle: Single;
begin
try
POV:= CameraCacheL.POV;
Rotation:= POV.Rotation;
tempMatrix:= Matrix(Rotation, Vector3.Create(0, 0, 0));
vAxisX:= Vector3.Create(tempMatrix.m[0][0], tempMatrix.m[0][1], tempMatrix.m[0][2]);
vAxisY:= Vector3.Create(tempMatrix.m[1][0], tempMatrix.m[1][1], tempMatrix.m[1][2]);
vAxisZ:= Vector3.Create(tempMatrix.m[2][0], tempMatrix.m[2][1], tempMatrix.m[2][2]);
vDelta:= WorldLocation - POV.Location;
vTransformed:= Vector3.Create(vDelta.Dot(vAxisY), vDelta.Dot(vAxisZ), vDelta.Dot(vAxisX));
if vTransformed.Z < 1 then
vTransformed.Z:= 1;
FovAngle:= POV.FOV;
ScreenCenterX:= s_width / 2;
ScreenCenterY:= s_height / 2;
Screenlocation.X:= ScreenCenterX + vTransformed.x * (ScreenCenterX / tan(FovAngle * Pi / 360)) / vTransformed.z;
Screenlocation.Y:= ScreenCenterY - vTransformed.y * (ScreenCenterX / tan(FovAngle * Pi / 360)) / vTransformed.z;
Screenlocation.Z:= vTransformed.Z;
Result:= Screenlocation;
except
Result:= Vector3.Create(0, 0, 0);
end;
end;
function MatrixMultiplication(M1, M2: D3DMATRIX): D3DMATRIX;
begin
Result._11:= M1._11 * M2._11 + M1._12 * M2._21 + M1._13 * M2._31 + M1._14 * M2._41;
Result._12:= M1._11 * M2._12 + M1._12 * M2._22 + M1._13 * M2._32 + M1._14 * M2._42;
Result._13:= M1._11 * M2._13 + M1._12 * M2._23 + M1._13 * M2._33 + M1._14 * M2._43;
Result._14:= M1._11 * M2._14 + M1._12 * M2._24 + M1._13 * M2._34 + M1._14 * M2._44;
Result._21:= M1._21 * M2._11 + M1._22 * M2._21 + M1._23 * M2._31 + M1._24 * M2._41;
Result._22:= M1._21 * M2._12 + M1._22 * M2._22 + M1._23 * M2._32 + M1._24 * M2._42;
Result._23:= M1._21 * M2._13 + M1._22 * M2._23 + M1._23 * M2._33 + M1._24 * M2._43;
Result._24:= M1._21 * M2._14 + M1._22 * M2._24 + M1._23 * M2._34 + M1._24 * M2._44;
Result._31:= M1._31 * M2._11 + M1._32 * M2._21 + M1._33 * M2._31 + M1._34 * M2._41;
Result._32:= M1._31 * M2._12 + M1._32 * M2._22 + M1._33 * M2._32 + M1._34 * M2._42;
Result._33:= M1._31 * M2._13 + M1._32 * M2._23 + M1._33 * M2._33 + M1._34 * M2._43;
Result._34:= M1._31 * M2._14 + M1._32 * M2._24 + M1._33 * M2._34 + M1._34 * M2._44;
Result._41:= M1._41 * M2._11 + M1._42 * M2._21 + M1._43 * M2._31 + M1._44 * M2._41;
Result._42:= M1._41 * M2._12 + M1._42 * M2._22 + M1._43 * M2._32 + M1._44 * M2._42;
Result._43:= M1._41 * M2._13 + M1._42 * M2._23 + M1._43 * M2._33 + M1._44 * M2._43;
Result._44:= M1._41 * M2._14 + M1._42 * M2._24 + M1._43 * M2._34 + M1._44 * M2._44;
end;
function GetBoneIndex(mesh: UInt64; index: Integer): FTransform;
var bonearray: UInt64;
begin
if Mem.Read(mesh + $960, @BonEarray, 8) then
Mem.Read(bonearray + index * $30, @Result, SizeOf(Result));
end;
function GetBoneWithRotation(mesh: UInt64; id: Integer): Vector3;
var bone, ComponentToWorld: FTransform;
Matrix: D3DXMATRIX;
begin
Result:= Vector3.Create(0, 0, 0);
bone:= GetBoneIndex(mesh, id);
if Mem.Read(mesh + $280, @ComponentToWorld, SizeOf(ComponentToWorld)) then
begin
Matrix:= MatrixMultiplication(bone.ToMatrixWithScale, ComponentToWorld.ToMatrixWithScale);
Result:= Vector3.Create(Matrix._41, Matrix._42, Matrix._43);
end;
end;
procedure DrawSkeleton(mesh: UInt64; color: D3DCOLOR);
var neckpos, pelvispos, previous, current, p1, c1: Vector3;
i, j, bone: Integer;
begin
for i := 0 to High(skeleton) do
begin
previous:= Vector3.Create(0, 0, 0);
for j := 0 to High(skeleton[i]) do
begin
bone:= Integer(skeleton[i][j]);
current:= GetBoneWithRotation(mesh, bone);
if bone = Integer(Bones.neck_01) then
neckpos:= current;
if bone = Integer(Bones.pelvis) then
pelvispos:= current;
if previous.X = 0 then
previous:= current;
p1:= WorldToScreen(previous, G.cameracache);
c1:= WorldToScreen(current, G.cameracache);
DrawLine(p1.X, p1.Y, c1.X, c1.Y, color);
previous:= current;
end;
end;
end;
begin
SetLength(skeleton[0], Length(upper_part));
SetLength(skeleton[1], Length(right_arm));
SetLength(skeleton[2], Length(left_arm));
SetLength(skeleton[3], Length(spine));
SetLength(skeleton[4], Length(lower_right));
SetLength(skeleton[5], Length(lower_left));
CopyMemory(@skeleton[0][0], @upper_part[0], SizeOf(upper_part));
CopyMemory(@skeleton[1][0], @right_arm[0], SizeOf(right_arm));
CopyMemory(@skeleton[2][0], @Left_arm[0], SizeOf(left_arm));
CopyMemory(@skeleton[3][0], @Spine[0], SizeOf(spine));
CopyMemory(@skeleton[4][0], @lower_right[0], SizeOf(lower_right));
CopyMemory(@skeleton[5][0], @lower_left[0], SizeOf(lower_left));
end.