44# # default: ObjArray based
55# #
66
7- import math, strutils
7+ import macros, math, strutils
88export math except isNan
99
1010{.push inline .}
@@ -230,13 +230,13 @@ elif true or defined(vmathObjArrayBased):
230230 GVec234 [T] = GVec2 [T] | GVec3 [T] | GVec4 [T]
231231
232232 template gvec2 * [T](x, y: T): GVec2 [T] =
233- GVec2 [T](arr:[T (x), T (y)])
233+ GVec2 [T](arr: [T (x), T (y)])
234234
235235 template gvec3 * [T](x, y, z: T): GVec3 [T] =
236- GVec3 [T](arr:[T (x), T (y), T (z)])
236+ GVec3 [T](arr: [T (x), T (y), T (z)])
237237
238238 template gvec4 * [T](x, y, z, w: T): GVec4 [T] =
239- GVec4 [T](arr:[T (x), T (y), T (z), T (w)])
239+ GVec4 [T](arr: [T (x), T (y), T (z), T (w)])
240240
241241 template x * [T](a: var GVec2 [T]): var T = a.arr[0 ]
242242 template y * [T](a: var GVec2 [T]): var T = a.arr[1 ]
@@ -436,6 +436,9 @@ proc isNan*(x: SomeFloat): bool =
436436 # # Returns true if number is a NaN.
437437 x != 0.0 and (x != x or x * 0.5 == x)
438438
439+ template lowerType (a: typed ): string =
440+ ($ type (a)).toLowerAscii ()
441+
439442template genConstructor (lower, upper, typ: untyped ) =
440443
441444 proc `lower 2` * (): `upper 2` = gvec2 [typ](typ (0 ), typ (0 ))
@@ -457,58 +460,145 @@ template genConstructor(lower, upper, typ: untyped) =
457460 proc `lower 4` * [T](x: GVec4 [T]): `upper 4` =
458461 gvec4 [typ](typ (x[0 ]), typ (x[1 ]), typ (x[2 ]), typ (x[3 ]))
459462
460- proc `lower 3` * [T](x: GVec2 [T]): `upper 3` =
461- gvec3 [typ](typ (x[0 ]), typ (x[1 ]), 0 )
462- proc `lower 4` * [T](x: GVec3 [T]): `upper 4` =
463- gvec4 [typ](typ (x[0 ]), typ (x[1 ]), typ (x[2 ]), 0 )
463+ proc `lower 3` * [T](x: GVec2 [T], z: T = 0 ): `upper 3` =
464+ gvec3 [typ](typ (x[0 ]), typ (x[1 ]), z)
465+ proc `lower 4` * [T](x: GVec3 [T], w: T = 0 ): `upper 4` =
466+ gvec4 [typ](typ (x[0 ]), typ (x[1 ]), typ (x[2 ]), w)
467+
468+ proc `lower 4` * [T](a, b: GVec2 [T]): `upper 4` =
469+ gvec4 [typ](typ (a[0 ]), typ (a[1 ]), typ (b[0 ]), typ (b[1 ]))
464470
465471 proc `$` * (a: `upper 2`): string =
466- ( $ type (a)). toLowerAscii ( ) & " (" & $ a.x & " , " & $ a.y & " )"
472+ lowerType (a ) & " (" & $ a.x & " , " & $ a.y & " )"
467473 proc `$` * (a: `upper 3`): string =
468- ( $ type (a)). toLowerAscii ( ) & " (" & $ a.x & " , " & $ a.y & " , " & $ a.z & " )"
474+ lowerType (a ) & " (" & $ a.x & " , " & $ a.y & " , " & $ a.z & " )"
469475 proc `$` * (a: `upper 4`): string =
470- ( $ type (a)). toLowerAscii ( ) & " (" & $ a.x & " , " & $ a.y & " , " & $ a.z & " , " & $ a.w & " )"
476+ lowerType (a ) & " (" & $ a.x & " , " & $ a.y & " , " & $ a.z & " , " & $ a.w & " )"
471477
472478genConstructor (bvec, BVec , bool )
473479genConstructor (ivec, IVec , int32 )
474480genConstructor (uvec, UVec , uint32 )
475481genConstructor (vec, Vec , float32 )
476482genConstructor (dvec, DVec , float64 )
477483
478- proc xy * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.x, a.y)
479- proc xz * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.x, a.z)
480- proc yx * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.y, a.x)
481- proc yz * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.y, a.z)
482- proc zx * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.z, a.x)
483- proc zy * [T](a: GVec234 [T]): GVec2 [T] = gvec2 [T](a.z, a.y)
484-
485- proc xxx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.x, a.x)
486- proc xxy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.x, a.y)
487- proc xxz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.x, a.z)
488- proc xyx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.y, a.x)
489- proc xyy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.y, a.y)
490- proc xyz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.y, a.z)
491- proc xzx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.z, a.x)
492- proc xzy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.z, a.y)
493- proc xzz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.x, a.z, a.z)
494- proc yxx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.x, a.x)
495- proc yxy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.x, a.y)
496- proc yxz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.x, a.z)
497- proc yyx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.y, a.x)
498- proc yyy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.y, a.y)
499- proc yyz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.y, a.z)
500- proc yzx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.z, a.x)
501- proc yzy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.z, a.y)
502- proc yzz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.y, a.z, a.z)
503- proc zxx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.x, a.x)
504- proc zxy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.x, a.y)
505- proc zxz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.x, a.z)
506- proc zyx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.y, a.x)
507- proc zyy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.y, a.y)
508- proc zyz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.y, a.z)
509- proc zzx * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.z, a.x)
510- proc zzy * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.z, a.y)
511- proc zzz * [T](a: GVec34 [T]): GVec3 [T] = gvec3 [T](a.z, a.z, a.z)
484+ {.experimental : " dotOperators" .}
485+ proc num (letter: char , fields: NimNode ): int =
486+ # # Given a swizzle character gives back the location number.
487+ case letter:
488+ of 'x' , 'r' , 's' : 0
489+ of 'y' , 'g' , 't' : 1
490+ of 'z' , 'b' , 'p' : 2
491+ of 'w' , 'a' , 'q' : 3
492+ else :
493+ error " invalid swizzle character: " & letter, fields
494+ quit ()
495+
496+ proc typePrefix (node: NimNode ): string =
497+ # # Given a node of type GVec234 gives its prefix type.
498+ # # IVec2 -> "i", DVec4 -> "d", Vec3 -> ""
499+ let typeName =
500+ when defined (vmathArrayBased):
501+ node.getType ()[2 ].repr
502+ elif defined (vmathObjBased):
503+ node.getType ()[2 ][0 ].getType ().repr
504+ elif true or defined (vmathObjArrayBased):
505+ node.getType ()[2 ][0 ].getType ()[2 ].repr
506+ case typeName:
507+ of " bool" : " b"
508+ of " int32" : " i"
509+ of " uint32" : " u"
510+ of " float32" : " "
511+ of " float" , " float64" : " d"
512+ else :
513+ error " invalid vector type: " & typeName, node
514+ quit ()
515+
516+ macro `.` * (v: GVec234 , fields: untyped ): untyped =
517+ # # Adds support for swizzle getter.
518+ # # x y z w
519+ # # r g b a
520+ # # s t p q
521+ # # v.xyz, v.xxx, v.zyx ...
522+ # # v.rgb, v.rrr, v.bgr ...
523+ # # v.stp, v.sss, v.pts ...
524+ let swizzle = fields.repr
525+ let vec = ident (typePrefix (v) & " vec" & $ swizzle.len)
526+ if swizzle.len == 1 :
527+ let a = num (swizzle[0 ], fields)
528+ result = quote do :
529+ `v`[`a`]
530+ elif swizzle.len == 2 :
531+ let
532+ a = num (swizzle[0 ], fields)
533+ b = num (swizzle[1 ], fields)
534+ result = quote do :
535+ `vec` (`v`[`a`], `v`[`b`])
536+ elif swizzle.len == 3 :
537+ let
538+ a = num (swizzle[0 ], fields)
539+ b = num (swizzle[1 ], fields)
540+ c = num (swizzle[2 ], fields)
541+ result = quote do :
542+ `vec` (`v`[`a`], `v`[`b`], `v`[`c`])
543+ elif swizzle.len == 4 :
544+ let
545+ a = num (swizzle[0 ], fields)
546+ b = num (swizzle[1 ], fields)
547+ c = num (swizzle[2 ], fields)
548+ d = num (swizzle[3 ], fields)
549+ result = quote do :
550+ `vec` (`v`[`a`], `v`[`b`], `v`[`c`], `v`[`d`])
551+ else :
552+ error " invalid number of swizzle characters: " & swizzle, fields
553+
554+ macro `.=` * (v: GVec234 , fields: untyped , e: untyped ): untyped =
555+ # # Adds support for swizzle setter.
556+ # # x y z w
557+ # # r g b a
558+ # # s t p q
559+ # # v.xyz, v.xxx, v.zyx ...
560+ # # v.rgb, v.rrr, v.bgr ...
561+ # # v.stp, v.sss, v.pts ...
562+ let swizzle = fields.repr
563+ if swizzle.len == 1 :
564+ let a = num (swizzle[0 ], fields)
565+ result = quote do :
566+ `v`[`a`] = `e`
567+ elif swizzle.len == 2 :
568+ let
569+ a = num (swizzle[0 ], fields)
570+ b = num (swizzle[1 ], fields)
571+ result = quote do :
572+ block :
573+ let tmp = `e`
574+ `v`[`a`] = tmp[0 ]
575+ `v`[`b`] = tmp[1 ]
576+ elif swizzle.len == 3 :
577+ let
578+ a = num (swizzle[0 ], fields)
579+ b = num (swizzle[1 ], fields)
580+ c = num (swizzle[2 ], fields)
581+ result = quote do :
582+ block :
583+ let tmp = `e`
584+ `v`[`a`] = tmp[0 ]
585+ `v`[`b`] = tmp[1 ]
586+ `v`[`c`] = tmp[2 ]
587+ elif swizzle.len == 4 :
588+ let
589+ a = num (swizzle[0 ], fields)
590+ b = num (swizzle[1 ], fields)
591+ c = num (swizzle[2 ], fields)
592+ d = num (swizzle[3 ], fields)
593+ result = quote do :
594+ block :
595+ let tmp = `e`
596+ `v`[`a`] = tmp[0 ]
597+ `v`[`b`] = tmp[1 ]
598+ `v`[`c`] = tmp[2 ]
599+ `v`[`d`] = tmp[3 ]
600+ else :
601+ error " invalid number of swizzle characters: " & swizzle, fields
512602
513603proc `==` * [T](a, b: GVec2 [T]): bool =
514604 a.x == b.x and a.y == b.y
0 commit comments