Add tempalte based swizzle to work around https://github.com/nim-lang/Nim/issues/13063
This commit is contained in:
parent
7082ed6452
commit
c15614ec2c
120
src/vmath.nim
120
src/vmath.nim
|
@ -521,124 +521,8 @@ proc ivec4*(uvec4: Uvec4): Ivec4 {.inline.} =
|
|||
proc uvec4*(ivec4: Ivec4): Uvec4 {.inline.} =
|
||||
uvec4(ivec4.x.uint32, ivec4.y.uint32, ivec4.z.uint32, ivec4.w.uint32)
|
||||
|
||||
{.experimental: "dotOperators".}
|
||||
proc num(letter: char, fields: NimNode): int =
|
||||
## Given a swizzle character gives back the location number.
|
||||
case letter:
|
||||
of 'x', 'r', 's': 0
|
||||
of 'y', 'g', 't': 1
|
||||
of 'z', 'b', 'p': 2
|
||||
of 'w', 'a', 'q': 3
|
||||
else:
|
||||
error "invalid swizzle character: " & letter, fields
|
||||
quit()
|
||||
|
||||
proc typePrefix(node: NimNode): string =
|
||||
## Given a node of type GVec234 gives its prefix type.
|
||||
## IVec2 -> "i", DVec4 -> "d", Vec3 -> ""
|
||||
let typeName =
|
||||
when defined(vmathArrayBased):
|
||||
node.getType()[2].repr
|
||||
elif defined(vmathObjBased):
|
||||
node.getType()[2][0].getType().repr
|
||||
elif true or defined(vmathObjArrayBased):
|
||||
node.getType()[2][0].getType()[2].repr
|
||||
case typeName:
|
||||
of "bool": "b"
|
||||
of "int32": "i"
|
||||
of "uint32": "u"
|
||||
of "float32": ""
|
||||
of "float", "float64": "d"
|
||||
else:
|
||||
error "invalid vector type: " & typeName, node
|
||||
quit()
|
||||
|
||||
macro `.`*(v: GVec234, fields: untyped): untyped =
|
||||
## Adds support for swizzle getter.
|
||||
## x y z w
|
||||
## r g b a
|
||||
## s t p q
|
||||
## v.xyz, v.xxx, v.zyx ...
|
||||
## v.rgb, v.rrr, v.bgr ...
|
||||
## v.stp, v.sss, v.pts ...
|
||||
let swizzle = fields.repr
|
||||
let vec = ident(typePrefix(v) & "vec" & $swizzle.len)
|
||||
if swizzle.len == 1:
|
||||
let a = num(swizzle[0], fields)
|
||||
result = quote do:
|
||||
`v`[`a`]
|
||||
elif swizzle.len == 2:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`])
|
||||
elif swizzle.len == 3:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`], `v`[`c`])
|
||||
elif swizzle.len == 4:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
d = num(swizzle[3], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`], `v`[`c`], `v`[`d`])
|
||||
else:
|
||||
error "invalid number of swizzle characters: " & swizzle, fields
|
||||
|
||||
macro `.=`*(v: GVec234, fields: untyped, e: untyped): untyped =
|
||||
## Adds support for swizzle setter.
|
||||
## x y z w
|
||||
## r g b a
|
||||
## s t p q
|
||||
## v.xyz, v.xxx, v.zyx ...
|
||||
## v.rgb, v.rrr, v.bgr ...
|
||||
## v.stp, v.sss, v.pts ...
|
||||
let swizzle = fields.repr
|
||||
if swizzle.len == 1:
|
||||
let a = num(swizzle[0], fields)
|
||||
result = quote do:
|
||||
`v`[`a`] = `e`
|
||||
elif swizzle.len == 2:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
elif swizzle.len == 3:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
`v`[`c`] = tmp[2]
|
||||
elif swizzle.len == 4:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
d = num(swizzle[3], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
`v`[`c`] = tmp[2]
|
||||
`v`[`d`] = tmp[3]
|
||||
else:
|
||||
error "invalid number of swizzle characters: " & swizzle, fields
|
||||
# TODO when https://github.com/nim-lang/Nim/issues/13063 is fixed use macros.
|
||||
include vmath/swizzle
|
||||
|
||||
proc `==`*[T](a, b: GVec2[T]): bool =
|
||||
a.x == b.x and a.y == b.y
|
||||
|
|
119
src/vmath/macroswizzle.nim
Normal file
119
src/vmath/macroswizzle.nim
Normal file
|
@ -0,0 +1,119 @@
|
|||
|
||||
{.experimental: "dotOperators".}
|
||||
proc num(letter: char, fields: NimNode): int =
|
||||
## Given a swizzle character gives back the location number.
|
||||
case letter:
|
||||
of 'x', 'r', 's': 0
|
||||
of 'y', 'g', 't': 1
|
||||
of 'z', 'b', 'p': 2
|
||||
of 'w', 'a', 'q': 3
|
||||
else:
|
||||
error "invalid swizzle character: " & letter, fields
|
||||
quit()
|
||||
|
||||
proc typePrefix(node: NimNode): string =
|
||||
## Given a node of type GVec234 gives its prefix type.
|
||||
## IVec2 -> "i", DVec4 -> "d", Vec3 -> ""
|
||||
let typeName =
|
||||
when defined(vmathArrayBased):
|
||||
node.getType()[2].repr
|
||||
elif defined(vmathObjBased):
|
||||
node.getType()[2][0].getType().repr
|
||||
elif true or defined(vmathObjArrayBased):
|
||||
node.getType()[2][0].getType()[2].repr
|
||||
case typeName:
|
||||
of "bool": "b"
|
||||
of "int32": "i"
|
||||
of "uint32": "u"
|
||||
of "float32": ""
|
||||
of "float", "float64": "d"
|
||||
else:
|
||||
error "invalid vector type: " & typeName, node
|
||||
quit()
|
||||
|
||||
macro `.`*(v: GVec234, fields: untyped): untyped =
|
||||
## Adds support for swizzle getter.
|
||||
## x y z w
|
||||
## r g b a
|
||||
## s t p q
|
||||
## v.xyz, v.xxx, v.zyx ...
|
||||
## v.rgb, v.rrr, v.bgr ...
|
||||
## v.stp, v.sss, v.pts ...
|
||||
let swizzle = fields.repr
|
||||
let vec = ident(typePrefix(v) & "vec" & $swizzle.len)
|
||||
if swizzle.len == 1:
|
||||
let a = num(swizzle[0], fields)
|
||||
result = quote do:
|
||||
`v`[`a`]
|
||||
elif swizzle.len == 2:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`])
|
||||
elif swizzle.len == 3:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`], `v`[`c`])
|
||||
elif swizzle.len == 4:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
d = num(swizzle[3], fields)
|
||||
result = quote do:
|
||||
`vec`(`v`[`a`], `v`[`b`], `v`[`c`], `v`[`d`])
|
||||
else:
|
||||
error "invalid number of swizzle characters: " & swizzle, fields
|
||||
|
||||
macro `.=`*(v: GVec234, fields: untyped, e: untyped): untyped =
|
||||
## Adds support for swizzle setter.
|
||||
## x y z w
|
||||
## r g b a
|
||||
## s t p q
|
||||
## v.xyz, v.xxx, v.zyx ...
|
||||
## v.rgb, v.rrr, v.bgr ...
|
||||
## v.stp, v.sss, v.pts ...
|
||||
let swizzle = fields.repr
|
||||
if swizzle.len == 1:
|
||||
let a = num(swizzle[0], fields)
|
||||
result = quote do:
|
||||
`v`[`a`] = `e`
|
||||
elif swizzle.len == 2:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
elif swizzle.len == 3:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
`v`[`c`] = tmp[2]
|
||||
elif swizzle.len == 4:
|
||||
let
|
||||
a = num(swizzle[0], fields)
|
||||
b = num(swizzle[1], fields)
|
||||
c = num(swizzle[2], fields)
|
||||
d = num(swizzle[3], fields)
|
||||
result = quote do:
|
||||
block:
|
||||
let tmp = `e`
|
||||
`v`[`a`] = tmp[0]
|
||||
`v`[`b`] = tmp[1]
|
||||
`v`[`c`] = tmp[2]
|
||||
`v`[`d`] = tmp[3]
|
||||
else:
|
||||
error "invalid number of swizzle characters: " & swizzle, fields
|
5079
src/vmath/swizzle.nim
Normal file
5079
src/vmath/swizzle.nim
Normal file
File diff suppressed because it is too large
Load diff
44
tools/genswizzle.nim
Normal file
44
tools/genswizzle.nim
Normal file
|
@ -0,0 +1,44 @@
|
|||
import strformat
|
||||
|
||||
var swizzles = @["xyzw", "rgba", "stpq"]
|
||||
|
||||
echo "# Generated by tools/gensswizzle"
|
||||
|
||||
for swizzle in swizzles[1 .. ^1]:
|
||||
echo "\n# 1 x ", swizzle
|
||||
for i1, s1 in swizzle:
|
||||
echo &"template {s1}*[T](a: GVec234[T]): T = a[{i1}]"
|
||||
echo &"func `{s1}=`*[T](a: var GVec234[T], b: T) = a[{i1}] = b"
|
||||
|
||||
for swizzle in swizzles:
|
||||
echo "\n# 2 x ", swizzle
|
||||
for i1, s1 in swizzle:
|
||||
for i2, s2 in swizzle:
|
||||
echo &"template {s1}{s2}*[T](a: GVec234[T]): GVec2[T] ="
|
||||
echo &" gvec2(a[{i1}], a[{i2}])"
|
||||
echo &"template `{s1}{s2}=`*[T](a: var GVec234[T], b: GVec2[T]) ="
|
||||
echo &" let x = b.x; let y = b.y"
|
||||
echo &" a[0{i1}] = x; a[{i2}] = y"
|
||||
|
||||
for swizzle in swizzles:
|
||||
echo "\n# 3 x ", swizzle
|
||||
for i1, s1 in swizzle:
|
||||
for i2, s2 in swizzle:
|
||||
for i3, s3 in swizzle:
|
||||
echo &"template {s1}{s2}{s3}*[T](a: GVec234[T]): GVec3[T] ="
|
||||
echo &" gvec3(a[{i1}], a[{i2}], a[{i3}])"
|
||||
echo &"template `{s1}{s2}{s3}=`*[T](a: var GVec234[T], b: GVec3[T]) ="
|
||||
echo &" let x = b.x; let y = b.y; let z = b.z"
|
||||
echo &" a[{i1}] = x; a[{i2}] = y; a[{i3}] = z"
|
||||
|
||||
for swizzle in swizzles:
|
||||
echo "\n# 4 x ", swizzle
|
||||
for i1, s1 in swizzle:
|
||||
for i2, s2 in swizzle:
|
||||
for i3, s3 in swizzle:
|
||||
for i4, s4 in swizzle:
|
||||
echo &"template {s1}{s2}{s3}{s4}*[T](a: GVec234[T]): GVec4[T] ="
|
||||
echo &" gvec4(a [{i1}], a[{i2}], a[{i3}], a[{i4}])"
|
||||
echo &"template `{s1}{s2}{s3}{s4}=`*[T](a: var GVec234[T], b: GVec4[T]) ="
|
||||
echo &" let x = b.x; let y = b.y; let z = b.z; let w = b.w"
|
||||
echo &" a[{i1}] = x; a[{i2}] = y; a[{i3}] = z; a[{i4}] = w"
|
Loading…
Reference in a new issue