Skip to content

Instantly share code, notes, and snippets.

@XProger
Created August 26, 2014 07:08
Show Gist options
  • Select an option

  • Save XProger/da9a74ae8b37905b421a to your computer and use it in GitHub Desktop.

Select an option

Save XProger/da9a74ae8b37905b421a to your computer and use it in GitHub Desktop.
Simple float3 vector operations
TVec3f = {$IFDEF FPC} object {$ELSE} record {$ENDIF}
x, y, z : Single;
{$IFNDEF FPC}
class operator Equal(const a, b: TVec3f): Boolean;
class operator Add(const a, b: TVec3f): TVec3f;
class operator Subtract(const a, b: TVec3f): TVec3f;
class operator Multiply(const a, b: TVec3f): TVec3f;
class operator Multiply(const v: TVec3f; x: Single): TVec3f;
{$ENDIF}
function Dot(const v: TVec3f): Single;
function Cross(const v: TVec3f): TVec3f;
function Reflect(const n: TVec3f): TVec3f;
function Refract(const n: TVec3f; Factor: Single): TVec3f;
function Length: Single;
function LengthQ: Single;
function Normal: TVec3f;
function Dist(const v: TVec3f): Single;
function DistQ(const v: TVec3f): Single;
function Lerp(const v: TVec3f; t: Single): TVec3f;
function MinV(const v: TVec3f): TVec3f;
function MaxV(const v: TVec3f): TVec3f;
function ClampV(const MinClamp, MaxClamp: TVec3f): TVec3f;
function Rotate(Angle: Single; const Axis: TVec3f): TVec3f;
function Angle(const v: TVec3f): Single;
function MultiOp(out r: TVec3f; const v1, v2, op1, op2: TVec3f): Single;
end;
{$IFDEF FPC}
operator = (const a, b: TVec3f): Boolean;
operator + (const a, b: TVec3f): TVec3f;
operator - (const a, b: TVec3f): TVec3f;
operator * (const a, b: TVec3f): TVec3f;
operator * (const v: TVec3f; x: Single): TVec3f;
{$ENDIF}
{$IFDEF FPC}operator = {$ELSE}class operator TVec3f.Equal{$ENDIF}
(const a, b: TVec3f): Boolean;
begin
with b - a do
Result := (abs(x) <= EPS) and (abs(y) <= EPS) and (abs(z) <= EPS);
end;
{$IFDEF FPC}operator + {$ELSE}class operator TVec3f.Add{$ENDIF}
(const a, b: TVec3f): TVec3f;
begin
Result.x := a.x + b.x;
Result.y := a.y + b.y;
Result.z := a.z + b.z;
end;
{$IFDEF FPC}operator - {$ELSE}class operator TVec3f.Subtract{$ENDIF}
(const a, b: TVec3f): TVec3f;
begin
Result.x := a.x - b.x;
Result.y := a.y - b.y;
Result.z := a.z - b.z;
end;
{$IFDEF FPC}operator * {$ELSE}class operator TVec3f.Multiply{$ENDIF}
(const a, b: TVec3f): TVec3f;
begin
Result.x := a.x * b.x;
Result.y := a.y * b.y;
Result.z := a.z * b.z;
end;
{$IFDEF FPC}operator * {$ELSE}class operator TVec3f.Multiply{$ENDIF}
(const v: TVec3f; x: Single): TVec3f;
begin
Result.x := v.x * x;
Result.y := v.y * x;
Result.z := v.z * x;
end;
function TVec3f.Dot(const v: TVec3f): Single;
begin
Result := x * v.x + y * v.y + z * v.z;
end;
function TVec3f.Cross(const v: TVec3f): TVec3f;
begin
Result.x := y * v.z - z * v.y;
Result.y := z * v.x - x * v.z;
Result.z := x * v.y - y * v.x;
end;
function TVec3f.Reflect(const n: TVec3f): TVec3f;
begin
Result := Self - n * (2 * Dot(n));
end;
function TVec3f.Refract(const n: TVec3f; Factor: Single): TVec3f;
var
d, s : Single;
begin
d := Dot(n);
s := (1 - sqr(Factor)) * (1 - sqr(d));
if s < 0 then
Result := Reflect(n)
else
Result := Self * Factor - n * (sqrt(s) + d * Factor);
end;
function TVec3f.Length: Single;
begin
Result := sqrt(LengthQ);
end;
function TVec3f.LengthQ: Single;
begin
Result := sqr(x) + sqr(y) + sqr(z);
end;
function TVec3f.Normal: TVec3f;
var
Len : Single;
begin
Len := Length;
if Len = 0 then
Result := Vec3f(0, 0, 0)
else
Result := Self * (1 / Len);
end;
function TVec3f.Dist(const v: TVec3f): Single;
var
p : TVec3f;
begin
p := v - Self;
Result := p.Length;
end;
function TVec3f.DistQ(const v: TVec3f): Single;
var
p : TVec3f;
begin
p := v - Self;
Result := p.LengthQ;
end;
function TVec3f.Lerp(const v: TVec3f; t: Single): TVec3f;
begin
Result := Self + (v - Self) * t;
end;
function TVec3f.MinV(const v: TVec3f): TVec3f;
begin
Result.x := Min(x, v.x);
Result.y := Min(y, v.y);
Result.z := Min(z, v.z);
end;
function TVec3f.MaxV(const v: TVec3f): TVec3f;
begin
Result.x := Max(x, v.x);
Result.y := Max(y, v.y);
Result.z := Max(z, v.z);
end;
function TVec3f.ClampV(const MinClamp, MaxClamp: TVec3f): TVec3f;
begin
Result := Vec3f(Clamp(x, MinClamp.x, MaxClamp.x),
Clamp(y, MinClamp.y, MaxClamp.y),
Clamp(z, MinClamp.z, MaxClamp.z));
end;
function TVec3f.Rotate(Angle: Single; const Axis: TVec3f): TVec3f;
var
s, c : Single;
v0, v1, v2 : TVec3f;
begin
SinCos(Angle, s, c);
v0 := Axis * Dot(Axis);
v1 := Self - v0;
v2 := Axis.Cross(v1);
Result.x := v0.x + v1.x * c + v2.x * s;
Result.y := v0.y + v1.y * c + v2.y * s;
Result.z := v0.z + v1.z * c + v2.z * s;
end;
function TVec3f.Angle(const v: TVec3f): Single;
begin
Result := ArcCos(Dot(v) / sqrt(LengthQ * v.LengthQ))
end;
function TVec3f.MultiOp(out r: TVec3f; const v1, v2, op1, op2: TVec3f): Single;
begin
r.x := v1.x * op1.x + v2.x * op2.x;
r.y := v1.y * op1.y + v2.y * op2.y;
r.z := v1.z * op1.z + v2.z * op2.z;
Result := r.x + r.y + r.z;
// add = (v1, v2, 1, 1)
// sub = (v1, v2, 1, -1)
// neg = (v1, 0, -1, 0)
// dot = (v1, 0, v2, 0)
// cross = (v1.yzx, v2.yzx, v2.zxy, -v1.zxy)
// lenq = (v1, 0, v1, 0)
// lerp = (v1, v2, 1 - t, t)
// etc.
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment