summaryrefslogtreecommitdiff
path: root/InfinitePlane.hs
blob: f35393237a87de7fddcb08efcbed58aced02693c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
module InfinitePlane where

import LambdaCube.GL.Mesh as LambdaCubeGL
import LambdaCube.GL
import qualified Data.Vector as V
import qualified Data.Map as Map

-- | You can draw an infinite plane using the standard rasterization pipeline.
-- The homogeneous coordinates it uses can represent "ideal" points (otherwise
-- known as vanishing points or points at infinity) just as happily as regular
-- Euclidean points, and likewise it is perfectly practical to set up a
-- projection matrix which places the far plane at infinity.
--
-- A simple way to do this would be to use one triangle per quadrant, as
-- follows:
xyplane_inf :: LambdaCubeGL.Mesh
xyplane_inf = Mesh
    -- vertices [x,y,z,w], for drawing an (x,y) coordinate plane, at (z==0):
    { mAttributes = Map.singleton "position" $ A_V4F $ V.fromList
        [ V4  0    0   0  1
        , V4  1    0   0  0
        , V4  0    1   0  0
        , V4 (-1)  0   0  0
        , V4  0   (-1) 0  0
        ]
    -- draw 4 triangles using indices: (0,1,2); (0,2,3); (0,3,4); (0,4,1)
    , mPrimitive = P_TrianglesI $ V.fromList
        [ 0, 1, 2
        , 0, 2, 3
        , 0, 3, 4
        , 0, 4, 1
        ]
    }

times1000 (V4 a b c d) = V4 (f a) (f b) (f c) d where f = (* 10000.0)


-- | This represents the xy-plane as a large triangle.  This makes it easier
-- to interpolate 3d world coordinates in the fragment.
xyplane :: LambdaCubeGL.Mesh
xyplane = Mesh
    { mAttributes = Map.singleton "position" $ A_V4F $ V.fromList $ map times1000
        [ V4             0             1 0 1
        , V4    (1/sqrt 2) ((-1)/sqrt 2) 0 1
        , V4 ((-1)/sqrt 2) ((-1)/sqrt 2) 0 1
        ]
    , mPrimitive = P_TrianglesI $ V.fromList
        [ 0, 1, 2
        ]
    }

-- | This represents the xz-plane as a large triangle.  This makes it easier
-- to interpolate 3d world coordinates in the fragment.
xzplane :: LambdaCubeGL.Mesh
xzplane = Mesh
    { mAttributes = Map.singleton "position" $ A_V4F $ V.fromList $ map times1000
        [ V4             0 0             1 1
        , V4    (1/sqrt 2) 0 ((-1)/sqrt 2) 1
        , V4 ((-1)/sqrt 2) 0 ((-1)/sqrt 2) 1
        ]
    , mPrimitive = P_TrianglesI $ V.fromList
        [ 0, 1, 2
        ]
    }