Merge pull request #3 from guzba/master

Moving a few things into vmath
This commit is contained in:
treeform 2020-03-07 19:24:18 -08:00 committed by GitHub
commit 4ad9fb081c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,7 +3,6 @@ import strutils
import random
export math
proc clamp*(n, min, max: float32): float32 =
## Clamps n to min, else returns max if n is higher.
if n < min:
@ -12,6 +11,10 @@ proc clamp*(n, min, max: float32): float32 =
return max
return n
proc between*(value, min, max: float32): bool =
## Returns true if value is between min and max or equal to them.
(value >= min) and (value <= max)
proc sign*(v: float32): float32 =
## Returns the sign of a number, -1 or 1.
if v >= 0:
@ -184,7 +187,6 @@ proc turnAngle*(a, b, speed: float32): float32 =
turn = -speed
return a + turn
type Vec3* = object
## 3D vector
x*: float32
@ -367,7 +369,6 @@ proc `$`*(a: Vec3): string =
a.y.formatfloat(ffDecimal,8) & ", " &
a.z.formatfloat(ffDecimal,8) & ")"
type Vec4* = object
## 4D Vector.
x*: float32
@ -461,7 +462,6 @@ proc `$`*(a: Vec4): string =
a.z.formatfloat(ffDecimal,8) & ", " &
a.w.formatfloat(ffDecimal,8) & ")"
proc vec3*(a: Vec2, z=0.0): Vec3 =
vec3(a.x, a.y, z)
@ -471,7 +471,6 @@ proc vec4*(a: Vec3, w=0.0): Vec4 =
proc vec4*(a: Vec2, z=0.0, w=0.0): Vec4 =
vec4(a.x, a.y, z, w)
type Mat3* = array[9, float32] ## 3x3 Matrix
proc mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 =
@ -485,11 +484,9 @@ proc mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 =
result[7] = h
result[8] = i
proc mat3*(a: Mat3): Mat3 =
result = a
proc identity*(a: var Mat3) =
a[0] = 1
a[1] = 0
@ -501,11 +498,9 @@ proc identity*(a: var Mat3) =
a[7] = 0
a[8] = 1
proc mat3*(): Mat3 =
result.identity()
proc transpose*(a: Mat3): Mat3 =
result[0] = a[0]
result[1] = a[3]
@ -517,7 +512,6 @@ proc transpose*(a: Mat3): Mat3 =
result[7] = a[5]
result[8] = a[8]
proc `$`*(a: Mat3): string =
return "[" &
a[0].formatfloat(ffDecimal,4) & ", " &
@ -564,13 +558,11 @@ proc `*`*(a: Mat3, b: Mat3): Mat3 =
result[7] = b20 * a01 + b21 * a11 + b22 * a21
result[8] = b20 * a02 + b21 * a12 + b22 * a22
proc `*`*(m: Mat3, v: Vec3): Vec3 =
result.x = m[0]*v.x + m[1]*v.y + m[2]*v.z
result.y = m[3]*v.x + m[4]*v.y + m[5]*v.z
result.z = m[6]*v.x + m[7]*v.y + m[8]*v.z
proc scale*(a: Mat3, v: Vec2): Mat3 =
result[0] = v.x * a[0]
result[1] = v.x * a[1]
@ -582,7 +574,6 @@ proc scale*(a: Mat3, v: Vec2): Mat3 =
result[7] = a[7]
result[8] = a[8]
proc scale*(a: Mat3, v: Vec3): Mat3 =
result[0] = v.x * a[0]
result[1] = v.x * a[1]
@ -594,7 +585,6 @@ proc scale*(a: Mat3, v: Vec3): Mat3 =
result[7] = v.z * a[7]
result[8] = v.z * a[8]
proc rotationMat3*(angle: float32): Mat3 =
# Create a matrix from an angle.
let
@ -612,20 +602,16 @@ proc rotationMat3*(angle: float32): Mat3 =
result[7] = 0
result[8] = 1
proc rotate*(a: Mat3, angle: float32): Mat3 =
# Rotates a matrix by an angle.
a * rotationMat3(angle)
proc `*`*(a: Mat3, b: Vec2): Vec2 =
result.x = a[0]*b.x + a[1]*b.y + a[6]
result.y = a[3]*b.x + a[4]*b.y + a[7]
type Mat4* = array[16, float32] ## 4x4 Matrix - OpenGL row order
proc mat4*(v0, v1, Vec2, Vec3, Vec4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15: float32): Mat4 =
result[0] = v0
result[1] = v1
@ -644,11 +630,9 @@ proc mat4*(v0, v1, Vec2, Vec3, Vec4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
result[14] = v14
result[15] = v15
proc mat4*(a: Mat4): Mat4 =
result = a
proc identity*(): Mat4 =
result[0] = 1
result[1] = 0
@ -667,11 +651,9 @@ proc identity*(): Mat4 =
result[14] = 0
result[15] = 1
proc mat4*(): Mat4 =
return identity()
proc transpose*(a: Mat4): Mat4 =
result[0] = a[0]
result[1] = a[4]
@ -693,7 +675,6 @@ proc transpose*(a: Mat4): Mat4 =
result[14] = a[11]
result[15] = a[15]
proc determinant*(a: Mat4): float32 =
var
a00 = a[0]
@ -722,7 +703,6 @@ proc determinant*(a: Mat4): float32 =
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33
)
proc inverse*(a: Mat4): Mat4 =
var
a00 = a[0]
@ -776,7 +756,6 @@ proc inverse*(a: Mat4): Mat4 =
result[14] = (-a30*b03 + a31*b01 - a32*b00)*invDet
result[15] = ( a20*b03 - a21*b01 + a22*b00)*invDet
proc `*`*(a, b: Mat4): Mat4 =
var
a00 = a[0]
@ -831,66 +810,55 @@ proc `*`*(a, b: Mat4): Mat4 =
result[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32
result[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33
proc `*`*(a: Mat4, b: Vec3): Vec3 =
result.x = a[0]*b.x + a[4]*b.y + a[8]*b.z + a[12]
result.y = a[1]*b.x + a[5]*b.y + a[9]*b.z + a[13]
result.z = a[2]*b.x + a[6]*b.y + a[10]*b.z + a[14]
proc right*(a: Mat4): Vec3 =
result.x = a[0]
result.y = a[1]
result.z = a[2]
proc `right=`*(a: var Mat4, b: Vec3) =
a[0] = b.x
a[1] = b.y
a[2] = b.z
proc up*(a: Mat4): Vec3 =
result.x = a[4]
result.y = a[5]
result.z = a[6]
proc `up=`*(a: var Mat4, b: Vec3) =
a[4] = b.x
a[5] = b.y
a[6] = b.z
proc fov*(a: Mat4): Vec3 =
result.x = a[8]
result.y = a[9]
result.z = a[10]
proc `fov=`*(a: var Mat4, b: Vec3) =
a[8] = b.x
a[9] = b.y
a[10] = b.z
proc pos*(a: Mat4): Vec3 =
result.x = a[12]
result.y = a[13]
result.z = a[14]
proc `pos=`*(a: var Mat4, b: Vec3) =
a[12] = b.x
a[13] = b.y
a[14] = b.z
proc rotationOnly*(a: Mat4): Mat4 =
result = a
result.pos = vec3(0,0,0)
proc dist*(a, b: Mat4): float32 =
var
x = a[12] - b[12]
@ -933,7 +901,6 @@ proc translate*(a: Mat4, v: Vec3): Mat4 =
result[15] = a03*v.x + a13*v.y + a23*v.z + a[15]
]#
proc translate*(v: Vec3): Mat4 =
result[0] = 1
result[5] = 1
@ -943,21 +910,18 @@ proc translate*(v: Vec3): Mat4 =
result[13] = v.y
result[14] = v.z
proc scale*(v: Vec3): Mat4 =
result[0] = v.x
result[5] = v.y
result[10] = v.z
result[15] = 1
proc close*(a: Mat4, b: Mat4): bool =
for i in 0..15:
if abs(a[i] - b[i]) > 0.001:
return false
return true
proc hrp*(m: Mat4): Vec3 =
var heading, pitch, roll: float32
if m[1] > 0.998: # singularity at north pole
@ -976,7 +940,6 @@ proc hrp*(m: Mat4): Vec3 =
result.y = pitch
result.z = roll
proc frustum*(left, right, bottom, top, near, far: float32): Mat4 =
var
rl = (right - left)
@ -999,14 +962,12 @@ proc frustum*(left, right, bottom, top, near, far: float32): Mat4 =
result[14] = -(far*near*2) / fn
result[15] = 0
proc perspective*(fovy, aspect, near, far: float32): Mat4 =
var
top = near * tan(fovy*PI / 360.0)
right = top * aspect
return frustum(-right, right, -top, top, near, far)
proc ortho*(left, right, bottom, top, near, far: float32): Mat4 =
var
rl = (right - left)
@ -1029,7 +990,6 @@ proc ortho*(left, right, bottom, top, near, far: float32): Mat4 =
result[14] = -(far + near) / fn
result[15] = 1
proc lookAt*(eye, center, up: Vec3): Mat4 =
var
eyex = eye[0]
@ -1107,7 +1067,6 @@ proc lookAt*(eye, center, up: Vec3): Mat4 =
result[14] = -(z0*eyex + z1*eyey + z2*eyez)
result[15] = 1
proc tofloat32*(m: Mat4): array[16, float32] =
return [
float32 m[0], float32 m[1], float32 m[2], float32 m[3],
@ -1116,7 +1075,6 @@ proc tofloat32*(m: Mat4): array[16, float32] =
float32 m[12], float32 m[13], float32 m[14], float32 m[15]
]
proc `$`*(a: Mat4): string =
return "[" &
a[0].formatfloat(ffDecimal, 5) & ", " &
@ -1136,28 +1094,24 @@ proc `$`*(a: Mat4): string =
a[14].formatfloat(ffDecimal, 5) & ", " &
a[15].formatfloat(ffDecimal, 5) & "]"
type Quat* = object
x*: float32
y*: float32
z*: float32
w*: float32
proc quat*(x, y, z, w: float32): Quat =
result.x = x
result.y = y
result.z = z
result.w = w
proc conjugate*(q: Quat): Quat =
result.w = q.w
result.x = -q.x
result.y = -q.y
result.z = -q.z
proc length*(q: Quat): float32 =
return sqrt(
q.w * q.w +
@ -1165,7 +1119,6 @@ proc length*(q: Quat): float32 =
q.y * q.y +
q.z * q.z)
proc normalize*(q: Quat): Quat =
var m = q.length
result.x = q.x / m
@ -1173,19 +1126,16 @@ proc normalize*(q: Quat): Quat =
result.z = q.z / m
result.w = q.w / m
proc xyz*(q: Quat): Vec3 =
result.x = q.x
result.y = q.y
result.z = q.z
proc `xyz=`*(q: var Quat, v: Vec3) =
q.x = v.x
q.y = v.y
q.z = v.z
proc `*`*(a, b: Quat): Quat =
## Multiply the quaternion by a quaternion.
#[
@ -1211,7 +1161,6 @@ proc `*`*(q: Quat, v: float32): Quat =
result.z = q.z * v
result.w = q.w * v
proc `*`*(q: Quat, v: Vec3): Vec3 =
## Multiply the quaternion by a vector.
var
@ -1233,7 +1182,6 @@ proc `*`*(q: Quat, v: Vec3): Vec3 =
result.y = iy * qw + iw * -qy + iz * -qx - ix * -qz
result.z = iz * qw + iw * -qz + ix * -qy - iy * -qx
proc mat3*(q: Quat): Mat3 =
var xx = q.x * q.x
var xy = q.x * q.y
@ -1259,8 +1207,6 @@ proc mat3*(q: Quat): Mat3 =
result[7] = 2 * ( yz + xw )
result[8] = 1 - 2 * ( xx + yy )
proc mat4*(q: Quat): Mat4 =
var xx = q.x * q.x
var xy = q.x * q.y
@ -1294,11 +1240,9 @@ proc mat4*(q: Quat): Mat4 =
result[14] = 0
result[15] = 1.0
proc reciprocalSqrt*(x: float32): float32 =
return 1.0/sqrt(x)
proc quat*(m: Mat4): Quat =
var
m00 = m[0]
@ -1336,7 +1280,6 @@ proc quat*(m: Mat4): Quat =
assert abs(q.length - 1.0) < 0.001
return q
proc fromAxisAngle*(axis: Vec3, angle: float32): Quat =
var a = axis.normalize()
var s = sin(angle / 2)
@ -1345,7 +1288,6 @@ proc fromAxisAngle*(axis: Vec3, angle: float32): Quat =
result.z = a.z * s
result.w = cos(angle / 2)
proc toAxisAngle*(q: Quat, axis: var Vec3, angle: var float32) =
var cosAngle = q.w
angle = arccos(cosAngle) * 2.0
@ -1358,7 +1300,6 @@ proc toAxisAngle*(q: Quat, axis: var Vec3, angle: var float32) =
axis.y = q.y / sinAngle
axis.z = q.z / sinAngle
proc quat*(heading, pitch, roll: float32): Quat =
var t0 = cos(heading * 0.5)
var t1 = sin(heading * 0.5)
@ -1371,7 +1312,6 @@ proc quat*(heading, pitch, roll: float32): Quat =
result.y = t0 * t2 * t5 + t1 * t3 * t4
result.z = t1 * t2 * t4 - t0 * t3 * t5
proc hrp*(q: Quat): Vec3 =
var ysqr = q.y * q.y
# roll
@ -1390,7 +1330,6 @@ proc hrp*(q: Quat): Vec3 =
var t4 = +1.0 - 2.0 * (ysqr + q.z * q.z)
result.x = arctan2(t3, t4)
proc `$`*(a: Quat): string =
return "q(" &
a.x.formatfloat(ffDecimal,8) & ", " &
@ -1398,35 +1337,27 @@ proc `$`*(a: Quat): string =
a.z.formatfloat(ffDecimal,8) & ", " &
a.w.formatfloat(ffDecimal,8) & ")"
proc rotate*(angle: float32, axis: Vec3): Mat4 =
fromAxisAngle(axis, angle).mat4()
proc rotateX*(angle: float32): Mat4 =
return rotate(angle, vec3(1, 0, 0))
proc rotateY*(angle: float32): Mat4 =
return rotate(angle, vec3(0, 1, 0))
proc rotateZ*(angle: float32): Mat4 =
return rotate(angle, vec3(0, 0, 1))
proc scaleMat*(scale: Vec3): Mat4 =
result[0] = scale.x
result[5] = scale.y
result[10] = scale.z
result[15] = 1.0
proc scaleMat*(scale: float32): Mat4 =
return scaleMat(vec3(scale, scale, scale))
type Rect* = object
x*: float32
y*: float32
@ -1471,10 +1402,12 @@ proc `/`*(r: Rect, v: float): Rect =
## / all elements of a Rect.
rect(r.x / v, r.y / v, r.w / v, r.h / v)
proc intersects*(rect: Rect, pos: Vec2): bool =
## Checks if pos is inside rect.
(rect.x <= pos.x and pos.x <= rect.x + rect.w) and (
rect.y <= pos.y and pos.y <= rect.y + rect.h)
proc `+`*(a, b: Rect): Rect =
## Add two boxes together.
result.x = a.x + b.x
result.y = a.y + b.y
result.w = a.w
result.h = a.h
proc `$`*(a: Rect): string =
return "(" &
@ -1482,3 +1415,15 @@ proc `$`*(a: Rect): string =
$a.y & ": " &
$a.w & " x " &
$a.h & ")"
proc inside*(pos: Vec2, rect: Rect): bool =
## Checks if pos is inside rect.
(rect.x <= pos.x and pos.x <= rect.x + rect.w) and (
rect.y <= pos.y and pos.y <= rect.y + rect.h)
proc overlap*(a, b: Rect): bool =
## Returns true if box a overlaps box b.
let
xOverlap = between(a.x, b.x, b.x + b.w) or between(b.x, a.x, a.x + a.w)
yOverlap = between(a.y, b.y, b.y + b.h) or between(b.y, a.y, a.y + a.h)
return xOverlap and yOverlap