]> gitweb.factorcode.org Git - factor.git/blob - extra/raylib/demo/mesh-picking/mesh-picking.factor
factor: trim using lists
[factor.git] / extra / raylib / demo / mesh-picking / mesh-picking.factor
1 ! See http://factorcode.org/license.txt for BSD license.
2 USING: accessors alien.enums arrays combinators.short-circuit
3 continuations destructors formatting grouping io.backend io.pathnames
4 kernel math math.functions.private math.vectors namespaces raylib
5 sequences vocabs.metadata ;
6
7 IN: raylib.demo.mesh-picking
8
9 CONSTANT: screen-width 800
10 CONSTANT: screen-height 800
11 : make-window ( -- )
12     screen-width screen-height "raylib [models] example - mesh-picking" init-window ;
13
14 : make-camera ( -- camera )
15     Camera3D new
16     20 30 20 <Vector3> >>position
17     0 10 0 <Vector3> >>target
18     0 1.6 0 <Vector3> >>up
19     45 >>fovy
20     CAMERA_PERSPECTIVE >>projection ;
21
22 : resource ( fname -- path )
23     "raylib.demo.mesh-picking" "_resources" vocab-file-path swap append-path normalize-path ;
24
25 ! TODO: raymath?
26 :: vector3-barycenter ( p a b c -- v3 )
27     b a v- :> v0
28     c a v- :> v1
29     p a v- :> v2
30     v0 dup vdot :> d00
31     v0 v1 vdot :> d01
32     v1 v1 vdot :> d11
33     v2 v0 vdot :> d20
34     v2 v1 vdot :> d21
35     d00 d11 * d01 d01 * - :> denom
36
37     d11 d20 * d01 d21 * - denom / :> y
38     d00 d21 * d01 d20 * - denom / :> z
39     1 z y + - :> x
40     x y z <Vector3> ; inline
41
42 : update-hit? ( nearest-hit-info hit-info -- nearest-hit-info ? )
43     2dup { [ nip hit>> ] [ swap [ distance>> ] bi@ < ] } 2&&
44     [ nip t ] [ drop f ] if ;
45
46 TUPLE: hit-state name color nearest-hit ;
47 : <hit-state> ( -- obj )
48     "None" WHITE
49     RayCollision new
50     most-positive-finite-float >>distance
51     f >>hit
52     hit-state boa ;
53
54 : reset-hit-state ( hit-state -- )
55     nearest-hit>>
56     most-positive-finite-float >>distance
57     f >>hit drop ;
58
59 : handle-ground-hit ( hit-state ray -- hit-state )
60     drop ;
61     ! FIXME: raylib 4.0 doesn't have GetCollisionRayGround
62     ! 0 get-collision-ray-ground
63     ! over nearest-hit>> swap update-hit?
64     ! [ >>nearest-hit ] dip
65     ! [ GREEN >>color "Ground" >>name ] when ;
66
67 : handle-triangle-hit ( hit-state ray ta tb tc -- hit-state ? )
68     get-ray-collision-triangle
69     over nearest-hit>> swap update-hit?
70     [ [ >>nearest-hit ] dip
71     [ PURPLE >>color "Triangle" >>name ] when ] keep ;
72
73 : handle-mesh-hit ( hit-state ray model bbox -- hit-state ? )
74     pick swap get-ray-collision-box
75     [
76       get-ray-collision-model
77       over nearest-hit>> swap update-hit?
78       [ >>nearest-hit ] dip
79       [ ORANGE >>color "Mesh" >>name ] when
80       t
81     ]
82     [ 2drop f ] if ;
83
84 TUPLE: tower model bbox position ;
85 : <tower> ( -- obj )
86     "turret.obj" resource load-model &unload-model
87     "turret_diffuse.png" resource load-texture &unload-texture
88     over materials>> first maps>> MATERIAL_MAP_DIFFUSE enum>number swap nth texture<<
89     dup meshes>> first get-mesh-bounding-box
90     0 0 0 <Vector3> tower boa ;
91
92 : init-assets ( -- tower triangle )
93     <tower>
94     -25 0.5 0 <Vector3>
95     -4 2.5 1 <Vector3>
96     -8 6.5 0 <Vector3> 3array ;
97
98 : draw-objects ( bbox? tower triangle -- )
99     2 <circular-clumps> [ first2 PURPLE draw-line-3d ] each
100     [ [ model>> ] [ position>> ] bi 1.0 WHITE draw-model ] keep
101     swap [ bbox>> LIME draw-bounding-box ] [ drop ] if ;
102
103 : draw-cursor ( hit-state -- )
104     dup nearest-hit>> hit>> [
105         [
106             [ nearest-hit>> point>> ] [ color>> ] bi
107             '[ 0.3 0.3 0.3 _ draw-cube ]
108             [ 0.3 0.3 0.3 RED draw-cube-wires ] bi
109         ]
110         [
111             nearest-hit>>
112             [ point>> dup ] [ normal>> ] bi v+ RED draw-line-3d
113         ] bi
114
115     ]
116     [ drop ] if ;
117
118 : while-raylib-window ( quot -- )
119     [ window-should-close not ] swap while ; inline
120
121 : with-window ( quot -- )
122     [ make-window ] prepose [ with-destructors ] curry
123     [ close-window ] [ ] cleanup ; inline
124
125 SYMBOL: mesh-picking-frame
126 :: main ( -- )
127     ! LOG_ALL set-trace-log-level
128     [
129         make-camera :> camera
130         Ray new :> ray
131         init-assets :> ( tower triangle )
132
133         f :> bary!
134         camera CAMERA_FREE set-camera-mode
135
136         60 set-target-fps
137         0 mesh-picking-frame set-global
138         <hit-state> :> the-hit-state
139         f :> hit-mesh-bbox!
140         [
141             ! NOTE: This doesn't work, probably because GL context is not handled correctly for switching?
142             ! mesh-picking-frame counter 100 mod 0 = [ yield ] when
143
144             camera update-camera
145
146             get-mouse-position camera get-mouse-ray :> ray
147
148             the-hit-state dup reset-hit-state
149             ray handle-ground-hit
150
151             ray triangle first3 handle-triangle-hit
152             [ dup nearest-hit>> point>> triangle first3 vector3-barycenter bary! ] [ f bary! ] if
153
154             ray tower [ model>> ] [ bbox>> ] bi handle-mesh-hit hit-mesh-bbox!
155
156             ! Drawing
157             begin-drawing
158             RAYWHITE clear-background
159             camera begin-mode-3d
160             hit-mesh-bbox tower triangle draw-objects
161
162             dup draw-cursor
163
164             ray MAROON draw-ray
165
166             10 10 draw-grid
167             end-mode-3d
168
169             ! Debug Gui Text
170             dup name>> "Hit Object: %s" sprintf 10 30 10 BLACK draw-text
171             nearest-hit>> dup hit>> [
172                 70 :> ypos
173                 [ distance>> "Distance: %3.2f" sprintf 10 ypos 10 BLACK draw-text ]
174                 [ point>> first3 "Hit Pos: %3.2f %3.2f %3.2f" sprintf 10 ypos 15 + 10 BLACK draw-text ]
175                 [ normal>> first3 "Hit Norm: %3.2f %3.2f %3.2f" sprintf 10 ypos 30 + 10 BLACK draw-text ]
176                 tri
177                 bary [ first3
178                        "Barycenter: %3.2f %3.2f %3.2f" sprintf 10 ypos 45 + 10 BLACK draw-text
179                      ] when*
180             ] [ drop ] if
181
182             "Use Mouse to Move Camera" 10 screen-height 20 - 10 GRAY draw-text
183             "(c) Turret 3D model by Alberto Cano" screen-width 200 - screen-height 20 - 10 GRAY draw-text
184
185             10 10 draw-fps
186             end-drawing
187         ] while-raylib-window
188     ] with-window ;
189
190 MAIN: main