{-# LANGUAGE FlexibleContexts #-}

module Gamgine.Math.Vect (module Data.Vec,Vect,Vect4,x,y,z,v3,v4,fromTuple,toTuple,fromVect4,len,
                          inverseVec,clampVec,maxVec,minVec,index,absVec,nullVec,and,or,all,any) where

import Gamgine.Utils
#include "Gamgine/Utils.cpp"
import qualified Gamgine.Math.Utils as U
import Data.Vec
import qualified Data.Vec as V
import Prelude hiding (and, or, all, any)
import Debug.Trace

type Vect  = Vec3 Double
type Vect4 = Vec4 Double

x :: Vect -> Double
x :: Vect -> Double
x (Double
x:.Double :. (Double :. ())
_) = Double
x

y :: Vect -> Double
y :: Vect -> Double
y (Double
_:.Double
y:.Double :. ()
_) = Double
y

z :: Vect -> Double
z :: Vect -> Double
z (Double
_:.Double
_:.Double
z:.()) = Double
z

v3 :: Double -> Double -> Double -> Vect
v3 :: Double -> Double -> Double -> Vect
v3 Double
x Double
y Double
z = Double
xDouble -> (Double :. (Double :. ())) -> Vect
forall a b. a -> b -> a :. b
:.Double
yDouble -> (Double :. ()) -> Double :. (Double :. ())
forall a b. a -> b -> a :. b
:.Double
zDouble -> () -> Double :. ()
forall a b. a -> b -> a :. b
:.()

v4 :: Double -> Double -> Double -> Double -> Vect4
v4 :: Double -> Double -> Double -> Double -> Vect4
v4 Double
x Double
y Double
z Double
w = Double
xDouble -> Vect -> Vect4
forall a b. a -> b -> a :. b
:.Double
yDouble -> (Double :. (Double :. ())) -> Vect
forall a b. a -> b -> a :. b
:.Double
zDouble -> (Double :. ()) -> Double :. (Double :. ())
forall a b. a -> b -> a :. b
:.Double
wDouble -> () -> Double :. ()
forall a b. a -> b -> a :. b
:.()

fromTuple :: (Double,Double,Double) -> Vect
fromTuple :: (Double, Double, Double) -> Vect
fromTuple (Double
x,Double
y,Double
z) = Double -> Double -> Double -> Vect
v3 Double
x Double
y Double
z

toTuple :: Vect -> (Double,Double,Double)
toTuple :: Vect -> (Double, Double, Double)
toTuple (Double
x:.Double
y:.Double
z:.()) = (Double
x,Double
y,Double
z)

fromVect4 :: Vect4 -> Vect
fromVect4 :: Vect4 -> Vect
fromVect4 (Double
x:.Double
y:.Double
z:.Double
w:.()) = Double -> Double -> Double -> Vect
v3 Double
x Double
y Double
z

len :: Vect -> Double
len :: Vect -> Double
len = Vect -> Double
forall v a.
(Num v, Floating a, Fold v a, ZipWith a a a v v v) =>
v -> a
norm

inverseVec :: u -> v
inverseVec u
v = (b -> b) -> u -> v
forall a b u v. Map a b u v => (a -> b) -> u -> v
V.map (b -> b -> b
forall a. Num a => a -> a -> a
* (-b
1)) u
v

index :: (Double -> Bool) -> Vect -> Int
index :: (Double -> Bool) -> Vect -> Int
index Double -> Bool
f (Double
x:.Double
y:.Double
z:.())
   | Double -> Bool
f Double
x = Int
0
   | Double -> Bool
f Double
y = Int
1
   | Double -> Bool
f Double
z = Int
2
   | Bool
otherwise = [Char] -> Int
forall a. HasCallStack => [Char] -> a
ERROR "Couldn't find elem!"

clampVec :: Vect -> Vect -> Vect -> Vect
clampVec :: Vect -> Vect -> Vect -> Vect
clampVec (Double
minX:.Double
minY:.Double
minZ:.()) (Double
maxX:.Double
maxY:.Double
maxZ:.()) (Double
x:.Double
y:.Double
z:.()) =
   Double -> Double -> Double -> Vect
v3 (Double -> Double -> Double -> Double
U.clamp Double
minX Double
maxX Double
x) (Double -> Double -> Double -> Double
U.clamp Double
minY Double
maxY Double
y) (Double -> Double -> Double -> Double
U.clamp Double
minZ Double
maxZ Double
z)

maxVec :: u -> v -> w
maxVec u
v1 v
v2 = (c -> c -> c) -> u -> v -> w
forall a b c u v w.
ZipWith a b c u v w =>
(a -> b -> c) -> u -> v -> w
V.zipWith c -> c -> c
forall a. Ord a => a -> a -> a
max u
v1 v
v2

minVec :: u -> v -> w
minVec u
v1 v
v2 = (c -> c -> c) -> u -> v -> w
forall a b c u v w.
ZipWith a b c u v w =>
(a -> b -> c) -> u -> v -> w
V.zipWith c -> c -> c
forall a. Ord a => a -> a -> a
min u
v1 v
v2

absVec :: u -> v
absVec u
v = (b -> b) -> u -> v
forall a b u v. Map a b u v => (a -> b) -> u -> v
V.map b -> b
forall a. Num a => a -> a
abs u
v

nullVec :: Vect
nullVec = Double -> Double -> Double -> Vect
v3 Double
0 Double
0 Double
0

and :: v -> Bool
and v
v = (Bool -> Bool -> Bool) -> Bool -> v -> Bool
forall b. (Bool -> b -> b) -> b -> v -> b
forall v a b. Fold v a => (a -> b -> b) -> b -> v -> b
V.foldr Bool -> Bool -> Bool
(&&) Bool
True v
v

or :: v -> Bool
or v
v = (Bool -> Bool -> Bool) -> Bool -> v -> Bool
forall b. (Bool -> b -> b) -> b -> v -> b
forall v a b. Fold v a => (a -> b -> b) -> b -> v -> b
V.foldr Bool -> Bool -> Bool
(||) Bool
False v
v

all :: (a -> b -> c) -> u -> v -> Bool
all a -> b -> c
f u
v1 v
v2 = v -> Bool
forall {v}. Fold v Bool => v -> Bool
and (v -> Bool) -> v -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> b -> c) -> u -> v -> v
forall a b c u v w.
ZipWith a b c u v w =>
(a -> b -> c) -> u -> v -> w
V.zipWith a -> b -> c
f u
v1 v
v2

any :: (a -> b -> c) -> u -> v -> Bool
any a -> b -> c
f u
v1 v
v2 = v -> Bool
forall {v}. Fold v Bool => v -> Bool
or (v -> Bool) -> v -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> b -> c) -> u -> v -> v
forall a b c u v w.
ZipWith a b c u v w =>
(a -> b -> c) -> u -> v -> w
V.zipWith a -> b -> c
f u
v1 v
v2