packages feed

crocodile-0.1: app/src/Matrix.hs

-- 4D Matrix Library
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}

module Matrix where

import Vector

data Matrix = Matrix ![Double] deriving (Show, Read, Eq)

-- Just pass back the identity matrix
identity ::  Matrix
identity = Matrix [1, 0, 0, 0,   0, 1, 0, 0,   0, 0, 1, 0,   0, 0, 0, 1]

-- This multiplies one element of the matrix against
mulElement :: Matrix -> Matrix -> Int -> Int -> Double
mulElement (Matrix mat1) (Matrix mat2) i j = sum [(mat1 !! (i * 4 + k)) * (mat2 !! (k * 4 + j)) | k <- [0..3]]

-- Multiply together two matrices
-- TODO - Turn mulElement into a lambda function?
mul :: Matrix -> Matrix -> Matrix
mul a b = Matrix [mulElement a b i j | j <- [0..3], i <- [0..3]]

-- Need matrix inversion code

-- Vector * Matrix
transformVector :: Matrix -> Vector -> Vector
transformVector (Matrix mat) (Vector !x !y !z !w) = Vector x' y' z' w'
                          where
                            !vec = [x, y, z, w]
                            !xvector = take 4 mat
                            !yvector = take 4 (drop 4 mat)
                            !zvector = take 4 (drop 8 mat)
                            !wvector = take 4 (drop 12 mat)
                            !x' = sum $ zipWith (*) vec xvector
                            !y' = sum $ zipWith (*) vec yvector
                            !z' = sum $ zipWith (*) vec zvector
                            !w' = sum $ zipWith (*) vec wvector

-- Build a matrix from 4 vectors
buildMatrix :: Vector -> Vector -> Vector -> Vector -> Matrix
buildMatrix (Vector xx xy xz _) (Vector yx yy yz _) (Vector zx zy zz _) (Vector px py pz _) = Matrix ([xx, xy, xz] ++ [px] ++
                                                                                                      [yx, yy, yz] ++ [py] ++
                                                                                                      [zx, zy, zz] ++ [pz] ++
                                                                                                      [0, 0, 0, 1])
getTranslation :: Matrix -> Vector
{-# SPECIALIZE INLINE getTranslation :: Matrix -> Vector #-}
getTranslation (Matrix a) = Vector x y z 1
    where
      [!x, !y, !z, _] = drop 12 a

translationMatrix :: Double -> Double -> Double -> Matrix
translationMatrix !x !y !z = Matrix [1, 0, 0, 0,   0, 1, 0, 0,   0, 0, 1, 0,   x, y, z, 1]
translationMatrix' :: Vector -> Matrix
translationMatrix' (Vector !x !y !z _) = Matrix [1, 0, 0, 0,   0, 1, 0, 0,   0, 0, 1, 0,   x, y, z, 1]