]> gitweb.factorcode.org Git - factor.git/blob - unmaintained/4DNav/4DNav.factor
Merge branch 'master' of git://github.com/Bigot/factor-bgt
[factor.git] / unmaintained / 4DNav / 4DNav.factor
1 ! Copyright (C) 2008 Jeff Bigot\r
2 ! See http://factorcode.org/license.txt for BSD license.\r
3 USING: kernel \r
4 namespaces\r
5 accessors\r
6 make\r
7 math\r
8 math.functions\r
9 math.trig\r
10 math.parser\r
11 hashtables\r
12 sequences\r
13 combinators\r
14 continuations\r
15 colors\r
16 prettyprint\r
17 vars\r
18 quotations\r
19 io\r
20 io.directories\r
21 io.pathnames\r
22 help.markup\r
23 io.files\r
24 ui.gadgets.panes\r
25  ui\r
26        ui.gadgets\r
27        ui.traverse\r
28        ui.gadgets.borders\r
29        ui.gadgets.handler\r
30        ui.gadgets.slate\r
31        ui.gadgets.theme\r
32        ui.gadgets.frames\r
33        ui.gadgets.tracks\r
34        ui.gadgets.labels\r
35        ui.gadgets.labelled       \r
36        ui.gadgets.lists\r
37        ui.gadgets.buttons\r
38        ui.gadgets.packs\r
39        ui.gadgets.grids\r
40        ui.gestures\r
41        ui.tools.workspace\r
42        ui.gadgets.scrollers\r
43 splitting\r
44 vectors\r
45 math.vectors\r
46 rewrite-closures\r
47 self\r
48 values\r
49 4DNav.turtle\r
50 4DNav.window3D\r
51 4DNav.deep\r
52 4DNav.space-file-decoder\r
53 models\r
54 fry\r
55 adsoda\r
56 adsoda.tools\r
57 ;\r
58 \r
59 IN: 4DNav\r
60 VALUE: selected-file\r
61 VALUE: translation-step\r
62 VALUE: rotation-step\r
63 \r
64 3 to: translation-step \r
65 5 to: rotation-step\r
66 \r
67 VAR: selected-file-model\r
68 VAR: observer3d \r
69 VAR: view1 \r
70 VAR: view2\r
71 VAR: view3\r
72 VAR: view4\r
73 VAR: present-space\r
74 \r
75 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
76 \r
77 ! replacement of namespaces.lib\r
78     \r
79 : make* ( seq -- seq ) [ dup quotation? [ call ] [ ] if ] map ;\r
80 \r
81 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
82 ! waiting for deep-cleave-quots\r
83 \r
84 : 4D-Rxy ( angle -- Rx ) deg>rad\r
85 [ 1.0 , 0.0 , 0.0       , 0.0 ,\r
86   0.0 , 1.0 , 0.0       , 0.0 ,\r
87   0.0 , 0.0 , dup cos  , dup sin neg  ,\r
88   0.0 , 0.0 , dup sin  , dup cos  ,  ] 4 make-matrix nip ;\r
89 \r
90 : 4D-Rxz ( angle -- Ry ) deg>rad\r
91 [ 1.0 , 0.0       , 0.0 , 0.0 ,\r
92   0.0 , dup cos  , 0.0 , dup sin neg  ,\r
93   0.0 , 0.0       , 1.0 , 0.0 ,\r
94   0.0 , dup sin  , 0.0 , dup cos  ,  ] 4 make-matrix nip ;\r
95 \r
96 : 4D-Rxw ( angle -- Rz ) deg>rad\r
97 [ 1.0 , 0.0       , 0.0           , 0.0 ,\r
98   0.0 , dup cos  , dup sin neg  , 0.0 ,\r
99   0.0 , dup sin  , dup cos     , 0.0 ,\r
100   0.0 , 0.0       , 0.0           , 1.0 , ] 4 make-matrix nip ;\r
101 \r
102 : 4D-Ryz ( angle -- Rx ) deg>rad\r
103 [ dup cos  , 0.0 , 0.0 , dup sin neg  ,\r
104   0.0       , 1.0 , 0.0 , 0.0 ,\r
105   0.0       , 0.0 , 1.0 , 0.0 ,\r
106   dup sin  , 0.0 , 0.0 , dup cos  ,   ] 4 make-matrix nip ;\r
107 \r
108 : 4D-Ryw ( angle -- Ry ) deg>rad\r
109 [ dup cos  , 0.0 , dup sin neg  , 0.0 ,\r
110   0.0       , 1.0 , 0.0           , 0.0 ,\r
111   dup sin  , 0.0 , dup cos     , 0.0 ,\r
112   0.0       , 0.0 , 0.0        , 1.0 ,  ] 4 make-matrix nip ;\r
113 \r
114 : 4D-Rzw ( angle -- Rz ) deg>rad\r
115 [ dup cos  , dup sin neg  , 0.0 , 0.0 ,\r
116   dup sin  , dup cos     , 0.0 , 0.0 ,\r
117   0.0       , 0.0           , 1.0 , 0.0 ,\r
118   0.0       , 0.0          , 0.0 , 1.0 ,  ] 4 make-matrix nip ;\r
119 \r
120 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
121 ! UI\r
122 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
123 \r
124 : button* ( string quot -- button ) \r
125     closed-quot <repeat-button>  ;\r
126 \r
127 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
128\r
129 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
130 \r
131 : model-projection-chooser ( -- gadget )\r
132    observer3d> projection-mode>>\r
133    { { 1 "perspective" } { 0 "orthogonal" } } \r
134    <toggle-buttons> ;\r
135 \r
136 : collision-detection-chooser ( -- gadget )\r
137    observer3d> collision-mode>>\r
138    { { t "on" } { f "off" }  } <toggle-buttons> ;\r
139 \r
140 : model-projection ( x -- space ) \r
141     present-space>  swap space-project ;\r
142 \r
143 : update-observer-projections (  -- )\r
144     view1> relayout-1 \r
145     view2> relayout-1 \r
146     view3> relayout-1 \r
147     view4> relayout-1 ;\r
148 \r
149 : update-model-projections (  -- )\r
150     0 model-projection <model> view1> (>>model)\r
151     1 model-projection <model> view2> (>>model)\r
152     2 model-projection <model> view3> (>>model)\r
153     3 model-projection <model> view4> (>>model) ;\r
154 \r
155 : camera-action ( quot -- quot ) \r
156     [ drop [ ] observer3d>  \r
157     with-self update-observer-projections ] \r
158     make* closed-quot ;\r
159 \r
160 : win3D ( text gadget -- ) \r
161     "navigateur 4D : " rot append open-window ;\r
162 \r
163 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
164 ! 4D object manipulation\r
165 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
166 \r
167 : (mvt-4D) ( quot -- )   \r
168     present-space>  \r
169         swap call space-ensure-solids \r
170     >present-space \r
171     update-model-projections \r
172     update-observer-projections ;\r
173 \r
174 : rotation-4D ( m -- ) \r
175     '[ _ [ [ middle-of-space dup vneg ] keep \r
176         swap space-translate ] dip\r
177          space-transform \r
178          swap space-translate\r
179     ] (mvt-4D) ;\r
180 \r
181 : translation-4D ( v -- ) '[ _ space-translate ] (mvt-4D) ;\r
182 \r
183 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
184 ! menu\r
185 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
186 \r
187 : menu-rotations-4D ( -- gadget )\r
188     <frame>\r
189          <pile> 1 >>fill\r
190           "XY +" [ drop rotation-step 4D-Rxy rotation-4D ] \r
191                 button* add-gadget\r
192           "XY -" [ drop rotation-step neg 4D-Rxy rotation-4D ] \r
193                 button* add-gadget \r
194        @top-left grid-add    \r
195         <pile> 1 >>fill\r
196           "XZ +" [ drop rotation-step 4D-Rxz rotation-4D ] \r
197                 button* add-gadget\r
198           "XZ -" [ drop rotation-step neg 4D-Rxz rotation-4D ] \r
199                 button* add-gadget \r
200        @top grid-add    \r
201         <pile> 1 >>fill\r
202           "YZ +" [ drop rotation-step 4D-Ryz rotation-4D ] \r
203                 button* add-gadget\r
204           "YZ -" [ drop rotation-step neg 4D-Ryz rotation-4D ] \r
205                 button* add-gadget \r
206         @center grid-add\r
207          <pile> 1 >>fill\r
208           "XW +" [ drop rotation-step 4D-Rxw rotation-4D ] \r
209                 button* add-gadget\r
210           "XW -" [ drop rotation-step neg 4D-Rxw rotation-4D ] \r
211                 button* add-gadget \r
212         @top-right grid-add   \r
213          <pile> 1 >>fill\r
214           "YW +" [ drop rotation-step 4D-Ryw rotation-4D ] \r
215                 button* add-gadget\r
216           "YW -" [ drop rotation-step neg 4D-Ryw rotation-4D ] \r
217                 button* add-gadget \r
218        @right grid-add    \r
219          <pile> 1 >>fill\r
220           "ZW +" [ drop rotation-step 4D-Rzw rotation-4D ] \r
221                 button* add-gadget\r
222           "ZW -" [ drop rotation-step neg 4D-Rzw rotation-4D ] \r
223                 button* add-gadget \r
224        @bottom-right grid-add    \r
225 ;\r
226 \r
227 : menu-translations-4D ( -- gadget )\r
228     <frame> \r
229         <pile> 1 >>fill\r
230             <shelf> 1 >>fill  \r
231                 "X+" [ drop {  1 0 0 0 } translation-step v*n \r
232                     translation-4D ] \r
233                     button* add-gadget\r
234                 "X-" [ drop { -1 0 0 0 } translation-step v*n \r
235                     translation-4D ] \r
236                     button* add-gadget \r
237             add-gadget\r
238             "YZW" <label> add-gadget\r
239          @bottom-right grid-add\r
240          <pile> 1 >>fill\r
241             "XZW" <label> add-gadget\r
242             <shelf> 1 >>fill\r
243                 "Y+" [ drop  { 0  1 0 0 } translation-step v*n \r
244                     translation-4D ] \r
245                     button* add-gadget\r
246                 "Y-" [ drop  { 0 -1 0 0 } translation-step v*n \r
247                     translation-4D ] \r
248                     button* add-gadget \r
249                 add-gadget\r
250          @top-right grid-add\r
251          <pile> 1 >>fill\r
252             "XYW" <label> add-gadget\r
253             <shelf> 1 >>fill\r
254                 "Z+" [ drop { 0 0  1 0 } translation-step v*n \r
255                     translation-4D ] \r
256                     button* add-gadget\r
257                 "Z-" [ drop { 0 0 -1 0 } translation-step v*n \r
258                     translation-4D ] \r
259                     button* add-gadget \r
260                 add-gadget                 \r
261         @top-left grid-add     \r
262         <pile> 1 >>fill\r
263             <shelf> 1 >>fill\r
264                 "W+" [ drop { 0 0 0 1  } translation-step v*n \r
265                     translation-4D ] \r
266                     button* add-gadget\r
267                 "W-" [ drop { 0 0 0 -1 } translation-step v*n \r
268                     translation-4D ] \r
269                     button* add-gadget \r
270                 add-gadget\r
271             "XYZ" <label> add-gadget\r
272         @bottom-left grid-add \r
273         "X" <label> @center grid-add\r
274 ;\r
275 \r
276 : menu-4D ( -- gadget )  \r
277     <shelf> \r
278         "rotations" <label>     add-gadget\r
279         menu-rotations-4D       add-gadget\r
280         "translations" <label>  add-gadget\r
281         menu-translations-4D    add-gadget\r
282         0.5 >>align\r
283         { 0 10 } >>gap\r
284 ;\r
285 \r
286 \r
287 ! ------------------------------------------------------\r
288 \r
289 : redraw-model ( space -- )\r
290     >present-space \r
291     update-model-projections \r
292     update-observer-projections ;\r
293 \r
294 : load-model-file ( -- )\r
295   selected-file dup selected-file-model> set-model \r
296   read-model-file \r
297   redraw-model ;\r
298 \r
299 : mvt-3D-X ( turn pitch -- quot )\r
300     '[ turtle-pos> norm neg reset-turtle \r
301         _ turn-left \r
302         _ pitch-up \r
303         step-turtle ] ;\r
304 \r
305 : mvt-3D-1 ( -- quot )      90  0 mvt-3D-X ; inline\r
306 : mvt-3D-2 ( -- quot )      0  90 mvt-3D-X ; inline\r
307 : mvt-3D-3 ( -- quot )      0   0 mvt-3D-X ; inline\r
308 : mvt-3D-4 ( -- quot )      45 45 mvt-3D-X ; inline\r
309 \r
310 : camera-button ( string quot -- button ) \r
311     [ <label>  ] dip camera-action <repeat-button> ;\r
312 \r
313 ! ----------------------------------------------------------\r
314 ! file chooser\r
315 ! ----------------------------------------------------------\r
316 : <run-file-button> ( file-name -- button )\r
317   dup '[ drop  _  \ selected-file set-value load-model-file \r
318    ] \r
319  closed-quot  <roll-button> { 0 0 } >>align ;\r
320 \r
321 : <list-runner> ( -- gadget )\r
322     "resource:extra/4DNav" \r
323   <pile> 1 >>fill \r
324     over dup directory-files  \r
325     [ ".xml" tail? ] filter \r
326     [ append-path ] with map\r
327     [ <run-file-button> add-gadget ] each\r
328     swap <labelled-gadget> ;\r
329 \r
330 ! -----------------------------------------------------\r
331 \r
332 : menu-rotations-3D ( -- gadget )\r
333     <frame>\r
334         "Turn\n left"  [ rotation-step  turn-left  ] \r
335             camera-button   @left grid-add     \r
336         "Turn\n right" [ rotation-step turn-right ] \r
337             camera-button   @right grid-add     \r
338         "Pitch down"   [ rotation-step  pitch-down ] \r
339             camera-button   @bottom grid-add     \r
340         "Pitch up"     [ rotation-step  pitch-up   ] \r
341             camera-button   @top grid-add     \r
342         <shelf>  1 >>fill\r
343             "Roll left\n (ctl)"  [ rotation-step  roll-left  ] \r
344                 camera-button   add-gadget  \r
345             "Roll right\n(ctl)"  [ rotation-step  roll-right ] \r
346                 camera-button   add-gadget  \r
347         @center grid-add \r
348 ;\r
349 \r
350 : menu-translations-3D ( -- gadget )\r
351     <frame>\r
352         "left\n(alt)"        [ translation-step  strafe-left  ]\r
353             camera-button @left grid-add  \r
354         "right\n(alt)"       [ translation-step  strafe-right ]\r
355             camera-button @right grid-add     \r
356         "Strafe up \n (alt)" [ translation-step strafe-up    ] \r
357             camera-button @top grid-add\r
358         "Strafe down\n (alt)" [ translation-step strafe-down  ]\r
359             camera-button @bottom grid-add    \r
360         <pile>  1 >>fill\r
361             "Forward (ctl)"  [  translation-step step-turtle ] \r
362                 camera-button add-gadget\r
363             "Backward (ctl)" \r
364                 [ translation-step neg step-turtle ] \r
365                 camera-button   add-gadget\r
366         @center grid-add\r
367 ;\r
368 \r
369 : menu-quick-views ( -- gadget )\r
370     <shelf>\r
371         "View 1 (1)" mvt-3D-1 camera-button   add-gadget\r
372         "View 2 (2)" mvt-3D-2 camera-button   add-gadget\r
373         "View 3 (3)" mvt-3D-3 camera-button   add-gadget \r
374         "View 4 (4)" mvt-3D-4 camera-button   add-gadget \r
375 ;\r
376 \r
377 : menu-3D ( -- gadget ) \r
378     <pile>\r
379         <shelf>   \r
380             menu-rotations-3D    add-gadget\r
381             menu-translations-3D add-gadget\r
382             0.5 >>align\r
383             { 0 10 } >>gap\r
384         add-gadget\r
385         menu-quick-views add-gadget ; \r
386 \r
387 : add-keyboard-delegate ( obj -- obj )\r
388  <handler>\r
389 {\r
390         { T{ key-down f f "LEFT" }  \r
391             [ [ rotation-step turn-left ] camera-action ] }\r
392         { T{ key-down f f "RIGHT" } \r
393             [ [ rotation-step turn-right ] camera-action ] }\r
394         { T{ key-down f f "UP" }    \r
395             [ [ rotation-step pitch-down ] camera-action ] }\r
396         { T{ key-down f f "DOWN" }  \r
397             [ [ rotation-step pitch-up ] camera-action ] }\r
398 \r
399         { T{ key-down f { C+ } "UP" } \r
400            [ [ translation-step step-turtle ] camera-action ] }\r
401         { T{ key-down f { C+ } "DOWN" } \r
402             [ [ translation-step neg step-turtle ] \r
403                     camera-action ] }\r
404         { T{ key-down f { C+ } "LEFT" } \r
405             [ [ rotation-step roll-left ] camera-action ] }\r
406         { T{ key-down f { C+ } "RIGHT" } \r
407             [ [ rotation-step roll-right ] camera-action ] }\r
408 \r
409         { T{ key-down f { A+ } "LEFT" }  \r
410            [ [ translation-step strafe-left ] camera-action ] }\r
411         { T{ key-down f { A+ } "RIGHT" } \r
412           [ [ translation-step strafe-right ] camera-action ] }\r
413         { T{ key-down f { A+ } "UP" }    \r
414             [ [ translation-step strafe-up ] camera-action ] }\r
415         { T{ key-down f { A+ } "DOWN" }  \r
416            [ [ translation-step strafe-down ] camera-action ] }\r
417 \r
418 \r
419         { T{ key-down f f "1" } [ mvt-3D-1 camera-action ] }\r
420         { T{ key-down f f "2" } [ mvt-3D-2 camera-action ] }\r
421         { T{ key-down f f "3" } [ mvt-3D-3  camera-action ] }\r
422         { T{ key-down f f "4" } [ mvt-3D-4  camera-action ] }\r
423 \r
424     } [ make* ] map >hashtable >>table\r
425     ;    \r
426 \r
427 ! --------------------------------------------\r
428 ! print elements \r
429 ! --------------------------------------------\r
430 ! print-content\r
431 \r
432 GENERIC: adsoda-display-model ( x -- ) \r
433 \r
434 M: light adsoda-display-model \r
435 "\n light : " .\r
436      { \r
437         [ direction>> "direction : " pprint . ] \r
438         [ color>> "color : " pprint . ]\r
439     }   cleave\r
440     ;\r
441 \r
442 M: face adsoda-display-model \r
443      {\r
444         [ halfspace>> "halfspace : " pprint . ] \r
445         [ touching-corners>> "touching corners : " pprint . ]\r
446     }   cleave\r
447     ;\r
448 M: solid adsoda-display-model \r
449      {\r
450         [ name>> "solid called : " pprint . ] \r
451         [ color>> "color : " pprint . ]\r
452         [ dimension>> "dimension : " pprint . ]\r
453         [ faces>> "composed of faces : " pprint \r
454             [ adsoda-display-model ] each ]\r
455     }   cleave\r
456     ;\r
457 M: space adsoda-display-model \r
458      {\r
459         [ dimension>> "dimension : " pprint . ] \r
460         [ ambient-color>> "ambient-color : " pprint . ]\r
461         [ solids>> "composed of solids : " pprint \r
462             [ adsoda-display-model ] each ]\r
463         [ lights>> "composed of lights : " pprint \r
464             [ adsoda-display-model ] each ] \r
465     }   cleave\r
466     ;\r
467 \r
468 ! ----------------------------------------------\r
469 : menu-bar ( -- gadget )\r
470        <shelf>\r
471           "reinit" [ drop load-model-file ] button* add-gadget\r
472           selected-file-model> <label-control> add-gadget\r
473     ;\r
474 \r
475 \r
476 : controller-window* ( -- gadget )\r
477     { 0 1 } <track>\r
478         menu-bar f track-add\r
479         <list-runner>  \r
480             <limited-scroller>  \r
481             { 200 400 } >>max-dim\r
482         f track-add\r
483         <shelf>\r
484             "Projection mode : " <label> add-gadget\r
485             model-projection-chooser add-gadget\r
486         f track-add\r
487         <shelf>\r
488             "Collision detection (slow and buggy ) : " \r
489                 <label> add-gadget\r
490             collision-detection-chooser add-gadget\r
491         f track-add\r
492         <pile>\r
493             0.5 >>align    \r
494             menu-4D add-gadget \r
495             light-purple solid-interior\r
496             "4D movements" <labelled-gadget>\r
497         f track-add\r
498         <pile>\r
499             0.5 >>align\r
500             { 2 2 } >>gap\r
501             menu-3D add-gadget\r
502             light-purple solid-interior \r
503             "Camera 3D" <labelled-gadget>\r
504         f track-add      \r
505         gray solid-interior\r
506  ;\r
507  \r
508 : viewer-windows* ( --  )\r
509     "YZW" view1> win3D \r
510     "XZW" view2> win3D \r
511     "XYW" view3> win3D \r
512     "XYZ" view4> win3D   \r
513 ;\r
514 \r
515 : navigator-window* ( -- )\r
516     controller-window*\r
517     viewer-windows*   \r
518     add-keyboard-delegate\r
519     "navigateur 4D" open-window\r
520 ;\r
521 \r
522 : windows ( -- ) [ [ navigator-window* ] with-scope ] with-ui ;\r
523 \r
524 \r
525 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r
526 \r
527 : init-variables ( -- )\r
528     "choose a file" <model> >selected-file-model  \r
529     <observer> >observer3d\r
530     [ observer3d> >self\r
531       reset-turtle \r
532       45 turn-left \r
533       45 pitch-up \r
534       -300 step-turtle \r
535     ] with-scope\r
536     \r
537 ;\r
538 \r
539 \r
540 : init-models ( -- )\r
541     0 model-projection observer3d> <window3D> >view1\r
542     1 model-projection observer3d> <window3D> >view2\r
543     2 model-projection observer3d> <window3D> >view3\r
544     3 model-projection observer3d> <window3D> >view4\r
545 ;\r
546 \r
547 : 4DNav ( -- ) \r
548     init-variables\r
549     selected-file read-model-file >present-space\r
550     init-models\r
551     windows\r
552 ;\r
553 \r
554 MAIN: 4DNav\r
555 \r
556 \r