diff --git a/README.md b/README.md index 7ca0d8e..87fc075 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # VMath +`nimble install vmath` + Collection of math routines for 2d and 3d graphics. Has functions for Vec2, Vec3, Vec4, Mat3, Mat4 and Quat. diff --git a/src/vmath.nim b/src/vmath.nim index 0ff5b8b..ed57e32 100644 --- a/src/vmath.nim +++ b/src/vmath.nim @@ -2,21 +2,19 @@ import hashes, math, random, strformat, strutils export math -func between*(value, min, max: float32): bool = +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) -func sign*(v: float32): float32 = +proc sign*(v: float32): float32 = ## Returns the sign of a number, -1 or 1. - if v >= 0: - return 1.0 - return -1.0 + if v >= 0: 1.0 else: -1.0 -func quantize*(v: float32, n: float32): float32 = +proc quantize*(v: float32, n: float32): float32 = ## Makes v be multipe of n. Rounding to integer quantize by 1.0. sign(v) * floor(abs(v) / n) * n -func lerp*(a: float32, b: float32, v: float32): float32 = +proc lerp*(a: float32, b: float32, v: float32): float32 = ## Interpolates value between a and b. ## * 0 -> a ## * 1 -> b @@ -28,99 +26,99 @@ type Vec2* = object x*: float32 y*: float32 -func vec2*(x, y: float32): Vec2 {.inline.} = +proc vec2*(x, y: float32): Vec2 {.inline.} = result.x = x result.y = y -func vec2*(v: float32): Vec2 {.inline.} = +proc vec2*(v: float32): Vec2 {.inline.} = result.x = v result.y = v -func vec2*(a: Vec2): Vec2 {.inline.} = +proc vec2*(a: Vec2): Vec2 {.inline.} = result.x = a.x result.y = a.y -func `+`*(a: Vec2, b: Vec2): Vec2 {.inline.} = +proc `+`*(a: Vec2, b: Vec2): Vec2 {.inline.} = result.x = a.x + b.x result.y = a.y + b.y -func `-`*(a: Vec2, b: Vec2): Vec2 {.inline.} = +proc `-`*(a: Vec2, b: Vec2): Vec2 {.inline.} = result.x = a.x - b.x result.y = a.y - b.y -func `*`*(a: Vec2, b: float32): Vec2 {.inline.} = +proc `*`*(a: Vec2, b: float32): Vec2 {.inline.} = result.x = a.x * b result.y = a.y * b -func `*`*(a: float32, b: Vec2): Vec2 {.inline.} = +proc `*`*(a: float32, b: Vec2): Vec2 {.inline.} = b * a -func `/`*(a: Vec2, b: float32): Vec2 {.inline.} = +proc `/`*(a: Vec2, b: float32): Vec2 {.inline.} = result.x = a.x / b result.y = a.y / b -func `+=`*(a: var Vec2, b: Vec2) {.inline.} = +proc `+=`*(a: var Vec2, b: Vec2) {.inline.} = a.x += b.x a.y += b.y -func `-=`*(a: var Vec2, b: Vec2) {.inline.} = +proc `-=`*(a: var Vec2, b: Vec2) {.inline.} = a.x -= b.x a.y -= b.y -func `*=`*(a: var Vec2, b: float32) {.inline.} = +proc `*=`*(a: var Vec2, b: float32) {.inline.} = a.x *= b a.y *= b -func `/=`*(a: var Vec2, b: float32) {.inline.} = +proc `/=`*(a: var Vec2, b: float32) {.inline.} = a.x /= b a.y /= b -func zero*(a: var Vec2) {.inline.} = +proc zero*(a: var Vec2) {.inline.} = a.x = 0 a.y = 0 -func `-`*(a: Vec2): Vec2 {.inline.} = +proc `-`*(a: Vec2): Vec2 {.inline.} = result.x = -a.x result.y = -a.y -func hash*(a: Vec2): Hash = +proc hash*(a: Vec2): Hash = hash((a.x, a.y)) -func lengthSq*(a: Vec2): float32 {.inline.} = +proc lengthSq*(a: Vec2): float32 {.inline.} = a.x * a.x + a.y * a.y -func length*(a: Vec2): float32 {.inline.} = - math.sqrt(a.lengthSq) +proc length*(a: Vec2): float32 {.inline.} = + sqrt(a.lengthSq) -func `length=`*(a: var Vec2, b: float32) {.inline.}= +proc `length=`*(a: var Vec2, b: float32) {.inline.} = a *= b / a.length -func normalize*(a: Vec2): Vec2 {.inline.} = +proc normalize*(a: Vec2): Vec2 {.inline.} = a / a.length -func dot*(a: Vec2, b: Vec2): float32 {.inline.} = +proc dot*(a: Vec2, b: Vec2): float32 {.inline.} = a.x*b.x + a.y*b.y -func dir*(at: Vec2, to: Vec2): Vec2 {.inline.} = +proc dir*(at: Vec2, to: Vec2): Vec2 {.inline.} = (at - to).normalize() -func dir*(th: float32): Vec2 {.inline.} = +proc dir*(th: float32): Vec2 {.inline.} = vec2(cos(th), sin(th)) -func dist*(at: Vec2, to: Vec2): float32 {.inline.} = +proc dist*(at: Vec2, to: Vec2): float32 {.inline.} = (at - to).length -func distSq*(at: Vec2, to: Vec2): float32 {.inline.} = +proc distSq*(at: Vec2, to: Vec2): float32 {.inline.} = (at - to).lengthSq -func lerp*(a: Vec2, b: Vec2, v: float32): Vec2 {.inline.} = +proc lerp*(a: Vec2, b: Vec2, v: float32): Vec2 {.inline.} = a * (1.0 - v) + b * v -func quantize*(v: Vec2, n: float32): Vec2 {.inline.} = +proc quantize*(v: Vec2, n: float32): Vec2 {.inline.} = result.x = sign(v.x) * floor(abs(v.x) / n) * n result.y = sign(v.y) * floor(abs(v.y) / n) * n -func inRect*(v: Vec2, a: Vec2, b: Vec2): bool {.inline.} = +proc inRect*(v: Vec2, a: Vec2, b: Vec2): bool {.inline.} = ## Check to see if v is inside a rectange formed by a and b. ## It does not matter how a and b are arranged. let @@ -128,14 +126,14 @@ func inRect*(v: Vec2, a: Vec2, b: Vec2): bool {.inline.} = max = vec2(max(a.x, b.x), max(a.y, b.y)) v.x > min.x and v.x < max.x and v.y > min.y and v.y < max.y -func `[]`*(a: Vec2, i: int): float32 = +proc `[]`*(a: Vec2, i: int): float32 = assert(i == 0 or i == 1) if i == 0: return a.x elif i == 1: return a.y -func `[]=`*(a: var Vec2, i: int, b: float32) = +proc `[]=`*(a: var Vec2, i: int, b: float32) = assert(i == 0 or i == 1) if i == 0: a.x = b @@ -147,10 +145,10 @@ proc randVec2*(): Vec2 = let v = rand(1.0) vec2(cos(a)*v, sin(a)*v) -func `$`*(a: Vec2): string = +proc `$`*(a: Vec2): string = &"({a.x:.4f}, {a.y:.4f})" -func fixAngle*(angle: float32): float32 = +proc fixAngle*(angle: float32): float32 = ## Make angle be from -PI to PI radians. var angle = angle while angle > PI: @@ -159,19 +157,19 @@ func fixAngle*(angle: float32): float32 = angle += PI*2 angle -func angle*(a: Vec2): float32 = +proc angle*(a: Vec2): float32 = ## Angle of a Vec2. - math.arctan2(a.y, a.x) + arctan2(a.y, a.x) -func angleBetween*(a: Vec2, b: Vec2): float32 = +proc angleBetween*(a: Vec2, b: Vec2): float32 = ## Angle between 2 Vec2. - fixAngle(math.arctan2(a.y - b.y, a.x - b.x)) + fixAngle(arctan2(a.y - b.y, a.x - b.x)) -func angleBetween*(a, b: float32): float32 = +proc angleBetween*(a, b: float32): float32 = ## Angle between angle a and angle b. (b - a).fixAngle -func turnAngle*(a, b, speed: float32): float32 = +proc turnAngle*(a, b, speed: float32): float32 = ## Move from angle a to angle b with step of v. var turn = fixAngle(b - a) @@ -189,17 +187,17 @@ type Vec3* = object y*: float32 z*: float32 -func vec3*(x, y, z: float32): Vec3 = +proc vec3*(x, y, z: float32): Vec3 = result.x = x result.y = y result.z = z -func vec3*(v: float32): Vec3 = +proc vec3*(v: float32): Vec3 = result.x = v result.y = v result.z = v -func vec3*(a: Vec3): Vec3 = +proc vec3*(a: Vec3): Vec3 = result.x = a.x result.y = a.y result.z = a.z @@ -208,127 +206,127 @@ const X_DIR* = vec3(1.0, 0.0, 0.0) const Y_DIR* = vec3(0.0, 1.0, 0.0) const Z_DIR* = vec3(0.0, 0.0, 1.0) -func `+`*(a: Vec3, b: Vec3): Vec3 = +proc `+`*(a: Vec3, b: Vec3): Vec3 = result.x = a.x + b.x result.y = a.y + b.y result.z = a.z + b.z -func `-`*(a: Vec3, b: Vec3): Vec3 = +proc `-`*(a: Vec3, b: Vec3): Vec3 = result.x = a.x - b.x result.y = a.y - b.y result.z = a.z - b.z -func `-`*(a: Vec3): Vec3 = +proc `-`*(a: Vec3): Vec3 = result.x = -a.x result.y = -a.y result.z = -a.z -func `*`*(a: Vec3, b: float32): Vec3 = +proc `*`*(a: Vec3, b: float32): Vec3 = result.x = a.x * b result.y = a.y * b result.z = a.z * b -func `*`*(a: float32, b: Vec3): Vec3 = +proc `*`*(a: float32, b: Vec3): Vec3 = b * a -func `/`*(a: Vec3, b: float32): Vec3 = +proc `/`*(a: Vec3, b: float32): Vec3 = result.x = a.x / b result.y = a.y / b result.z = a.z / b -func `/`*(a: float32, b: Vec3): Vec3 = +proc `/`*(a: float32, b: Vec3): Vec3 = result.x = a / b.x result.y = a / b.y result.z = a / b.z -func `+=`*(a: var Vec3, b: Vec3) = +proc `+=`*(a: var Vec3, b: Vec3) = a.x += b.x a.y += b.y a.z += b.z -func `-=`*(a: var Vec3, b: Vec3) = +proc `-=`*(a: var Vec3, b: Vec3) = a.x -= b.x a.y -= b.y a.z -= b.z -func `*=`*(a: var Vec3, b: float32) = +proc `*=`*(a: var Vec3, b: float32) = a.x *= b a.y *= b a.z *= b -func `/=`*(a: var Vec3, b: float32) = +proc `/=`*(a: var Vec3, b: float32) = a.x /= b a.y /= b a.z /= b -func zero*(a: var Vec3) = +proc zero*(a: var Vec3) = a.x = 0 a.y = 0 a.z = 0 -func `-`*(a: var Vec3): Vec3 = +proc `-`*(a: var Vec3): Vec3 = result.x = -a.x result.y = -a.y result.z = -a.z -func hash*(a: Vec3): Hash = +proc hash*(a: Vec3): Hash = hash((a.x, a.y, a.z)) -func lengthSq*(a: Vec3): float32 = +proc lengthSq*(a: Vec3): float32 = a.x * a.x + a.y * a.y + a.z * a.z -func length*(a: Vec3): float32 = - math.sqrt(a.lengthSq) +proc length*(a: Vec3): float32 = + sqrt(a.lengthSq) -func `length=`*(a: var Vec3, b: float32) = +proc `length=`*(a: var Vec3, b: float32) = a *= b / a.length -func floor*(a: Vec3): Vec3 = +proc floor*(a: Vec3): Vec3 = vec3(floor(a.x), floor(a.y), floor(a.z)) -func round*(a: Vec3): Vec3 = +proc round*(a: Vec3): Vec3 = vec3(round(a.x), round(a.y), round(a.z)) -func ceil*(a: Vec3): Vec3 = +proc ceil*(a: Vec3): Vec3 = vec3(ceil(a.x), ceil(a.y), ceil(a.z)) -func normalize*(a: Vec3): Vec3 = - a / math.sqrt(a.x*a.x + a.y*a.y + a.z*a.z) +proc normalize*(a: Vec3): Vec3 = + a / sqrt(a.x*a.x + a.y*a.y + a.z*a.z) -func cross*(a: Vec3, b: Vec3): Vec3 = +proc cross*(a: Vec3, b: Vec3): Vec3 = result.x = a.y*b.z - a.z*b.y result.y = a.z*b.x - a.x*b.z result.z = a.x*b.y - a.y*b.x -func computeNormal*(a, b, c: Vec3): Vec3 = +proc computeNormal*(a, b, c: Vec3): Vec3 = cross(c - b, b - a).normalize() -func dot*(a: Vec3, b: Vec3): float32 = +proc dot*(a: Vec3, b: Vec3): float32 = a.x*b.x + a.y*b.y + a.z*b.z -func dir*(at: Vec3, to: Vec3): Vec3 = +proc dir*(at: Vec3, to: Vec3): Vec3 = (at - to).normalize() -func dist*(at: Vec3, to: Vec3): float32 = +proc dist*(at: Vec3, to: Vec3): float32 = (at - to).length -func distSq*(at: Vec3, to: Vec3): float32 = +proc distSq*(at: Vec3, to: Vec3): float32 = (at - to).lengthSq -func lerp*(a: Vec3, b: Vec3, v: float32): Vec3 = +proc lerp*(a: Vec3, b: Vec3, v: float32): Vec3 = a * (1.0 - v) + b * v -func quantize*(v: Vec3, n: float32): Vec3 = +proc quantize*(v: Vec3, n: float32): Vec3 = result.x = sign(v.x) * floor(abs(v.x) / n) * n result.y = sign(v.y) * floor(abs(v.y) / n) * n result.z = sign(v.z) * floor(abs(v.z) / n) * n -func angleBetween*(a, b: Vec3): float32 = +proc angleBetween*(a, b: Vec3): float32 = var dot = dot(a, b) dot = dot / (a.length * b.length) arccos(dot) -func `[]`*(a: Vec3, i: int): float32 = +proc `[]`*(a: Vec3, i: int): float32 = assert(i == 0 or i == 1 or i == 2) if i == 0: return a.x @@ -337,7 +335,7 @@ func `[]`*(a: Vec3, i: int): float32 = elif i == 2: return a.z -func `[]=`*(a: var Vec3, i: int, b: float32) = +proc `[]=`*(a: var Vec3, i: int, b: float32) = assert(i == 0 or i == 1 or i == 2) if i == 0: a.x = b @@ -346,25 +344,25 @@ func `[]=`*(a: var Vec3, i: int, b: float32) = elif i == 2: a.z = b -func xy*(a: Vec3): Vec2 = +proc xy*(a: Vec3): Vec2 = vec2(a.x, a.y) -func xz*(a: Vec3): Vec2 = +proc xz*(a: Vec3): Vec2 = vec2(a.x, a.z) -func yx*(a: Vec3): Vec2 = +proc yx*(a: Vec3): Vec2 = vec2(a.y, a.x) -func yz*(a: Vec3): Vec2 = +proc yz*(a: Vec3): Vec2 = vec2(a.y, a.z) -func zx*(a: Vec3): Vec2 = +proc zx*(a: Vec3): Vec2 = vec2(a.y, a.x) -func zy*(a: Vec3): Vec2 = +proc zy*(a: Vec3): Vec2 = vec2(a.z, a.y) -func almostEquals*(a, b: Vec3, precision = 1e-6): bool = +proc almostEquals*(a, b: Vec3, precision = 1e-6): bool = let c = a - b abs(c.x) < precision and abs(c.y) < precision and abs(c.z) < precision @@ -382,7 +380,7 @@ proc randVec3*(): Vec3 = cos(ph) ) -func `$`*(a: Vec3): string = +proc `$`*(a: Vec3): string = &"({a.x:.8f}, {a.y:.8f}, {a.z:.8f})" type Vec4* = object @@ -392,92 +390,92 @@ type Vec4* = object z*: float32 w*: float32 -func vec4*(x, y, z, w: float32): Vec4 = +proc vec4*(x, y, z, w: float32): Vec4 = result.x = x result.y = y result.z = z result.w = w -func vec4*(v: float32): Vec4 = +proc vec4*(v: float32): Vec4 = result.x = v result.y = v result.z = v result.w = v -func `+`*(a: Vec4, b: Vec4): Vec4 = +proc `+`*(a: Vec4, b: Vec4): Vec4 = result.x = a.x + b.x result.y = a.y + b.y result.z = a.z + b.z result.w = a.w + b.w -func `-`*(a: Vec4, b: Vec4): Vec4 = +proc `-`*(a: Vec4, b: Vec4): Vec4 = result.x = a.x - b.x result.y = a.y - b.y result.z = a.z - b.z result.w = a.w - b.w -func `-`*(a: Vec4): Vec4 = +proc `-`*(a: Vec4): Vec4 = result.x = -a.x result.y = -a.y result.z = -a.z result.w = -a.w -func `*`*(a: Vec4, b: float32): Vec4 = +proc `*`*(a: Vec4, b: float32): Vec4 = result.x = a.x * b result.y = a.y * b result.z = a.z * b result.w = a.w * b -func `*`*(a: float32, b: Vec4): Vec4 = +proc `*`*(a: float32, b: Vec4): Vec4 = b * a -func `/`*(a: Vec4, b: float32): Vec4 = +proc `/`*(a: Vec4, b: float32): Vec4 = result.x = a.x / b result.y = a.y / b result.z = a.z / b result.w = a.w / b -func `/`*(a: float32, b: Vec4): Vec4 = +proc `/`*(a: float32, b: Vec4): Vec4 = result.x = a / b.x result.y = a / b.y result.z = a / b.z result.w = a / b.w -func `+=`*(a: var Vec4, b: Vec4) = +proc `+=`*(a: var Vec4, b: Vec4) = a.x += b.x a.y += b.y a.z += b.z a.w += b.w -func `-=`*(a: var Vec4, b: Vec4) = +proc `-=`*(a: var Vec4, b: Vec4) = a.x -= b.x a.y -= b.y a.z -= b.z a.w -= b.w -func `*=`*(a: var Vec4, b: float32) = +proc `*=`*(a: var Vec4, b: float32) = a.x *= b a.y *= b a.z *= b a.w *= b -func `/=`*(a: var Vec4, b: float32) = +proc `/=`*(a: var Vec4, b: float32) = a.x /= b a.y /= b a.z /= b a.w /= b -func zero*(a: var Vec4) = +proc zero*(a: var Vec4) = a.x = 0 a.y = 0 a.z = 0 a.w = 0 -func hash*(a: Vec4): Hash = +proc hash*(a: Vec4): Hash = hash((a.x, a.y, a.z, a.w)) -func `[]`*(a: Vec4, i: int): float32 = +proc `[]`*(a: Vec4, i: int): float32 = assert(i == 0 or i == 1 or i == 2) if i == 0: return a.x @@ -488,7 +486,7 @@ func `[]`*(a: Vec4, i: int): float32 = elif i == 3: return a.w -func `[]=`*(a: var Vec4, i: int, b: float32) = +proc `[]=`*(a: var Vec4, i: int, b: float32) = assert(i == 0 or i == 1 or i == 2) if i == 0: a.x = b @@ -499,30 +497,30 @@ func `[]=`*(a: var Vec4, i: int, b: float32) = elif i == 3: a.w = b -func lerp*(a: Vec4, b: Vec4, v: float32): Vec4 = +proc lerp*(a: Vec4, b: Vec4, v: float32): Vec4 = a * (1.0 - v) + b * v -func xyz*(a: Vec4): Vec3 = +proc xyz*(a: Vec4): Vec3 = vec3(a.x, a.y, a.z) -func `$`*(a: Vec4): string = +proc `$`*(a: Vec4): string = &"({a.x:.8f}, {a.y:.8f}, {a.z:.8f}, {a.w:.8f})" -func vec3*(a: Vec2, z = 0.0): Vec3 = +proc vec3*(a: Vec2, z = 0.0): Vec3 = vec3(a.x, a.y, z) -func vec4*(a: Vec3, w = 0.0): Vec4 = +proc vec4*(a: Vec3, w = 0.0): Vec4 = vec4(a.x, a.y, a.z, w) -func vec4*(a: Vec2, z = 0.0, 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 -template `[]`*(a: Mat3, i, j: int): float32 = a[i * 3 + j ] +template `[]`*(a: Mat3, i, j: int): float32 = a[i * 3 + j] template `[]=`*(a: Mat3, i, j: int, v: float32) = a[i * 3 + j] = v -func mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 = +proc mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 = result[0] = a result[1] = b result[2] = c @@ -533,10 +531,10 @@ func mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 = result[7] = h result[8] = i -func mat3*(a: Mat3): Mat3 = +proc mat3*(a: Mat3): Mat3 = a -func identity*(a: var Mat3) = +proc identity*(a: var Mat3) = a[0] = 1 a[1] = 0 a[2] = 0 @@ -547,10 +545,10 @@ func identity*(a: var Mat3) = a[7] = 0 a[8] = 1 -func mat3*(): Mat3 = +proc mat3*(): Mat3 = result.identity() -func transpose*(a: Mat3): Mat3 = +proc transpose*(a: Mat3): Mat3 = result[0] = a[0] result[1] = a[3] result[2] = a[6] @@ -561,12 +559,12 @@ func transpose*(a: Mat3): Mat3 = result[7] = a[5] result[8] = a[8] -func `$`*(a: Mat3): string = +proc `$`*(a: Mat3): string = &"""[{a[0]:.4f}, {a[1]:.4f}, {a[2]:.4f}, {a[3]:.4f}, {a[4]:.4f}, {a[5]:.4f}, {a[6]:.4f}, {a[7]:.4f}, {a[8]:.4f}]""" -func `*`*(a: Mat3, b: Mat3): Mat3 = +proc `*`*(a: Mat3, b: Mat3): Mat3 = result[0, 0] += b[0, 0] * a[0, 0] + b[0, 1] * a[1, 0] + b[0, 2] * a[2, 0] result[0, 1] += b[0, 0] * a[0, 1] + b[0, 1] * a[1, 1] + b[0, 2] * a[2, 1] result[0, 2] += b[0, 0] * a[0, 2] + b[0, 1] * a[1, 2] + b[0, 2] * a[2, 2] @@ -577,7 +575,7 @@ func `*`*(a: Mat3, b: Mat3): Mat3 = result[2, 1] += b[2, 0] * a[0, 1] + b[2, 1] * a[1, 1] + b[2, 2] * a[2, 1] result[2, 2] += b[2, 0] * a[0, 2] + b[2, 1] * a[1, 2] + b[2, 2] * a[2, 2] -func scale*(a: Mat3, v: Vec2): Mat3 = +proc scale*(a: Mat3, v: Vec2): Mat3 = result[0] = v.x * a[0] result[1] = v.x * a[1] result[2] = v.x * a[2] @@ -588,7 +586,7 @@ func scale*(a: Mat3, v: Vec2): Mat3 = result[7] = a[7] result[8] = a[8] -func scale*(a: Mat3, v: Vec3): Mat3 = +proc scale*(a: Mat3, v: Vec3): Mat3 = result[0] = v.x * a[0] result[1] = v.x * a[1] result[2] = v.x * a[2] @@ -599,19 +597,19 @@ func scale*(a: Mat3, v: Vec3): Mat3 = result[7] = v.z * a[7] result[8] = v.z * a[8] -func translate*(v: Vec2): Mat3 = +proc translate*(v: Vec2): Mat3 = result[0, 0] = 1 result[1, 1] = 1 result[2, 0] = v.x result[2, 1] = v.y result[2, 2] = 1 -func scale*(v: Vec2): Mat3 = +proc scale*(v: Vec2): Mat3 = result[0, 0] = v.x result[1, 1] = v.y result[2, 2] = 1 -func rotationMat3*(angle: float32): Mat3 = +proc rotationMat3*(angle: float32): Mat3 = # Create a matrix from an angle. let sin = sin(angle) @@ -628,20 +626,20 @@ func rotationMat3*(angle: float32): Mat3 = result[2, 1] = 0 result[2, 2] = 1 -func rotate*(a: Mat3, angle: float32): Mat3 = +proc rotate*(a: Mat3, angle: float32): Mat3 = # Rotates a matrix by an angle. a * rotationMat3(angle) -func `*`*(a: Mat3, b: Vec2): Vec2 = +proc `*`*(a: Mat3, b: Vec2): Vec2 = result.x = a[0, 0]*b.x + a[1, 0]*b.y + a[2, 0] result.y = a[0, 1]*b.x + a[1, 1]*b.y + a[2, 1] -func `*`*(a: Mat3, b: Vec3): Vec3 = +proc `*`*(a: Mat3, b: Vec3): Vec3 = result.x = a[0, 0]*b.x + a[1, 0]*b.y + a[2, 0]*b.z result.y = a[0, 1]*b.x + a[1, 1]*b.y + a[2, 1]*b.z result.z = a[0, 2]*b.x + a[1, 2]*b.y + a[2, 2]*b.z -func inverse*(a: Mat3): Mat3 = +proc inverse*(a: Mat3): Mat3 = let determinant = ( a[0, 0] * (a[1, 1] * a[2, 2] - a[2, 1] * a[1, 2]) - a[0, 1] * (a[1, 0] * a[2, 2] - a[1, 2] * a[2, 0]) + @@ -662,10 +660,10 @@ func inverse*(a: Mat3): Mat3 = type Mat4* = array[16, float32] ## 4x4 Matrix - OpenGL row order -template `[]`*(a: Mat4, i, j: int): float32 = a[i * 4 + j ] +template `[]`*(a: Mat4, i, j: int): float32 = a[i * 4 + j] template `[]=`*(a: Mat4, i, j: int, v: float32) = a[i * 4 + j] = v -func mat4*(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, +proc mat4*(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15: float32): Mat4 = result[0] = v0 result[1] = v1 @@ -684,10 +682,10 @@ func mat4*(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, result[14] = v14 result[15] = v15 -func mat4*(a: Mat4): Mat4 = +proc mat4*(a: Mat4): Mat4 = a -func identity*(): Mat4 = +proc identity*(): Mat4 = result[0] = 1 result[1] = 0 result[2] = 0 @@ -705,10 +703,10 @@ func identity*(): Mat4 = result[14] = 0 result[15] = 1 -func mat4*(): Mat4 = +proc mat4*(): Mat4 = identity() -func transpose*(a: Mat4): Mat4 = +proc transpose*(a: Mat4): Mat4 = result[0] = a[0] result[1] = a[4] result[2] = a[8] @@ -729,7 +727,7 @@ func transpose*(a: Mat4): Mat4 = result[14] = a[11] result[15] = a[15] -func determinant*(a: Mat4): float32 = +proc determinant*(a: Mat4): float32 = var a00 = a[0] a01 = a[1] @@ -757,7 +755,7 @@ func determinant*(a: Mat4): float32 = a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33 ) -func inverse*(a: Mat4): Mat4 = +proc inverse*(a: Mat4): Mat4 = var a00 = a[0] a01 = a[1] @@ -810,7 +808,7 @@ func inverse*(a: Mat4): Mat4 = result[14] = (-a30*b03 + a31*b01 - a32*b00)*invDet result[15] = (+a20*b03 - a21*b01 + a22*b00)*invDet -func `*`*(a, b: Mat4): Mat4 = +proc `*`*(a, b: Mat4): Mat4 = var a00 = a[0] a01 = a[1] @@ -864,62 +862,62 @@ func `*`*(a, b: Mat4): Mat4 = result[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32 result[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33 -func `*`*(a: Mat4, b: Vec3): Vec3 = +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] -func `*`*(a: Mat4, b: Vec4): Vec4 = +proc `*`*(a: Mat4, b: Vec4): Vec4 = result.x = a[0]*b.x + a[4]*b.y + a[8]*b.z + a[12]*b.w result.y = a[1]*b.x + a[5]*b.y + a[9]*b.z + a[13]*b.w result.z = a[2]*b.x + a[6]*b.y + a[10]*b.z + a[14]*b.w result.w = a[3]*b.x + a[7]*b.y + a[11]*b.z + a[15]*b.w -func right*(a: Mat4): Vec3 = +proc right*(a: Mat4): Vec3 = result.x = a[0] result.y = a[1] result.z = a[2] -func `right=`*(a: var Mat4, b: Vec3) = +proc `right=`*(a: var Mat4, b: Vec3) = a[0] = b.x a[1] = b.y a[2] = b.z -func up*(a: Mat4): Vec3 = +proc up*(a: Mat4): Vec3 = result.x = a[4] result.y = a[5] result.z = a[6] -func `up=`*(a: var Mat4, b: Vec3) = +proc `up=`*(a: var Mat4, b: Vec3) = a[4] = b.x a[5] = b.y a[6] = b.z -func forward*(a: Mat4): Vec3 = +proc forward*(a: Mat4): Vec3 = result.x = a[8] result.y = a[9] result.z = a[10] -func `forward=`*(a: var Mat4, b: Vec3) = +proc `forward=`*(a: var Mat4, b: Vec3) = a[8] = b.x a[9] = b.y a[10] = b.z -func pos*(a: Mat4): Vec3 = +proc pos*(a: Mat4): Vec3 = result.x = a[12] result.y = a[13] result.z = a[14] -func `pos=`*(a: var Mat4, b: Vec3) = +proc `pos=`*(a: var Mat4, b: Vec3) = a[12] = b.x a[13] = b.y a[14] = b.z -func rotationOnly*(a: Mat4): Mat4 = +proc rotationOnly*(a: Mat4): Mat4 = result = a result.pos = vec3(0, 0, 0) -func dist*(a, b: Mat4): float32 = +proc dist*(a, b: Mat4): float32 = var x = a[12] - b[12] y = a[13] - b[13] @@ -927,7 +925,7 @@ func dist*(a, b: Mat4): float32 = sqrt(x*x + y*y + z*z) #[ -func translate*(a: Mat4, v: Vec3): Mat4 = +proc translate*(a: Mat4, v: Vec3): Mat4 = var a00 = a[0] a01 = a[1] @@ -961,7 +959,7 @@ func translate*(a: Mat4, v: Vec3): Mat4 = result[15] = a03*v.x + a13*v.y + a23*v.z + a[15] ]# -func translate*(v: Vec3): Mat4 = +proc translate*(v: Vec3): Mat4 = result[0] = 1 result[5] = 1 result[10] = 1 @@ -970,19 +968,19 @@ func translate*(v: Vec3): Mat4 = result[13] = v.y result[14] = v.z -func scale*(v: Vec3): Mat4 = +proc scale*(v: Vec3): Mat4 = result[0] = v.x result[5] = v.y result[10] = v.z result[15] = 1 -func close*(a: Mat4, b: Mat4): bool = +proc close*(a: Mat4, b: Mat4): bool = for i in 0..15: if abs(a[i] - b[i]) > 0.001: return false true -func hrp*(m: Mat4): Vec3 = +proc hrp*(m: Mat4): Vec3 = var heading, pitch, roll: float32 if m[1] > 0.998: # singularity at north pole heading = arctan2(m[2], m[10]) @@ -1000,7 +998,7 @@ func hrp*(m: Mat4): Vec3 = result.y = pitch result.z = roll -func frustum*(left, right, bottom, top, near, far: float32): Mat4 = +proc frustum*(left, right, bottom, top, near, far: float32): Mat4 = var rl = (right - left) tb = (top - bottom) @@ -1022,13 +1020,13 @@ func frustum*(left, right, bottom, top, near, far: float32): Mat4 = result[14] = -(far*near*2) / fn result[15] = 0 -func perspective*(fovy, aspect, near, far: float32): Mat4 = +proc perspective*(fovy, aspect, near, far: float32): Mat4 = var top = near * tan(fovy*PI / 360.0) right = top * aspect frustum(-right, right, -top, top, near, far) -func ortho*(left, right, bottom, top, near, far: float32): Mat4 = +proc ortho*(left, right, bottom, top, near, far: float32): Mat4 = var rl = (right - left) tb = (top - bottom) @@ -1050,7 +1048,7 @@ func ortho*(left, right, bottom, top, near, far: float32): Mat4 = result[14] = -(far + near) / fn result[15] = 1 -func lookAt*(eye, center, up: Vec3): Mat4 = +proc lookAt*(eye, center, up: Vec3): Mat4 = var eyex = eye[0] eyey = eye[1] @@ -1127,7 +1125,7 @@ func lookAt*(eye, center, up: Vec3): Mat4 = result[14] = -(z0*eyex + z1*eyey + z2*eyez) result[15] = 1 -func mat3*(m: Mat4): Mat3 = +proc mat3*(m: Mat4): Mat3 = ## Gets rotation and translation, ignoring z coordinates. result[0, 0] = m[0, 0] result[0, 1] = m[0, 1] @@ -1139,7 +1137,7 @@ func mat3*(m: Mat4): Mat3 = result[2, 1] = m[3, 1] result[2, 2] = 0 -func mat3Rotation*(m: Mat4): Mat3 = +proc mat3Rotation*(m: Mat4): Mat3 = ## Gets the rotational part of the 4x4 matrix. result[0, 0] = m[0, 0] result[0, 1] = m[0, 1] @@ -1151,7 +1149,7 @@ func mat3Rotation*(m: Mat4): Mat3 = result[2, 1] = m[2, 1] result[2, 2] = m[2, 2] -func mat4*(m: Mat3): Mat4 = +proc mat4*(m: Mat3): Mat4 = ## Takes a 2d Mat3 with position and converts to a 3d matrix. result[0, 0] = m[0, 0] result[0, 1] = m[0, 1] @@ -1173,7 +1171,7 @@ func mat4*(m: Mat3): Mat4 = result[3, 2] = 0 result[3, 3] = 1 -func mat4Rotation*(m: Mat3): Mat4 = +proc mat4Rotation*(m: Mat3): Mat4 = ## Gets the rotational part of the 3x3 matrix into a 4x4 matrix. result[0, 0] = m[0, 0] result[0, 1] = m[0, 1] @@ -1185,7 +1183,7 @@ func mat4Rotation*(m: Mat3): Mat4 = result[2, 1] = m[2, 1] result[2, 2] = m[2, 2] -func `$`*(a: Mat4): string = +proc `$`*(a: Mat4): string = &"""[{a[0]:.5f}, {a[1]:.5f}, {a[2]:.5f}, {a[3]:.5f}, {a[4]:.5f}, {a[5]:.5f}, {a[6]:.5f}, {a[7]:.5f}, {a[8]:.5f}, {a[9]:.5f}, {a[10]:.5f}, {a[11]:.5f}, @@ -1197,55 +1195,56 @@ type Quat* = object z*: float32 w*: float32 -func quat*(x, y, z, w: float32): Quat = +proc quat*(x, y, z, w: float32): Quat = result.x = x result.y = y result.z = z result.w = w -func conjugate*(q: Quat): Quat = +proc conjugate*(q: Quat): Quat = result.w = +q.w result.x = -q.x result.y = -q.y result.z = -q.z -func length*(q: Quat): float32 = +proc length*(q: Quat): float32 = sqrt( q.w * q.w + q.x * q.x + q.y * q.y + - q.z * q.z) + q.z * q.z + ) -func normalize*(q: Quat): Quat = +proc normalize*(q: Quat): Quat = var m = q.length result.x = q.x / m result.y = q.y / m result.z = q.z / m result.w = q.w / m -func xyz*(q: Quat): Vec3 = +proc xyz*(q: Quat): Vec3 = result.x = q.x result.y = q.y result.z = q.z -func `xyz=`*(q: var Quat, v: Vec3) = +proc `xyz=`*(q: var Quat, v: Vec3) = q.x = v.x q.y = v.y q.z = v.z -func `-`*(a: var Quat): Quat = +proc `-`*(a: var Quat): Quat = result.x = -a.x result.y = -a.y result.z = -a.z result.w = -a.w -func `+`*(a: Quat, b: Quat): Quat = +proc `+`*(a: Quat, b: Quat): Quat = result.x = a.x + b.x result.y = a.y + b.y result.z = a.z + b.z result.w = a.w + b.w -func `*`*(a, b: Quat): Quat = +proc `*`*(a, b: Quat): Quat = ## Multiply the quaternion by a quaternion. #[ var q = quat(0,0,0,0) @@ -1263,14 +1262,14 @@ func `*`*(a, b: Quat): Quat = result.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x result.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z -func `*`*(q: Quat, v: float32): Quat = +proc `*`*(q: Quat, v: float32): Quat = ## Multiply the quaternion by a float32. result.x = q.x * v result.y = q.y * v result.z = q.z * v result.w = q.w * v -func `*`*(q: Quat, v: Vec3): Vec3 = +proc `*`*(q: Quat, v: Vec3): Vec3 = ## Multiply the quaternion by a vector. var x = v.x @@ -1291,7 +1290,7 @@ func `*`*(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 -func `[]=`*(a: var Quat, i: int, b: float32) = +proc `[]=`*(a: var Quat, i: int, b: float32) = assert(i == 0 or i == 1 or i == 2 or i == 3) if i == 0: a.x = b @@ -1302,7 +1301,7 @@ func `[]=`*(a: var Quat, i: int, b: float32) = elif i == 3: a.w = b -func mat3*(q: Quat): Mat3 = +proc mat3*(q: Quat): Mat3 = var xx = q.x * q.x var xy = q.x * q.y var xz = q.x * q.z @@ -1325,7 +1324,7 @@ func mat3*(q: Quat): Mat3 = result[7] = 0 + 2 * (yz + xw) result[8] = 1 - 2 * (xx + yy) -func mat4*(q: Quat): Mat4 = +proc mat4*(q: Quat): Mat4 = var xx = q.x * q.x var xy = q.x * q.y var xz = q.x * q.z @@ -1356,7 +1355,7 @@ func mat4*(q: Quat): Mat4 = result[14] = 0 result[15] = 1.0 -func recifuncalSqrt*(x: float32): float32 = +proc recifuncalSqrt*(x: float32): float32 = 1.0/sqrt(x) proc quat*(m: Mat4): Quat = @@ -1395,7 +1394,7 @@ proc quat*(m: Mat4): Quat = assert abs(q.length - 1.0) < 0.001 q -func fromAxisAngle*(axis: Vec3, angle: float32): Quat = +proc fromAxisAngle*(axis: Vec3, angle: float32): Quat = var a = axis.normalize() var s = sin(angle / 2) result.x = a.x * s @@ -1403,7 +1402,7 @@ func fromAxisAngle*(axis: Vec3, angle: float32): Quat = result.z = a.z * s result.w = cos(angle / 2) -func toAxisAngle*(q: Quat, axis: var Vec3, angle: var float32) = +proc toAxisAngle*(q: Quat, axis: var Vec3, angle: var float32) = var cosAngle = q.w angle = arccos(cosAngle) * 2.0 var sinAngle = sqrt(1.0 - cosAngle * cosAngle) @@ -1415,7 +1414,7 @@ func toAxisAngle*(q: Quat, axis: var Vec3, angle: var float32) = axis.y = q.y / sinAngle axis.z = q.z / sinAngle -func quat*(heading, pitch, roll: float32): Quat = +proc quat*(heading, pitch, roll: float32): Quat = var t0 = cos(heading * 0.5) var t1 = sin(heading * 0.5) var t2 = cos(roll * 0.5) @@ -1427,10 +1426,10 @@ func quat*(heading, pitch, roll: float32): Quat = result.y = t0 * t2 * t5 + t1 * t3 * t4 result.z = t1 * t2 * t4 - t0 * t3 * t5 -func quat*(hpr: Vec3): Quat = +proc quat*(hpr: Vec3): Quat = quat(hpr.x, hpr.y, hpr.z) -func hrp*(q: Quat): Vec3 = +proc hrp*(q: Quat): Vec3 = var ysqr = q.y * q.y # roll var t0 = +2.0 * (q.w * q.x + q.y * q.z) @@ -1448,38 +1447,38 @@ func hrp*(q: Quat): Vec3 = var t4 = +1.0 - 2.0 * (ysqr + q.z * q.z) result.x = arctan2(t3, t4) -func dot*(a: Quat, b: Quat): float32 = +proc dot*(a: Quat, b: Quat): float32 = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w -func nlerp*(a: Quat, b: Quat, v: float32): Quat = +proc nlerp*(a: Quat, b: Quat, v: float32): Quat = if dot(a, b) < 0: var c = a (-c * (1.0 - v) + b * v).normalize() else: (a * (1.0 - v) + b * v).normalize() -func `$`*(a: Quat): string = +proc `$`*(a: Quat): string = &"q({a.x:.8f}, {a.y:.8f}, {a.z:.8f}, {a.w:.8f})" -func rotate*(angle: float32, axis: Vec3): Mat4 = +proc rotate*(angle: float32, axis: Vec3): Mat4 = fromAxisAngle(axis, angle).mat4() -func rotateX*(angle: float32): Mat4 = +proc rotateX*(angle: float32): Mat4 = rotate(angle, vec3(1, 0, 0)) -func rotateY*(angle: float32): Mat4 = +proc rotateY*(angle: float32): Mat4 = rotate(angle, vec3(0, 1, 0)) -func rotateZ*(angle: float32): Mat4 = +proc rotateZ*(angle: float32): Mat4 = rotate(angle, vec3(0, 0, 1)) -func scaleMat*(scale: Vec3): Mat4 = +proc scaleMat*(scale: Vec3): Mat4 = result[0] = scale.x result[5] = scale.y result[10] = scale.z result[15] = 1.0 -func scaleMat*(scale: float32): Mat4 = +proc scaleMat*(scale: float32): Mat4 = scaleMat(vec3(scale, scale, scale)) type Rect* = object @@ -1488,60 +1487,60 @@ type Rect* = object w*: float32 h*: float32 -func rect*(x, y, w, h: float32): Rect = +proc rect*(x, y, w, h: float32): Rect = result.x = x result.y = y result.w = w result.h = h -func rect*(pos, size: Vec2): Rect = +proc rect*(pos, size: Vec2): Rect = result.x = pos.x result.y = pos.y result.w = size.x result.h = size.y -func xy*(rect: Rect): Vec2 = +proc xy*(rect: Rect): Vec2 = ## Gets the xy as a Vec2. vec2(rect.x, rect.y) -func `xy=`*(rect: var Rect, v: Vec2) = +proc `xy=`*(rect: var Rect, v: Vec2) = ## Sets the xy from Vec2. rect.x = v.x rect.y = v.y -func wh*(rect: Rect): Vec2 = +proc wh*(rect: Rect): Vec2 = ## Gets the wh as a Vec2. vec2(rect.w, rect.h) -func `wh=`*(rect: var Rect, v: Vec2) = +proc `wh=`*(rect: var Rect, v: Vec2) = ## Sets the wh from Vec2. rect.w = v.x rect.h = v.y -func `*`*(r: Rect, v: float): Rect = +proc `*`*(r: Rect, v: float): Rect = ## * all elements of a Rect. rect(r.x * v, r.y * v, r.w * v, r.h * v) -func `/`*(r: Rect, v: float): Rect = +proc `/`*(r: Rect, v: float): Rect = ## / all elements of a Rect. rect(r.x / v, r.y / v, r.w / v, r.h / v) -func `+`*(a, b: Rect): Rect = +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 -func `$`*(a: Rect): string = +proc `$`*(a: Rect): string = &"({a.x}, {a.y}: {a.w} x {a.h})" -func inside*(pos: Vec2, rect: Rect): bool = +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) -func overlap*(a, b: Rect): bool = +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) diff --git a/vmath.nimble b/vmath.nimble index 2e7f54d..916f528 100644 --- a/vmath.nimble +++ b/vmath.nimble @@ -1,5 +1,3 @@ -# Package - version = "0.3.3" author = "treeform" description = "Math vector library for graphical things." @@ -7,6 +5,4 @@ license = "MIT" srcDir = "src" -# Dependencies - requires "nim >= 0.19.1"