{- - 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)