diff options
Diffstat (limited to 'src/Graphics/Formats/Collada/GenerateObjects.hs')
-rw-r--r-- | src/Graphics/Formats/Collada/GenerateObjects.hs | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/src/Graphics/Formats/Collada/GenerateObjects.hs b/src/Graphics/Formats/Collada/GenerateObjects.hs new file mode 100644 index 0000000..c1dcae7 --- /dev/null +++ b/src/Graphics/Formats/Collada/GenerateObjects.hs | |||
@@ -0,0 +1,285 @@ | |||
1 | module Graphics.Formats.Collada.GenerateObjects | ||
2 | where | ||
3 | |||
4 | import Data.Enumerable | ||
5 | import Data.Tree | ||
6 | import Data.Tuple.Enum | ||
7 | import Data.Word | ||
8 | import qualified Data.Vector as V | ||
9 | import Data.Vector (Vector) | ||
10 | import Graphics.Formats.Collada.ColladaTypes | ||
11 | import Graphics.Formats.Collada.Vector2D3D | ||
12 | |||
13 | -- type Scene = Tree SceneNode | ||
14 | n x = Node x [] | ||
15 | makeScene sid sceneNodes = Node (SceneNode sid NOTYPE [] tranrot [] [] [] []) (map n sceneNodes) | ||
16 | |||
17 | -- | An animated cube | ||
18 | animatedCube :: (Scene, [Animation]) | ||
19 | animatedCube = (aScene, animation) | ||
20 | |||
21 | -- | Example scene with a cube | ||
22 | aScene :: Scene | ||
23 | aScene = makeScene "aCube" (cameraAndLight ++ [aCube]) | ||
24 | |||
25 | lightedGeometry :: [Geometry] -> Scene | ||
26 | lightedGeometry g = makeScene "g" (cameraAndLight ++ (map ge g)) | ||
27 | |||
28 | lightedSceneNode :: SceneNode -> Scene | ||
29 | lightedSceneNode node = makeScene "node" (cameraAndLight ++ [node]) | ||
30 | |||
31 | lightedScene :: Scene -> Scene | ||
32 | lightedScene node = Node EmptyRoot ((map n cameraAndLight) ++ [node]) | ||
33 | |||
34 | -- | Every scene needs a camera and light | ||
35 | cameraAndLight = [ aCamera, | ||
36 | pointLight "pointLight" 3 4 10, | ||
37 | pointLight "pointL" (-500) 1000 400 ] | ||
38 | |||
39 | rot x y z = Rotate (V3 1 0 0) x | ||
40 | (V3 0 1 0) y | ||
41 | (V3 0 0 1) z | ||
42 | |||
43 | tranrot = [ ("tran", Translate (V3 0 0 0)), ("rot", rot 0 0 0) ] -- there have to be values for an animation channel to access | ||
44 | |||
45 | aCamera = SceneNode "camera0" NOTYPE [] | ||
46 | [("tran", Translate (V3 1000 2000 2500)), | ||
47 | ("rot", rot (-22) 13 0)] | ||
48 | -- [("lookat", LookAt (1000,1000,2500) (0,0,0) (0,1,0))] | ||
49 | [(Perspective "Persp" (ViewSizeXY (37,37)) (Z 10 1000) )] | ||
50 | [] [] [] | ||
51 | |||
52 | pointLight str x y z = SceneNode str NOTYPE [] | ||
53 | [("tran", Translate (V3 x y z)), | ||
54 | ("rot", rot 0 0 0)] | ||
55 | [] [] [] | ||
56 | [(Point "point" (RGB 1 1 1) (Attenuation 1 0 0) )] | ||
57 | |||
58 | ambientLight = SceneNode "ambientLight" NOTYPE [] | ||
59 | [("tran", Translate (V3 (-500) 1000 400)), | ||
60 | ("rot", rot 0 0 0)] | ||
61 | [] [] [] | ||
62 | [(Ambient "ambient" (RGB 1 1 1) )] | ||
63 | |||
64 | aCube :: SceneNode | ||
65 | aCube = SceneNode "cube_geometry" NOTYPE [] tranrot [] [] [cube] [] | ||
66 | |||
67 | obj :: String -> [Geometry] -> V3 -> SceneNode | ||
68 | obj name c tr = SceneNode name NOTYPE [] | ||
69 | [("tran", Translate tr), | ||
70 | ("rot", rot 0 0 0)] | ||
71 | [] [] | ||
72 | c -- geometries | ||
73 | [] | ||
74 | |||
75 | -- | Example animation of the cube | ||
76 | animation :: [Animation] | ||
77 | animation = [Node ("cube_rotate", anim_channel) []] | ||
78 | |||
79 | anim_channel = AnimChannel ("input", [0, 1, 2, 3], [[("name","TIME"), ("type","Float")]] ) | ||
80 | ("output",[0, 50, 100, 150], [[("name","ANGLE"), ("type","Float")]] ) | ||
81 | [ Bezier [-0.333333, 0] [2.5, 0], -- intangent outtangent | ||
82 | Bezier [5,0] [7.916667, 0], | ||
83 | Bezier [8.333333, 56] [9.166667, 56], | ||
84 | Bezier [9.583333, 18.666666] [10.333333, -14.933331] ] | ||
85 | [("cube_geometry/rotateY","ANGLE")] | ||
86 | |||
87 | fl = V.fromList | ||
88 | |||
89 | -- | A blue/textured cube | ||
90 | cube :: Geometry | ||
91 | cube = Geometry "cube" | ||
92 | [PL (LinePrimitive | ||
93 | (fl [fl [0,2,3,1], fl [0,1,5,4], fl [6,7,3,2], fl [0,4,6,2], fl [3,7,5,1], fl [5,7,6,4]]) -- indices to vertices | ||
94 | (fl [fl [0,0,0,0], fl [1,1,1,1], fl [2,2,2,2], fl [3,3,3,3], fl [4,4,4,4], fl [5,5,5,5]]) -- indices to normals | ||
95 | (fl [fl [0,1,2,3], fl [0,1,2,3], fl [0,1,2,3], fl [0,1,2,3], fl [0,1,2,3], fl [0,1,2,3]]) -- indices to texture coordinates, use an empty list when no texture | ||
96 | [logo] | ||
97 | -- [blue] | ||
98 | )] | ||
99 | (Vertices "cube_vertices" | ||
100 | (fl [(V3 (-10) 10 10), (V3 10 10 10), (V3 (-10) (-10) 10), (V3 10 (-10) 10), -- vertices | ||
101 | (V3 (-10) 10 (-10)),(V3 10 10 (-10)),(V3 (-10) (-10) (-10)),(V3 10 (-10) (-10))]) | ||
102 | (fl [(V3 0 0 1), (V3 0 1 0), (V3 0 (-1) 0), (V3 (-1) 0 0), (V3 1 0 0), (V3 0 0 (-1))]) -- normals | ||
103 | ) | ||
104 | |||
105 | blue = ("blue", COMMON "" NoParam | ||
106 | (PhongCol [CEmission (Color (V4 0 0 0 1)), | ||
107 | CAmbient (Color (V4 0 0 0 1)), | ||
108 | CDiffuse(Color (V4 0.137255 0.403922 0.870588 1)), | ||
109 | CSpecular(Color (V4 0.5 0.5 0.5 1)), | ||
110 | CShininess 16, | ||
111 | CReflective (Color (V4 0 0 0 1)), | ||
112 | CReflectivity 0.5, | ||
113 | CTransparent (Color (V4 0 0 0 1)), | ||
114 | CTransparency 1, | ||
115 | CIndex_of_refraction 0] | ||
116 | ) | ||
117 | "" | ||
118 | ) | ||
119 | |||
120 | diffuse c str (a, COMMON asset NoParam (PhongCol cs) s) = ("color_" ++ str, COMMON asset NoParam (PhongCol (map (replaceDiff c) cs)) s) | ||
121 | |||
122 | replaceDiff c (CDiffuse _) = CDiffuse (Color c) | ||
123 | replaceDiff _ c = c | ||
124 | |||
125 | ambient c str (a, COMMON asset NoParam (PhongCol cs) s) = ("color_" ++ str, COMMON asset NoParam (PhongCol (map (replaceAmb c) cs)) s) | ||
126 | |||
127 | replaceAmb c (CAmbient _) = CAmbient (Color c) | ||
128 | replaceAmb _ c = c | ||
129 | |||
130 | |||
131 | getDiffuseColor ( CDiffuse (Color c) ) = Just c | ||
132 | getDiffuseColor _ = Nothing | ||
133 | |||
134 | getAmbientColor ( CAmbient (Color c) ) = Just c | ||
135 | getAmbientColor _ = Nothing | ||
136 | |||
137 | logo = ("haskell-logo", COMMON "" NoParam | ||
138 | (PhongTex [(TDiffuse tex)] | ||
139 | [[0,0,1,0,1,1,0,1]] -- [u0,v0,u1,v1,..] -coordinates (Floats between 0 and 1) that point into the texture | ||
140 | ) | ||
141 | "" | ||
142 | ) | ||
143 | |||
144 | tex = Texture "logo" "Haskell-Logo-Variation.png" Nothing | ||
145 | |||
146 | polys :: Vector V3 -> Vector V3 -> Vector (Vector Int) -> Vector (Vector Int) -> [Geometry] | ||
147 | polys p n pi ni = [Geometry "polygons" | ||
148 | [PL (LinePrimitive pi -- indices to vertices | ||
149 | ni -- indices to normals | ||
150 | V.empty -- no texure | ||
151 | [blue] | ||
152 | )] | ||
153 | (Vertices "polygons_vertices" p n)] | ||
154 | |||
155 | |||
156 | lines :: Vector V3 -> Vector V3 -> Vector (Vector Int) -> Vector (Vector Int) -> [Geometry] | ||
157 | lines p n pi ni = [Geometry "lines" | ||
158 | [LS (LinePrimitive pi -- indices to vertices | ||
159 | ni -- indices to normals | ||
160 | V.empty -- no texure | ||
161 | [blue] | ||
162 | )] | ||
163 | (Vertices "lines_vertices" p n)] | ||
164 | |||
165 | |||
166 | trifans :: Vector V3 -> Vector V3 -> Vector (Vector Int)-> Vector (Vector Int) -> [Geometry] | ||
167 | trifans p n pi ni = [Geometry "trifans" | ||
168 | [Trf (LinePrimitive pi -- indices to vertices | ||
169 | ni -- indices to normals | ||
170 | V.empty -- no texure | ||
171 | [blue] | ||
172 | )] | ||
173 | (Vertices "trifans_vertices" p n)] | ||
174 | |||
175 | |||
176 | tristrips :: Vector V3 -> Vector V3 -> Vector (Vector Int) -> Vector (Vector Int) -> [Geometry] | ||
177 | tristrips p n pi ni = [Geometry "tristrips" | ||
178 | [Trs (LinePrimitive pi -- indices to vertices | ||
179 | ni -- indices to normals | ||
180 | V.empty -- no texure | ||
181 | [blue] | ||
182 | )] | ||
183 | (Vertices "trifans_vertices" p n)] | ||
184 | |||
185 | |||
186 | ge :: Geometry -> SceneNode | ||
187 | ge (Geometry name p v) = obj name [Geometry name p v] (V3 0 0 0) | ||
188 | -- ------------------ | ||
189 | -- a bigger example | ||
190 | -- ------------------ | ||
191 | animatedCubes = (scene2, animation2) | ||
192 | animatedCubes2 = [(scene2, animation2)] | ||
193 | |||
194 | scene2 :: Scene | ||
195 | scene2 = Node EmptyRoot $ [ n aCamera, n (pointLight "pl" (-500) 1000 400) ] ++ (map n test_objs) | ||
196 | |||
197 | -- | Animation of several cubes | ||
198 | animation2 :: [Animation] | ||
199 | animation2 = [Node ("cube_rotate", new_channels anim_channel test_objs) []] | ||
200 | |||
201 | emptyAnimation :: [[Animation]] | ||
202 | emptyAnimation = [] | ||
203 | |||
204 | emptyAnim :: [Animation] | ||
205 | emptyAnim = [] | ||
206 | |||
207 | -- | generate an animation that points to the cubes | ||
208 | new_channels :: AnimChannel -> [SceneNode] -> AnimChannel | ||
209 | new_channels (AnimChannel i o interp _) nodes = | ||
210 | AnimChannel i o interp $ map (\obj -> ((obj_name obj) ++ "/rotateY","ANGLE")) nodes | ||
211 | |||
212 | obj_name (SceneNode n _ _ _ _ _ _ _) = n | ||
213 | |||
214 | -- | a helper function for xyz_grid | ||
215 | tran :: SceneNode -> V3 -> String -> SceneNode | ||
216 | tran (SceneNode _ typ layer tr cam contr geo light) v3 str = | ||
217 | (SceneNode str typ layer [("tr", Translate v3)] cam contr geo light) | ||
218 | |||
219 | test_objs :: [SceneNode] | ||
220 | test_objs = xyz_grid 10 10 10 150 aCube | ||
221 | |||
222 | -- | Generate a 3 dimensional grid where an object (stored in a SceneNode) is repeated in along the grid | ||
223 | xyz_grid :: Int -> Int -> Int -> Float -> SceneNode -> [SceneNode] | ||
224 | xyz_grid x y z d obj = zipWith (tran obj) | ||
225 | (concat (concat (x_line x (map (map (\(V3 a b c) -> (V3 (a+d) b c)))) $ | ||
226 | x_line y (map (\(V3 a b c) -> (V3 a (b+d) c))) $ | ||
227 | x_line z (\(V3 a b c) -> (V3 a b (c+d))) (V3 0 0 0)) )) | ||
228 | (enum_obj obj [1..(x*y*z)]) | ||
229 | |||
230 | enum_obj obj (i:is) = ((obj_name obj) ++ (show i)) : (enum_obj obj is) | ||
231 | |||
232 | x_line 0 change value = [] | ||
233 | x_line n change value = value : ( x_line (n-1) change (change value) ) | ||
234 | |||
235 | ------------------------------------------------------------------- | ||
236 | -- visualizing a stream of positions with copies of a base object | ||
237 | ------------------------------------------------------------------- | ||
238 | |||
239 | positions = map (\(x, y, z) -> (x*100, y*100, z*100) ) $ | ||
240 | -- map (\(x,y,z) -> (fromIntegral x, fromIntegral y, fromIntegral z)) | ||
241 | en | ||
242 | |||
243 | en :: [(Float,Float,Float)] | ||
244 | -- en :: [(Word8,Word8,Word8)] | ||
245 | -- en = take 100 enumerate | ||
246 | -- en = take 100 all3s | ||
247 | |||
248 | en = map (\(V x y)->(x*20,y*20,0)) [] | ||
249 | |||
250 | base_objects = map (rename aCube) (map show [1..(length positions)]) | ||
251 | |||
252 | rename :: SceneNode -> String -> SceneNode | ||
253 | rename (SceneNode str typ layer tr cam contr geo light) s = | ||
254 | (SceneNode (str ++ s) typ layer tr cam contr geo light) | ||
255 | |||
256 | getName (SceneNode str _ _ _ _ _ _ _) = str | ||
257 | get_name (Geometry str _ _) = str | ||
258 | |||
259 | animatedStream = (streamScene base_objects, streamAnimation positions base_objects) | ||
260 | |||
261 | streamScene :: [SceneNode] -> Scene | ||
262 | streamScene objects = Node EmptyRoot $ [ n aCamera, | ||
263 | n (pointLight "pl" (-500) 1000 400) ] ++ | ||
264 | (map n $ objects) | ||
265 | |||
266 | streamAnimation :: [(Float,Float,Float)] -> [SceneNode] -> [Animation] | ||
267 | streamAnimation ps base_objects = | ||
268 | [Node ("cube_stream", EmptyAnim) (map n $ concat $ | ||
269 | zipWith (\ind bo -> [tr_channel ind ((show ind) ++ "1") bo (length ps) s1 "X"] ++ | ||
270 | [tr_channel ind ((show ind) ++ "2") bo (length ps) s2 "Y"] ++ | ||
271 | [tr_channel ind ((show ind) ++ "3") bo (length ps) s3 "Z"]) | ||
272 | [1..(length ps)] (map getName base_objects) ) | ||
273 | ] | ||
274 | where | ||
275 | s1 = map (\(a,b,c) -> a) ps | ||
276 | s2 = map (\(a,b,c) -> b) ps | ||
277 | s3 = map (\(a,b,c) -> c) ps | ||
278 | |||
279 | tr_channel ind name bname lps s c = ( "anim" ++ name, | ||
280 | AnimChannel ("input", map (*0.3) (map fromIntegral [0..(lps-1)]), [[("name","TIME"), ("type","Float")]] ) | ||
281 | ("output", (take ind s) ++ (take (lps-ind) (repeat (head (drop ind s)))), | ||
282 | [[("name",c), ("type","Float")]] ) | ||
283 | (take lps (repeat Linear)) | ||
284 | [(bname ++ "/tran",c)] | ||
285 | ) | ||