summaryrefslogtreecommitdiff
path: root/testsuite/tests/programs/galois_raytrace/Surface.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/programs/galois_raytrace/Surface.hs')
-rw-r--r--testsuite/tests/programs/galois_raytrace/Surface.hs115
1 files changed, 115 insertions, 0 deletions
diff --git a/testsuite/tests/programs/galois_raytrace/Surface.hs b/testsuite/tests/programs/galois_raytrace/Surface.hs
new file mode 100644
index 0000000000..832f0fcae2
--- /dev/null
+++ b/testsuite/tests/programs/galois_raytrace/Surface.hs
@@ -0,0 +1,115 @@
+-- Copyright (c) 2000 Galois Connections, Inc.
+-- All rights reserved. This software is distributed as
+-- free software under the license in the file "LICENSE",
+-- which is included in the distribution.
+
+module Surface
+ ( SurfaceFn (..)
+ , Properties
+ , sfun, sconst
+ , prop
+ , matte, shiny
+ , chgColor
+ , surface
+ ) where
+
+import Geometry
+import CSG
+import Misc
+
+-- the surface gets passed face then u then v.
+data SurfaceFn c v = SFun (Int -> Double -> Double -> Properties c v)
+ | SConst (Properties c v)
+
+sfun :: (Int -> Double -> Double -> Properties c v) -> SurfaceFn c v
+sfun = SFun
+sconst :: Properties c v -> SurfaceFn c v
+sconst = SConst
+
+type Properties c v = (c, v, v, v)
+
+prop c d s p = (c, d, s, p)
+
+matte = (white, 1.0, 0.0, 1.0)
+shiny = (white, 0.0, 1.0, 1.0)
+
+chgColor :: c -> Properties d v -> Properties c v
+chgColor c (_, d, s, p) = (c, d, s, p)
+
+instance (Show c, Show v) => Show (SurfaceFn c v) where
+ show (SFun _) = "Surface function"
+ -- show (SConst p) = "Surface constant: " ++ show p
+ show (SConst p) = "Surface constant"
+
+evalSurface :: SurfaceFn Color Double -> Int -> Double -> Double -> Properties Color Double
+evalSurface (SConst p) = \_ _ _ -> p
+evalSurface (SFun f) = f
+
+-- calculate surface properties, given the type of
+-- surface, and intersection point in object coordinates
+
+-- surface :: Surface SurfaceFn -> (Int, Point) -> (Vector, Properties)
+
+surface (Planar _ v0 v1) (n, p0, fn)
+ = (norm, evalSurface fn n' u v)
+ where norm = normalize $ cross v0 v1
+ (n', u, v) = planarUV n p0
+
+surface (Spherical _ v0 v1) (_, p0, fn)
+ = (norm, evalSurface fn 0 u v)
+ where x = xCoord p0
+ y = yCoord p0
+ z = zCoord p0
+ k = sqrt (1 - sq y)
+ theta = adjustRadian (atan2 (x / k) (z / k))
+ -- correct so that the image grows left-to-right
+ -- instead of right-to-left
+ u = 1.0 - clampf (theta / (2 * pi))
+ v = clampf ((y + 1) / 2)
+ norm = normalize $ cross v0 v1
+
+-- ZZ ignore the (incorrect) surface model, and estimate the normal
+-- from the intersection in object space
+surface (Cylindrical _ v0 v1) (_, p0, fn)
+ = (norm, evalSurface fn 0 u v)
+ where x = xCoord p0
+ y = yCoord p0
+ z = zCoord p0
+ u = clampf $ adjustRadian (atan2 x z) / (2 * pi)
+ v = y
+ norm = normalize $ cross v0 v1
+
+-- ZZ ignore the (incorrect) surface model, and estimate the normal
+-- from the intersection in object space
+surface (Conic _ v0 v1) (_, p0, fn)
+ = (norm, evalSurface fn 0 u v)
+ where x = xCoord p0
+ y = yCoord p0
+ z = zCoord p0
+ u = clampf $ adjustRadian (atan2 (x / y) (z / y)) / (2 * pi)
+ v = y
+ norm = normalize $ cross v0 v1
+
+planarUV face p0
+ = case face of
+ PlaneFace -> (0, x, z)
+
+ CubeFront -> (0, x, y)
+ CubeBack -> (1, x, y)
+ CubeLeft -> (2, z, y)
+ CubeRight -> (3, z, y)
+ CubeTop -> (4, x, z)
+ CubeBottom -> (5, x, z)
+
+ CylinderTop -> (1, (x + 1) / 2, (z + 1) / 2)
+ CylinderBottom -> (2, (x + 1) / 2, (z + 1) / 2)
+
+ ConeBase -> (1, (x + 1) / 2, (z + 1) / 2)
+ where x = xCoord p0
+ y = yCoord p0
+ z = zCoord p0
+
+-- misc
+
+adjustRadian :: Radian -> Radian
+adjustRadian r = if r > 0 then r else r + 2 * pi