diff --git a/README.md b/README.md index fadbea4..5a4c076 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,44 @@ + + # VMath `nimble install vmath` -Collection of math routines for 2d and 3d graphics. +Your single stop for vector math routines for 2d and 3d graphics. -Has functions for Vec2, Vec3, Vec4, Mat3, Mat4 and Quat. +Pure nim no dependencies. Fast. Easy to use. + +## Has functions for: + +Type | Constructor | Description +------|-------------| --------------------------------------------------- +BVec# | bvec# | a vector of booleans +IVec# | ivec# | a vector of signed integers +UVec# | uvec# | a vector of unsigned integers +Vec# | vec# | a vector of single-precision floating-point numbers +DVec# | dvec# | a vector of double-precision floating-point numbers + +## And these types: + +NIM | GLSL | 2 | 3 | 4 | 9 | 16 | 4 | +--------|--------|-------|-------|-------|-------|-------|-------| +bool | bool | BVec2 | BVec3 | BVec4 | | | | +int32 | int | IVec2 | IVec3 | IVec4 | | | | +uint32 | uint | UVec2 | UVec3 | UVec4 | | | | +float32 | float | Vec2 | Vec3 | Vec4 | Mat3 | Mat4 | Quat | +float64 | double | DVec2 | DVec3 | DVec4 | DMat3 | DMat4 | DQuat | + + +# 0.x.x to 1.0.0 vmath breaking changes: + +* `vec3(v)` no longer works please use `vec3(v.x, v.y, 0)` instead. +* `vec3(v, 0)` no longer works please use `vec3(v.x, v.y, 0)` instead. +* `2 * v` no longer works due to more vec types please use `v * 2` instead. +* `m[15]` no longer works because matrices are now m[x, y]. +* Concept of 3x3 rotation 3d matrix was removed. +* `angleBetween` got renamed to `angle(a, b)` +* `scaleMat` got renamed to `scale(v)` +* `rotationMat3` got renamed to `rotate(x)` # API: vmath @@ -12,12 +46,138 @@ Has functions for Vec2, Vec3, Vec4, Mat3, Mat4 and Quat. import vmath ``` +## **type** GVec2 + + +```nim +GVec2[T] = array[2, T] +``` + +## **type** GVec3 + + +```nim +GVec3[T] = array[3, T] +``` + +## **type** GVec4 + + +```nim +GVec4[T] = array[4, T] +``` + +## **type** BVec2 + + +```nim +BVec2 = GVec2[bool] +``` + +## **type** BVec3 + + +```nim +BVec3 = GVec3[bool] +``` + +## **type** BVec4 + + +```nim +BVec4 = GVec4[bool] +``` + +## **type** IVec2 + + +```nim +IVec2 = GVec2[int32] +``` + +## **type** IVec3 + + +```nim +IVec3 = GVec3[int32] +``` + +## **type** IVec4 + + +```nim +IVec4 = GVec4[int32] +``` + +## **type** UVec2 + + +```nim +UVec2 = GVec2[uint32] +``` + +## **type** UVec3 + + +```nim +UVec3 = GVec3[uint32] +``` + +## **type** UVec4 + + +```nim +UVec4 = GVec4[uint32] +``` + +## **type** Vec2 + + +```nim +Vec2 = GVec2[float32] +``` + +## **type** Vec3 + + +```nim +Vec3 = GVec3[float32] +``` + +## **type** Vec4 + + +```nim +Vec4 = GVec4[float32] +``` + +## **type** DVec2 + + +```nim +DVec2 = GVec2[float64] +``` + +## **type** DVec3 + + +```nim +DVec3 = GVec3[float64] +``` + +## **type** DVec4 + + +```nim +DVec4 = GVec4[float64] +``` + ## **proc** `~=` Almost equal. ```nim -proc `~=`(a, b: float32): bool +proc `~=`[T: SomeFloat](a, b: T): bool {.inline.} ``` ## **proc** between @@ -25,7 +185,7 @@ proc `~=`(a, b: float32): bool Returns true if value is between min and max or equal to them. ```nim -proc between(value, min, max: float32): bool {.inline.} +proc between[T](value, min, max: T): bool {.inline.} ``` ## **proc** sign @@ -33,15 +193,15 @@ proc between(value, min, max: float32): bool {.inline.} Returns the sign of a number, -1 or 1. ```nim -proc sign(v: float32): float32 {.inline.} +proc sign[T](v: T): T {.inline.} ``` ## **proc** quantize -Makes v be multipe of n. Rounding to integer quantize by 1.0. +Makes v be multiple of n. Rounding to integer quantize by 1.0. ```nim -proc quantize(v, n: float32): float32 {.inline.} +proc quantize[T: SomeFloat](v, n: T): T {.inline.} ``` ## **proc** lerp @@ -52,7 +212,7 @@ Interpolates value between a and b. * 0.5 -> between a and b ```nim -proc lerp(a, b, v: float32): float32 {.inline.} +proc lerp[T: SomeFloat](a, b, v: T): T {.inline.} ``` ## **proc** fixAngle @@ -60,7 +220,7 @@ proc lerp(a, b, v: float32): float32 {.inline.} Make angle be from -PI to PI radians. ```nim -proc fixAngle(angle: float32): float32 +proc fixAngle[T: SomeFloat](angle: T): T {.inline.} ``` ## **proc** angleBetween @@ -68,7 +228,7 @@ proc fixAngle(angle: float32): float32 Angle between angle a and angle b. ```nim -proc angleBetween(a, b: float32): float32 {.inline.} +proc angleBetween[T: SomeFloat](a, b: T): T {.inline.} ``` ## **proc** turnAngle @@ -76,1052 +236,2054 @@ proc angleBetween(a, b: float32): float32 {.inline.} Move from angle a to angle b with step of v. ```nim -proc turnAngle(a, b, speed: float32): float32 +proc turnAngle[T: SomeFloat](a, b, speed: T): T {.inline.} ``` -## **type** Vec2 +## **proc** toRadians -2D vector ```nim -Vec2 = object - x*: float32 - y*: float32 +proc toRadians[T: SomeFloat](deg: T): T {.inline.} +``` + +## **proc** toDegrees + + +```nim +proc toDegrees[T: SomeFloat](rad: T): T {.inline.} +``` + +## **proc** gvec2 + + +```nim +proc gvec2[T](x, y: T): GVec2[T] {.inline.} +``` + +## **proc** gvec3 + + +```nim +proc gvec3[T](x, y, z: T): GVec3[T] {.inline.} +``` + +## **proc** gvec4 + + +```nim +proc gvec4[T](x, y, z, w: T): GVec4[T] {.inline.} +``` + +## **proc** bvec2 + + +```nim +proc bvec2(x`gensym4, y`gensym4: bool): BVec2 {.inline.} +``` + +## **proc** bvec3 + + +```nim +proc bvec3(x`gensym4, y`gensym4, z`gensym4: bool): BVec3 {.inline, tags: [].} +``` + +## **proc** bvec4 + + +```nim +proc bvec4(x`gensym4, y`gensym4, z`gensym4, w`gensym4: bool): BVec4 {.inline, raises: [].} +``` + +## **proc** bvec2 + + +```nim +proc bvec2(x`gensym4: bool): BVec2 {.inline.} +``` + +## **proc** bvec3 + + +```nim +proc bvec3(x`gensym4: bool): BVec3 {.inline.} +``` + +## **proc** bvec4 + + +```nim +proc bvec4(x`gensym4: bool): BVec4 {.inline.} +``` + +## **proc** bvec2 + + +```nim +proc bvec2[T](x`gensym4: GVec2[T]): BVec2 {.inline.} +``` + +## **proc** bvec3 + + +```nim +proc bvec3[T](x`gensym4: GVec3[T]): BVec3 {.inline.} +``` + +## **proc** bvec4 + + +```nim +proc bvec4[T](x`gensym4: GVec4[T]): BVec4 {.inline.} +``` + +## **proc** bvec3 + + +```nim +proc bvec3[T](x`gensym4: GVec2[T]): BVec3 {.inline.} +``` + +## **proc** bvec4 + + +```nim +proc bvec4[T](x`gensym4: GVec3[T]): BVec4 {.inline.} +``` + +## **proc** ivec2 + + +```nim +proc ivec2(x`gensym5, y`gensym5: int32): IVec2 {.inline.} +``` + +## **proc** ivec3 + + +```nim +proc ivec3(x`gensym5, y`gensym5, z`gensym5: int32): IVec3 {.inline, tags: [].} +``` + +## **proc** ivec4 + + +```nim +proc ivec4(x`gensym5, y`gensym5, z`gensym5, w`gensym5: int32): IVec4 {.inline, raises: [].} +``` + +## **proc** ivec2 + + +```nim +proc ivec2(x`gensym5: int32): IVec2 {.inline.} +``` + +## **proc** ivec3 + + +```nim +proc ivec3(x`gensym5: int32): IVec3 {.inline.} +``` + +## **proc** ivec4 + + +```nim +proc ivec4(x`gensym5: int32): IVec4 {.inline.} +``` + +## **proc** ivec2 + + +```nim +proc ivec2[T](x`gensym5: GVec2[T]): IVec2 {.inline.} +``` + +## **proc** ivec3 + + +```nim +proc ivec3[T](x`gensym5: GVec3[T]): IVec3 {.inline.} +``` + +## **proc** ivec4 + + +```nim +proc ivec4[T](x`gensym5: GVec4[T]): IVec4 {.inline.} +``` + +## **proc** ivec3 + + +```nim +proc ivec3[T](x`gensym5: GVec2[T]): IVec3 {.inline.} +``` + +## **proc** ivec4 + + +```nim +proc ivec4[T](x`gensym5: GVec3[T]): IVec4 {.inline.} +``` + +## **proc** uvec2 + + +```nim +proc uvec2(x`gensym6, y`gensym6: uint32): UVec2 {.inline.} +``` + +## **proc** uvec3 + + +```nim +proc uvec3(x`gensym6, y`gensym6, z`gensym6: uint32): UVec3 {.inline, tags: [].} +``` + +## **proc** uvec4 + + +```nim +proc uvec4(x`gensym6, y`gensym6, z`gensym6, w`gensym6: uint32): UVec4 {.inline, raises: [].} +``` + +## **proc** uvec2 + + +```nim +proc uvec2(x`gensym6: uint32): UVec2 {.inline.} +``` + +## **proc** uvec3 + + +```nim +proc uvec3(x`gensym6: uint32): UVec3 {.inline.} +``` + +## **proc** uvec4 + + +```nim +proc uvec4(x`gensym6: uint32): UVec4 {.inline.} +``` + +## **proc** uvec2 + + +```nim +proc uvec2[T](x`gensym6: GVec2[T]): UVec2 {.inline.} +``` + +## **proc** uvec3 + + +```nim +proc uvec3[T](x`gensym6: GVec3[T]): UVec3 {.inline.} +``` + +## **proc** uvec4 + + +```nim +proc uvec4[T](x`gensym6: GVec4[T]): UVec4 {.inline.} +``` + +## **proc** uvec3 + + +```nim +proc uvec3[T](x`gensym6: GVec2[T]): UVec3 {.inline.} +``` + +## **proc** uvec4 + + +```nim +proc uvec4[T](x`gensym6: GVec3[T]): UVec4 {.inline.} ``` ## **proc** vec2 ```nim -proc vec2(x, y: float32): Vec2 {.inline.} +proc vec2(x`gensym7, y`gensym7: float32): Vec2 {.inline.} +``` + +## **proc** vec3 + + +```nim +proc vec3(x`gensym7, y`gensym7, z`gensym7: float32): Vec3 {.inline, tags: [].} +``` + +## **proc** vec4 + + +```nim +proc vec4(x`gensym7, y`gensym7, z`gensym7, w`gensym7: float32): Vec4 {.inline, raises: [].} ``` ## **proc** vec2 ```nim -proc vec2(v: float32): Vec2 {.inline.} +proc vec2(x`gensym7: float32): Vec2 {.inline.} +``` + +## **proc** vec3 + + +```nim +proc vec3(x`gensym7: float32): Vec3 {.inline.} +``` + +## **proc** vec4 + + +```nim +proc vec4(x`gensym7: float32): Vec4 {.inline.} ``` ## **proc** vec2 ```nim -proc vec2(a: Vec2): Vec2 {.inline.} -``` - -## **proc** `~=` - - -```nim -proc `~=`(a, b: Vec2): bool -``` - -## **proc** `+` - - -```nim -proc `+`(a, b: Vec2): Vec2 {.inline.} -``` - -## **proc** `-` - - -```nim -proc `-`(a, b: Vec2): Vec2 {.inline.} -``` - -## **proc** `*` - - -```nim -proc `*`(a: Vec2; b: float32): Vec2 {.inline.} -``` - -## **proc** `*` - - -```nim -proc `*`(a: float32; b: Vec2): Vec2 {.inline.} -``` - -## **proc** `/` - - -```nim -proc `/`(a: Vec2; b: float32): Vec2 {.inline.} -``` - -## **proc** `+=` - - -```nim -proc `+=`(a: var Vec2; b: Vec2) {.inline.} -``` - -## **proc** `-=` - - -```nim -proc `-=`(a: var Vec2; b: Vec2) {.inline.} -``` - -## **proc** `*=` - - -```nim -proc `*=`(a: var Vec2; b: float32) {.inline.} -``` - -## **proc** `/=` - - -```nim -proc `/=`(a: var Vec2; b: float32) {.inline.} -``` - -## **proc** zero - - -```nim -proc zero(a: var Vec2) {.inline.} -``` - -## **proc** `-` - - -```nim -proc `-`(a: Vec2): Vec2 {.inline.} -``` - -## **proc** hash - - -```nim -proc hash(a: Vec2): Hash {.inline.} -``` - -## **proc** lengthSq - - -```nim -proc lengthSq(a: Vec2): float32 {.inline.} -``` - -## **proc** length - - -```nim -proc length(a: Vec2): float32 {.inline.} -``` - -## **proc** length= - - -```nim -proc length=(a: var Vec2; b: float32) {.inline.} -``` - -## **proc** normalize - - -```nim -proc normalize(a: Vec2): Vec2 {.inline.} -``` - -## **proc** floor - - -```nim -proc floor(a: Vec2): Vec2 {.inline.} -``` - -## **proc** round - - -```nim -proc round(a: Vec2): Vec2 {.inline.} -``` - -## **proc** ceil - - -```nim -proc ceil(a: Vec2): Vec2 {.inline.} -``` - -## **proc** dot - - -```nim -proc dot(a, b: Vec2): float32 {.inline.} -``` - -## **proc** dir - - -```nim -proc dir(at, to: Vec2): Vec2 {.inline.} -``` - -## **proc** dir - - -```nim -proc dir(th: float32): Vec2 {.inline.} -``` - -## **proc** dist - - -```nim -proc dist(at, to: Vec2): float32 {.inline.} -``` - -## **proc** distSq - - -```nim -proc distSq(at, to: Vec2): float32 {.inline.} -``` - -## **proc** lerp - - -```nim -proc lerp(a, b: Vec2; v: float32): Vec2 {.inline.} -``` - -## **proc** quantize - - -```nim -proc quantize(v: Vec2; n: float32): Vec2 {.inline.} -``` - -## **proc** `[]` - - -```nim -proc `[]`(a: Vec2; i: int): float32 -``` - -## **proc** `[]=` - - -```nim -proc `[]=`(a: var Vec2; i: int; b: float32) -``` - -## **proc** randVec2 - - -```nim -proc randVec2(r: var Rand): Vec2 -``` - -## **proc** `$` - - -```nim -proc `$`(a: Vec2): string {.raises: [ValueError].} -``` - -## **proc** angle - -Angle of a Vec2. - -```nim -proc angle(a: Vec2): float32 {.inline.} -``` - -## **proc** angleBetween - -Angle between 2 Vec2. - -```nim -proc angleBetween(a: Vec2; b: Vec2): float32 {.inline.} -``` - -## **type** Vec3 - -3D vector - -```nim -Vec3 = object - x*: float32 - y*: float32 - z*: float32 +proc vec2[T](x`gensym7: GVec2[T]): Vec2 {.inline.} ``` ## **proc** vec3 ```nim -proc vec3(x, y, z: float32): Vec3 {.inline.} +proc vec3[T](x`gensym7: GVec3[T]): Vec3 {.inline.} +``` + +## **proc** vec4 + + +```nim +proc vec4[T](x`gensym7: GVec4[T]): Vec4 {.inline.} ``` ## **proc** vec3 ```nim -proc vec3(v: float32): Vec3 {.inline.} +proc vec3[T](x`gensym7: GVec2[T]): Vec3 {.inline.} ``` -## **proc** vec3 +## **proc** vec4 ```nim -proc vec3(a: Vec3): Vec3 {.inline.} +proc vec4[T](x`gensym7: GVec3[T]): Vec4 {.inline.} ``` -## **const** X_DIR +## **proc** dvec2 ```nim -X_DIR = (x: 1.0, y: 0.0, z: 0.0) +proc dvec2(x`gensym8, y`gensym8: float64): DVec2 {.inline.} ``` -## **const** Y_DIR +## **proc** dvec3 ```nim -Y_DIR = (x: 0.0, y: 1.0, z: 0.0) +proc dvec3(x`gensym8, y`gensym8, z`gensym8: float64): DVec3 {.inline, raises: [].} ``` -## **const** Z_DIR +## **proc** dvec4 ```nim -Z_DIR = (x: 0.0, y: 0.0, z: 1.0) +proc dvec4(x`gensym8, y`gensym8, z`gensym8, w`gensym8: float64): DVec4 {.inline, raises: [].} ``` -## **proc** `~=` +## **proc** dvec2 ```nim -proc `~=`(a, b: Vec3): bool +proc dvec2(x`gensym8: float64): DVec2 {.inline.} ``` -## **proc** `+` +## **proc** dvec3 ```nim -proc `+`(a, b: Vec3): Vec3 {.inline.} +proc dvec3(x`gensym8: float64): DVec3 {.inline.} ``` -## **proc** `-` +## **proc** dvec4 ```nim -proc `-`(a, b: Vec3): Vec3 {.inline.} +proc dvec4(x`gensym8: float64): DVec4 {.inline.} ``` -## **proc** `-` +## **proc** dvec2 ```nim -proc `-`(a: Vec3): Vec3 {.inline.} +proc dvec2[T](x`gensym8: GVec2[T]): DVec2 {.inline.} ``` -## **proc** `*` +## **proc** dvec3 ```nim -proc `*`(a: Vec3; b: float32): Vec3 {.inline.} +proc dvec3[T](x`gensym8: GVec3[T]): DVec3 {.inline.} ``` -## **proc** `*` +## **proc** dvec4 ```nim -proc `*`(a: float32; b: Vec3): Vec3 {.inline.} +proc dvec4[T](x`gensym8: GVec4[T]): DVec4 {.inline.} ``` -## **proc** `/` +## **proc** dvec3 ```nim -proc `/`(a: Vec3; b: float32): Vec3 {.inline.} +proc dvec3[T](x`gensym8: GVec2[T]): DVec3 {.inline.} ``` -## **proc** `/` +## **proc** dvec4 ```nim -proc `/`(a: float32; b: Vec3): Vec3 {.inline.} +proc dvec4[T](x`gensym8: GVec3[T]): DVec4 {.inline.} ``` -## **proc** `+=` +## **proc** x ```nim -proc `+=`(a: var Vec3; b: Vec3) {.inline.} +proc x[T](a: var GVec2[T]): var T {.inline.} ``` -## **proc** `-=` +## **proc** y ```nim -proc `-=`(a: var Vec3; b: Vec3) {.inline.} +proc y[T](a: var GVec2[T]): var T {.inline.} ``` -## **proc** `*=` +## **proc** x ```nim -proc `*=`(a: var Vec3; b: float32) {.inline.} +proc x[T](a: var GVec3[T]): var T {.inline.} ``` -## **proc** `/=` +## **proc** y ```nim -proc `/=`(a: var Vec3; b: float32) {.inline.} +proc y[T](a: var GVec3[T]): var T {.inline.} ``` -## **proc** zero +## **proc** z ```nim -proc zero(a: var Vec3) {.inline.} +proc z[T](a: var GVec3[T]): var T {.inline.} ``` -## **proc** `-` +## **proc** x ```nim -proc `-`(a: var Vec3): Vec3 {.inline.} +proc x[T](a: var GVec4[T]): var T {.inline.} ``` -## **proc** hash +## **proc** y ```nim -proc hash(a: Vec3): Hash {.inline.} +proc y[T](a: var GVec4[T]): var T {.inline.} ``` -## **proc** lengthSq +## **proc** z ```nim -proc lengthSq(a: Vec3): float32 {.inline.} +proc z[T](a: var GVec4[T]): var T {.inline.} ``` -## **proc** length +## **proc** w ```nim -proc length(a: Vec3): float32 {.inline.} +proc w[T](a: var GVec4[T]): var T {.inline.} ``` -## **proc** length= +## **proc** x ```nim -proc length=(a: var Vec3; b: float32) {.inline.} +proc x[T](a: GVec2[T]): T {.inline.} ``` -## **proc** floor +## **proc** x ```nim -proc floor(a: Vec3): Vec3 {.inline.} +proc x[T](a: GVec3[T]): T {.inline.} ``` -## **proc** round +## **proc** x ```nim -proc round(a: Vec3): Vec3 {.inline.} +proc x[T](a: GVec4[T]): T {.inline.} ``` -## **proc** ceil +## **proc** y ```nim -proc ceil(a: Vec3): Vec3 {.inline.} +proc y[T](a: GVec2[T]): T {.inline.} ``` -## **proc** normalize +## **proc** y ```nim -proc normalize(a: Vec3): Vec3 {.inline.} +proc y[T](a: GVec3[T]): T {.inline.} ``` -## **proc** cross +## **proc** y ```nim -proc cross(a, b: Vec3): Vec3 {.inline.} +proc y[T](a: GVec4[T]): T {.inline.} ``` -## **proc** computeNormal +## **proc** z ```nim -proc computeNormal(a, b, c: Vec3): Vec3 +proc z[T](a: GVec2[T]): T {.inline.} ``` -## **proc** dot +## **proc** z ```nim -proc dot(a, b: Vec3): float32 {.inline.} +proc z[T](a: GVec3[T]): T {.inline.} ``` -## **proc** dir +## **proc** z ```nim -proc dir(at, to: Vec3): Vec3 {.inline.} +proc z[T](a: GVec4[T]): T {.inline.} ``` -## **proc** dist +## **proc** w ```nim -proc dist(at, to: Vec3): float32 {.inline.} +proc w[T](a: GVec2[T]): T {.inline.} ``` -## **proc** distSq +## **proc** w ```nim -proc distSq(at, to: Vec3): float32 {.inline.} +proc w[T](a: GVec3[T]): T {.inline.} ``` -## **proc** lerp +## **proc** w ```nim -proc lerp(a, b: Vec3; v: float32): Vec3 {.inline.} +proc w[T](a: GVec4[T]): T {.inline.} ``` -## **proc** quantize +## **proc** x= ```nim -proc quantize(v: Vec3; n: float32): Vec3 +proc x=[T](a: var GVec234[T]; value: T) {.inline.} ``` -## **proc** angleBetween +## **proc** y= ```nim -proc angleBetween(a, b: Vec3): float32 +proc y=[T](a: var GVec234[T]; value: T) {.inline.} ``` -## **proc** `[]` +## **proc** z= ```nim -proc `[]`(a: Vec3; i: int): float32 +proc z=[T](a: var GVec34[T]; value: T) {.inline.} ``` -## **proc** `[]=` +## **proc** w= ```nim -proc `[]=`(a: var Vec3; i: int; b: float32) +proc w=[T](a: var GVec4[T]; value: T) {.inline.} ``` ## **proc** xy ```nim -proc xy(a: Vec3): Vec2 {.inline.} +proc xy[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** xz ```nim -proc xz(a: Vec3): Vec2 {.inline.} +proc xz[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** yx ```nim -proc yx(a: Vec3): Vec2 {.inline.} +proc yx[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** yz ```nim -proc yz(a: Vec3): Vec2 {.inline.} +proc yz[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** zx ```nim -proc zx(a: Vec3): Vec2 {.inline.} +proc zx[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** zy ```nim -proc zy(a: Vec3): Vec2 {.inline.} +proc zy[T](a: GVec234[T]): GVec2[T] {.inline.} ``` ## **proc** xxx ```nim -proc xxx(a: Vec3): Vec3 {.inline.} +proc xxx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xxy ```nim -proc xxy(a: Vec3): Vec3 {.inline.} +proc xxy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xxz ```nim -proc xxz(a: Vec3): Vec3 {.inline.} +proc xxz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xyx ```nim -proc xyx(a: Vec3): Vec3 {.inline.} +proc xyx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xyy ```nim -proc xyy(a: Vec3): Vec3 {.inline.} +proc xyy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xyz ```nim -proc xyz(a: Vec3): Vec3 {.inline.} +proc xyz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xzx ```nim -proc xzx(a: Vec3): Vec3 {.inline.} +proc xzx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xzy ```nim -proc xzy(a: Vec3): Vec3 {.inline.} +proc xzy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** xzz ```nim -proc xzz(a: Vec3): Vec3 {.inline.} +proc xzz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yxx ```nim -proc yxx(a: Vec3): Vec3 {.inline.} +proc yxx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yxy ```nim -proc yxy(a: Vec3): Vec3 {.inline.} +proc yxy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yxz ```nim -proc yxz(a: Vec3): Vec3 {.inline.} +proc yxz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yyx ```nim -proc yyx(a: Vec3): Vec3 {.inline.} +proc yyx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yyy ```nim -proc yyy(a: Vec3): Vec3 {.inline.} +proc yyy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yyz ```nim -proc yyz(a: Vec3): Vec3 {.inline.} +proc yyz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yzx ```nim -proc yzx(a: Vec3): Vec3 {.inline.} +proc yzx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yzy ```nim -proc yzy(a: Vec3): Vec3 {.inline.} +proc yzy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** yzz ```nim -proc yzz(a: Vec3): Vec3 {.inline.} +proc yzz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zxx ```nim -proc zxx(a: Vec3): Vec3 {.inline.} +proc zxx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zxy ```nim -proc zxy(a: Vec3): Vec3 {.inline.} +proc zxy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zxz ```nim -proc zxz(a: Vec3): Vec3 {.inline.} +proc zxz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zyx ```nim -proc zyx(a: Vec3): Vec3 {.inline.} +proc zyx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zyy ```nim -proc zyy(a: Vec3): Vec3 {.inline.} +proc zyy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zyz ```nim -proc zyz(a: Vec3): Vec3 {.inline.} +proc zyz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zzx ```nim -proc zzx(a: Vec3): Vec3 {.inline.} +proc zzx[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zzy ```nim -proc zzy(a: Vec3): Vec3 {.inline.} +proc zzy[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** zzz ```nim -proc zzz(a: Vec3): Vec3 {.inline.} -``` - -## **proc** randVec3 - -Generates a random unit vector based on http://mathworld.wolfram.com/SpherePointPicking.html - -```nim -proc randVec3(r: var Rand): Vec3 -``` - -## **proc** `$` - - -```nim -proc `$`(a: Vec3): string {.raises: [ValueError].} -``` - -## **type** Vec4 - -4D Vector. - -```nim -Vec4 = object - x*: float32 - y*: float32 - z*: float32 - w*: float32 -``` - -## **proc** vec4 - - -```nim -proc vec4(x, y, z, w: float32): Vec4 {.inline.} -``` - -## **proc** vec4 - - -```nim -proc vec4(v: float32): Vec4 {.inline.} -``` - -## **proc** `~=` - - -```nim -proc `~=`(a, b: Vec4): bool +proc zzz[T](a: GVec34[T]): GVec3[T] {.inline.} ``` ## **proc** `+` ```nim -proc `+`(a, b: Vec4): Vec4 {.inline.} +proc `+`[T](a`gensym9, b`gensym9: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9, b`gensym9: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9, b`gensym9: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: GVec2[T]; b`gensym9: T): GVec2[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: GVec3[T]; b`gensym9: T): GVec3[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: GVec4[T]; b`gensym9: T): GVec4[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: T; b`gensym9: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: T; b`gensym9: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `+` + + +```nim +proc `+`[T](a`gensym9: T; b`gensym9: GVec4[T]): GVec4[T] {.inline.} ``` ## **proc** `-` ```nim -proc `-`(a, b: Vec4): Vec4 {.inline.} +proc `-`[T](a`gensym10, b`gensym10: GVec2[T]): GVec2[T] {.inline.} ``` ## **proc** `-` ```nim -proc `-`(a: Vec4): Vec4 {.inline.} +proc `-`[T](a`gensym10, b`gensym10: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10, b`gensym10: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: GVec2[T]; b`gensym10: T): GVec2[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: GVec3[T]; b`gensym10: T): GVec3[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: GVec4[T]; b`gensym10: T): GVec4[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: T; b`gensym10: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: T; b`gensym10: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](a`gensym10: T; b`gensym10: GVec4[T]): GVec4[T] {.inline.} ``` ## **proc** `*` ```nim -proc `*`(a: Vec4; b: float32): Vec4 {.inline.} +proc `*`[T](a`gensym11, b`gensym11: GVec2[T]): GVec2[T] {.inline.} ``` ## **proc** `*` ```nim -proc `*`(a: float32; b: Vec4): Vec4 {.inline.} +proc `*`[T](a`gensym11, b`gensym11: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11, b`gensym11: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: GVec2[T]; b`gensym11: T): GVec2[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: GVec3[T]; b`gensym11: T): GVec3[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: GVec4[T]; b`gensym11: T): GVec4[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: T; b`gensym11: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: T; b`gensym11: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `*` + + +```nim +proc `*`[T](a`gensym11: T; b`gensym11: GVec4[T]): GVec4[T] {.inline.} ``` ## **proc** `/` ```nim -proc `/`(a: Vec4; b: float32): Vec4 {.inline.} +proc `/`[T](a`gensym12, b`gensym12: GVec2[T]): GVec2[T] {.inline.} ``` ## **proc** `/` ```nim -proc `/`(a: float32; b: Vec4): Vec4 {.inline.} +proc `/`[T](a`gensym12, b`gensym12: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12, b`gensym12: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: GVec2[T]; b`gensym12: T): GVec2[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: GVec3[T]; b`gensym12: T): GVec3[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: GVec4[T]; b`gensym12: T): GVec4[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: T; b`gensym12: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: T; b`gensym12: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `/` + + +```nim +proc `/`[T](a`gensym12: T; b`gensym12: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13, b`gensym13: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13, b`gensym13: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13, b`gensym13: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: GVec2[T]; b`gensym13: T): GVec2[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: GVec3[T]; b`gensym13: T): GVec3[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: GVec4[T]; b`gensym13: T): GVec4[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: T; b`gensym13: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: T; b`gensym13: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `mod` + + +```nim +proc `mod`[T](a`gensym13: T; b`gensym13: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14, b`gensym14: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14, b`gensym14: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14, b`gensym14: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: GVec2[T]; b`gensym14: T): GVec2[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: GVec3[T]; b`gensym14: T): GVec3[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: GVec4[T]; b`gensym14: T): GVec4[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: T; b`gensym14: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: T; b`gensym14: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `div` + + +```nim +proc `div`[T](a`gensym14: T; b`gensym14: GVec4[T]): GVec4[T] {.inline.} ``` ## **proc** `+=` ```nim -proc `+=`(a: var Vec4; b: Vec4) {.inline.} +proc `+=`[T](a`gensym15: var GVec2[T]; b`gensym15: GVec2[T]) {.inline.} +``` + +## **proc** `+=` + + +```nim +proc `+=`[T](a`gensym15: var GVec3[T]; b`gensym15: GVec3[T]) {.inline.} +``` + +## **proc** `+=` + + +```nim +proc `+=`[T](a`gensym15: var GVec4[T]; b`gensym15: GVec4[T]) {.inline.} +``` + +## **proc** `+=` + + +```nim +proc `+=`[T](a`gensym15: var GVec2[T]; b`gensym15: T) {.inline.} +``` + +## **proc** `+=` + + +```nim +proc `+=`[T](a`gensym15: var GVec3[T]; b`gensym15: T) {.inline.} +``` + +## **proc** `+=` + + +```nim +proc `+=`[T](a`gensym15: var GVec4[T]; b`gensym15: T) {.inline.} ``` ## **proc** `-=` ```nim -proc `-=`(a: var Vec4; b: Vec4) {.inline.} +proc `-=`[T](a`gensym16: var GVec2[T]; b`gensym16: GVec2[T]) {.inline.} +``` + +## **proc** `-=` + + +```nim +proc `-=`[T](a`gensym16: var GVec3[T]; b`gensym16: GVec3[T]) {.inline.} +``` + +## **proc** `-=` + + +```nim +proc `-=`[T](a`gensym16: var GVec4[T]; b`gensym16: GVec4[T]) {.inline.} +``` + +## **proc** `-=` + + +```nim +proc `-=`[T](a`gensym16: var GVec2[T]; b`gensym16: T) {.inline.} +``` + +## **proc** `-=` + + +```nim +proc `-=`[T](a`gensym16: var GVec3[T]; b`gensym16: T) {.inline.} +``` + +## **proc** `-=` + + +```nim +proc `-=`[T](a`gensym16: var GVec4[T]; b`gensym16: T) {.inline.} ``` ## **proc** `*=` ```nim -proc `*=`(a: var Vec4; b: float32) {.inline.} +proc `*=`[T](a`gensym17: var GVec2[T]; b`gensym17: GVec2[T]) {.inline.} +``` + +## **proc** `*=` + + +```nim +proc `*=`[T](a`gensym17: var GVec3[T]; b`gensym17: GVec3[T]) {.inline.} +``` + +## **proc** `*=` + + +```nim +proc `*=`[T](a`gensym17: var GVec4[T]; b`gensym17: GVec4[T]) {.inline.} +``` + +## **proc** `*=` + + +```nim +proc `*=`[T](a`gensym17: var GVec2[T]; b`gensym17: T) {.inline.} +``` + +## **proc** `*=` + + +```nim +proc `*=`[T](a`gensym17: var GVec3[T]; b`gensym17: T) {.inline.} +``` + +## **proc** `*=` + + +```nim +proc `*=`[T](a`gensym17: var GVec4[T]; b`gensym17: T) {.inline.} ``` ## **proc** `/=` ```nim -proc `/=`(a: var Vec4; b: float32) {.inline.} +proc `/=`[T](a`gensym18: var GVec2[T]; b`gensym18: GVec2[T]) {.inline.} ``` -## **proc** zero +## **proc** `/=` ```nim -proc zero(a: var Vec4) {.inline.} +proc `/=`[T](a`gensym18: var GVec3[T]; b`gensym18: GVec3[T]) {.inline.} ``` -## **proc** hash +## **proc** `/=` ```nim -proc hash(a: Vec4): Hash {.inline.} +proc `/=`[T](a`gensym18: var GVec4[T]; b`gensym18: GVec4[T]) {.inline.} +``` + +## **proc** `/=` + + +```nim +proc `/=`[T](a`gensym18: var GVec2[T]; b`gensym18: T) {.inline.} +``` + +## **proc** `/=` + + +```nim +proc `/=`[T](a`gensym18: var GVec3[T]; b`gensym18: T) {.inline.} +``` + +## **proc** `/=` + + +```nim +proc `/=`[T](a`gensym18: var GVec4[T]; b`gensym18: T) {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](v`gensym19: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](v`gensym19: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** `-` + + +```nim +proc `-`[T](v`gensym19: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** sin + + +```nim +proc sin[T](v`gensym20: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** sin + + +```nim +proc sin[T](v`gensym20: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** sin + + +```nim +proc sin[T](v`gensym20: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** cos + + +```nim +proc cos[T](v`gensym21: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** cos + + +```nim +proc cos[T](v`gensym21: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** cos + + +```nim +proc cos[T](v`gensym21: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** tan + + +```nim +proc tan[T](v`gensym22: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** tan + + +```nim +proc tan[T](v`gensym22: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** tan + + +```nim +proc tan[T](v`gensym22: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** arcsin + + +```nim +proc arcsin[T](v`gensym23: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** arcsin + + +```nim +proc arcsin[T](v`gensym23: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** arcsin + + +```nim +proc arcsin[T](v`gensym23: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** arccos + + +```nim +proc arccos[T](v`gensym24: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** arccos + + +```nim +proc arccos[T](v`gensym24: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** arccos + + +```nim +proc arccos[T](v`gensym24: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** arctan + + +```nim +proc arctan[T](v`gensym25: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** arctan + + +```nim +proc arctan[T](v`gensym25: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** arctan + + +```nim +proc arctan[T](v`gensym25: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** sinh + + +```nim +proc sinh[T](v`gensym26: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** sinh + + +```nim +proc sinh[T](v`gensym26: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** sinh + + +```nim +proc sinh[T](v`gensym26: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** cosh + + +```nim +proc cosh[T](v`gensym27: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** cosh + + +```nim +proc cosh[T](v`gensym27: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** cosh + + +```nim +proc cosh[T](v`gensym27: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** tanh + + +```nim +proc tanh[T](v`gensym28: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** tanh + + +```nim +proc tanh[T](v`gensym28: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** tanh + + +```nim +proc tanh[T](v`gensym28: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** exp2 + + +```nim +proc exp2[T](v`gensym29: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** exp2 + + +```nim +proc exp2[T](v`gensym29: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** exp2 + + +```nim +proc exp2[T](v`gensym29: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** inversesqrt + + +```nim +proc inversesqrt[T](v`gensym30: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** inversesqrt + + +```nim +proc inversesqrt[T](v`gensym30: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** inversesqrt + + +```nim +proc inversesqrt[T](v`gensym30: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** exp + + +```nim +proc exp[T](v`gensym31: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** exp + + +```nim +proc exp[T](v`gensym31: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** exp + + +```nim +proc exp[T](v`gensym31: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** ln + + +```nim +proc ln[T](v`gensym32: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** ln + + +```nim +proc ln[T](v`gensym32: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** ln + + +```nim +proc ln[T](v`gensym32: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** log2 + + +```nim +proc log2[T](v`gensym33: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** log2 + + +```nim +proc log2[T](v`gensym33: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** log2 + + +```nim +proc log2[T](v`gensym33: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** sqrt + + +```nim +proc sqrt[T](v`gensym34: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** sqrt + + +```nim +proc sqrt[T](v`gensym34: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** sqrt + + +```nim +proc sqrt[T](v`gensym34: GVec4[T]): GVec4[T] {.inline.} ``` ## **proc** floor ```nim -proc floor(a: Vec4): Vec4 {.inline.} +proc floor[T](v`gensym35: GVec2[T]): GVec2[T] {.inline.} ``` -## **proc** round +## **proc** floor ```nim -proc round(a: Vec4): Vec4 {.inline.} +proc floor[T](v`gensym35: GVec3[T]): GVec3[T] {.inline.} ``` -## **proc** ceil +## **proc** floor ```nim -proc ceil(a: Vec4): Vec4 {.inline.} +proc floor[T](v`gensym35: GVec4[T]): GVec4[T] {.inline.} ``` -## **proc** `[]` +## **proc** ciel ```nim -proc `[]`(a: Vec4; i: int): float32 +proc ciel[T](v`gensym36: GVec2[T]): GVec2[T] {.inline.} ``` -## **proc** `[]=` +## **proc** ciel ```nim -proc `[]=`(a: var Vec4; i: int; b: float32) +proc ciel[T](v`gensym36: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** ciel + + +```nim +proc ciel[T](v`gensym36: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** abs + + +```nim +proc abs[T](v`gensym37: GVec2[T]): GVec2[T] {.inline.} +``` + +## **proc** abs + + +```nim +proc abs[T](v`gensym37: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** abs + + +```nim +proc abs[T](v`gensym37: GVec4[T]): GVec4[T] {.inline.} +``` + +## **proc** `~=` + +Almost equal. + +```nim +proc `~=`[T](a, b: GVec2[T]): bool {.inline.} +``` + +## **proc** `~=` + +Almost equal. + +```nim +proc `~=`[T](a, b: GVec3[T]): bool {.inline.} +``` + +## **proc** `~=` + +Almost equal. + +```nim +proc `~=`[T](a, b: GVec4[T]): bool {.inline.} +``` + +## **proc** length + + +```nim +proc length[T](a: GVec2[T]): T {.inline.} +``` + +## **proc** length + + +```nim +proc length[T](a: GVec3[T]): T {.inline.} +``` + +## **proc** length + + +```nim +proc length[T](a: GVec4[T]): T {.inline.} +``` + +## **proc** lengthSq + + +```nim +proc lengthSq[T](a: GVec2[T]): T {.inline.} +``` + +## **proc** lengthSq + + +```nim +proc lengthSq[T](a: GVec3[T]): T {.inline.} +``` + +## **proc** lengthSq + + +```nim +proc lengthSq[T](a: GVec4[T]): T {.inline.} +``` + +## **proc** normalize + + +```nim +proc normalize[T](a: GVec234[T]): type(a) {.inline.} ``` ## **proc** lerp ```nim -proc lerp(a: Vec4; b: Vec4; v: float32): Vec4 {.inline.} +proc lerp[T: SomeFloat](a, b: GVec234[T]; v: T): type(a) {.inline.} ``` -## **proc** xyz +## **proc** dot ```nim -proc xyz(a: Vec4): Vec3 {.inline.} +proc dot[T](a, b: GVec2[T]): T {.inline.} ``` -## **proc** `$` +## **proc** dot ```nim -proc `$`(a: Vec4): string {.raises: [ValueError].} +proc dot[T](a, b: GVec3[T]): T {.inline.} ``` -## **proc** vec3 +## **proc** dot ```nim -proc vec3(a: Vec2; z = 0.0): Vec3 {.inline.} +proc dot[T](a, b: GVec4[T]): T {.inline.} ``` -## **proc** vec4 +## **proc** cross ```nim -proc vec4(a: Vec3; w = 0.0): Vec4 {.inline.} +proc cross[T](a, b: GVec3[T]): GVec3[T] {.inline.} ``` -## **proc** vec4 +## **proc** dist ```nim -proc vec4(a: Vec2; z = 0.0; w = 0.0): Vec4 {.inline.} +proc dist[T](at, to: GVec234[T]): T {.inline.} +``` + +## **proc** distSq + + +```nim +proc distSq[T](at, to: GVec234[T]): T {.inline.} +``` + +## **proc** dir + + +```nim +proc dir[T](at, to: GVec234[T]): type(to) {.inline.} +``` + +## **proc** dir + + +```nim +proc dir[T](angle: T): GVec2[T] {.inline.} +``` + +## **type** GMat2 + + +```nim +GMat2[T] = array[2, GVec2[T]] +``` + +## **type** GMat3 + + +```nim +GMat3[T] = array[3, GVec3[T]] +``` + +## **type** GMat4 + + +```nim +GMat4[T] = array[4, GVec4[T]] +``` + +## **type** Mat2 + + +```nim +Mat2 = GMat2[float32] ``` ## **type** Mat3 -3x3 Matrix ```nim -Mat3 = array[9, float32] +Mat3 = GMat3[float32] ``` -## **proc** `[]` +## **type** Mat4 ```nim -proc `[]`(a: Mat3; i, j: int): float32 {.inline.} +Mat4 = GMat4[float32] ``` -## **proc** `[]=` +## **type** DMat2 ```nim -proc `[]=`(a: var Mat3; i, j: int; v: float32) {.inline.} +DMat2 = GMat2[float64] +``` + +## **type** DMat3 + + +```nim +DMat3 = GMat3[float64] +``` + +## **type** DMat4 + + +```nim +DMat4 = GMat4[float64] +``` + +## **proc** mat2 + + +```nim +proc mat2(a`gensym38, b`gensym38, c`gensym38, d`gensym38: float32): Mat2 {. inline.} ``` ## **proc** mat3 ```nim -proc mat3(a, b, c, d, e, f, g, h, i: float32): Mat3 {.inline, tags: [].} +proc mat3(a`gensym38, b`gensym38, c`gensym38, d`gensym38, e`gensym38, f`gensym38, g`gensym38, h`gensym38, i`gensym38: float32): Mat3 {. inline.} +``` + +## **proc** mat4 + + +```nim +proc mat4(a`gensym38, b`gensym38, c`gensym38, d`gensym38, e`gensym38, f`gensym38, g`gensym38, h`gensym38, i`gensym38, j`gensym38, k`gensym38, l`gensym38, m`gensym38, n`gensym38, o`gensym38, p`gensym38: float32): Mat4 {. inline.} +``` + +## **proc** mat2 + + +```nim +proc mat2(a`gensym38, b`gensym38: GVec2[float32]): Mat2 {.inline, tags: [].} ``` ## **proc** mat3 ```nim -proc mat3(a: Mat3): Mat3 {.inline.} +proc mat3(a`gensym38, b`gensym38, c`gensym38: GVec3[float32]): Mat3 {.inline, raises: [].} ``` -## **proc** `~=` +## **proc** mat4 ```nim -proc `~=`(a: Mat3; b: Mat3): bool +proc mat4(a`gensym38, b`gensym38, c`gensym38, d`gensym38: GVec4[float32]): Mat4 {. inline.} ``` -## **proc** identity +## **proc** mat2 ```nim -proc identity(a: var Mat3) {.inline.} +proc mat2(m`gensym38: GMat3[float32]): Mat2 {.inline.} +``` + +## **proc** mat3 + + +```nim +proc mat3(m`gensym38: GMat4[float32]): Mat3 {.inline.} +``` + +## **proc** mat3 + + +```nim +proc mat3(m`gensym38: GMat2[float32]): Mat3 {.inline.} +``` + +## **proc** mat4 + + +```nim +proc mat4(m`gensym38: GMat3[float32]): Mat4 {.inline.} +``` + +## **proc** mat2 + + +```nim +proc mat2(): Mat2 {.inline.} ``` ## **proc** mat3 @@ -1131,147 +2293,6 @@ proc identity(a: var Mat3) {.inline.} proc mat3(): Mat3 {.inline.} ``` -## **proc** transpose - - -```nim -proc transpose(a: Mat3): Mat3 {.inline.} -``` - -## **proc** `$` - - -```nim -proc `$`(a: Mat3): string {.raises: [ValueError].} -``` - -## **proc** `*` - - -```nim -proc `*`(a, b: Mat3): Mat3 -``` - -## **proc** scale - - -```nim -proc scale(a: Mat3; v: Vec2): Mat3 {.inline.} -``` - -## **proc** scale - - -```nim -proc scale(a: Mat3; v: Vec3): Mat3 {.inline.} -``` - -## **proc** translate - - -```nim -proc translate(v: Vec2): Mat3 {.inline.} -``` - -## **proc** scale - - -```nim -proc scale(v: Vec2): Mat3 {.inline.} -``` - -## **proc** rotationMat3 - - -```nim -proc rotationMat3(angle: float32): Mat3 {.inline.} -``` - -## **proc** rotate - - -```nim -proc rotate(a: Mat3; angle: float32): Mat3 {.inline.} -``` - -## **proc** `*` - - -```nim -proc `*`(a: Mat3; b: Vec2): Vec2 -``` - -## **proc** `*` - - -```nim -proc `*`(a: Mat3; b: Vec3): Vec3 -``` - -## **proc** inverse - - -```nim -proc inverse(a: Mat3): Mat3 -``` - -## **proc** pos - - -```nim -proc pos(a: Mat3): Vec2 {.inline.} -``` - -## **proc** pos= - - -```nim -proc pos=(a: var Mat3; b: Vec2) {.inline.} -``` - -## **type** Mat4 - -4x4 Matrix - OpenGL row order - -```nim -Mat4 = array[16, float32] -``` - -## **proc** `[]` - - -```nim -proc `[]`(a: Mat4; i, j: int): float32 -``` - -## **proc** `[]=` - - -```nim -proc `[]=`(a: var Mat4; i, j: int; v: float32) -``` - -## **proc** mat4 - - -```nim -proc mat4(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15: float32): Mat4 {. inline.} -``` - -## **proc** mat4 - - -```nim -proc mat4(a: Mat4): Mat4 {.inline.} -``` - -## **proc** identity - - -```nim -proc identity(): Mat4 {.inline.} -``` - ## **proc** mat4 @@ -1279,469 +2300,426 @@ proc identity(): Mat4 {.inline.} proc mat4(): Mat4 {.inline.} ``` -## **proc** `~=` +## **proc** dmat2 ```nim -proc `~=`(a: Mat4; b: Mat4): bool +proc dmat2(a`gensym39, b`gensym39, c`gensym39, d`gensym39: float64): DMat2 {. inline.} ``` -## **proc** transpose +## **proc** dmat3 ```nim -proc transpose(a: Mat4): Mat4 {.inline.} +proc dmat3(a`gensym39, b`gensym39, c`gensym39, d`gensym39, e`gensym39, f`gensym39, g`gensym39, h`gensym39, i`gensym39: float64): DMat3 {. inline.} ``` -## **proc** determinant +## **proc** dmat4 ```nim -proc determinant(a: Mat4): float32 +proc dmat4(a`gensym39, b`gensym39, c`gensym39, d`gensym39, e`gensym39, f`gensym39, g`gensym39, h`gensym39, i`gensym39, j`gensym39, k`gensym39, l`gensym39, m`gensym39, n`gensym39, o`gensym39, p`gensym39: float64): DMat4 {.inline.} ``` -## **proc** inverse +## **proc** dmat2 ```nim -proc inverse(a: Mat4): Mat4 +proc dmat2(a`gensym39, b`gensym39: GVec2[float64]): DMat2 {.inline, tags: [].} ``` -## **proc** `*` +## **proc** dmat3 ```nim -proc `*`(a, b: Mat4): Mat4 +proc dmat3(a`gensym39, b`gensym39, c`gensym39: GVec3[float64]): DMat3 {.inline, raises: [].} ``` -## **proc** `*` +## **proc** dmat4 ```nim -proc `*`(a: Mat4; b: Vec3): Vec3 +proc dmat4(a`gensym39, b`gensym39, c`gensym39, d`gensym39: GVec4[float64]): DMat4 {. inline.} ``` -## **proc** `*` +## **proc** dmat2 ```nim -proc `*`(a: Mat4; b: Vec4): Vec4 +proc dmat2(m`gensym39: GMat3[float64]): DMat2 {.inline.} ``` -## **proc** right +## **proc** dmat3 ```nim -proc right(a: Mat4): Vec3 {.inline.} +proc dmat3(m`gensym39: GMat4[float64]): DMat3 {.inline.} ``` -## **proc** right= +## **proc** dmat3 ```nim -proc right=(a: var Mat4; b: Vec3) {.inline.} +proc dmat3(m`gensym39: GMat2[float64]): DMat3 {.inline.} ``` -## **proc** up +## **proc** dmat4 ```nim -proc up(a: Mat4): Vec3 {.inline.} +proc dmat4(m`gensym39: GMat3[float64]): DMat4 {.inline.} ``` -## **proc** up= +## **proc** dmat2 ```nim -proc up=(a: var Mat4; b: Vec3) {.inline.} +proc dmat2(): DMat2 {.inline.} ``` -## **proc** forward +## **proc** dmat3 ```nim -proc forward(a: Mat4): Vec3 {.inline.} +proc dmat3(): DMat3 {.inline.} ``` -## **proc** forward= +## **proc** dmat4 ```nim -proc forward=(a: var Mat4; b: Vec3) {.inline.} -``` - -## **proc** pos - - -```nim -proc pos(a: Mat4): Vec3 {.inline.} -``` - -## **proc** pos= - - -```nim -proc pos=(a: var Mat4; b: Vec3) {.inline.} -``` - -## **proc** rotationOnly - - -```nim -proc rotationOnly(a: Mat4): Mat4 {.inline.} -``` - -## **proc** dist - - -```nim -proc dist(a, b: Mat4): float32 {.inline.} -``` - -## **proc** translate - - -```nim -proc translate(v: Vec3): Mat4 -``` - -## **proc** scale - - -```nim -proc scale(v: Vec3): Mat4 -``` - -## **proc** hrp - - -```nim -proc hrp(m: Mat4): Vec3 -``` - -## **proc** frustum - - -```nim -proc frustum(left, right, bottom, top, near, far: float32): Mat4 -``` - -## **proc** perspective - - -```nim -proc perspective(fovy, aspect, near, far: float32): Mat4 -``` - -## **proc** ortho - - -```nim -proc ortho(left, right, bottom, top, near, far: float32): Mat4 -``` - -## **proc** lookAt - - -```nim -proc lookAt(eye, center, up: Vec3): Mat4 -``` - -## **proc** mat3 - -Gets rotation and translation, ignoring z coordinates. - -```nim -proc mat3(m: Mat4): Mat3 -``` - -## **proc** mat3Rotation - -Gets the rotational part of the 4x4 matrix. - -```nim -proc mat3Rotation(m: Mat4): Mat3 -``` - -## **proc** mat4 - -Takes a 2d Mat3 with position and converts to a 3d matrix. - -```nim -proc mat4(m: Mat3): Mat4 -``` - -## **proc** mat4Rotation - -Gets the rotational part of the 3x3 matrix into a 4x4 matrix. - -```nim -proc mat4Rotation(m: Mat3): Mat4 -``` - -## **proc** `$` - - -```nim -proc `$`(a: Mat4): string {.raises: [ValueError].} -``` - -## **type** Quat - - -```nim -Quat = object - x*: float32 - y*: float32 - z*: float32 - w*: float32 -``` - -## **proc** quat - - -```nim -proc quat(x, y, z, w: float32): Quat {.inline.} -``` - -## **proc** `~=` - - -```nim -proc `~=`(a, b: Quat): bool -``` - -## **proc** conjugate - - -```nim -proc conjugate(q: Quat): Quat {.inline.} -``` - -## **proc** length - - -```nim -proc length(q: Quat): float32 {.inline.} -``` - -## **proc** normalize - - -```nim -proc normalize(q: Quat): Quat -``` - -## **proc** xyz - - -```nim -proc xyz(q: Quat): Vec3 {.inline.} -``` - -## **proc** xyz= - - -```nim -proc xyz=(q: var Quat; v: Vec3) {.inline.} -``` - -## **proc** `-` - - -```nim -proc `-`(a: var Quat): Quat {.inline.} -``` - -## **proc** `+` - - -```nim -proc `+`(a: Quat; b: Quat): Quat {.inline.} -``` - -## **proc** `*` - -Multiply the quaternion by a quaternion. - -```nim -proc `*`(a, b: Quat): Quat -``` - -## **proc** `*` - -Multiply the quaternion by a float32. - -```nim -proc `*`(q: Quat; v: float32): Quat {.inline.} -``` - -## **proc** `/` - -Divide the quaternion by a float32. - -```nim -proc `/`(q: Quat; v: float32): Quat {.inline.} -``` - -## **proc** `*=` - - -```nim -proc `*=`(a: var Quat; b: float32) {.inline.} -``` - -## **proc** `/=` - - -```nim -proc `/=`(a: var Quat; b: float32) {.inline.} -``` - -## **proc** `*` - -Multiply the quaternion by a vector. - -```nim -proc `*`(q: Quat; v: Vec3): Vec3 +proc dmat4(): DMat4 {.inline.} ``` ## **proc** `[]` ```nim -proc `[]`(a: var Quat; i: int; b: float32) +proc `[]`[T](a: GMat234[T]; i, j: int): T {.inline.} ``` ## **proc** `[]=` ```nim -proc `[]=`(a: var Quat; i: int; b: float32) +proc `[]=`[T](a: var GMat234[T]; i, j: int; v: T) {.inline.} ``` -## **proc** mat3 +## **proc** `~=` ```nim -proc mat3(q: Quat): Mat3 +proc `~=`[T](a, b: GMat2[T]): bool {.inline.} ``` -## **proc** mat4 +## **proc** `~=` ```nim -proc mat4(q: Quat): Mat4 +proc `~=`[T](a, b: GMat3[T]): bool {.inline.} ``` -## **proc** reciprocalSqrt +## **proc** `~=` ```nim -proc reciprocalSqrt(x: float32): float32 {.inline.} +proc `~=`[T](a, b: GMat4[T]): bool {.inline.} ``` -## **proc** quat +## **proc** `*` ```nim -proc quat(m: Mat4): Quat +proc `*`[T](a, b: GMat3[T]): GMat3[T] {.inline.} ``` -## **proc** fromAxisAngle +## **proc** `*` ```nim -proc fromAxisAngle(axis: Vec3; angle: float32): Quat +proc `*`[T](a: GMat3[T]; b: GVec2[T]): GVec2[T] {.inline.} ``` -## **proc** toAxisAngle +## **proc** `*` ```nim -proc toAxisAngle(q: Quat; axis: var Vec3; angle: var float32) +proc `*`[T](a, b: GMat4[T]): GMat4[T] {.inline.} ``` -## **proc** quat +## **proc** `*` ```nim -proc quat(heading, pitch, roll: float32): Quat +proc `*`[T](a: GMat4[T]; b: GVec3[T]): GVec3[T] {.inline.} ``` -## **proc** quat +## **proc** transpose ```nim -proc quat(hpr: Vec3): Quat {.inline.} +proc transpose[T](a: GMat3[T]): GMat3[T] {.inline.} ``` -## **proc** hrp +## **proc** transpose ```nim -proc hrp(q: Quat): Vec3 +proc transpose[T](a: GMat4[T]): GMat4[T] {.inline.} ``` -## **proc** dot +## **proc** determinant ```nim -proc dot(a: Quat; b: Quat): float32 {.inline.} +proc determinant[T](a: GMat4[T]): T {.inline.} ``` -## **proc** nlerp +## **proc** inverse ```nim -proc nlerp(a: Quat; b: Quat; v: float32): Quat +proc inverse[T](a: GMat3[T]): GMat3[T] {.inline.} ``` -## **proc** `$` +## **proc** inverse ```nim -proc `$`(a: Quat): string {.raises: [ValueError].} +proc inverse[T](a: GMat4[T]): GMat4[T] {.inline.} +``` + +## **proc** scale + + +```nim +proc scale[T](v: GVec2[T]): GMat3[T] {.inline.} +``` + +## **proc** scale + + +```nim +proc scale[T](v: GVec3[T]): GMat4[T] {.inline.} +``` + +## **proc** translate + + +```nim +proc translate[T](v: GVec2[T]): GMat3[T] {.inline.} +``` + +## **proc** translate + + +```nim +proc translate[T](v: GVec3[T]): GMat4[T] {.inline.} ``` ## **proc** rotate ```nim -proc rotate(angle: float32; axis: Vec3): Mat4 {.inline.} +proc rotate[T](angle: T): GMat3[T] {.inline.} +``` + +## **proc** hrp + + +```nim +proc hrp[T](m: GMat4[T]): GVec3[T] {.inline.} +``` + +## **proc** frustum + + +```nim +proc frustum[T](left, right, bottom, top, near, far: T): GMat4[T] {.inline.} +``` + +## **proc** perspective + + +```nim +proc perspective[T](fovy, aspect, near, far: T): GMat4[T] {.inline.} +``` + +## **proc** ortho + + +```nim +proc ortho[T](left, right, bottom, top, near, far: T): GMat4[T] {.inline.} +``` + +## **proc** lookAt + + +```nim +proc lookAt[T](eye, center: GVec3[T]; up = [T(0), 0, 1]): GMat4[T] {.inline.} +``` + +## **proc** angle + +Angle of a Vec2. + +```nim +proc angle[T](a: GVec2[T]): T {.inline.} +``` + +## **proc** angle + +Angle between 2 Vec2. + +```nim +proc angle[T](a, b: GVec2[T]): T {.inline.} +``` + +## **proc** angle + +Angle between 2 Vec3. + +```nim +proc angle[T](a, b: GVec3[T]): T {.inline.} +``` + +## **type** Quat + + +```nim +Quat = GVec4[float32] +``` + +## **type** DQuat + + +```nim +DQuat = GVec4[float64] +``` + +## **proc** quat + + +```nim +proc quat(): Quat {.inline.} +``` + +## **proc** quat + + +```nim +proc quat(x`gensym41, y`gensym41, z`gensym41, w`gensym41: float32): Quat {. inline.} +``` + +## **proc** quat + + +```nim +proc quat(x`gensym41: float32): Quat {.inline.} +``` + +## **proc** quat + + +```nim +proc quat[T](x`gensym41: GVec4[T]): Quat {.inline.} +``` + +## **proc** dquat + + +```nim +proc dquat(): DQuat {.inline.} +``` + +## **proc** dquat + + +```nim +proc dquat(x`gensym42, y`gensym42, z`gensym42, w`gensym42: float64): DQuat {. inline.} +``` + +## **proc** dquat + + +```nim +proc dquat(x`gensym42: float64): DQuat {.inline.} +``` + +## **proc** dquat + + +```nim +proc dquat[T](x`gensym42: GVec4[T]): DQuat {.inline.} +``` + +## **proc** fromAxisAngle + + +```nim +proc fromAxisAngle[T](axis: GVec3[T]; angle: T): GVec4[T] {.inline.} +``` + +## **proc** toAxisAngle + + +```nim +proc toAxisAngle[T](q: GVec4[T]): (GVec3[T], T) {.inline.} +``` + +## **proc** orthogonal + + +```nim +proc orthogonal[T](v: GVec3[T]): GVec3[T] {.inline.} +``` + +## **proc** fromTwoVectors + +Return a quat that would take a and rotate it into b. + +```nim +proc fromTwoVectors[T](a, b: GVec3[T]): GVec4[T] {.inline.} +``` + +## **proc** quat + + +```nim +proc quat[T](m: GMat4[T]): GVec4[T] {.inline.} +``` + +## **proc** mat4 + + +```nim +proc mat4[T](q: GVec4[T]): GMat4[T] {.inline.} +``` + +## **proc** rotate + + +```nim +proc rotate[T](angle: T; axis: GVec3[T]): GMat4[T] {.inline.} ``` ## **proc** rotateX ```nim -proc rotateX(angle: float32): Mat4 {.inline.} +proc rotateX[T](angle: T): GMat4[T] {.inline.} ``` ## **proc** rotateY ```nim -proc rotateY(angle: float32): Mat4 {.inline.} +proc rotateY[T](angle: T): GMat4[T] {.inline.} ``` ## **proc** rotateZ ```nim -proc rotateZ(angle: float32): Mat4 {.inline.} -``` - -## **proc** scaleMat - - -```nim -proc scaleMat(scale: Vec3): Mat4 {.inline.} -``` - -## **proc** scaleMat - - -```nim -proc scaleMat(scale: float32): Mat4 {.inline.} +proc rotateZ[T](angle: T): GMat4[T] {.inline.} ``` diff --git a/docs/banner.png b/docs/banner.png new file mode 100644 index 0000000..8a111d6 Binary files /dev/null and b/docs/banner.png differ diff --git a/src/vmath.nim b/src/vmath.nim index 7f16ef8..4539625 100644 --- a/src/vmath.nim +++ b/src/vmath.nim @@ -1,32 +1,64 @@ -import hashes, math, random, strformat, strutils +import math export math -proc `~=`*(a, b: float32): bool = +type + GVec2*[T] = array[2, T] + GVec3*[T] = array[3, T] + GVec4*[T] = array[4, T] + + BVec2* = GVec2[bool] + BVec3* = GVec3[bool] + BVec4* = GVec4[bool] + + IVec2* = GVec2[int32] + IVec3* = GVec3[int32] + IVec4* = GVec4[int32] + + UVec2* = GVec2[uint32] + UVec3* = GVec3[uint32] + UVec4* = GVec4[uint32] + + Vec2* = GVec2[float32] + Vec3* = GVec3[float32] + Vec4* = GVec4[float32] + + DVec2* = GVec2[float64] + DVec3* = GVec3[float64] + DVec4* = GVec4[float64] + + GVec34[T] = GVec3[T] | GVec4[T] + GVec234[T] = GVec2[T] | GVec3[T] | GVec4[T] + +{.push inline.} +when defined(release): + {.push noinit, checks: off.} + +proc `~=`*[T: SomeFloat](a, b: T): bool = ## Almost equal. const epsilon = 0.000001 - abs(a - b) < epsilon + abs(a - b) <= epsilon -proc between*(value, min, max: float32): bool {.inline.} = +proc between*[T](value, min, max: T): bool = ## Returns true if value is between min and max or equal to them. (value >= min) and (value <= max) -proc sign*(v: float32): float32 {.inline.} = +proc sign*[T](v: T): T = ## Returns the sign of a number, -1 or 1. - if v >= 0: 1.0 else: -1.0 + if v >= 0: 1 else: -1 -proc quantize*(v, n: float32): float32 {.inline.} = - ## Makes v be multipe of n. Rounding to integer quantize by 1.0. +proc quantize*[T: SomeFloat](v, n: T): T = + ## Makes v be multiple of n. Rounding to integer quantize by 1.0. sign(v) * floor(abs(v) / n) * n -proc lerp*(a, b, v: float32): float32 {.inline.} = +proc lerp*[T: SomeFloat](a, b, v: T): T = ## Interpolates value between a and b. ## * 0 -> a ## * 1 -> b ## * 0.5 -> between a and b a * (1.0 - v) + b * v -proc fixAngle*(angle: float32): float32 = +proc fixAngle*[T: SomeFloat](angle: T): T = ## Make angle be from -PI to PI radians. var angle = angle while angle > PI: @@ -35,11 +67,11 @@ proc fixAngle*(angle: float32): float32 = angle += PI * 2 angle -proc angleBetween*(a, b: float32): float32 {.inline.} = +proc angleBetween*[T: SomeFloat](a, b: T): T = ## Angle between angle a and angle b. fixAngle(b - a) -proc turnAngle*(a, b, speed: float32): float32 = +proc turnAngle*[T: SomeFloat](a, b, speed: T): T = ## Move from angle a to angle b with step of v. var turn = fixAngle(b - a) @@ -51,704 +83,530 @@ proc turnAngle*(a, b, speed: float32): float32 = turn = -speed a + turn -type Vec2* = object - ## 2D vector - x*: float32 - y*: float32 +proc toRadians*[T: SomeFloat](deg: T): T = + return PI * deg / 180.0 -proc vec2*(x, y: float32): Vec2 {.inline.} = - result.x = x - result.y = y +proc toDegrees*[T: SomeFloat](rad: T): T = + return fixAngle(180.0 * rad / PI) -proc vec2*(v: float32): Vec2 {.inline.} = - result.x = v - result.y = v +proc gvec2*[T](x, y: T): GVec2[T] = + [x, y] -proc vec2*(a: Vec2): Vec2 {.inline.} = - result.x = a.x - result.y = a.y +proc gvec3*[T](x, y, z: T): GVec3[T] = + [x, y, z] -proc `~=`*(a, b: Vec2): bool = +proc gvec4*[T](x, y, z, w: T): GVec4[T] = + [x, y, z, w] + +template genConstructor(lower, upper, typ: untyped) = + proc `lower 2`*(x, y: typ): `upper 2` = gvec2[typ](x, y) + proc `lower 3`*(x, y, z: typ): `upper 3` = gvec3[typ](x, y, z) + proc `lower 4`*(x, y, z, w: typ): `upper 4` = gvec4[typ](x, y, z, w) + + proc `lower 2`*(x: typ): `upper 2` = gvec2[typ](x, x) + proc `lower 3`*(x: typ): `upper 3` = gvec3[typ](x, x, x) + proc `lower 4`*(x: typ): `upper 4` = gvec4[typ](x, x, x, x) + + proc `lower 2`*[T](x: GVec2[T]): `upper 2` = + gvec2[typ](typ(x[0]), typ(x[1])) + proc `lower 3`*[T](x: GVec3[T]): `upper 3` = + gvec3[typ](typ(x[0]), typ(x[1]), typ(x[2])) + proc `lower 4`*[T](x: GVec4[T]): `upper 4` = + gvec4[typ](typ(x[0]), typ(x[1]), typ(x[2]), typ(x[3])) + + proc `lower 3`*[T](x: GVec2[T]): `upper 3` = + gvec3[typ](typ(x[0]), typ(x[1]), 0) + proc `lower 4`*[T](x: GVec3[T]): `upper 4` = + gvec4[typ](typ(x[0]), typ(x[1]), typ(x[2]), 0) + +genConstructor(bvec, BVec, bool) +genConstructor(ivec, IVec, int32) +genConstructor(uvec, UVec, uint32) +genConstructor(vec, Vec, float32) +genConstructor(dvec, DVec, float64) + +proc x*[T](a: var GVec2[T]): var T = a[0] +proc y*[T](a: var GVec2[T]): var T = a[1] + +proc x*[T](a: var GVec3[T]): var T = a[0] +proc y*[T](a: var GVec3[T]): var T = a[1] +proc z*[T](a: var GVec3[T]): var T = a[2] + +proc x*[T](a: var GVec4[T]): var T = a[0] +proc y*[T](a: var GVec4[T]): var T = a[1] +proc z*[T](a: var GVec4[T]): var T = a[2] +proc w*[T](a: var GVec4[T]): var T = a[3] + +proc x*[T](a: GVec2[T]): T = a[0] +proc x*[T](a: GVec3[T]): T = a[0] +proc x*[T](a: GVec4[T]): T = a[0] + +proc y*[T](a: GVec2[T]): T = a[1] +proc y*[T](a: GVec3[T]): T = a[1] +proc y*[T](a: GVec4[T]): T = a[1] + +proc z*[T](a: GVec2[T]): T = {.error: "using .w on a Vec2".} +proc z*[T](a: GVec3[T]): T = a[2] +proc z*[T](a: GVec4[T]): T = a[2] + +proc w*[T](a: GVec2[T]): T = {.error: "using .w on a Vec2".} +proc w*[T](a: GVec3[T]): T = {.error: "using .w on a Vec3".} +proc w*[T](a: GVec4[T]): T = a[3] + +proc `x=`*[T](a: var GVec234[T], value: T) = a[0] = value +proc `y=`*[T](a: var GVec234[T], value: T) = a[1] = value +proc `z=`*[T](a: var GVec34[T], value: T) = a[2] = value +proc `w=`*[T](a: var GVec4[T], value: T) = a[3] = value + +proc xy*[T](a: GVec234[T]): GVec2[T] = [a.x, a.y] +proc xz*[T](a: GVec234[T]): GVec2[T] = [a.x, a.z] +proc yx*[T](a: GVec234[T]): GVec2[T] = [a.y, a.x] +proc yz*[T](a: GVec234[T]): GVec2[T] = [a.y, a.z] +proc zx*[T](a: GVec234[T]): GVec2[T] = [a.z, a.x] +proc zy*[T](a: GVec234[T]): GVec2[T] = [a.z, a.y] + +proc xxx*[T](a: GVec34[T]): GVec3[T] = [a.x, a.x, a.x] +proc xxy*[T](a: GVec34[T]): GVec3[T] = [a.x, a.x, a.y] +proc xxz*[T](a: GVec34[T]): GVec3[T] = [a.x, a.x, a.z] +proc xyx*[T](a: GVec34[T]): GVec3[T] = [a.x, a.y, a.x] +proc xyy*[T](a: GVec34[T]): GVec3[T] = [a.x, a.y, a.y] +proc xyz*[T](a: GVec34[T]): GVec3[T] = [a.x, a.y, a.z] +proc xzx*[T](a: GVec34[T]): GVec3[T] = [a.x, a.z, a.x] +proc xzy*[T](a: GVec34[T]): GVec3[T] = [a.x, a.z, a.y] +proc xzz*[T](a: GVec34[T]): GVec3[T] = [a.x, a.z, a.z] +proc yxx*[T](a: GVec34[T]): GVec3[T] = [a.y, a.x, a.x] +proc yxy*[T](a: GVec34[T]): GVec3[T] = [a.y, a.x, a.y] +proc yxz*[T](a: GVec34[T]): GVec3[T] = [a.y, a.x, a.z] +proc yyx*[T](a: GVec34[T]): GVec3[T] = [a.y, a.y, a.x] +proc yyy*[T](a: GVec34[T]): GVec3[T] = [a.y, a.y, a.y] +proc yyz*[T](a: GVec34[T]): GVec3[T] = [a.y, a.y, a.z] +proc yzx*[T](a: GVec34[T]): GVec3[T] = [a.y, a.z, a.x] +proc yzy*[T](a: GVec34[T]): GVec3[T] = [a.y, a.z, a.y] +proc yzz*[T](a: GVec34[T]): GVec3[T] = [a.y, a.z, a.z] +proc zxx*[T](a: GVec34[T]): GVec3[T] = [a.z, a.x, a.x] +proc zxy*[T](a: GVec34[T]): GVec3[T] = [a.z, a.x, a.y] +proc zxz*[T](a: GVec34[T]): GVec3[T] = [a.z, a.x, a.z] +proc zyx*[T](a: GVec34[T]): GVec3[T] = [a.z, a.y, a.x] +proc zyy*[T](a: GVec34[T]): GVec3[T] = [a.z, a.y, a.y] +proc zyz*[T](a: GVec34[T]): GVec3[T] = [a.z, a.y, a.z] +proc zzx*[T](a: GVec34[T]): GVec3[T] = [a.z, a.z, a.x] +proc zzy*[T](a: GVec34[T]): GVec3[T] = [a.z, a.z, a.y] +proc zzz*[T](a: GVec34[T]): GVec3[T] = [a.z, a.z, a.z] + +template genOp(op: untyped) = + proc op*[T](a, b: GVec2[T]): GVec2[T] = + [ + op(a[0], b[0]), + op(a[1], b[1]) + ] + + proc op*[T](a, b: GVec3[T]): GVec3[T] = + [ + op(a[0], b[0]), + op(a[1], b[1]), + op(a[2], b[2]) + ] + + proc op*[T](a, b: GVec4[T]): GVec4[T] = + [ + op(a[0], b[0]), + op(a[1], b[1]), + op(a[2], b[2]), + op(a[3], b[3]) + ] + + proc op*[T](a: GVec2[T], b: T): GVec2[T] = + [ + op(a[0], b), + op(a[1], b) + ] + + proc op*[T](a: GVec3[T], b: T): GVec3[T] = + [ + op(a[0], b), + op(a[1], b), + op(a[2], b) + ] + + proc op*[T](a: GVec4[T], b: T): GVec4[T] = + [ + op(a[0], b), + op(a[1], b), + op(a[2], b), + op(a[3], b) + ] + + proc op*[T](a: T, b: GVec2[T]): GVec2[T] = + [ + op(a, b[0]), + op(a, b[1]) + ] + + proc op*[T](a: T, b: GVec3[T]): GVec3[T] = + [ + op(a, b[0]), + op(a, b[1]), + op(a, b[2]) + ] + + proc op*[T](a: T, b: GVec4[T]): GVec4[T] = + [ + op(a, b[0]), + op(a, b[1]), + op(a, b[2]), + op(a, b[3]) + ] + +genOp(`+`) +genOp(`-`) +genOp(`*`) +genOp(`/`) +genOp(`mod`) +genOp(`div`) + +template genEqOp(op: untyped) = + proc op*[T](a: var GVec2[T], b: GVec2[T]) = + op(a[0], b[0]) + op(a[1], b[1]) + + proc op*[T](a: var GVec3[T], b: GVec3[T]) = + op(a[0], b[0]) + op(a[1], b[1]) + op(a[2], b[2]) + + proc op*[T](a: var GVec4[T], b: GVec4[T]) = + op(a[0], b[0]) + op(a[1], b[1]) + op(a[2], b[2]) + op(a[3], b[3]) + + proc op*[T](a: var GVec2[T], b: T) = + op(a[0], b) + op(a[1], b) + + proc op*[T](a: var GVec3[T], b: T) = + op(a[0], b) + op(a[1], b) + op(a[2], b) + + proc op*[T](a: var GVec4[T], b: T) = + op(a[0], b) + op(a[1], b) + op(a[2], b) + op(a[3], b) + +genEqOp(`+=`) +genEqOp(`-=`) +genEqOp(`*=`) +genEqOp(`/=`) + +template genMathFn(fn: untyped) = + proc fn*[T](v: GVec2[T]): GVec2[T] = + [ + fn(v[0]), + fn(v[1]) + ] + + proc fn*[T](v: GVec3[T]): GVec3[T] = + [ + fn(v[0]), + fn(v[1]), + fn(v[2]) + ] + + proc fn*[T](v: GVec4[T]): GVec4[T] = + [ + fn(v[0]), + fn(v[1]), + fn(v[2]), + fn(v[3]) + ] + +genMathFn(`-`) +genMathFn(sin) +genMathFn(cos) +genMathFn(tan) +genMathFn(arcsin) +genMathFn(arccos) +genMathFn(arctan) +genMathFn(sinh) +genMathFn(cosh) +genMathFn(tanh) +genMathFn(exp2) +genMathFn(inversesqrt) +genMathFn(exp) +genMathFn(ln) +genMathFn(log2) +genMathFn(sqrt) +genMathFn(floor) +genMathFn(ciel) +genMathFn(abs) + +proc `~=`*[T](a, b: GVec2[T]): bool = + ## Almost equal. a.x ~= b.x and a.y ~= b.y -proc `+`*(a, b: Vec2): Vec2 {.inline.} = - result.x = a.x + b.x - result.y = a.y + b.y - -proc `-`*(a, b: Vec2): Vec2 {.inline.} = - result.x = a.x - b.x - result.y = a.y - b.y - -proc `*`*(a: Vec2, b: float32): Vec2 {.inline.} = - result.x = a.x * b - result.y = a.y * b - -proc `*`*(a: float32, b: Vec2): Vec2 {.inline.} = - b * a - -proc `/`*(a: Vec2, b: float32): Vec2 {.inline.} = - result.x = a.x / b - result.y = a.y / b - -proc `+=`*(a: var Vec2, b: Vec2) {.inline.} = - a.x += b.x - a.y += b.y - -proc `-=`*(a: var Vec2, b: Vec2) {.inline.} = - a.x -= b.x - a.y -= b.y - -proc `*=`*(a: var Vec2, b: float32) {.inline.} = - a.x *= b - a.y *= b - -proc `/=`*(a: var Vec2, b: float32) {.inline.} = - a.x /= b - a.y /= b - -proc zero*(a: var Vec2) {.inline.} = - a.x = 0 - a.y = 0 - -proc `-`*(a: Vec2): Vec2 {.inline.} = - result.x = -a.x - result.y = -a.y - -proc hash*(a: Vec2): Hash {.inline.} = - hash((a.x, a.y)) - -proc lengthSq*(a: Vec2): float32 {.inline.} = - a.x * a.x + a.y * a.y - -proc length*(a: Vec2): float32 {.inline.} = - sqrt(a.lengthSq) - -proc `length=`*(a: var Vec2, b: float32) {.inline.} = - a *= b / a.length - -proc normalize*(a: Vec2): Vec2 {.inline.} = - a / a.length - -proc floor*(a: Vec2): Vec2 {.inline.} = - vec2(floor(a.x), floor(a.y)) - -proc round*(a: Vec2): Vec2 {.inline.} = - vec2(round(a.x), round(a.y)) - -proc ceil*(a: Vec2): Vec2 {.inline.} = - vec2(ceil(a.x), ceil(a.y)) - -proc dot*(a, b: Vec2): float32 {.inline.} = - a.x * b.x + a.y * b.y - -proc dir*(at, to: Vec2): Vec2 {.inline.} = - (at - to).normalize() - -proc dir*(th: float32): Vec2 {.inline.} = - vec2(cos(th), sin(th)) - -proc dist*(at, to: Vec2): float32 {.inline.} = - (at - to).length - -proc distSq*(at, to: Vec2): float32 {.inline.} = - (at - to).lengthSq - -proc lerp*(a, b: Vec2, v: float32): Vec2 {.inline.} = - a * (1.0 - v) + b * v - -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 - -proc `[]`*(a: Vec2, i: int): float32 = - case i - of 0: a.x - of 1: a.y - else: raise newException(IndexDefect, "Index not in 0 .. 1") - -proc `[]=`*(a: var Vec2, i: int, b: float32) = - case i - of 0: a.x = b - of 1: a.y = b - else: raise newException(IndexDefect, "Index not in 0 .. 1") - -proc randVec2*(r: var Rand): Vec2 = - let a = r.rand(PI * 2) - let v = r.rand(1.0) - vec2(cos(a) * v, sin(a) * v) - -proc `$`*(a: Vec2): string = - &"({a.x:.7f}, {a.y:.7f})" - -proc angle*(a: Vec2): float32 {.inline.} = - ## Angle of a Vec2. - arctan2(a.y, a.x) - -proc angleBetween*(a: Vec2, b: Vec2): float32 {.inline.} = - ## Angle between 2 Vec2. - fixAngle(arctan2(a.y - b.y, a.x - b.x)) - -type Vec3* = object - ## 3D vector - x*: float32 - y*: float32 - z*: float32 - -proc vec3*(x, y, z: float32): Vec3 {.inline.} = - result.x = x - result.y = y - result.z = z - -proc vec3*(v: float32): Vec3 {.inline.} = - result.x = v - result.y = v - result.z = v - -proc vec3*(a: Vec3): Vec3 {.inline.} = - result.x = a.x - result.y = a.y - result.z = a.z - -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) - -proc `~=`*(a, b: Vec3): bool = +proc `~=`*[T](a, b: GVec3[T]): bool = + ## Almost equal. a.x ~= b.x and a.y ~= b.y and a.z ~= b.z -proc `+`*(a, b: Vec3): Vec3 {.inline.} = - result.x = a.x + b.x - result.y = a.y + b.y - result.z = a.z + b.z - -proc `-`*(a, b: Vec3): Vec3 {.inline.} = - result.x = a.x - b.x - result.y = a.y - b.y - result.z = a.z - b.z - -proc `-`*(a: Vec3): Vec3 {.inline.} = - result.x = -a.x - result.y = -a.y - result.z = -a.z - -proc `*`*(a: Vec3, b: float32): Vec3 {.inline.} = - result.x = a.x * b - result.y = a.y * b - result.z = a.z * b - -proc `*`*(a: float32, b: Vec3): Vec3 {.inline.} = - b * a - -proc `/`*(a: Vec3, b: float32): Vec3 {.inline.} = - result.x = a.x / b - result.y = a.y / b - result.z = a.z / b - -proc `/`*(a: float32, b: Vec3): Vec3 {.inline.} = - result.x = a / b.x - result.y = a / b.y - result.z = a / b.z - -proc `+=`*(a: var Vec3, b: Vec3) {.inline.} = - a.x += b.x - a.y += b.y - a.z += b.z - -proc `-=`*(a: var Vec3, b: Vec3) {.inline.} = - a.x -= b.x - a.y -= b.y - a.z -= b.z - -proc `*=`*(a: var Vec3, b: float32) {.inline.} = - a.x *= b - a.y *= b - a.z *= b - -proc `/=`*(a: var Vec3, b: float32) {.inline.} = - a.x /= b - a.y /= b - a.z /= b - -proc zero*(a: var Vec3) {.inline.} = - a.x = 0 - a.y = 0 - a.z = 0 - -proc `-`*(a: var Vec3): Vec3 {.inline.} = - result.x = -a.x - result.y = -a.y - result.z = -a.z - -proc hash*(a: Vec3): Hash {.inline.} = - hash((a.x, a.y, a.z)) - -proc lengthSq*(a: Vec3): float32 {.inline.} = - a.x * a.x + a.y * a.y + a.z * a.z - -proc length*(a: Vec3): float32 {.inline.} = - sqrt(a.lengthSq) - -proc `length=`*(a: var Vec3, b: float32) {.inline.} = - a *= b / a.length - -proc floor*(a: Vec3): Vec3 {.inline.} = - vec3(floor(a.x), floor(a.y), floor(a.z)) - -proc round*(a: Vec3): Vec3 {.inline.} = - vec3(round(a.x), round(a.y), round(a.z)) - -proc ceil*(a: Vec3): Vec3 {.inline.} = - vec3(ceil(a.x), ceil(a.y), ceil(a.z)) - -proc normalize*(a: Vec3): Vec3 {.inline.} = - a / sqrt(a.x * a.x + a.y * a.y + a.z * a.z) - -proc cross*(a, b: Vec3): Vec3 {.inline.} = - 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 - -proc computeNormal*(a, b, c: Vec3): Vec3 = - cross(c - b, b - a).normalize() - -proc dot*(a, b: Vec3): float32 {.inline.} = - a.x * b.x + a.y * b.y + a.z * b.z - -proc dir*(at, to: Vec3): Vec3 {.inline.} = - (at - to).normalize() - -proc dist*(at, to: Vec3): float32 {.inline.} = - (at - to).length - -proc distSq*(at, to: Vec3): float32 {.inline.} = - (at - to).lengthSq - -proc lerp*(a, b: Vec3, v: float32): Vec3 {.inline.} = - a * (1.0 - v) + b * v - -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 - -proc angleBetween*(a, b: Vec3): float32 = - var dot = dot(a, b) - dot = dot / (a.length * b.length) - arccos(dot) - -proc `[]`*(a: Vec3, i: int): float32 = - case i - of 0: a.x - of 1: a.y - of 2: a.z - else: raise newException(IndexDefect, "Index not in 0 .. 2") - -proc `[]=`*(a: var Vec3, i: int, b: float32) = - case i - of 0: a.x = b - of 1: a.y = b - of 2: a.z = b - else: raise newException(IndexDefect, "Index not in 0 .. 2") - -proc xy*(a: Vec3): Vec2 {.inline.} = vec2(a.x, a.y) -proc xz*(a: Vec3): Vec2 {.inline.} = vec2(a.x, a.z) -proc yx*(a: Vec3): Vec2 {.inline.} = vec2(a.y, a.x) -proc yz*(a: Vec3): Vec2 {.inline.} = vec2(a.y, a.z) -proc zx*(a: Vec3): Vec2 {.inline.} = vec2(a.z, a.x) -proc zy*(a: Vec3): Vec2 {.inline.} = vec2(a.z, a.y) - -proc xxx*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.x, a.x) -proc xxy*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.x, a.y) -proc xxz*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.x, a.z) -proc xyx*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.y, a.x) -proc xyy*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.y, a.y) -proc xyz*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.y, a.z) -proc xzx*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.z, a.x) -proc xzy*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.z, a.y) -proc xzz*(a: Vec3): Vec3 {.inline.} = vec3(a.x, a.z, a.z) -proc yxx*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.x, a.x) -proc yxy*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.x, a.y) -proc yxz*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.x, a.z) -proc yyx*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.y, a.x) -proc yyy*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.y, a.y) -proc yyz*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.y, a.z) -proc yzx*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.z, a.x) -proc yzy*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.z, a.y) -proc yzz*(a: Vec3): Vec3 {.inline.} = vec3(a.y, a.z, a.z) -proc zxx*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.x, a.x) -proc zxy*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.x, a.y) -proc zxz*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.x, a.z) -proc zyx*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.y, a.x) -proc zyy*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.y, a.y) -proc zyz*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.y, a.z) -proc zzx*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.z, a.x) -proc zzy*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.z, a.y) -proc zzz*(a: Vec3): Vec3 {.inline.} = vec3(a.z, a.z, a.z) - -proc randVec3*(r: var Rand): Vec3 = - ## Generates a random unit vector based on - ## http://mathworld.wolfram.com/SpherePointPicking.html - let - u = r.rand(0.0 .. 1.0) - v = r.rand(0.0 .. 1.0) - th = 2 * PI * u - ph = arccos(2 * v - 1) - vec3( - cos(th) * sin(ph), - sin(th) * sin(ph), - cos(ph) - ) - -proc `$`*(a: Vec3): string = - &"({a.x:.8f}, {a.y:.8f}, {a.z:.8f})" - -type Vec4* = object - ## 4D Vector. - x*: float32 - y*: float32 - z*: float32 - w*: float32 - -proc vec4*(x, y, z, w: float32): Vec4 {.inline.} = - result.x = x - result.y = y - result.z = z - result.w = w - -proc vec4*(v: float32): Vec4 {.inline.} = - result.x = v - result.y = v - result.z = v - result.w = v - -proc `~=`*(a, b: Vec4): bool = +proc `~=`*[T](a, b: GVec4[T]): bool = + ## Almost equal. a.x ~= b.x and a.y ~= b.y and a.z ~= b.z and a.w ~= b.w -proc `+`*(a, b: Vec4): Vec4 {.inline.} = - result.x = a.x + b.x - result.y = a.y + b.y - result.z = a.z + b.z - result.w = a.w + b.w +proc length*[T](a: GVec2[T]): T = + sqrt(a.x*a.x + a.y*a.y) -proc `-`*(a, b: Vec4): Vec4 {.inline.} = - result.x = a.x - b.x - result.y = a.y - b.y - result.z = a.z - b.z - result.w = a.w - b.w +proc length*[T](a: GVec3[T]): T = + sqrt(a.x*a.x + a.y*a.y + a.z*a.z) -proc `-`*(a: Vec4): Vec4 {.inline.} = - result.x = -a.x - result.y = -a.y - result.z = -a.z - result.w = -a.w +proc length*[T](a: GVec4[T]): T = + sqrt(a.x*a.x + a.y*a.y + a.z*a.z + a.w*a.w) -proc `*`*(a: Vec4, b: float32): Vec4 {.inline.} = - result.x = a.x * b - result.y = a.y * b - result.z = a.z * b - result.w = a.w * b +proc lengthSq*[T](a: GVec2[T]): T = + a.x*a.x + a.y*a.y -proc `*`*(a: float32, b: Vec4): Vec4 {.inline.} = - b * a +proc lengthSq*[T](a: GVec3[T]): T = + a.x*a.x + a.y*a.y + a.z*a.z -proc `/`*(a: Vec4, b: float32): Vec4 {.inline.} = - result.x = a.x / b - result.y = a.y / b - result.z = a.z / b - result.w = a.w / b +proc lengthSq*[T](a: GVec4[T]): T = + a.x*a.x + a.y*a.y + a.z*a.z + a.w*a.w -proc `/`*(a: float32, b: Vec4): Vec4 {.inline.} = - result.x = a / b.x - result.y = a / b.y - result.z = a / b.z - result.w = a / b.w +proc normalize*[T](a: GVec234[T]): type(a) = + a / a.length -proc `+=`*(a: var Vec4, b: Vec4) {.inline.} = - a.x += b.x - a.y += b.y - a.z += b.z - a.w += b.w - -proc `-=`*(a: var Vec4, b: Vec4) {.inline.} = - a.x -= b.x - a.y -= b.y - a.z -= b.z - a.w -= b.w - -proc `*=`*(a: var Vec4, b: float32) {.inline.} = - a.x *= b - a.y *= b - a.z *= b - a.w *= b - -proc `/=`*(a: var Vec4, b: float32) {.inline.} = - a.x /= b - a.y /= b - a.z /= b - a.w /= b - -proc zero*(a: var Vec4) {.inline.} = - a.x = 0 - a.y = 0 - a.z = 0 - a.w = 0 - -proc hash*(a: Vec4): Hash {.inline.} = - hash((a.x, a.y, a.z, a.w)) - -proc floor*(a: Vec4): Vec4 {.inline.} = - vec4(floor(a.x), floor(a.y), floor(a.z), floor(a.w)) - -proc round*(a: Vec4): Vec4 {.inline.} = - vec4(round(a.x), round(a.y), round(a.z), round(a.w)) - -proc ceil*(a: Vec4): Vec4 {.inline.} = - vec4(ceil(a.x), ceil(a.y), ceil(a.z), ceil(a.w)) - -proc `[]`*(a: Vec4, i: int): float32 = - case i - of 0: a.x - of 1: a.y - of 2: a.z - of 3: a.w - else: raise newException(IndexDefect, "Index not in 0 .. 3") - -proc `[]=`*(a: var Vec4, i: int, b: float32) = - case i - of 0: a.x = b - of 1: a.y = b - of 2: a.z = b - of 3: a.w = b - else: raise newException(IndexDefect, "Index not in 0 .. 3") - -proc lerp*(a: Vec4, b: Vec4, v: float32): Vec4 {.inline.} = +proc lerp*[T: SomeFloat](a, b: GVec234[T], v: T): type(a) = a * (1.0 - v) + b * v -proc xyz*(a: Vec4): Vec3 {.inline.} = - vec3(a.x, a.y, a.z) +proc dot*[T](a, b: GVec2[T]): T = + a.x * b.x + a.y * b.y -proc `$`*(a: Vec4): string = - &"({a.x:.8f}, {a.y:.8f}, {a.z:.8f}, {a.w:.8f})" +proc dot*[T](a, b: GVec3[T]): T = + a.x * b.x + a.y * b.y + a.z * b.z -proc vec3*(a: Vec2, z = 0.0): Vec3 {.inline.} = - vec3(a.x, a.y, z) +proc dot*[T](a, b: GVec4[T]): T = + a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w -proc vec4*(a: Vec3, w = 0.0): Vec4 {.inline.} = - vec4(a.x, a.y, a.z, w) - -proc vec4*(a: Vec2, z = 0.0, w = 0.0): Vec4 {.inline.} = - vec4(a.x, a.y, z, w) - -type Mat3* = array[9, float32] ## 3x3 Matrix - -proc `[]`*(a: Mat3, i, j: int): float32 {.inline.} = a[i * 3 + j] -proc `[]=`*(a: var Mat3, i, j: int, v: float32) {.inline.} = a[i * 3 + j] = v - -proc mat3*(a, b, c, d, e, f, g, h, i: float32): Mat3 {.inline.} = +proc cross*[T](a, b: GVec3[T]): GVec3[T] = [ - a, b, c, - d, e, f, - g, h, i + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x ] -proc mat3*(a: Mat3): Mat3 {.inline.} = - a +proc dist*[T](at, to: GVec234[T]): T = + (at - to).length -proc `~=`*(a: Mat3, b: Mat3): bool = - for i in 0 .. 8: - if not(a[i] ~= b[i]): - return false - true +proc distSq*[T](at, to: GVec234[T]): T = + (at - to).lengthSq -proc identity*(a: var Mat3) {.inline.} = - a = [ - 1.float32, 0, 0, - 0, 1, 0, - 0, 0, 1 - ] +proc dir*[T](at, to: GVec234[T]): type(to) = + (at - to).normalize -proc mat3*(): Mat3 {.inline.} = - result.identity() - -proc transpose*(a: Mat3): Mat3 {.inline.} = +proc dir*[T](angle: T): GVec2[T] = [ - a[0, 0], a[1, 0], a[2, 0], - a[0, 1], a[1, 1], a[2, 1], - a[0, 2], a[1, 2], a[2, 2] + cos(angle), + sin(angle), ] -proc `$`*(a: Mat3): string = - &"""[{a[0]:.7f}, {a[1]:.7f}, {a[2]:.7f}, -{a[3]:.7f}, {a[4]:.7f}, {a[5]:.7f}, -{a[6]:.7f}, {a[7]:.7f}, {a[8]:.7f}]""" +type + GMat2*[T] = array[2, GVec2[T]] + GMat3*[T] = array[3, GVec3[T]] + GMat4*[T] = array[4, GVec4[T]] -proc `*`*(a, b: Mat3): Mat3 = + Mat2* = GMat2[float32] + Mat3* = GMat3[float32] + Mat4* = GMat4[float32] + + DMat2* = GMat2[float64] + DMat3* = GMat3[float64] + DMat4* = GMat4[float64] + + GMat234[T] = GMat2[T] | GMat3[T] | GMat4[T] + GMat34[T] = GMat3[T] | GMat4[T] + +template genMatConstructor(lower, upper, T: untyped) = + proc `lower 2`*(a, b, c, d: T): `upper 2` = + [[a, b], [c, d]] + proc `lower 3`*(a, b, c, d, e, f, g, h, i: T): `upper 3` = + [[T(a), b, c], [d, e, f], [g, h, i]] + proc `lower 4`*( + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p: T + ): `upper 4` = + [[T(a), b, c, d], [e, f, g, h], [i, j, k, l], [m, n, o, p]] + + proc `lower 2`*(a, b: GVec2[T]): `upper 2` = [a, b] + proc `lower 3`*(a, b, c: GVec3[T]): `upper 3` = [a, b, c] + proc `lower 4`*(a, b, c, d: GVec4[T]): `upper 4` = [a, b, c, d] + + proc `lower 2`*(m: GMat3[T]): `upper 2` = [m[0].xy, m[1].xy] + proc `lower 3`*(m: GMat4[T]): `upper 3` = [m[0].xyz, m[1].xyz, [T(0), 0, 1]] + + proc `lower 3`*(m: GMat2[T]): `upper 3` = + [ + [m[0][0], m[0][1], 0], + [m[1][0], m[1][1], 0], + [T(0), 0, 1] + ] + + proc `lower 4`*(m: GMat3[T]): `upper 4` = + [ + [m[0][0], m[0][1], m[0][2], 0], + [m[1][0], m[1][1], m[1][2], 0], + [T(0), 0, 1, 0], + [m[2][0], m[2][1], m[2][2], 1] + ] + + proc `lower 2`*(): `upper 2` = + [ + [T(1), 0], + [T(0), 1] + ] + proc `lower 3`*(): `upper 3` = + [ + [T(1), 0, 0], + [T(0), 1, 0], + [T(0), 0, 1] + ] + proc `lower 4`*(): `upper 4` = + [ + [T(1), 0, 0, 0], + [T(0), 1, 0, 0], + [T(0), 0, 1, 0], + [T(0), 0, 0, 1] + ] + +genMatConstructor(mat, Mat, float32) +genMatConstructor(dmat, DMat, float64) + +proc `[]`*[T](a: GMat234[T], i, j: int): T = a[i][j] +proc `[]=`*[T](a: var GMat234[T], i, j: int, v: T) = a[i][j] = v + +proc `~=`*[T](a, b: GMat2[T]): bool = + a[0] ~= b[0] and a[1] ~= b[1] + +proc `~=`*[T](a, b: GMat3[T]): bool = + a[0] ~= b[0] and a[1] ~= b[1] and a[2] ~= b[2] + +proc `~=`*[T](a, b: GMat4[T]): bool = + a[0] ~= b[0] and a[1] ~= b[1] and a[2] ~= b[2] and a[3] ~= b[3] + +proc `*`*[T](a, b: GMat3[T]): GMat3[T] = 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] + result[1, 0] = b[1, 0] * a[0, 0] + b[1, 1] * a[1, 0] + b[1, 2] * a[2, 0] result[1, 1] = b[1, 0] * a[0, 1] + b[1, 1] * a[1, 1] + b[1, 2] * a[2, 1] result[1, 2] = b[1, 0] * a[0, 2] + b[1, 1] * a[1, 2] + b[1, 2] * a[2, 2] + result[2, 0] = b[2, 0] * a[0, 0] + b[2, 1] * a[1, 0] + b[2, 2] * a[2, 0] 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] -proc scale*(a: Mat3, v: Vec2): Mat3 {.inline.} = +proc `*`*[T](a: GMat3[T], b: GVec2[T]): GVec2[T] = [ - v.x * a[0], v.x * a[1], v.x * a[2], - v.y * a[3], v.y * a[4], v.y * a[5], - a[6], a[7], a[8] + a[0, 0] * b.x + a[1, 0] * b.y + a[2, 0], + a[0, 1] * b.x + a[1, 1] * b.y + a[2, 1] ] -proc scale*(a: Mat3, v: Vec3): Mat3 {.inline.} = - [ - v.x * a[0], v.x * a[1], v.x * a[2], - v.y * a[3], v.y * a[4], v.y * a[5], - v.z * a[6], v.z * a[7], v.z * a[8] - ] - -proc translate*(v: Vec2): Mat3 {.inline.} = - [ - 1.float32, 0, 0, - 0, 1, 0, - v.x, v.y, 1 - ] - -proc scale*(v: Vec2): Mat3 {.inline.} = - [ - v.x, 0, 0, - 0, v.y, 0, - 0, 0, 1 - ] - -proc rotationMat3*(angle: float32): Mat3 {.inline.} = - # Create a matrix from an angle. +proc `*`*[T](a, b: GMat4[T]): GMat4[T] = let - sin = sin(angle) - cos = cos(angle) - result = [ - cos, -sin, 0, - sin, cos, 0, - 0, 0, 1 - ] + a00 = a[0, 0] + a01 = a[0, 1] + a02 = a[0, 2] + a03 = a[0, 3] + a10 = a[1, 0] + a11 = a[1, 1] + a12 = a[1, 2] + a13 = a[1, 3] + a20 = a[2, 0] + a21 = a[2, 1] + a22 = a[2, 2] + a23 = a[2, 3] + a30 = a[3, 0] + a31 = a[3, 1] + a32 = a[3, 2] + a33 = a[3, 3] -proc rotate*(a: Mat3, angle: float32): Mat3 {.inline.} = - # Rotates a matrix by an angle. - a * rotationMat3(angle) - -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] - -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 - -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]) + - a[0, 2] * (a[1, 0] * a[2, 1] - a[1, 1] * a[2, 0]) - ) - invDet = 1 / determinant + b00 = b[0, 0] + b01 = b[0, 1] + b02 = b[0, 2] + b03 = b[0, 3] + b10 = b[1, 0] + b11 = b[1, 1] + b12 = b[1, 2] + b13 = b[1, 3] + b20 = b[2, 0] + b21 = b[2, 1] + b22 = b[2, 2] + b23 = b[2, 3] + b30 = b[3, 0] + b31 = b[3, 1] + b32 = b[3, 2] + b33 = b[3, 3] - result[0, 0] = (a[1, 1] * a[2, 2] - a[2, 1] * a[1, 2]) * invDet - result[0, 1] = -(a[0, 1] * a[2, 2] - a[0, 2] * a[2, 1]) * invDet - result[0, 2] = (a[0, 1] * a[1, 2] - a[0, 2] * a[1, 1]) * invDet + result[0, 0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30 + result[0, 1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31 + result[0, 2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32 + result[0, 3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33 - result[1, 0] = -(a[1, 0] * a[2, 2] - a[1, 2] * a[2, 0]) * invDet - result[1, 1] = (a[0, 0] * a[2, 2] - a[0, 2] * a[2, 0]) * invDet - result[1, 2] = -(a[0, 0] * a[1, 2] - a[1, 0] * a[0, 2]) * invDet + result[1, 0] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30 + result[1, 1] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31 + result[1, 2] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32 + result[1, 3] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33 - result[2, 0] = (a[1, 0] * a[2, 1] - a[2, 0] * a[1, 1]) * invDet - result[2, 1] = -(a[0, 0] * a[2, 1] - a[2, 0] * a[0, 1]) * invDet - result[2, 2] = (a[0, 0] * a[1, 1] - a[1, 0] * a[0, 1]) * invDet + result[2, 0] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30 + result[2, 1] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31 + result[2, 2] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32 + result[2, 3] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33 -proc pos*(a: Mat3): Vec2 {.inline.} = - result.x = a[2, 0] - result.y = a[2, 1] + result[3, 0] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30 + result[3, 1] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31 + result[3, 2] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32 + result[3, 3] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33 -proc `pos=`*(a: var Mat3, b: Vec2) {.inline.} = - a[2, 0] = b.x - a[2, 1] = b.y - -proc hash*(a: Mat3): Hash {.inline.} = - hash(( - a[0], - a[1], - a[2], - a[3], - a[4], - a[5], - a[6], - a[7], - a[8] - )) - -type Mat4* = array[16, float32] ## 4x4 Matrix - OpenGL row order - -proc `[]`*(a: Mat4, i, j: int): float32 = a[i * 4 + j] -proc `[]=`*(a: var Mat4, i, j: int, v: float32) = a[i * 4 + j] = v - -proc mat4*( - v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15: float32 -): Mat4 {.inline.} = +proc `*`*[T](a: GMat4[T], b: GVec3[T]): GVec3[T] = [ - v0, v1, v2, v3, - v4, v5, v6, v7, - v8, v9, v10, v11, - v12, v13, v14, v15 + a[0, 0] * b.x + a[1, 0] * b.y + a[2, 0] * b.z + a[3, 0], + a[0, 1] * b.x + a[1, 1] * b.y + a[2, 1] * b.z + a[3, 1], + a[0, 2] * b.x + a[1, 2] * b.y + a[2, 2] * b.z + a[3, 2] ] -proc mat4*(a: Mat4): Mat4 {.inline.} = - a - -proc identity*(): Mat4 {.inline.} = +proc transpose*[T](a: GMat3[T]): GMat3[T] = [ - 1.float32, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + [a[0, 0], a[1, 0], a[2, 0]], + [a[0, 1], a[1, 1], a[2, 1]], + [a[0, 2], a[1, 2], a[2, 2]] ] -proc mat4*(): Mat4 {.inline.} = - identity() - -proc `~=`*(a: Mat4, b: Mat4): bool = - for i in 0 .. 15: - if not(a[i] ~= b[i]): - return false - true - -proc transpose*(a: Mat4): Mat4 {.inline.} = +proc transpose*[T](a: GMat4[T]): GMat4[T] = [ - a[0, 0], a[1, 0], a[2, 0], a[3, 0], - a[0, 1], a[1, 1], a[2, 1], a[3, 1], - a[0, 2], a[1, 2], a[2, 2], a[3, 2], - a[0, 3], a[1, 3], a[2, 3], a[3, 3] + [a[0, 0], a[1, 0], a[2, 0], a[3, 0]], + [a[0, 1], a[1, 1], a[2, 1], a[3, 1]], + [a[0, 2], a[1, 2], a[2, 2], a[3, 2]], + [a[0, 3], a[1, 3], a[2, 3], a[3, 3]] ] -proc determinant*(a: Mat4): float32 = +proc determinant*[T](a: GMat4[T]): T = let - a00 = a[0] - a01 = a[1] - a02 = a[2] - a03 = a[3] - a10 = a[4] - a11 = a[5] - a12 = a[6] - a13 = a[7] - a20 = a[8] - a21 = a[9] - a22 = a[10] - a23 = a[11] - a30 = a[12] - a31 = a[13] - a32 = a[14] - a33 = a[15] - + a00 = a[0, 0] + a01 = a[0, 1] + a02 = a[0, 2] + a03 = a[0, 3] + a10 = a[1, 0] + a11 = a[1, 1] + a12 = a[1, 2] + a13 = a[1, 3] + a20 = a[2, 0] + a21 = a[2, 1] + a22 = a[2, 2] + a23 = a[2, 3] + a30 = a[3, 0] + a31 = a[3, 1] + a32 = a[3, 2] + a33 = a[3, 3] ( a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + @@ -758,24 +616,45 @@ 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 = +proc inverse*[T](a: GMat3[T]): GMat3[T] = let - a00 = a[0] - a01 = a[1] - a02 = a[2] - a03 = a[3] - a10 = a[4] - a11 = a[5] - a12 = a[6] - a13 = a[7] - a20 = a[8] - a21 = a[9] - a22 = a[10] - a23 = a[11] - a30 = a[12] - a31 = a[13] - a32 = a[14] - a33 = a[15] + 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]) + + a[0, 2] * (a[1, 0] * a[2, 1] - a[1, 1] * a[2, 0]) + ) + invDet = 1 / determinant + + result[0, 0] = +(a[1, 1] * a[2, 2] - a[2, 1] * a[1, 2]) * invDet + result[0, 1] = -(a[0, 1] * a[2, 2] - a[0, 2] * a[2, 1]) * invDet + result[0, 2] = +(a[0, 1] * a[1, 2] - a[0, 2] * a[1, 1]) * invDet + + result[1, 0] = -(a[1, 0] * a[2, 2] - a[1, 2] * a[2, 0]) * invDet + result[1, 1] = +(a[0, 0] * a[2, 2] - a[0, 2] * a[2, 0]) * invDet + result[1, 2] = -(a[0, 0] * a[1, 2] - a[1, 0] * a[0, 2]) * invDet + + result[2, 0] = +(a[1, 0] * a[2, 1] - a[2, 0] * a[1, 1]) * invDet + result[2, 1] = -(a[0, 0] * a[2, 1] - a[2, 0] * a[0, 1]) * invDet + result[2, 2] = +(a[0, 0] * a[1, 1] - a[1, 0] * a[0, 1]) * invDet + +proc inverse*[T](a: GMat4[T]): GMat4[T] = + let + a00 = a[0, 0] + a01 = a[0, 1] + a02 = a[0, 2] + a03 = a[0, 3] + a10 = a[1, 0] + a11 = a[1, 1] + a12 = a[1, 2] + a13 = a[1, 3] + a20 = a[2, 0] + a21 = a[2, 1] + a22 = a[2, 2] + a23 = a[2, 3] + a30 = a[3, 0] + a31 = a[3, 1] + a32 = a[3, 2] + a33 = a[3, 3] let b00 = a00 * a11 - a01 * a10 @@ -792,157 +671,69 @@ proc inverse*(a: Mat4): Mat4 = b11 = a22 * a33 - a23 * a32 # Calculate the inverse determinant. - let invDet = 1.0/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06) + let invDet = T(1.0)/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06) - result[00] = (+a11 * b11 - a12 * b10 + a13 * b09) * invDet - result[01] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet - result[02] = (+a31 * b05 - a32 * b04 + a33 * b03) * invDet - result[03] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet - result[04] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet - result[05] = (+a00 * b11 - a02 * b08 + a03 * b07) * invDet - result[06] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet - result[07] = (+a20 * b05 - a22 * b02 + a23 * b01) * invDet - result[08] = (+a10 * b10 - a11 * b08 + a13 * b06) * invDet - result[09] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet - result[10] = (+a30 * b04 - a31 * b02 + a33 * b00) * invDet - result[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet - result[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet - result[13] = (+a00 * b09 - a01 * b07 + a02 * b06) * invDet - result[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet - result[15] = (+a20 * b03 - a21 * b01 + a22 * b00) * invDet + result[0, 0] = (+a11 * b11 - a12 * b10 + a13 * b09) * invDet + result[0, 1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet + result[0, 2] = (+a31 * b05 - a32 * b04 + a33 * b03) * invDet + result[0, 3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet -proc `*`*(a, b: Mat4): Mat4 = + result[1, 0] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet + result[1, 1] = (+a00 * b11 - a02 * b08 + a03 * b07) * invDet + result[1, 2] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet + result[1, 3] = (+a20 * b05 - a22 * b02 + a23 * b01) * invDet + + result[2, 0] = (+a10 * b10 - a11 * b08 + a13 * b06) * invDet + result[2, 1] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet + result[2, 2] = (+a30 * b04 - a31 * b02 + a33 * b00) * invDet + result[2, 3] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet + + result[3, 0] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet + result[3, 1] = (+a00 * b09 - a01 * b07 + a02 * b06) * invDet + result[3, 2] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet + result[3, 3] = (+a20 * b03 - a21 * b01 + a22 * b00) * invDet + +proc scale*[T](v: GVec2[T]): GMat3[T] = + [ + [v.x, 0, 0], + [T(0), v.y, 0], + [T(0), 0, 1] + ] + +proc scale*[T](v: GVec3[T]): GMat4[T] = + [ + [v.x, 0, 0, 0], + [T(0), v.y, 0, 0], + [T(0), 0, v.z, 0], + [T(0), 0, 0, 1] + ] + +proc translate*[T](v: GVec2[T]): GMat3[T] = + [ + [T(1), 0, 0], + [T(0), 1, 0], + [v.x, v.y, 1] + ] + +proc translate*[T](v: GVec3[T]): GMat4[T] = + [ + [T(1), 0, 0, 0], + [T(0), 1, 0, 0], + [T(0), 0, 1, 0], + [v.x, v.y, v.z, 1] + ] + +proc rotate*[T](angle: T): GMat3[T] = let - a00 = a[0] - a01 = a[1] - a02 = a[2] - a03 = a[3] - a10 = a[4] - a11 = a[5] - a12 = a[6] - a13 = a[7] - a20 = a[8] - a21 = a[9] - a22 = a[10] - a23 = a[11] - a30 = a[12] - a31 = a[13] - a32 = a[14] - a33 = a[15] + sin = sin(angle) + cos = cos(angle) + [ + [cos, -sin, 0], + [sin, cos, 0], + [T(0), 0, 1] + ] - let - b00 = b[0] - b01 = b[1] - b02 = b[2] - b03 = b[3] - b10 = b[4] - b11 = b[5] - b12 = b[6] - b13 = b[7] - b20 = b[8] - b21 = b[9] - b22 = b[10] - b23 = b[11] - b30 = b[12] - b31 = b[13] - b32 = b[14] - b33 = b[15] - - result[00] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30 - result[01] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31 - result[02] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32 - result[03] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33 - result[04] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30 - result[05] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31 - result[06] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32 - result[07] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33 - result[08] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30 - result[09] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31 - result[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32 - result[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33 - result[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30 - result[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31 - 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 `*`*(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 - -proc right*(a: Mat4): Vec3 {.inline.} = - result.x = a[0] - result.y = a[1] - result.z = a[2] - -proc `right=`*(a: var Mat4, b: Vec3) {.inline.} = - a[0] = b.x - a[1] = b.y - a[2] = b.z - -proc up*(a: Mat4): Vec3 {.inline.} = - result.x = a[4] - result.y = a[5] - result.z = a[6] - -proc `up=`*(a: var Mat4, b: Vec3) {.inline.} = - a[4] = b.x - a[5] = b.y - a[6] = b.z - -proc forward*(a: Mat4): Vec3 {.inline.} = - result.x = a[8] - result.y = a[9] - result.z = a[10] - -proc `forward=`*(a: var Mat4, b: Vec3) {.inline.} = - a[8] = b.x - a[9] = b.y - a[10] = b.z - -proc pos*(a: Mat4): Vec3 {.inline.} = - result.x = a[12] - result.y = a[13] - result.z = a[14] - -proc `pos=`*(a: var Mat4, b: Vec3) {.inline.} = - a[12] = b.x - a[13] = b.y - a[14] = b.z - -proc rotationOnly*(a: Mat4): Mat4 {.inline.} = - result = a - result.pos = vec3(0, 0, 0) - -proc dist*(a, b: Mat4): float32 {.inline.} = - let - x = a[12] - b[12] - y = a[13] - b[13] - z = a[14] - b[14] - sqrt(x * x + y * y + z * z) - -proc translate*(v: Vec3): Mat4 = - result[0] = 1 - result[5] = 1 - result[10] = 1 - result[15] = 1 - result[12] = v.x - 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 hrp*(m: Mat4): Vec3 = +proc hrp*[T](m: GMat4[T]): GVec3[T] = var heading, pitch, roll: float32 if m[1] > 0.998: # singularity at north pole heading = arctan2(m[2], m[10]) @@ -956,61 +747,67 @@ proc hrp*(m: Mat4): Vec3 = heading = arctan2(-m[8], m[0]) pitch = arctan2(-m[6], m[5]) roll = arcsin(m[4]) - result.x = heading - result.y = pitch - result.z = roll + [heading, pitch, roll] -proc frustum*(left, right, bottom, top, near, far: float32): Mat4 = +proc frustum*[T](left, right, bottom, top, near, far: T): GMat4[T] = let rl = (right - left) tb = (top - bottom) fn = (far - near) - result[0] = (near * 2) / rl - result[1] = 0 - result[2] = 0 - result[3] = 0 - result[4] = 0 - result[5] = (near * 2) / tb - result[6] = 0 - result[7] = 0 - result[8] = (right + left) / rl - result[9] = (top + bottom) / tb - result[10] = -(far + near) / fn - result[11] = -1 - result[12] = 0 - result[13] = 0 - result[14] = -(far * near * 2) / fn - result[15] = 0 -proc perspective*(fovy, aspect, near, far: float32): Mat4 = + result[0, 0] = (near * 2) / rl + result[0, 1] = 0 + result[0, 2] = 0 + result[0, 3] = 0 + + result[1, 0] = 0 + result[1, 1] = (near * 2) / tb + result[1, 2] = 0 + result[1, 3] = 0 + + result[2, 0] = (right + left) / rl + result[2, 1] = (top + bottom) / tb + result[2, 2] = -(far + near) / fn + result[2, 3] = -1 + + result[3, 0] = 0 + result[3, 1] = 0 + result[3, 2] = -(far * near * 2) / fn + result[3, 3] = 0 + +proc perspective*[T](fovy, aspect, near, far: T): GMat4[T] = let top = near * tan(fovy * PI / 360.0) right = top * aspect frustum(-right, right, -top, top, near, far) -proc ortho*(left, right, bottom, top, near, far: float32): Mat4 = +proc ortho*[T](left, right, bottom, top, near, far: T): GMat4[T] = let rl = (right - left) tb = (top - bottom) fn = (far - near) - result[0] = 2 / rl - result[1] = 0 - result[2] = 0 - result[3] = 0 - result[4] = 0 - result[5] = 2 / tb - result[6] = 0 - result[7] = 0 - result[8] = 0 - result[9] = 0 - result[10] = -2 / fn - result[11] = 0 - result[12] = -(left + right) / rl - result[13] = -(top + bottom) / tb - result[14] = -(far + near) / fn - result[15] = 1 -proc lookAt*(eye, center, up: Vec3): Mat4 = + result[0, 0] = 2 / rl + result[0, 1] = 0 + result[0, 2] = 0 + result[0, 3] = 0 + + result[1, 0] = 0 + result[1, 1] = 2 / tb + result[1, 2] = 0 + result[1, 3] = 0 + + result[2, 0] = 0 + result[2, 1] = 0 + result[2, 2] = -2 / fn + result[2, 3] = 0 + + result[3, 0] = -(left + right) / rl + result[3, 1] = -(top + bottom) / tb + result[3, 2] = -(far + near) / fn + result[3, 3] = 1 + +proc lookAt*[T](eye, center: GVec3[T], up = [T(0), 0, 1]): GMat4[T] = let eyex = eye[0] eyey = eye[1] @@ -1023,7 +820,7 @@ proc lookAt*(eye, center, up: Vec3): Mat4 = centerz = center[2] if eyex == centerx and eyey == centery and eyez == centerz: - return identity() + return mat4[T]() var # vec3.direction(eye, center, z) @@ -1070,424 +867,204 @@ proc lookAt*(eye, center, up: Vec3): Mat4 = y1 *= len y2 *= len - result[0] = x0 - result[1] = y0 - result[2] = z0 - result[3] = 0 - result[4] = x1 - result[5] = y1 - result[6] = z1 - result[7] = 0 - result[8] = x2 - result[9] = y2 - result[10] = z2 - result[11] = 0 - result[12] = -(x0 * eyex + x1 * eyey + x2 * eyez) - result[13] = -(y0 * eyex + y1 * eyey + y2 * eyez) - result[14] = -(z0 * eyex + z1 * eyey + z2 * eyez) - result[15] = 1 - -proc mat3*(m: Mat4): Mat3 = - ## Gets rotation and translation, ignoring z coordinates. - result[0, 0] = m[0, 0] - result[0, 1] = m[0, 1] - result[0, 2] = 0 - result[1, 0] = m[1, 0] - result[1, 1] = m[1, 1] - result[1, 2] = 0 - result[2, 0] = m[3, 0] - result[2, 1] = m[3, 1] - result[2, 2] = 0 - -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] - result[0, 2] = m[0, 2] - result[1, 0] = m[1, 0] - result[1, 1] = m[1, 1] - result[1, 2] = m[1, 2] - result[2, 0] = m[2, 0] - result[2, 1] = m[2, 1] - result[2, 2] = m[2, 2] - -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] - result[0, 2] = 0 + result[0, 0] = x0 + result[0, 1] = y0 + result[0, 2] = z0 result[0, 3] = 0 - result[1, 0] = m[1, 0] - result[1, 1] = m[1, 1] - result[1, 2] = 0 + result[1, 0] = x1 + result[1, 1] = y1 + result[1, 2] = z1 result[1, 3] = 0 - result[2, 0] = 0 - result[2, 1] = 0 - result[2, 2] = 1 + result[2, 0] = x2 + result[2, 1] = y2 + result[2, 2] = z2 result[2, 3] = 0 - result[3, 0] = m[2, 0] - result[3, 1] = m[2, 1] - result[3, 2] = 0 + result[3, 0] = -(x0 * eyex + x1 * eyey + x2 * eyez) + result[3, 1] = -(y0 * eyex + y1 * eyey + y2 * eyez) + result[3, 2] = -(z0 * eyex + z1 * eyey + z2 * eyez) result[3, 3] = 1 -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] - result[0, 2] = m[0, 2] - result[1, 0] = m[1, 0] - result[1, 1] = m[1, 1] - result[1, 2] = m[1, 2] - result[2, 0] = m[2, 0] - result[2, 1] = m[2, 1] - result[2, 2] = m[2, 2] +proc angle*[T](a: GVec2[T]): T = + ## Angle of a Vec2. + arctan2(a.y, a.x) -proc hash*(a: Mat4): Hash {.inline.} = - hash(( - a[0], - a[1], - a[2], - a[3], - a[4], - a[5], - a[6], - a[7], - a[8], - a[9], - a[10], - a[11], - a[12], - a[13], - a[14], - a[15], - )) +proc angle*[T](a, b: GVec2[T]): T = + ## Angle between 2 Vec2. + fixAngle(arctan2(a.y - b.y, a.x - b.x)) -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}, -{a[12]:.5f}, {a[13]:.5f}, {a[14]:.5f}, {a[15]:.5f}]""" +proc angle*[T](a, b: GVec3[T]): T = + ## Angle between 2 Vec3. + var dot = dot(a, b) + dot = dot / (a.length * b.length) + arccos(dot) -type Quat* = object - x*: float32 - y*: float32 - z*: float32 - w*: float32 +type + Quat* = GVec4[float32] + DQuat* = GVec4[float64] -proc quat*(x, y, z, w: float32): Quat {.inline.} = - result.x = x - result.y = y - result.z = z - result.w = w +template genQuatConstructor(lower, upper, typ: untyped) = -proc `~=`*(a, b: Quat): bool = - a.x ~= b.x and a.y ~= b.y and a.z ~= b.z and a.w ~= b.w + proc `lower`*(): `upper` = gvec4[typ](0, 0, 0, 1) + proc `lower`*(x, y, z, w: typ): `upper` = gvec4[typ](x, y, z, w) + proc `lower`*(x: typ): `upper` = gvec4[typ](x, x, x, x) + proc `lower`*[T](x: GVec4[T]): `upper` = + gvec4[typ](typ(x[0]), typ(x[1]), typ(x[2]), typ(x[3])) -proc conjugate*(q: Quat): Quat {.inline.} = - result.w = +q.w - result.x = -q.x - result.y = -q.y - result.z = -q.z +genQuatConstructor(quat, Quat, float32) +genQuatConstructor(dquat, DQuat, float64) -proc length*(q: Quat): float32 {.inline.} = - sqrt( - q.w * q.w + - q.x * q.x + - q.y * q.y + - q.z * q.z - ) - -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 - -proc xyz*(q: Quat): Vec3 {.inline.} = - result.x = q.x - result.y = q.y - result.z = q.z - -proc `xyz=`*(q: var Quat, v: Vec3) {.inline.} = - q.x = v.x - q.y = v.y - q.z = v.z - -proc `-`*(a: var Quat): Quat {.inline.} = - result.x = -a.x - result.y = -a.y - result.z = -a.z - result.w = -a.w - -proc `+`*(a: Quat, b: Quat): Quat {.inline.} = - result.x = a.x + b.x - result.y = a.y + b.y - result.z = a.z + b.z - result.w = a.w + b.w - -proc `*`*(a, b: Quat): Quat = - ## Multiply the quaternion by a quaternion. - #[ - var q = quat(0,0,0,0) - q.w = dot(a.xyz, b.xyz) - var va = cross(a.xyz, b.xyz) - var vb = a.xyz * b.w - var vc = b.xyz * a.w - va = va + vb - q.xyz = va + vc - return q.normalize() - ]# - - result.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y - result.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z - 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 - -proc `*`*(q: Quat, v: float32): Quat {.inline.} = - ## 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 - -proc `/`*(q: Quat, v: float32): Quat {.inline.} = - ## Divide 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 - -proc `*=`*(a: var Quat, b: float32) {.inline.} = - a = a * b - -proc `/=`*(a: var Quat, b: float32) {.inline.} = - a = a / b - -proc `*`*(q: Quat, v: Vec3): Vec3 = - ## Multiply the quaternion by a vector. - let - x = v.x - y = v.y - z = v.z - - qx = q.x - qy = q.y - qz = q.z - qw = q.w - - ix = +qw * x + qy * z - qz * y - iy = +qw * y + qz * x - qx * z - iz = +qw * z + qx * y - qy * x - iw = -qx * x - qy * y - qz * z - - result.x = ix * qw + iw * -qx + iy * -qz - iz * -qy - result.y = iy * qw + iw * -qy + iz * -qx - ix * -qz - result.z = iz * qw + iw * -qz + ix * -qy - iy * -qx - -proc `[]`*(a: var Quat, i: int, b: float32) = - case i - of 0: a.x - of 1: a.y - of 2: a.z - of 3: a.w - else: raise newException(IndexDefect, "Index not in 0 .. 3") - -proc `[]=`*(a: var Quat, i: int, b: float32) = - case i - of 0: a.x = b - of 1: a.y = b - of 2: a.z = b - of 3: a.w = b - else: raise newException(IndexDefect, "Index not in 0 .. 3") - -proc mat3*(q: Quat): Mat3 = - let - xx = q.x * q.x - xy = q.x * q.y - xz = q.x * q.z - xw = q.x * q.w - - yy = q.y * q.y - yz = q.y * q.z - yw = q.y * q.w - - zz = q.z * q.z - zw = q.z * q.w - - result[0] = 1 - 2 * (yy + zz) - result[1] = 0 + 2 * (xy - zw) - result[2] = 0 + 2 * (xz + yw) - result[3] = 0 + 2 * (xy + zw) - result[4] = 1 - 2 * (xx + zz) - result[5] = 0 + 2 * (yz - xw) - result[6] = 0 + 2 * (xz - yw) - result[7] = 0 + 2 * (yz + xw) - result[8] = 1 - 2 * (xx + yy) - -proc mat4*(q: Quat): Mat4 = - let - xx = q.x * q.x - xy = q.x * q.y - xz = q.x * q.z - xw = q.x * q.w - - yy = q.y * q.y - yz = q.y * q.z - yw = q.y * q.w - - zz = q.z * q.z - zw = q.z * q.w - - result[00] = 1 - 2 * (yy + zz) - result[01] = 0 + 2 * (xy - zw) - result[02] = 0 + 2 * (xz + yw) - result[04] = 0 + 2 * (xy + zw) - result[05] = 1 - 2 * (xx + zz) - result[06] = 0 + 2 * (yz - xw) - result[08] = 0 + 2 * (xz - yw) - result[09] = 0 + 2 * (yz + xw) - result[10] = 1 - 2 * (xx + yy) - - result[3] = 0 - result[7] = 0 - result[11] = 0 - result[12] = 0 - result[13] = 0 - result[14] = 0 - result[15] = 1.0 - -proc reciprocalSqrt*(x: float32): float32 {.inline.} = - 1.0 / sqrt(x) - -proc quat*(m: Mat4): Quat = - let - m00 = m[0] - m01 = m[4] - m02 = m[8] - - m10 = m[1] - m11 = m[5] - m12 = m[9] - - m20 = m[2] - m21 = m[6] - m22 = m[10] - - var - q: Quat - t: float32 - - if m22 < 0: - if m00 > m11: - t = 1 + m00 - m11 - m22 - q = quat(t, m01 + m10, m20 + m02, m12 - m21) - else: - t = 1 - m00 + m11 - m22 - q = quat(m01 + m10, t, m12 + m21, m20 - m02) - else: - if m00 < - m11: - t = 1 - m00 - m11 + m22 - q = quat(m20 + m02, m12 + m21, t, m01 - m10) - else: - t = 1 + m00 + m11 + m22 - q = quat(m12 - m21, m20 - m02, m01 - m10, t) - q = q * (0.5 / sqrt(t)) - - assert abs(q.length - 1.0) < 0.001 - q - -proc fromAxisAngle*(axis: Vec3, angle: float32): Quat = +proc fromAxisAngle*[T](axis: GVec3[T], angle: T): GVec4[T] = let a = axis.normalize() s = sin(angle / 2) - result.x = a.x * s - result.y = a.y * s - result.z = a.z * s - result.w = cos(angle / 2) + [ + a.x * s, + a.y * s, + a.z * s, + cos(angle / 2) + ] -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) +proc toAxisAngle*[T](q: GVec4[T]): (GVec3[T], T) = + let cosAngle = q.w + let angle = arccos(cosAngle) * 2.0 + var + sinAngle = sqrt(1.0 - cosAngle * cosAngle) + axis: GVec4[T] if abs(sinAngle) < 0.0005: sinAngle = 1.0 - axis.x = q.x / sinAngle - axis.y = q.y / sinAngle - axis.z = q.z / sinAngle + axis.x = [ + q.x / sinAngle, + q.y / sinAngle, + q.z / sinAngle + ] + return (axis, angle) -proc quat*(heading, pitch, roll: float32): Quat = +proc orthogonal*[T](v: GVec3[T]): GVec3[T] = + let v = abs(v) + var other: type(v) = + if v.x < v.y: + if v.x < v.z: + [T(1), 0, 0] # X_AXIS + else: + [T(0), 0, 1] # Z_AXIS + elif v.y < v.z: + [T(0), 1, 0] # Y_AXIS + else: + [T(0), 0, 1] # Z_AXIS + return cross(v, other) + +proc fromTwoVectors*[T](a, b: GVec3[T]): GVec4[T] = + ## Return a quat that would take a and rotate it into b. + + # It is important that the inputs are of equal length when + # calculating the half-way vector. let - t0 = cos(heading * 0.5) - t1 = sin(heading * 0.5) - t2 = cos(roll * 0.5) - t3 = sin(roll * 0.5) - t4 = cos(pitch * 0.5) - t5 = sin(pitch * 0.5) - result.w = t0 * t2 * t4 + t1 * t3 * t5 - result.x = t0 * t3 * t4 - t1 * t2 * t5 - result.y = t0 * t2 * t5 + t1 * t3 * t4 - result.z = t1 * t2 * t4 - t0 * t3 * t5 + u = b.normalize() + v = a.normalize() -proc quat*(hpr: Vec3): Quat {.inline.} = - quat(hpr.x, hpr.y, hpr.z) + # Unfortunately, we have to check for when u == -v, as u + v + # in this case will be (0, 0, 0), which cannot be normalized. + if (u == -v): + # 180 degree rotation around any orthogonal vector + let q = normalize(orthogonal(u)) + return [q.x, q.y, q.z, 0] -proc hrp*(q: Quat): Vec3 = - var ysqr = q.y * q.y - # roll - var t0 = +2.0 * (q.w * q.x + q.y * q.z) - var t1 = +1.0 - 2.0 * (q.x * q.x + ysqr) - result.z = arctan2(t0, t1) - # pitch - var t2 = +2.0 * (q.w * q.y - q.z * q.x) - if t2 > 1.0: - t2 = 1.0 - if t2 < -1.0: - t2 = -1.0 - result.y = arcsin(t2) - # heading - var t3 = +2.0 * (q.w * q.z + q.x * q.y) - var t4 = +1.0 - 2.0 * (ysqr + q.z * q.z) - result.x = arctan2(t3, t4) + let + half = normalize(u + v) + q = cross(u, half) + w = dot(u, half) + return [q.x, q.y, q.z, w] -proc dot*(a: Quat, b: Quat): float32 {.inline.} = - a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w +proc quat*[T](m: GMat4[T]): GVec4[T] = + let + m00 = m[0, 0] + m01 = m[1, 0] + m02 = m[2, 0] -proc nlerp*(a: Quat, b: Quat, v: float32): Quat = - if dot(a, b) < 0: - var c = a - (-c * (1.0 - v) + b * v).normalize() + m10 = m[0, 1] + m11 = m[1, 1] + m12 = m[2, 1] + + m20 = m[0, 2] + m21 = m[1, 2] + m22 = m[2, 2] + + var + q: GVec4[T] + t: T + + if m22 < 0: + if m00 > m11: + t = 1 + m00 - m11 - m22 + q = gvec4(t, m01 + m10, m20 + m02, m12 - m21) + else: + t = 1 - m00 + m11 - m22 + q = gvec4(m01 + m10, t, m12 + m21, m20 - m02) else: - (a * (1.0 - v) + b * v).normalize() + if m00 < - m11: + t = 1 - m00 - m11 + m22 + q = gvec4(m20 + m02, m12 + m21, t, m01 - m10) + else: + t = 1 + m00 + m11 + m22 + q = gvec4(m12 - m21, m20 - m02, m01 - m10, t) + q = q * (0.5 / sqrt(t)) -proc hash*(a: Quat): Hash {.inline.} = - hash((a.x, a.y, a.z, a.w)) + if abs(q.length - 1.0) > 0.001: + return [T(0), 0, 0, 1] -proc `$`*(a: Quat): string = - &"q({a.x:.8f}, {a.y:.8f}, {a.z:.8f}, {a.w:.8f})" + return q -proc rotate*(angle: float32, axis: Vec3): Mat4 {.inline.} = +proc mat4*[T](q: GVec4[T]): GMat4[T] = + let + xx = q.x * q.x + xy = q.x * q.y + xz = q.x * q.z + xw = q.x * q.w + + yy = q.y * q.y + yz = q.y * q.z + yw = q.y * q.w + + zz = q.z * q.z + zw = q.z * q.w + + result[0, 0] = 1 - 2 * (yy + zz) + result[0, 1] = 0 + 2 * (xy - zw) + result[0, 2] = 0 + 2 * (xz + yw) + result[0, 3] = 0 + + result[1, 0] = 0 + 2 * (xy + zw) + result[1, 1] = 1 - 2 * (xx + zz) + result[1, 2] = 0 + 2 * (yz - xw) + result[1, 3] = 0 + + result[2, 0] = 0 + 2 * (xz - yw) + result[2, 1] = 0 + 2 * (yz + xw) + result[2, 2] = 1 - 2 * (xx + yy) + result[2, 3] = 0 + + result[3, 0] = 0 + result[3, 1] = 0 + result[3, 2] = 0 + result[3, 3] = 1.0 + +proc rotate*[T](angle: T, axis: GVec3[T]): GMat4[T] = fromAxisAngle(axis, angle).mat4() -proc rotateX*(angle: float32): Mat4 {.inline.} = - rotate(angle, vec3(1, 0, 0)) +proc rotateX*[T](angle: T): GMat4[T] = + fromAxisAngle([T(1), 0, 0], angle).mat4() -proc rotateY*(angle: float32): Mat4 {.inline.} = - rotate(angle, vec3(0, 1, 0)) +proc rotateY*[T](angle: T): GMat4[T] = + fromAxisAngle([T(0), 1, 0], angle).mat4() -proc rotateZ*(angle: float32): Mat4 {.inline.} = - rotate(angle, vec3(0, 0, 1)) +proc rotateZ*[T](angle: T): GMat4[T] = + fromAxisAngle([T(0), 0, 1], angle).mat4() -proc scaleMat*(scale: Vec3): Mat4 {.inline.} = - result[0] = scale.x - result[5] = scale.y - result[10] = scale.z - result[15] = 1.0 - -proc scaleMat*(scale: float32): Mat4 {.inline.} = - scaleMat(vec3(scale, scale, scale)) +when defined(release): + {.pop.} +{.pop.} diff --git a/tests/bench.nim b/tests/bench.nim new file mode 100644 index 0000000..f9d3e51 --- /dev/null +++ b/tests/bench.nim @@ -0,0 +1,50 @@ +import benchy, vmath + +# TODO: I don't trust these simple benchmarks, make a better test. +# echo "new vmath" +# var v = vec3(1, 2, 3) +# timeIt "+": +# for i in 0 ..< 1_000_000: +# v += vec3(4, 5, 6) + +# timeIt "-": +# for i in 0 ..< 1_000_000: +# v -= vec3(4, 5, 6) + +# timeIt "*": +# for i in 0 ..< 1_000_000: +# v *= PI + +# timeIt "/": +# for i in 0 ..< 1_000_000: +# v /= PI + +# timeIt "int +": +# var v = ivec3(1, 2, 3) +# for i in 0 ..< 1_000_000: +# keep v + ivec3(4, 5, 6) + +# timeIt "int -": +# var v = ivec3(1, 2, 3) +# for i in 0 ..< 1_000_000: +# keep v - ivec3(4, 5, 6) + +timeIt "matrix mat4": + var m = mat4() + for i in 0 ..< 10_000: + m = m * + rotate(0.2.float32, vec3(1, 0, 0)) * + scale(vec3(0.3)) * + translate(vec3(1)) + keep m + +timeIt "matrix mat3": + var m = mat3() + for i in 0 ..< 10_000: + m = m * rotate(0.2.float32) * scale(vec2(0.3)) * translate(vec2(1)) + keep m + +timeIt "matrix quat": + var m = rotate(0.2.float32, vec3(1, 0, 0)) * scale(vec3(0.3)) * translate(vec3(1)) + for i in 0 ..< 100_000: + keep m.quat().mat4() diff --git a/tests/test.nim b/tests/test.nim index 9dc2465..b3c3aef 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -1,4 +1,4 @@ -import vmath, random +import random, vmath randomize(1234) @@ -12,22 +12,30 @@ block: doAssert not(0.001 ~= 0.002) doAssert not(0.0001 ~= 0.0002) doAssert not(0.00001 ~= 0.00002) + # Diff < epsilon. doAssert 0.000001 ~= 0.000002 + doAssert -0.000001 ~= -0.000002 doAssert vec2(1.0, 2.0) ~= vec2(1.0, 2.0) doAssert vec3(1.0, 2.0, 3.0) ~= vec3(1.0, 2.0, 3.0) doAssert vec4(1.0, 2.0, 3.0, 4.0) ~= vec4(1.0, 2.0, 3.0, 4.0) doAssert quat(1.0, 2.0, 3.0, 4.0) ~= quat(1.0, 2.0, 3.0, 4.0) + doAssert dvec2(1) ~= dvec2(1) + doAssert dvec4(1, 2, 3, 4).xy ~= dvec2(1, 2) + + when compiles(1 ~= 1): + doAssert false + block: # Test simple functions. doAssert between(0.5, 0, 1) doAssert not between(1.5, 0, 1) - doAssert sign(-1) == -1.0 - doAssert sign(0) == 1.0 - doAssert sign(1) == 1.0 + doAssert sign(-1.0) == -1.0 + doAssert sign(0.0) == 1.0 + doAssert sign(1.0) == 1.0 doAssert quantize(1.23456789, 1.0) ~= 1 doAssert quantize(1.23456789, 0.1) ~= 1.2 @@ -51,9 +59,9 @@ block: doAssert fixAngle(-3.1) ~= -3.1 doAssert fixAngle(-4.1) ~= 2.183185577392578 - doAssert angleBetween(0, 1.0) ~= 1.0 - doAssert angleBetween(0, PI) ~= PI - doAssert angleBetween(0, PI + 0.2) ~= (-PI + 0.2) + doAssert angleBetween(0.0, 1.0) ~= 1.0 + doAssert angleBetween(0.0, PI) ~= PI + doAssert angleBetween(0.0, PI + 0.2) ~= (-PI + 0.2) doAssert angleBetween(0.1, 0.2) ~= 0.1 doAssert angleBetween(0.1, 0.2 + PI*2) ~= 0.1 doAssert angleBetween(0.1, 0.2 - PI*2) ~= 0.1 @@ -65,7 +73,7 @@ block: doAssert angleBetween(0.2 + PI*2, 0.1) ~= -0.1 doAssert angleBetween(0.2 - PI*2, 0.1) ~= -0.1 - doAssert turnAngle(0, PI, 0.5) ~= 0.5 + doAssert turnAngle(0.0, PI, 0.5) ~= 0.5 doAssert turnAngle(0.5, PI, 3.5) ~= PI block: @@ -133,6 +141,214 @@ block: a /= n doAssert a ~= vec4(1.0, 2.0, 3.0, 4.0) +block: + # Test all type constructors compile + let + _ = bvec2(true, false) + _ = bvec3(true, false, true) + _ = bvec4(true, false, true, false) + + _ = ivec2(-1, 2) + _ = ivec3(-1, 2, 3) + _ = ivec4(-1, 2, 3, 4) + + _ = uvec2(1, 2) + _ = uvec3(1, 2, 3) + _ = uvec4(1, 2, 3, 4) + + _ = vec2(1.0, 2.0) + _ = vec3(1.0, 2.0, 3.0) + _ = vec4(1.0, 2.0, 3.0, 4.0) + + _ = dvec2(1.0, 2.0) + _ = dvec3(1.0, 2.0, 3.0) + _ = dvec4(1.0, 2.0, 3.0, 4.0) + + _ = bvec2(true, false) + _ = bvec3(true, false, true) + _ = bvec4(true, false, true, false) + + _ = ivec2(-1) + _ = ivec3(-1) + _ = ivec4(-1) + + _ = uvec2(1) + _ = uvec3(1) + _ = uvec4(1) + + _ = vec2(1.0) + _ = vec3(1.0) + _ = vec4(1.0) + + _ = dvec2(1.0) + _ = dvec3(1.0) + _ = dvec4(1.0) + +block: + # Test basic vector mat constructors. + block: + let + _ = mat2() + _ = mat3() + _ = mat4() + + block: + let + _ = mat2( + 1, 0, + 0, 1 + ) + _ = mat3( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ) + _ = mat4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ) + + block: + let + _ = mat2( + vec2(1, 0), + vec2(0, 1) + ) + _ = mat3( + vec3(1, 0, 0), + vec3(0, 1, 0), + vec3(0, 0, 1) + ) + _ = mat4( + vec4(1, 0, 0, 0), + vec4(0, 1, 0, 0), + vec4(0, 0, 1, 0), + vec4(0, 0, 0, 1) + ) + + block: + let + _ = dmat2() + _ = dmat3() + _ = dmat4() + + block: + let + _ = dmat2( + 1, 0, + 0, 1 + ) + _ = dmat3( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ) + _ = dmat4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ) + + block: + let + _ = dmat2( + dvec2(1, 0), + dvec2(0, 1) + ) + _ = dmat3( + dvec3(1, 0, 0), + dvec3(0, 1, 0), + dvec3(0, 0, 1) + ) + _ = dmat4( + dvec4(1, 0, 0, 0), + dvec4(0, 1, 0, 0), + dvec4(0, 0, 1, 0), + dvec4(0, 0, 0, 1) + ) + +block: + # Test basic mat functions. + doAssert dmat3().transpose() ~= [ + [1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0] + ] + doAssert dmat4().transpose() ~= [ + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [0.0, 0.0, 0.0, 1.0] + ] + + doAssert scale(dvec2(1, 2)) ~= [ + [1.0, 0.0, 0.0], + [0.0, 2.0, 0.0], + [0.0, 0.0, 1.0] + ] + doAssert scale(dvec3(2, 2, 3)) ~= [ + [2.0, 0.0, 0.0, 0.0], + [0.0, 2.0, 0.0, 0.0], + [0.0, 0.0, 3.0, 0.0], + [0.0, 0.0, 0.0, 1.0] + ] + + doAssert translate(dvec2(1, 2)) ~= [ + [1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [1.0, 2.0, 1.0] + ] + doAssert translate(dvec3(1, 2, 3)) ~= [ + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [1.0, 2.0, 3.0, 1.0] + ] + + doAssert rotate(1.0) ~= [ + [0.5403023058681398, -0.8414709848078965, 0.0], + [0.8414709848078965, 0.5403023058681398, 0.0], + [0.0, 0.0, 1.0] + ] + + doAssert scale(dvec2(2)) ~= [ + [2.0, 0.0, 0.0], + [0.0, 2.0, 0.0], + [0.0, 0.0, 1.0] + ] + doAssert scale(dvec3(2)) ~= [ + [2.0, 0.0, 0.0, 0.0], + [0.0, 2.0, 0.0, 0.0], + [0.0, 0.0, 2.0, 0.0], + [0.0, 0.0, 0.0, 1.0] + ] + doAssert translate(dvec2(2)) ~= [ + [1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [2.0, 2.0, 1.0] + ] + doAssert translate(dvec3(2)) ~= [ + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [2.0, 2.0, 2.0, 1.0] + ] + + doAssert rotate(1.0).inverse() ~= [ + [0.5403023058681398, 0.8414709848078965, -0.0], + [-0.8414709848078965, 0.5403023058681398, -0.0], + [0.0, -0.0, 1.0] + ] + doAssert rotate(1.0, dvec3(1, 0, 0)).inverse() ~= [ + [1.0, 0.0, 0.0, 0.0], + [-0.0, 0.5403022766113281, 0.8414710164070129, 0.0], + [0.0, -0.8414710164070129, 0.5403022766113281, 0.0], + [0.0, 0.0, 0.0, 1.0] + ] + block: # Test basic vector mat4 and quat. var m1 = mat4( @@ -163,59 +379,59 @@ block: block: # Test Y 90. - var m1 = rotate(PI/2, vec3(0, 1, 0)) + var m1 = rotate(PI/2, dvec3(0, 1, 0)) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test -Y 90. - var m1 = rotate(PI/2, vec3(0, -1, 0)) + var m1 = rotate(PI/2, dvec3(0, -1, 0)) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test X 90. - var m1 = rotate(PI/2, vec3(1, 0, 0)) + var m1 = rotate(PI/2, dvec3(1, 0, 0)) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test Y 90. - var m1 = rotate(PI/2, vec3(1, 0, 0)) + var m1 = rotate(PI/2, dvec3(1, 0, 0)) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test 1,1,1 1.11rad. - var m1 = rotate(PI*1.11, vec3(1, 1, 1).normalize()) + var m1 = rotate(PI*1.11, dvec3(1, 1, 1).normalize()) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test 1,1,1 1.11rad. - var m1 = rotate(PI*1.11, vec3(-1, 1, 1).normalize()) + var m1 = rotate(PI*1.11, dvec3(-1, 1, 1).normalize()) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test 1,1,1 1.11rad. - var m1 = rotate(PI*1.11, vec3(-1, 0.34, 1.123).normalize()) + var m1 = rotate(PI*1.11, dvec3(-1, 0.34, 1.123).normalize()) var q1 = m1.quat() var m2 = q1.mat4() doAssert m1 ~= m2 block: # Test super random quat test. - for i in 0 .. 100: + for i in 0 ..< 1000: var m1 = rotate( PI*rand(2.0), - vec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize() + dvec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize() ) var q1 = m1.quat() var m2 = q1.mat4() @@ -256,49 +472,62 @@ block: 77.64571380615234, 0.0, 1.0 ) - doAssert (a3.mat4 * b3.mat4).mat3 ~= mat3( - 1.0000, 0.0000, 0.0000, - 0.0000, 1.0000, 0.0000, - 50.0000, 50.0000, 0.0000 - ) doAssert a3 * b3 ~= mat3( 1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 50.0000, 50.0000, 1.0000 ) - doAssert ( - mat3(1,2,3,4,5,6,7,8,9).mat4Rotation * - mat3(10,20,30,40,50,60,70,80,90).mat4Rotation - ).mat3Rotation ~= mat3( + doAssert mat3(1, 2, 3, 4, 5, 6, 7, 8, 9) * + mat3(10, 20, 30, 40, 50, 60, 70, 80, 90) ~= mat3( 300.0000, 360.0000, 420.0000, 660.0000, 810.0000, 960.0000, 1020.0000, 1260.0000, 1500.0000 ) - doAssert mat3(1,2,3,4,5,6,7,8,9) * mat3(10,20,30,40,50,60,70,80,90) ~= mat3( - 300.0000, 360.0000, 420.0000, - 660.0000, 810.0000, 960.0000, - 1020.0000, 1260.0000, 1500.0000 - ) - doAssert a3.mat4 * vec3(77.64571380615234, 0, 1) ~= vec3(50.0, 50.0, 1.0) doAssert a3 * vec2(77.64571380615234, 0) ~= vec2(50.0, 50.0) - doAssert a3 * vec3(77.64571380615234, 0, 1.0) ~= vec3(50.0, 50.0, 1.0) block: - # hashing - doAssert hash(vec2(PI, E)) == 1311648097060332001 - doAssert hash(vec3(PI, E, TAU)) == 5625953707464987239 - doAssert hash(vec4(PI, E, TAU, sqrt(2.0))) == -6538384897102876123 - doAssert hash(quat(1, 0, 0, sqrt(2.0))) == 1497919211694084820 - doAssert hash( mat3( - 300.0000, 360.0000, 420.0000, - 660.0000, 810.0000, 960.0000, - 1020.0000, 1260.0000, 1500.0000 - )) == -4194936143766837151 - doAssert hash(mat4( - 1.00000, 0.00000, 0.00000, 0.00000, - 0.00000, 1.00000, 0.00000, 0.00000, - 0.00000, 0.00000, 1.00000, 0.00000, - 7.00000, 8.00000, 9.00000, 1.00000 - )) == 7507518476139335223 + # test quat and matrix lookat + doAssert lookAt(vec3(1, 2, 3), vec3(0, 0, 0)).quat ~= + quat( + 0.07232953608036041, + 0.3063928484916687, + 0.9237624406814575, + 0.2180707305669785 + ) + doAssert lookAt(vec3(0, 0, 0), vec3(0, 0, 0)).quat ~= quat(0.0, 0.0, 0.0, 1.0) + doAssert lookAt(vec3(1, 0, 0), vec3(0, 0, 0)).quat ~= quat(0.5, 0.5, 0.5, 0.5) + doAssert lookAt(vec3(0, 1, 0), vec3(0, 0, 0)).quat ~= + quat( + 0.0, + 0.7071067690849304, + 0.7071067690849304, + 0.0 + ) + doAssert lookAt(vec3(0, 0, 1), vec3(0, 0, 0)).quat ~= quat(0.0, 0.0, 0.0, 1.0) + + # Test super random quat test. + for i in 0 ..< 1000: + var m1 = rotate( + PI*rand(2.0), + dvec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize() + ) + var q1 = m1.quat() + var m2 = q1.mat4() + doAssert m1 ~= m2 + +block: + # test fromTwoVectors + let + a = vec3(1, 0, 0) + b = vec3(0, 1, 0) + q1 = fromTwoVectors(a, b) + doAssert q1.mat4 * a ~= b + + for i in 0 ..< 1000: + let + a = vec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize() + b = vec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize() + q = fromTwoVectors(a, b) + doAssert q.mat4 * a ~= b diff --git a/vmath.nimble b/vmath.nimble index 26d8f4c..a90da73 100644 --- a/vmath.nimble +++ b/vmath.nimble @@ -1,6 +1,6 @@ -version = "0.5.0" +version = "1.0.0" author = "treeform" -description = "Math vector library for graphical things." +description = "Your single stop for vector math routines for 2d and 3d graphics." license = "MIT" srcDir = "src"