{-
- Fulsom (The Solid Modeller, written in Haskell)
-
- Copyright 1990,1991,1992,1993 Duncan Sinclair
-
- Permissiom to use, copy, modify, and distribute this software for any
- purpose and without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies, and
- that my name not be used in advertising or publicity pertaining to this
- software without specific, written prior permission. I makes no
- representations about the suitability of this software for any purpose.
- It is provided ``as is'' without express or implied warranty.
-
- Duncan Sinclair 1993.
-
- CSG evaluation engine.
-
-}
module Csg(calc) where
import Matrix
import Types
import Interval
#if !defined(__HASKELL98__)
#define realToFrac fromRealFrac
#endif
-- no is returned when there is "no" change to the csg.
no = error ("Evaluated dead csg.")
calc :: Csg -> Calc
calc (Func f) rgb xyz = f rgb xyz
calc (Matrix a mat) rgb xyz
= (ans,newc,newr,prune)
where
newc = if prune then (if b then newc' else newc'') else (no)
(newc',b) = if prune then (reduceM newc'' mat) else (no)
xyz' = mat4x1 mat xyz
(ans,newc'',newr,prune) = calc a rgb xyz'
calc (Object X) rgb (x,y,z) = (x,no,rgb,False)
calc (Object Y) rgb (x,y,z) = (y,no,rgb,False)
calc (Object Z) rgb (x,y,z) = (z,no,rgb,False)
calc (Object (Plane a b c d)) rgb xyz
= (ans,(no),rgb,False)
where
ans = dorow (a,b,c,d) xyz
calc (Object (Sphere a b c r)) rgb xyz
= (ans,newc,rgb,True)
where
(ans,_,_,_) = calc newc rgb xyz
newc = Func f
f rgb zyx = (sphere zyx,no,rgb,False)
sphere :: (R3 BI) -> BI
sphere (x,y,z) = sqr (x-a') + sqr (y-b') + sqr (z-c') - sqr r'
a' = realToFrac a ; b' = realToFrac b ; c' = realToFrac c
r' = realToFrac r
calc (Object (Cube a b c r)) rgb xyz
= (ans,newc',rgb,bool)
where
newc'' = if bool then newc else newc'
(ans,newc,_,bool) = calc newc' rgb xyz
newc' = Inter xx (Inter yy zz)
xx = Inter x1 x2
yy = Inter y1 y2
zz = Inter z1 z2
x1 = Object (Plane ( 1) 0 0 (-(a+r)))
y1 = Object (Plane 0 ( 1) 0 (-(b+r)))
z1 = Object (Plane 0 0 ( 1) (-(c+r)))
x2 = Object (Plane (-1) 0 0 ( (a-r)))
y2 = Object (Plane 0 (-1) 0 ( (b-r)))
z2 = Object (Plane 0 0 (-1) ( (c-r)))
calc (Union a b) rgb xyz
= (min an1 an2,newc,newr,bool)
where
(an1,c1,rgb1,b1) = calc a rgb xyz
(an2,c2,rgb2,b2) = calc b rgb xyz
bool = b1 || b2
ca = if b1 then c1 else a
cb = if b2 then c2 else b
newr | an1 < an2 = rgb1
| an1 > an2 = rgb2
| otherwise = rgb
newc | an1 < an2 = ca
| an1 > an2 = cb
| not bool = (no)
| otherwise = Union ca cb
calc (Inter a b) rgb xyz
= (max an1 an2,newc,newr,bool)
where
(an1,c1,rgb1,b1) = calc a rgb xyz
(an2,c2,rgb2,b2) = calc b rgb xyz
bool = b1 || b2
ca = if b1 then c1 else a
cb = if b2 then c2 else b
newr | an1 > an2 = rgb1
| an1 < an2 = rgb2
| otherwise = rgb
newc | an1 > an2 = ca
| an1 < an2 = cb
| not bool = (no)
| otherwise = Inter ca cb
calc (Comp a) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
m1 = (-1, 0, 0, 0)
m2 = ( 0,-1, 0, 0)
m3 = ( 0, 0,-1, 0)
calc (Colour c a) rgb xyz
= (ans,newc,c,bool)
where
newc = if bool then (Colour c newc') else (no)
(ans,newc',_,bool) = calc a c xyz
calc (Sub a b) rgb xyz
= (ans,newc'',newr,True)
where
newc' = (a `Inter` (Comp b))
newc'' = if bool then newc else newc'
(ans,newc,newr,bool) = calc newc' rgb xyz
calc (Geom a (Trans h w d)) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
m1 = ( 1, 0, 0, h)
m2 = ( 0, 1, 0, w)
m3 = ( 0, 0, 1, d)
calc (Geom a (Scale h w d)) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
m1 = ( h, 0, 0, 0)
m2 = ( 0, w, 0, 0)
m3 = ( 0, 0, d, 0)
calc (Geom a (RotX rad)) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
c = cos rad
s = sin rad
m1 = ( 1, 0, 0, 0)
m2 = ( 0, c,-s, 0)
m3 = ( 0, s, c, 0)
calc (Geom a (RotY rad)) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
c = cos rad
s = sin rad
m1 = ( c, 0, s, 0)
m2 = ( 0, 1, 0, 0)
m3 = (-s, 0, c, 0)
calc (Geom a (RotZ rad)) rgb xyz
= (ans,newc'',newr,True)
where
(ans,newc,newr,b) = calc newc' rgb xyz
newc'' = if b then newc else newc'
newc' = Matrix a mat
mat = (m1,m2,m3)
c = cos rad
s = sin rad
m1 = ( c, s, 0, 0)
m2 = (-s, c, 0, 0)
m3 = ( 0, 0, 1, 0)
-- conflate matrices together and into planes planes...
reduceM (Object X) mata
= case (mat1x4 (1,0,0,0) mata) of
(x,y,z,w) -> (Object (Plane x y z w),True)
reduceM (Object Y) mata
= case (mat1x4 (0,1,0,0) mata) of
(x,y,z,w) -> (Object (Plane x y z w),True)
reduceM (Object Z) mata
= case (mat1x4 (0,0,1,0) mata) of
(x,y,z,w) -> (Object (Plane x y z w),True)
reduceM (Object (Plane a b c d)) mata
= case (mat1x4 (a,b,c,d) mata) of
(x,y,z,w) -> (Object (Plane x y z w),True)
reduceM (Matrix b matb) mata
= case (mat4x4 mata matb) of
matc -> (Matrix b matc,True)
reduceM _ _ = (no,False)