factor/extra/4DNav/4DNav.factor

568 lines
17 KiB
Factor
Executable File

! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: kernel
namespaces
accessors
assocs
make
math
math.functions
math.trig
math.parser
hashtables
sequences
combinators
continuations
colors
colors.constants
prettyprint
vars
quotations
io
io.directories
io.pathnames
help.markup
io.files
ui.gadgets.panes
ui
ui.gadgets
ui.traverse
ui.gadgets.borders
ui.gadgets.frames
ui.gadgets.tracks
ui.gadgets.labels
ui.gadgets.labeled
ui.gadgets.lists
ui.gadgets.buttons
ui.gadgets.packs
ui.gadgets.grids
ui.gadgets.corners
ui.gestures
ui.gadgets.scrollers
splitting
vectors
math.vectors
values
4DNav.turtle
4DNav.window3D
4DNav.deep
4DNav.space-file-decoder
models
fry
adsoda
adsoda.tools
;
QUALIFIED-WITH: ui.pens.solid s
QUALIFIED-WITH: ui.gadgets.wrappers w
IN: 4DNav
VALUE: selected-file
VALUE: translation-step
VALUE: rotation-step
3 to: translation-step
5 to: rotation-step
VAR: selected-file-model
VAR: observer3d
VAR: view1
VAR: view2
VAR: view3
VAR: view4
VAR: present-space
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! namespace utilities
: closed-quot ( quot -- quot )
namestack swap '[ namestack [ _ set-namestack @ ] dip set-namestack ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! waiting for deep-cleave-quots
: 4D-Rxy ( angle -- Rx ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , dup cos , dup sin neg ,
0.0 , 0.0 , dup sin , dup cos , ] 4 make-matrix nip ;
: 4D-Rxz ( angle -- Ry ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , dup cos , 0.0 , dup sin neg ,
0.0 , 0.0 , 1.0 , 0.0 ,
0.0 , dup sin , 0.0 , dup cos , ] 4 make-matrix nip ;
: 4D-Rxw ( angle -- Rz ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , dup cos , dup sin neg , 0.0 ,
0.0 , dup sin , dup cos , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
: 4D-Ryz ( angle -- Rx ) deg>rad
[ dup cos , 0.0 , 0.0 , dup sin neg ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , 1.0 , 0.0 ,
dup sin , 0.0 , 0.0 , dup cos , ] 4 make-matrix nip ;
: 4D-Ryw ( angle -- Ry ) deg>rad
[ dup cos , 0.0 , dup sin neg , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
dup sin , 0.0 , dup cos , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
: 4D-Rzw ( angle -- Rz ) deg>rad
[ dup cos , dup sin neg , 0.0 , 0.0 ,
dup sin , dup cos , 0.0 , 0.0 ,
0.0 , 0.0 , 1.0 , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! UI
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: button* ( string quot -- button )
closed-quot <repeat-button> ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: model-projection-chooser ( -- gadget )
observer3d> projection-mode>>
{ { 1 "perspective" } { 0 "orthogonal" } }
<radio-buttons> ;
: collision-detection-chooser ( -- gadget )
observer3d> collision-mode>>
{ { t "on" } { f "off" } } <radio-buttons> ;
: model-projection ( x -- space )
present-space> swap space-project ;
: update-observer-projections ( -- )
view1> relayout-1
view2> relayout-1
view3> relayout-1
view4> relayout-1 ;
: update-model-projections ( -- )
0 model-projection <model> view1> (>>model)
1 model-projection <model> view2> (>>model)
2 model-projection <model> view3> (>>model)
3 model-projection <model> view4> (>>model) ;
: camera-action ( quot -- quot )
'[ drop _ observer3d>
with-self update-observer-projections ]
closed-quot ;
: win3D ( text gadget -- )
"navigateur 4D : " rot append open-window ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 4D object manipulation
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: (mvt-4D) ( quot -- )
present-space>
swap call space-ensure-solids
>present-space
update-model-projections
update-observer-projections ; inline
: rotation-4D ( m -- )
'[ _ [ [ middle-of-space dup vneg ] keep
swap space-translate ] dip
space-transform
swap space-translate
] (mvt-4D) ;
: translation-4D ( v -- ) '[ _ space-translate ] (mvt-4D) ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! menu
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: menu-rotations-4D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
<pile> 1 >>fill
"XY +" [ drop rotation-step 4D-Rxy rotation-4D ]
button* add-gadget
"XY -" [ drop rotation-step neg 4D-Rxy rotation-4D ]
button* add-gadget
@top-left grid-add
<pile> 1 >>fill
"XZ +" [ drop rotation-step 4D-Rxz rotation-4D ]
button* add-gadget
"XZ -" [ drop rotation-step neg 4D-Rxz rotation-4D ]
button* add-gadget
@top grid-add
<pile> 1 >>fill
"YZ +" [ drop rotation-step 4D-Ryz rotation-4D ]
button* add-gadget
"YZ -" [ drop rotation-step neg 4D-Ryz rotation-4D ]
button* add-gadget
@center grid-add
<pile> 1 >>fill
"XW +" [ drop rotation-step 4D-Rxw rotation-4D ]
button* add-gadget
"XW -" [ drop rotation-step neg 4D-Rxw rotation-4D ]
button* add-gadget
@top-right grid-add
<pile> 1 >>fill
"YW +" [ drop rotation-step 4D-Ryw rotation-4D ]
button* add-gadget
"YW -" [ drop rotation-step neg 4D-Ryw rotation-4D ]
button* add-gadget
@right grid-add
<pile> 1 >>fill
"ZW +" [ drop rotation-step 4D-Rzw rotation-4D ]
button* add-gadget
"ZW -" [ drop rotation-step neg 4D-Rzw rotation-4D ]
button* add-gadget
@bottom-right grid-add
;
: menu-translations-4D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
<pile> 1 >>fill
<shelf> 1 >>fill
"X+" [ drop { 1 0 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
"X-" [ drop { -1 0 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
"YZW" <label> add-gadget
@bottom-right grid-add
<pile> 1 >>fill
"XZW" <label> add-gadget
<shelf> 1 >>fill
"Y+" [ drop { 0 1 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
"Y-" [ drop { 0 -1 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
@top-right grid-add
<pile> 1 >>fill
"XYW" <label> add-gadget
<shelf> 1 >>fill
"Z+" [ drop { 0 0 1 0 } translation-step v*n
translation-4D ]
button* add-gadget
"Z-" [ drop { 0 0 -1 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
@top-left grid-add
<pile> 1 >>fill
<shelf> 1 >>fill
"W+" [ drop { 0 0 0 1 } translation-step v*n
translation-4D ]
button* add-gadget
"W-" [ drop { 0 0 0 -1 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
"XYZ" <label> add-gadget
@bottom-left grid-add
"X" <label> @center grid-add
;
: menu-4D ( -- gadget )
<shelf>
"rotations" <label> add-gadget
menu-rotations-4D add-gadget
"translations" <label> add-gadget
menu-translations-4D add-gadget
0.5 >>align
{ 0 10 } >>gap
;
! ------------------------------------------------------
: redraw-model ( space -- )
>present-space
update-model-projections
update-observer-projections ;
: load-model-file ( -- )
selected-file dup selected-file-model> set-model
read-model-file
redraw-model ;
: mvt-3D-X ( turn pitch -- quot )
'[ turtle-pos> norm neg reset-turtle
_ turn-left
_ pitch-up
step-turtle ] ;
: mvt-3D-1 ( -- quot ) 90 0 mvt-3D-X ; inline
: mvt-3D-2 ( -- quot ) 0 90 mvt-3D-X ; inline
: mvt-3D-3 ( -- quot ) 0 0 mvt-3D-X ; inline
: mvt-3D-4 ( -- quot ) 45 45 mvt-3D-X ; inline
: camera-button ( string quot -- button )
[ <label> ] dip camera-action <repeat-button> ;
! ----------------------------------------------------------
! file chooser
! ----------------------------------------------------------
: <run-file-button> ( file-name -- button )
dup '[ drop _ \ selected-file set-value load-model-file
]
closed-quot <roll-button> { 0 0 } >>align ;
: <list-runner> ( -- gadget )
"resource:extra/4DNav"
<pile> 1 >>fill
over dup directory-files
[ ".xml" tail? ] filter
[ append-path ] with map
[ <run-file-button> add-gadget ] each
swap <labeled-gadget> ;
! -----------------------------------------------------
: menu-rotations-3D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
"Turn\n left" [ rotation-step turn-left ]
camera-button @left grid-add
"Turn\n right" [ rotation-step turn-right ]
camera-button @right grid-add
"Pitch down" [ rotation-step pitch-down ]
camera-button @bottom grid-add
"Pitch up" [ rotation-step pitch-up ]
camera-button @top grid-add
<shelf> 1 >>fill
"Roll left\n (ctl)" [ rotation-step roll-left ]
camera-button add-gadget
"Roll right\n(ctl)" [ rotation-step roll-right ]
camera-button add-gadget
@center grid-add
;
: menu-translations-3D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
"left\n(alt)" [ translation-step strafe-left ]
camera-button @left grid-add
"right\n(alt)" [ translation-step strafe-right ]
camera-button @right grid-add
"Strafe up \n (alt)" [ translation-step strafe-up ]
camera-button @top grid-add
"Strafe down\n (alt)" [ translation-step strafe-down ]
camera-button @bottom grid-add
<pile> 1 >>fill
"Forward (ctl)" [ translation-step step-turtle ]
camera-button add-gadget
"Backward (ctl)"
[ translation-step neg step-turtle ]
camera-button add-gadget
@center grid-add
;
: menu-quick-views ( -- gadget )
<shelf>
"View 1 (1)" mvt-3D-1 camera-button add-gadget
"View 2 (2)" mvt-3D-2 camera-button add-gadget
"View 3 (3)" mvt-3D-3 camera-button add-gadget
"View 4 (4)" mvt-3D-4 camera-button add-gadget
;
: menu-3D ( -- gadget )
<pile>
<shelf>
menu-rotations-3D add-gadget
menu-translations-3D add-gadget
0.5 >>align
{ 0 10 } >>gap
add-gadget
menu-quick-views add-gadget ;
TUPLE: handler < w:wrapper table ;
: <handler> ( child -- handler ) handler w:new-wrapper ;
M: handler handle-gesture ( gesture gadget -- ? )
tuck table>> at dup [ call( gadget -- ) f ] [ 2drop t ] if ;
: add-keyboard-delegate ( obj -- obj )
<handler>
H{
{ T{ key-down f f "LEFT" }
[ [ rotation-step turn-left ] camera-action ] }
{ T{ key-down f f "RIGHT" }
[ [ rotation-step turn-right ] camera-action ] }
{ T{ key-down f f "UP" }
[ [ rotation-step pitch-down ] camera-action ] }
{ T{ key-down f f "DOWN" }
[ [ rotation-step pitch-up ] camera-action ] }
{ T{ key-down f { C+ } "UP" }
[ [ translation-step step-turtle ] camera-action ] }
{ T{ key-down f { C+ } "DOWN" }
[ [ translation-step neg step-turtle ]
camera-action ] }
{ T{ key-down f { C+ } "LEFT" }
[ [ rotation-step roll-left ] camera-action ] }
{ T{ key-down f { C+ } "RIGHT" }
[ [ rotation-step roll-right ] camera-action ] }
{ T{ key-down f { A+ } "LEFT" }
[ [ translation-step strafe-left ] camera-action ] }
{ T{ key-down f { A+ } "RIGHT" }
[ [ translation-step strafe-right ] camera-action ] }
{ T{ key-down f { A+ } "UP" }
[ [ translation-step strafe-up ] camera-action ] }
{ T{ key-down f { A+ } "DOWN" }
[ [ translation-step strafe-down ] camera-action ] }
{ T{ key-down f f "1" } [ mvt-3D-1 camera-action ] }
{ T{ key-down f f "2" } [ mvt-3D-2 camera-action ] }
{ T{ key-down f f "3" } [ mvt-3D-3 camera-action ] }
{ T{ key-down f f "4" } [ mvt-3D-4 camera-action ] }
} >>table
;
! --------------------------------------------
! print elements
! --------------------------------------------
! print-content
GENERIC: adsoda-display-model ( x -- )
M: light adsoda-display-model
"\n light : " .
{
[ direction>> "direction : " pprint . ]
[ color>> "color : " pprint . ]
} cleave
;
M: face adsoda-display-model
{
[ halfspace>> "halfspace : " pprint . ]
[ touching-corners>> "touching corners : " pprint . ]
} cleave
;
M: solid adsoda-display-model
{
[ name>> "solid called : " pprint . ]
[ color>> "color : " pprint . ]
[ dimension>> "dimension : " pprint . ]
[ faces>> "composed of faces : " pprint
[ adsoda-display-model ] each ]
} cleave
;
M: space adsoda-display-model
{
[ dimension>> "dimension : " pprint . ]
[ ambient-color>> "ambient-color : " pprint . ]
[ solids>> "composed of solids : " pprint
[ adsoda-display-model ] each ]
[ lights>> "composed of lights : " pprint
[ adsoda-display-model ] each ]
} cleave
;
! ----------------------------------------------
: menu-bar ( -- gadget )
<shelf>
"reinit" [ drop load-model-file ] button* add-gadget
selected-file-model> <label-control> add-gadget
;
: controller-window* ( -- gadget )
{ 0 1 } <track>
menu-bar f track-add
<list-runner>
<scroller>
f track-add
<shelf>
"Projection mode : " <label> add-gadget
model-projection-chooser add-gadget
f track-add
<shelf>
"Collision detection (slow and buggy ) : "
<label> add-gadget
collision-detection-chooser add-gadget
f track-add
<pile>
0.5 >>align
menu-4D add-gadget
COLOR: purple s:<solid> >>interior
"4D movements" <labeled-gadget>
f track-add
<pile>
0.5 >>align
{ 2 2 } >>gap
menu-3D add-gadget
COLOR: purple s:<solid> >>interior
"Camera 3D" <labeled-gadget>
f track-add
COLOR: gray s:<solid> >>interior
;
: viewer-windows* ( -- )
"YZW" view1> win3D
"XZW" view2> win3D
"XYW" view3> win3D
"XYZ" view4> win3D
;
: navigator-window* ( -- )
controller-window*
viewer-windows*
add-keyboard-delegate
"navigateur 4D" open-window
;
: windows ( -- ) [ [ navigator-window* ] with-scope ] with-ui ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init-variables ( -- )
"choose a file" <model> >selected-file-model
<observer> >observer3d
[ observer3d> >self
reset-turtle
45 turn-left
45 pitch-up
-300 step-turtle
] with-scope
;
: init-models ( -- )
0 model-projection observer3d> <window3D> >view1
1 model-projection observer3d> <window3D> >view2
2 model-projection observer3d> <window3D> >view3
3 model-projection observer3d> <window3D> >view4
;
: 4DNav ( -- )
init-variables
selected-file read-model-file >present-space
init-models
windows
;
MAIN: 4DNav