Mercurial > games > semicongine
comparison src/zamikongine/math/vector.nim @ 19:b55d6ecde79d
did: introduce scene graph, meshs and generic vertex buffers
| author | Sam <sam@basx.dev> |
|---|---|
| date | Mon, 09 Jan 2023 11:04:19 +0700 |
| parents | src/math/vector.nim@b40466fa446a |
| children | beb86492b178 |
comparison
equal
deleted
inserted
replaced
| 18:90e117952f74 | 19:b55d6ecde79d |
|---|---|
| 1 import std/random | |
| 2 import std/math | |
| 3 import std/strutils | |
| 4 import std/macros | |
| 5 import std/typetraits | |
| 6 import std/tables | |
| 7 | |
| 8 | |
| 9 type | |
| 10 Vec2*[T: SomeNumber] = array[2, T] | |
| 11 Vec3*[T: SomeNumber] = array[3, T] | |
| 12 Vec4*[T: SomeNumber] = array[4, T] | |
| 13 Vec* = Vec2|Vec3|Vec4 | |
| 14 | |
| 15 # define some often used constants | |
| 16 func ConstOne2[T: SomeNumber](): auto {.compiletime.} = Vec2[T]([T(1), T(1)]) | |
| 17 func ConstOne3[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(1), T(1), T(1)]) | |
| 18 func ConstOne4[T: SomeNumber](): auto {.compiletime.} = Vec4[T]([T(1), T(1), T(1), T(1)]) | |
| 19 func ConstX[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(1), T(0), T(0)]) | |
| 20 func ConstY[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(0), T(1), T(0)]) | |
| 21 func ConstZ[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(0), T(0), T(1)]) | |
| 22 func ConstR[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(1), T(0), T(0)]) | |
| 23 func ConstG[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(0), T(1), T(0)]) | |
| 24 func ConstB[T: SomeNumber](): auto {.compiletime.} = Vec3[T]([T(0), T(0), T(1)]) | |
| 25 | |
| 26 # generates constants: Xf, Xf32, Xf64, Xi, Xi8, Xi16, Xi32, Xi64 | |
| 27 # Also for Y, Z, R, G, B and One | |
| 28 # not sure if this is necessary or even a good idea... | |
| 29 macro generateAllConsts() = | |
| 30 result = newStmtList() | |
| 31 for component in ["X", "Y", "Z", "R", "G", "B", "One2", "One3", "One4"]: | |
| 32 for theType in ["int", "int8", "int16", "int32", "int64", "float", "float32", "float64"]: | |
| 33 var typename = theType[0 .. 0] | |
| 34 if theType[^2].isDigit: | |
| 35 typename = typename & theType[^2] | |
| 36 if theType[^1].isDigit: | |
| 37 typename = typename & theType[^1] | |
| 38 result.add( | |
| 39 newConstStmt( | |
| 40 postfix(ident(component & typename), "*"), | |
| 41 newCall(nnkBracketExpr.newTree(ident("Const" & component), ident(theType))) | |
| 42 ) | |
| 43 ) | |
| 44 | |
| 45 generateAllConsts() | |
| 46 | |
| 47 const X* = ConstX[float]() | |
| 48 const Y* = ConstY[float]() | |
| 49 const Z* = ConstZ[float]() | |
| 50 const One2* = ConstOne2[float]() | |
| 51 const One3* = ConstOne3[float]() | |
| 52 const One4* = ConstOne4[float]() | |
| 53 | |
| 54 func newVec2*[T](x, y: T): auto = Vec2([x, y]) | |
| 55 func newVec3*[T](x, y, z: T): auto = Vec3([x, y, z]) | |
| 56 func newVec4*[T](x, y, z, w: T): auto = Vec4([x, y, z, w]) | |
| 57 | |
| 58 func to*[T](v: Vec2): auto = Vec2([T(v[0]), T(v[1])]) | |
| 59 func to*[T](v: Vec3): auto = Vec3([T(v[0]), T(v[1]), T(v[2])]) | |
| 60 func to*[T](v: Vec4): auto = Vec4([T(v[0]), T(v[1]), T(v[2]), T(v[3])]) | |
| 61 | |
| 62 func toString[T](value: T): string = | |
| 63 var items: seq[string] | |
| 64 for item in value: | |
| 65 items.add($item) | |
| 66 $T & "(" & join(items, " ") & ")" | |
| 67 | |
| 68 func `$`*(v: Vec2[SomeNumber]): string = toString[Vec2[SomeNumber]](v) | |
| 69 func `$`*(v: Vec3[SomeNumber]): string = toString[Vec3[SomeNumber]](v) | |
| 70 func `$`*(v: Vec4[SomeNumber]): string = toString[Vec4[SomeNumber]](v) | |
| 71 | |
| 72 func length*(vec: Vec2[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1]) | |
| 73 func length*(vec: Vec2[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[1] * vec[1])) | |
| 74 func length*(vec: Vec3[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]) | |
| 75 func length*(vec: Vec3[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2])) | |
| 76 func length*(vec: Vec4[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3]) | |
| 77 func length*(vec: Vec4[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3])) | |
| 78 | |
| 79 func normalized*[T](vec: Vec2[T]): auto = | |
| 80 let l = vec.length | |
| 81 when T is SomeFloat: | |
| 82 Vec2[T]([vec[0] / l, vec[1] / l]) | |
| 83 else: | |
| 84 Vec2[float]([float(vec[0]) / l, float(vec[1]) / l]) | |
| 85 func normalized*[T](vec: Vec3[T]): auto = | |
| 86 let l = vec.length | |
| 87 when T is SomeFloat: | |
| 88 Vec3[T]([vec[0] / l, vec[1] / l, vec[2] / l]) | |
| 89 else: | |
| 90 Vec3[float]([float(vec[0]) / l, float(vec[1]) / l, float(vec[2]) / l]) | |
| 91 func normalized*[T](vec: Vec4[T]): auto = | |
| 92 let l = vec.length | |
| 93 when T is SomeFloat: | |
| 94 Vec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) | |
| 95 else: | |
| 96 Vec4[float]([float(vec[0]) / l, float(vec[1]) / l, float(vec[2]) / l, float(vec[3]) / l]) | |
| 97 | |
| 98 # scalar operations | |
| 99 func `+`*(a: Vec2, b: SomeNumber): auto = Vec2([a[0] + b, a[1] + b]) | |
| 100 func `+`*(a: Vec3, b: SomeNumber): auto = Vec3([a[0] + b, a[1] + b, a[2] + b]) | |
| 101 func `+`*(a: Vec4, b: SomeNumber): auto = Vec4([a[0] + b, a[1] + b, a[2] + b, a[3] + b]) | |
| 102 func `-`*(a: Vec2, b: SomeNumber): auto = Vec2([a[0] - b, a[1] - b]) | |
| 103 func `-`*(a: Vec3, b: SomeNumber): auto = Vec3([a[0] - b, a[1] - b, a[2] - b]) | |
| 104 func `-`*(a: Vec4, b: SomeNumber): auto = Vec4([a[0] - b, a[1] - b, a[2] - b, a[3] - b]) | |
| 105 func `*`*(a: Vec2, b: SomeNumber): auto = Vec2([a[0] * b, a[1] * b]) | |
| 106 func `*`*(a: Vec3, b: SomeNumber): auto = Vec3([a[0] * b, a[1] * b, a[2] * b]) | |
| 107 func `*`*(a: Vec4, b: SomeNumber): auto = Vec4([a[0] * b, a[1] * b, a[2] * b, a[3] * b]) | |
| 108 func `/`*[T: SomeInteger](a: Vec2[T], b: SomeInteger): auto = Vec2([a[0] div b, a[1] div b]) | |
| 109 func `/`*[T: SomeFloat](a: Vec2[T], b: SomeFloat): auto = Vec2([a[0] / b, a[1] / b]) | |
| 110 func `/`*[T: SomeInteger](a: Vec3[T], b: SomeInteger): auto = Vec3([a[0] div b, a[1] div b, a[2] div b]) | |
| 111 func `/`*[T: SomeFloat](a: Vec3[T], b: SomeFloat): auto = Vec3([a[0] / b, a[1] / b, a[2] / b]) | |
| 112 func `/`*[T: SomeInteger](a: Vec4[T], b: SomeInteger): auto = Vec4([a[0] div b, a[1] div b, a[2] div b, a[3] div b]) | |
| 113 func `/`*[T: SomeFloat](a: Vec4[T], b: SomeFloat): auto = Vec4([a[0] / b, a[1] / b, a[2] / b, a[3] / b]) | |
| 114 | |
| 115 func `+`*(a: SomeNumber, b: Vec2): auto = Vec2([a + b[0], a + b[1]]) | |
| 116 func `+`*(a: SomeNumber, b: Vec3): auto = Vec3([a + b[0], a + b[1], a + b[2]]) | |
| 117 func `+`*(a: SomeNumber, b: Vec4): auto = Vec4([a + b[0], a + b[1], a + b[2], a + b[3]]) | |
| 118 func `-`*(a: SomeNumber, b: Vec2): auto = Vec2([a - b[0], a - b[1]]) | |
| 119 func `-`*(a: SomeNumber, b: Vec3): auto = Vec3([a - b[0], a - b[1], a - b[2]]) | |
| 120 func `-`*(a: SomeNumber, b: Vec4): auto = Vec4([a - b[0], a - b[1], a - b[2], a - b[3]]) | |
| 121 func `*`*(a: SomeNumber, b: Vec2): auto = Vec2([a * b[0], a * b[1]]) | |
| 122 func `*`*(a: SomeNumber, b: Vec3): auto = Vec3([a * b[0], a * b[1], a * b[2]]) | |
| 123 func `*`*(a: SomeNumber, b: Vec4): auto = Vec4([a * b[0], a * b[1], a * b[2], a * b[3]]) | |
| 124 func `/`*[T: SomeInteger](a: SomeInteger, b: Vec2[T]): auto = Vec2([a div b[0], a div b[1]]) | |
| 125 func `/`*[T: SomeFloat](a: SomeFloat, b: Vec2[T]): auto = Vec2([a / b[0], a / b[1]]) | |
| 126 func `/`*[T: SomeInteger](a: SomeInteger, b: Vec3[T]): auto = Vec3([a div b[0], a div b[1], a div b[2]]) | |
| 127 func `/`*[T: SomeFloat](a: SomeFloat, b: Vec3[T]): auto = Vec3([a / b[0], a / b[1], a / b[2]]) | |
| 128 func `/`*[T: SomeInteger](a: SomeInteger, b: Vec4[T]): auto = Vec4([a div b[0], a div b[1], a div b[2], a div b[3]]) | |
| 129 func `/`*[T: SomeFloat](a: SomeFloat, b: Vec4[T]): auto = Vec4([a / b[0], a / b[1], a / b[2], a / b[3]]) | |
| 130 | |
| 131 # compontent-wise operations | |
| 132 func `+`*(a, b: Vec2): auto = Vec2([a[0] + b[0], a[1] + b[1]]) | |
| 133 func `+`*(a, b: Vec3): auto = Vec3([a[0] + b[0], a[1] + b[1], a[2] + b[2]]) | |
| 134 func `+`*(a, b: Vec4): auto = Vec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]]) | |
| 135 func `-`*(a: Vec2): auto = Vec2([-a[0], -a[1]]) | |
| 136 func `-`*(a: Vec3): auto = Vec3([-a[0], -a[1], -a[2]]) | |
| 137 func `-`*(a: Vec4): auto = Vec4([-a[0], -a[1], -a[2], -a[3]]) | |
| 138 func `-`*(a, b: Vec2): auto = Vec2([a[0] - b[0], a[1] - b[1]]) | |
| 139 func `-`*(a, b: Vec3): auto = Vec3([a[0] - b[0], a[1] - b[1], a[2] - b[2]]) | |
| 140 func `-`*(a, b: Vec4): auto = Vec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]]) | |
| 141 func `*`*(a, b: Vec2): auto = Vec2([a[0] * b[0], a[1] * b[1]]) | |
| 142 func `*`*(a, b: Vec3): auto = Vec3([a[0] * b[0], a[1] * b[1], a[2] * b[2]]) | |
| 143 func `*`*(a, b: Vec4): auto = Vec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]]) | |
| 144 func `/`*[T: SomeInteger](a, b: Vec2[T]): auto = Vec2([a[0] div b[0], a[1] div b[1]]) | |
| 145 func `/`*[T: SomeFloat](a, b: Vec2[T]): auto = Vec2([a[0] / b[0], a[1] / b[1]]) | |
| 146 func `/`*[T: SomeInteger](a, b: Vec3[T]): auto = Vec3([a[0] div b[0], a[1] div b[1], a[2] div b[2]]) | |
| 147 func `/`*[T: SomeFloat](a, b: Vec3[T]): auto = Vec3([a[0] / b[0], a[1] / b[1], a[2] / b[2]]) | |
| 148 func `/`*[T: SomeInteger](a, b: Vec4[T]): auto = Vec4([a[0] div b[0], a[1] div b[1], a[2] div b[2], a[3] div b[3]]) | |
| 149 func `/`*[T: SomeFloat](a, b: Vec4[T]): auto = Vec4([a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3]]) | |
| 150 | |
| 151 # special operations | |
| 152 func dot*(a, b: Vec2): auto = a[0] * b[0] + a[1] * b[1] | |
| 153 func dot*(a, b: Vec3): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] | |
| 154 func dot*(a, b: Vec4): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] | |
| 155 func cross*(a, b: Vec3): auto = Vec3([ | |
| 156 a[1] * b[2] - a[2] * b[1], | |
| 157 a[2] * b[0] - a[0] * b[2], | |
| 158 a[0] * b[1] - a[1] * b[0], | |
| 159 ]) | |
| 160 | |
| 161 | |
| 162 # macro to allow creation of new vectors by specifying vector components as attributes | |
| 163 # e.g. myVec.xxy will return a new Vec3 that contains the components x, x an y of the original vector | |
| 164 # (instead of x, y, z for a simple copy) | |
| 165 proc vectorAttributeAccessor(accessor: string): NimNode = | |
| 166 const ACCESSOR_INDICES = { | |
| 167 'x': 0, | |
| 168 'y': 1, | |
| 169 'z': 2, | |
| 170 'w': 3, | |
| 171 'r': 0, | |
| 172 'g': 1, | |
| 173 'b': 2, | |
| 174 'a': 3, | |
| 175 }.toTable | |
| 176 var ret: NimNode | |
| 177 let accessorvalue = accessor | |
| 178 | |
| 179 if accessorvalue.len == 0: | |
| 180 raise newException(Exception, "empty attribute") | |
| 181 elif accessorvalue.len == 1: | |
| 182 ret = nnkBracket.newTree(ident("value"), newLit(ACCESSOR_INDICES[accessorvalue[0]])) | |
| 183 if accessorvalue.len > 1: | |
| 184 var attrs = nnkBracket.newTree() | |
| 185 for attrname in accessorvalue: | |
| 186 attrs.add(nnkBracketExpr.newTree(ident("value"), newLit(ACCESSOR_INDICES[attrname]))) | |
| 187 ret = nnkCall.newTree(ident("Vec" & $accessorvalue.len), attrs) | |
| 188 | |
| 189 newProc( | |
| 190 name=nnkPostfix.newTree(ident("*"), ident(accessor)), | |
| 191 params=[ident("auto"), nnkIdentDefs.newTree(ident("value"), ident("Vec"), newEmptyNode())], | |
| 192 body=newStmtList(ret), | |
| 193 procType = nnkFuncDef, | |
| 194 ) | |
| 195 | |
| 196 macro createVectorAttribAccessorFuncs() = | |
| 197 const COORD_ATTRS = ["x", "y", "z", "w"] | |
| 198 const COLOR_ATTRS = ["r", "g", "b", "a"] | |
| 199 result = nnkStmtList.newTree() | |
| 200 for attlist in [COORD_ATTRS, COLOR_ATTRS]: | |
| 201 for i in attlist: | |
| 202 result.add(vectorAttributeAccessor(i)) | |
| 203 for j in attlist: | |
| 204 result.add(vectorAttributeAccessor(i & j)) | |
| 205 for k in attlist: | |
| 206 result.add(vectorAttributeAccessor(i & j & k)) | |
| 207 for l in attlist: | |
| 208 result.add(vectorAttributeAccessor(i & j & k & l)) | |
| 209 | |
| 210 createVectorAttribAccessorFuncs() | |
| 211 | |
| 212 # call e.g. Vec2[int]().randomized() to get a random matrix | |
| 213 template makeRandomInit(mattype: typedesc) = | |
| 214 proc randomized*[T: SomeInteger](m: mattype[T]): mattype[T] = | |
| 215 for i in 0 ..< result.len: | |
| 216 result[i] = rand(low(typeof(m[0])) .. high(typeof(m[0]))) | |
| 217 proc randomized*[T: SomeFloat](m: mattype[T]): mattype[T] = | |
| 218 for i in 0 ..< result.len: | |
| 219 result[i] = rand(1.0) | |
| 220 | |
| 221 makeRandomInit(Vec2) | |
| 222 makeRandomInit(Vec3) | |
| 223 makeRandomInit(Vec4) |
