Skip to content

Instantly share code, notes, and snippets.

@nandor
Created November 25, 2013 11:53
Show Gist options
  • Save nandor/7640209 to your computer and use it in GitHub Desktop.
Save nandor/7640209 to your computer and use it in GitHub Desktop.
-- |3D Vector
data Vec3 a
= Vec3 { v3x :: a
, v3y :: a
, v3z :: a
}
deriving ( Eq, Ord, Show )
-- |Creates a 3D vector
vec3 :: [ a ] -> Vec3 a
vec3 [ x, y, z ]
= Vec3 x y z
-- |Adds 3D vectors
vec3Add :: Num a => Vec3 a -> Vec3 a -> Vec3 a
vec3Add (Vec3 ax ay az) (Vec3 bx by bz)
= Vec3 (ax + bx) (ay + by) (az + bz)
-- |Subtracts 3D vectors
vec3Sub :: Num a => Vec3 a -> Vec3 a -> Vec3 a
vec3Sub (Vec3 ax ay az) (Vec3 bx by bz)
= Vec3 (ax - bx) (ay - by) (az - bz)
-- |Computes the cross product of 3D vectors
vec3Cross :: Num a => Vec3 a -> Vec3 a -> Vec3 a
vec3Cross (Vec3 ax ay az) (Vec3 bx by bz)
= Vec3 { v3x = ay * bz - az * by
, v3y = ax * bz - az * bx
, v3z = ax * by - ay * bx
}
-- |Computes the dot product of 3D vectors
vec3Dot :: Num a => Vec3 a -> Vec3 a -> a
vec3Dot (Vec3 ax ay az) (Vec3 bx by bz)
= ax * bx + ay * by + az * bz
-- |Computes the length of a 3D vector
vec3Length :: Floating a => Vec3 a -> a
vec3Length (Vec3 x y z)
= sqrt (x * x + y * y + z * z)
-- |Normalizes a 3D vector
vec3Normalize :: Floating a => Vec3 a -> Vec3 a
vec3Normalize v@(Vec3 x y z)
= Vec3 (x / l) (y / l) (z / l)
where
l = vec3Length v
-- |3D Matrix
data Mat3 a
= Mat3 { m3x :: Vec3 a
, m3y :: Vec3 a
, m3z :: Vec3 a
}
deriving ( Eq, Ord, Show )
-- |Creates a 3D matrix
mat3 :: [ a ] -> Mat3 a
mat3 [ a00, a01, a02
, a10, a11, a12
, a20, a21, a22
]
= Mat3 (Vec3 a00 a01 a02)
(Vec3 a10 a11 a12)
(Vec3 a20 a21 a22)
-- |Returns the 3D Identity matrix
mat3Id :: Num a => Mat3 a
mat3Id
= Mat3 (Vec3 1 0 0)
(Vec3 0 1 0)
(Vec3 0 0 1)
-- |Transposes a 3D matrix
mat3Trans :: Mat3 a -> Mat3 a
mat3Trans (Mat3 (Vec3 a00 a01 a02) (Vec3 a10 a11 a12) (Vec3 a20 a21 a22))
= Mat3 (Vec3 a00 a10 a20)
(Vec3 a01 a11 a21)
(Vec3 a02 a12 a22)
-- |Adds two 3D matrices
mat3Add :: Num a => Mat3 a -> Mat3 a -> Mat3 a
mat3Add (Mat3 (Vec3 a00 a01 a02) (Vec3 a10 a11 a12) (Vec3 a20 a21 a22))
(Mat3 (Vec3 b00 b01 b02) (Vec3 b10 b11 b12) (Vec3 b20 b21 b22))
= Mat3 (Vec3 (a00 + b00) (a01 + b01) (a02 + b02))
(Vec3 (a10 + b10) (a11 + b11) (a12 + b12))
(Vec3 (a20 + b20) (a21 + b21) (a22 + b22))
-- |Subtracts two 3D matrices
mat3Sub :: Num a => Mat3 a -> Mat3 a -> Mat3 a
mat3Sub (Mat3 (Vec3 a00 a01 a02) (Vec3 a10 a11 a12) (Vec3 a20 a21 a22))
(Mat3 (Vec3 b00 b01 b02) (Vec3 b10 b11 b12) (Vec3 b20 b21 b22))
= Mat3 (Vec3 (a00 - b00) (a01 - b01) (a02 - b02))
(Vec3 (a10 - b10) (a11 - b11) (a12 - b12))
(Vec3 (a20 - b20) (a21 - b21) (a22 - b22))
-- |Multiplies two 3D matrices
mat3Mul :: Num a => Mat3 a -> Mat3 a -> Mat3 a
mat3Mul (Mat3 (Vec3 a00 a01 a02) (Vec3 a10 a11 a12) (Vec3 a20 a21 a22))
(Mat3 (Vec3 b00 b01 b02) (Vec3 b10 b11 b12) (Vec3 b20 b21 b22))
= Mat3 (Vec3 (a00 * b00 + a10 * b01 + a20 * b02)
(a00 * b10 + a10 * b11 + a20 * b12)
(a00 * b20 + a10 * b21 + a20 * b22))
(Vec3 (a01 * b00 + a11 * b01 + a21 * b02)
(a01 * b10 + a11 * b11 + a21 * b12)
(a01 * b20 + a11 * b21 + a21 * b22))
(Vec3 (a02 * b00 + a12 * b01 + a22 * b02)
(a02 * b10 + a12 * b11 + a22 * b12)
(a02 * b20 + a12 * b21 + a22 * b22))
-- |Computes the determinant of a matrix
mat3Det :: Num a => Mat3 a -> a
mat3Det (Mat3 (Vec3 a00 a01 a02) (Vec3 a10 a11 a12) (Vec3 a20 a21 a22))
= a00 * a11 * a22 + a10 * a21 * a02 + a01 * a12 * a20 -
a20 * a11 * a02 - a10 * a01 * a22 - a00 * a21 * a12
-- |4D Vector
data Vec4 a
= Vec4 { v4x :: a
, v4y :: a
, v4z :: a
, v4w :: a
}
deriving ( Eq, Ord, Show )
-- |Creates a 4D vector
vec4 :: [ a ] -> Vec4 a
vec4 [ x, y, z, w ]
= Vec4 x y z w
-- |Adds 4D vectors
vec4Add :: Num a => Vec4 a -> Vec4 a -> Vec4 a
vec4Add (Vec4 ax ay az aw) (Vec4 bx by bz bw)
= Vec4 (ax + bx) (ay + by) (az + bz) (aw + bw)
-- |Subtracts 4D vectors
vec4Sub :: Num a => Vec4 a -> Vec4 a -> Vec4 a
vec4Sub (Vec4 ax ay az aw) (Vec4 bx by bz bw)
= Vec4 (ax - bx) (ay - by) (az - bz) (aw - bw)
-- |Computes the dot product of 4D vectors
vec4Dot :: Num a => Vec4 a -> Vec4 a -> a
vec4Dot (Vec4 ax ay az aw) (Vec4 bx by bz bw)
= ax * bx + ay * by + az * bz + aw * bw
-- |Computes the length of a 4D vector
vec4Length :: Floating a => Vec4 a -> a
vec4Length (Vec4 x y z w)
= sqrt (x * x + y * y + z * z + w * w)
-- |Normalizes a 4D vector
vec4Normalize :: Floating a => Vec4 a -> Vec4 a
vec4Normalize v@(Vec4 x y z w)
= Vec4 (x / l) (y / l) (z / l) (w / l)
where
l = vec4Length v
-- |4D Matrix
data Mat4 a
= Mat4 { m4x :: Vec4 a
, m4y :: Vec4 a
, m4z :: Vec4 a
, m4w :: Vec4 a
}
deriving ( Eq, Ord, Show )
-- |Creates a 4D matrix
mat4 :: [ a ] -> Mat4 a
mat4 [ a00, a01, a02, a03
, a10, a11, a12, a13
, a20, a21, a22, a23
, a30, a31, a32, a33
]
= Mat4 (Vec4 a00 a01 a02 a03)
(Vec4 a10 a11 a12 a13)
(Vec4 a20 a21 a22 a23)
(Vec4 a30 a31 a32 a33)
-- |Returns the 4D identity matrix
mat4Id :: Num a => Mat4 a
mat4Id
= Mat4 (Vec4 1 0 0 0)
(Vec4 0 1 0 0)
(Vec4 0 0 1 0)
(Vec4 0 0 0 1)
-- |Transposes a 4D matrix
mat4Trans :: Mat4 a -> Mat4 a
mat4Trans (Mat4 (Vec4 a00 a01 a02 a03)
(Vec4 a10 a11 a12 a13)
(Vec4 a20 a21 a22 a23)
(Vec4 a30 a31 a32 a33))
= Mat4 (Vec4 a00 a10 a20 a30)
(Vec4 a01 a11 a21 a31)
(Vec4 a02 a12 a22 a32)
(Vec4 a03 a13 a23 a33)
-- |Creates a perspective projection matrix
mat4Persp :: Floating a => a -> a -> a -> a -> Mat4 a
mat4Persp fov a n f
= Mat4 (Vec4 ( 1 / (a * t)) 0.0 0.0 0.0)
(Vec4 0.0 (1 / t) 0.0 0.0)
(Vec4 0.0 0.0 ((n + f) / d) (-1.0))
(Vec4 0.0 0.0 (2 * n * f / d) 0.0)
where
t = tan (fov / 2.0)
d = n - f
-- |Creates an ortographic projection matrix
mat4Ortho :: Floating a => a -> a -> a -> a -> a -> a -> Mat4 a
mat4Ortho l r b t n f
= Mat4 (Vec4 (2.0 / w) 0.0 0.0 0.0)
(Vec4 0.0 (2.0 / h) 0.0 0.0)
(Vec4 0.0 0.0 (-2.0 / d) 0.0)
(Vec4 (-(r + l) / w) (-(t + b) / h) (-(f + n) / d) 1.0)
where
w = r - l
h = t - b
d = f - n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment