Additionnal functions and a few remarks
flintforge opened this issue · 1 comments
These are a few personal notes I wrote when I first tried vmath.
I was hoping to get some time to code some nim, unfortunately I don't have that time.
and didn't keep a very closed eye on the project, so it is perfectly possible these remarks fall flat.
(I saw something on the swizzle ops passing by), still, hoping they will be helpful :
#+Date:[2022-06-18 15:25:23]
# additional functions to suiggest in vmath
import vmath
type
GV2 = Vec2 | array[2,float32] | tuple[x,y:float32] # a generic vector of size 2
GV3 = Vec3 | array[3,float32] | tuple[x,y,z:float32] # a generic vector of size 3
GV4 = Vec4 | array[4,float32] | tuple[x,y,z,w:float32] # a generic vector of size 4
GVec234[T] = GVec2[T] | GVec3[T] | GVec4[T]
Vec4f* = Vec4
Mat4f* = Mat4
template `=`*[T](a: var GVec234[T], b:GV2) = (a[0], a[1]) = (b[0], b[1])
template `=`*[T](a: var GVec234[T], b:GV3) = (a[0], a[1], a[2]) = (b[0], b[1], b[3])
template `=`*[T](a: var GVec234[T], b:GV4) = (a[0], a[1], a[2],a[3]) = (b[0], b[1], b[2], b[3])
template `xy=`*[T](a: var GVec234[T], b: GV2) = (a[0], a[1]) = (b[0], b[1])
# add or mul of a vec with a smaller one is accepted
proc `*=`*(a: var Vec3, b:GV2) = a.x *= b[0]; a.y *= b[1]
proc `+=`*(a: var Vec3, b:GV2) = a.x += b[0]; a.y += b[1]
template `=`*(a: var Vec3, b:Vec2) = (a[0], a[1], a[2]) = (b[0], b[1], 0.0)
# allow int parameter given to vec2f ctor
proc vec2*(x,y:int):Vec2 = return vec2(float(x), float(y))
when isMainModule:
let a:int=0
assert vec2(a,1) is GVec2[float32]
# vec2f accept a vec3 as ctor
proc vec2*(v:Vec3):Vec2 = return vec2(v.xy)
when isMainModule:
assert type(vec2(vec3())) is GVec2[float32]
# the identity. Often requested, must be passed by copy
const IDT*:Mat4f = gmat4(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f )
# If passed bycopy is the following still necessary ?
# proc Identity(m:var Mat4f)= m = IDT
const DEGREE_TO_RADIAN* = 0.01745329251994329576
proc mat4[T](Q:Quat):GMat4[T]=
# create a matrix from a quaterniop located at origin
let (w, x, y, z) = Q
result = [[1.f-2.f*(y*y+z*z), 2.f*(x*y+w*z), 2.f*(x*z-w*y), 0.f],
[2.f*(x*y-w*z), 1.f-2.f*(x*x+z*z), 2.f*(y*z+w*x), 0.f],
[2.f*(x*z+w*y), 2.f*(y*z-w*x), 1.f-2.f*(x*x+y*y), 0.f],
[0.f, 0.f, 0.f, 1.f]]
Aren't those naming dubious :
translate, rotate, scale ?
If they aren't performing operations
but returning the corresponing
matrices in canonical base,
then they should be named
translation, rotation, and scaling
while translate would modify the given matrix as parameter
# aren't we missing quaternion templates ?
# proc `*`(p,q:Quat):Quat=
# let
# w1 = p[0] # w
# v1 = vec3(p[1],p[2],p[3])
# w2 = q[0]
# v2 = vec3(q[1],q[2], q[3])
# (x,y,z) = (w1 * v2 + w2 * v1 + cross(v1, v2)).xyz
# result = quat(w1*w2 - dot(v1, v2), x,y,z )
from math import sqrt
proc arcball*(x, y : float32):Quat=
# TODO
let h2 = x*x + y*y
var v:Vec3
if h2 > 1.0f:
let h = sqrt(h2)
v = vec3(x/h, y/h, 0f)
else:
v = vec3(x, y, sqrt(1.0f-h2))
return quat(v.x, v.y, v.z, 0.0f)
proc translate*[T](m: var GMat4[T], v:GVec3[T]): GMat4[T] =
## Create translation matrix.
m[0][3] += v[0]
m[1][3] += v[1]
m[2][3] += v[2]
m
I really wish I could do more than that.
Keep up the good work !
Sorry, I am not into the many suggests that are here. This vector stuff hard enough and I just see me making bugs where I pass a vec2 into a vec3 and it just magically works. Some amount of magic is nice, while too much can lead to all kind of confusion its totally personal taste.
Sorry not a fan of array or tuples acting like vectors, I feel like if you have a type it should stay that type. Nim is all about type safety I don't want to throw it a way.
You are probably right about the names: translate, rotate, scale. I don't think they are that bad that it all needs chaining and breaking backward compatibility.
I actually like the idea of "allow int parameter given to vec2f ctor" and maybe I'll do some thing like this. I do feel like vec3 is a typed thing and should except integers etc... up-casting to a higher precession.
When you create a mat4() its already an identity mat, why do you want another one?
And quat to mat4 already exists. It just takes a vec4 which is what GLSL does.
I probably need to add other quat functions though.