1 USING: accessors alien.c-types alien.data alien.data.map arrays
\r
2 assocs byte-arrays colors combinators combinators.short-circuit
\r
3 destructors euler.b-rep euler.b-rep.triangulation fry game.input
\r
4 game.loop game.models.half-edge game.worlds gml.printer gpu
\r
5 gpu.buffers gpu.framebuffers gpu.render gpu.shaders gpu.state
\r
6 gpu.util.wasd growable images kernel literals locals math
\r
7 math.order math.ranges math.vectors math.vectors.conversion
\r
8 math.vectors.simd math.vectors.simd.cords method-chains models
\r
9 namespaces sequences sets specialized-vectors typed ui
\r
10 ui.gadgets ui.gadgets.worlds ui.gestures ui.pixel-formats
\r
12 FROM: math.matrices => m.v ;
\r
13 FROM: models => change-model ;
\r
14 SPECIALIZED-VECTORS: ushort float-4 ;
\r
17 CONSTANT: neutral-edge-color float-4{ 1 1 1 1 }
\r
18 CONSTANT: neutral-face-color float-4{ 1 1 1 1 }
\r
19 CONSTANT: selected-face-color float-4{ 1 0.9 0.8 1 }
\r
21 : double-4>float-4 ( in: double-4 -- out: float-4 )
\r
22 [ head>> ] [ tail>> ] bi double-2 float-4 vconvert ; inline
\r
23 : rgba>float-4 ( in: rgba -- out: float-4 )
\r
24 >rgba-components float-4-boa ; inline
\r
26 : face-color ( edge -- color )
\r
27 face-normal float-4{ 0 1 0.1 0 } v. 0.3 * 0.4 + dup dup 1.0 float-4-boa ; inline
\r
29 TUPLE: b-rep-vertices
\r
30 { array byte-array read-only }
\r
31 { face-vertex-count integer read-only }
\r
32 { edge-vertex-count integer read-only }
\r
33 { point-vertex-count integer read-only } ;
\r
35 :: <b-rep-vertices> ( face-array face-count
\r
36 edge-array edge-count
\r
37 point-array point-count -- vxs )
\r
38 face-array edge-array point-array 3append
\r
39 face-count edge-count point-count \ b-rep-vertices boa ; inline
\r
41 : face-selected? ( face selected -- ? )
\r
42 [ f ] 2dip [ edge>> ] dip '[ _ in? or ] each-face-edge ;
\r
44 :: b-rep-face-vertices ( b-rep selected -- vertices count indices )
\r
45 float-4-vector{ } clone :> vertices
\r
46 ushort-vector{ } clone :> indices
\r
48 0 b-rep faces>> [| count face |
\r
49 face selected face-selected? :> selected?
\r
50 face dup base-face>> eq? [
\r
51 face edge>> face-color
\r
52 selected? selected-face-color neutral-face-color ? v* :> color
\r
53 face triangulate-face seq>> :> triangles
\r
54 triangles members :> tri-vertices
\r
55 tri-vertices >index-hash :> vx-indices
\r
58 position>> double-4>float-4 vertices push
\r
61 triangles [ vx-indices at count + indices push ] each
\r
63 count tri-vertices length +
\r
66 vertices float-4 >c-array underlying>>
\r
68 indices ushort-array{ } like ;
\r
70 : b-rep-edge-vertices ( b-rep -- vertices count )
\r
73 position>> [ double-4>float-4 ] keep
\r
74 [ drop neutral-edge-color ]
\r
75 [ vertex-color rgba>float-4 ] 2bi
\r
76 ] data-map( object -- float-4[4] )
\r
77 ] [ length 2 * ] bi ; inline
\r
79 GENERIC: selected-vectors ( object -- vectors )
\r
80 M: object selected-vectors drop { } ;
\r
81 M: double-4 selected-vectors 1array ;
\r
82 M: sequence selected-vectors [ selected-vectors ] map concat ;
\r
84 : selected-vertices ( selected -- vertices count )
\r
86 [ [ double-4>float-4 ] [ vertex-color rgba>float-4 ] bi ]
\r
87 data-map( object -- float-4[2] )
\r
88 ] [ length ] bi ; inline
\r
90 : edge-vertex-index ( e vertex-indices selected -- n selected? )
\r
91 [ dup vertex>> ] [ at 2 * ] [ swapd in? [ [ 1 + ] when ] keep ] tri* ;
\r
93 :: b-rep-edge-index-array ( b-rep selected offset -- edge-indices )
\r
94 b-rep vertices>> >index-hash :> vertex-indices
\r
95 b-rep edges>> length <ushort-vector> :> edge-indices
\r
97 b-rep edges>> [| e |
\r
98 e opposite-edge>> :> o
\r
99 e vertex-indices selected edge-vertex-index [ offset + ] dip :> ( from e-selected? )
\r
100 o vertex-indices selected edge-vertex-index [ offset + ] dip :> ( to o-selected? )
\r
102 from to < [ from edge-indices push to edge-indices push ] when
\r
105 edge-indices ushort-array{ } like ;
\r
107 :: make-b-rep-vertices ( b-rep selected -- vertices face-indices edge-indices point-indices )
\r
108 b-rep selected b-rep-face-vertices :> ( face-vertices face-count face-indices )
\r
109 b-rep b-rep-edge-vertices :> ( edge-vertices edge-count )
\r
110 selected selected-vertices :> ( sel-vertices sel-count )
\r
111 face-vertices face-count edge-vertices edge-count sel-vertices sel-count
\r
112 <b-rep-vertices> :> vertices
\r
118 b-rep selected vertices face-vertex-count>> b-rep-edge-index-array
\r
121 [ face-vertex-count>> ]
\r
122 [ edge-vertex-count>> + dup ]
\r
123 [ point-vertex-count>> + ] tri
\r
124 [a,b) ushort >c-array ;
\r
126 VERTEX-FORMAT: wire-vertex-format
\r
127 { "vertex" float-components 3 f }
\r
128 { f float-components 1 f }
\r
129 { "color" float-components 4 f } ;
\r
131 GLSL-SHADER-FILE: gml-viewer-vertex-shader vertex-shader "viewer.v.glsl"
\r
132 GLSL-SHADER-FILE: gml-viewer-fragment-shader fragment-shader "viewer.f.glsl"
\r
133 GLSL-PROGRAM: gml-viewer-program
\r
134 gml-viewer-vertex-shader gml-viewer-fragment-shader
\r
135 wire-vertex-format ;
\r
137 TUPLE: gml-viewer-world < wasd-world
\r
142 face-indices edge-indices point-indices
\r
143 view-faces? view-edges?
\r
146 TYPED: refresh-b-rep-view ( world: gml-viewer-world -- )
\r
147 dup control-value >>b-rep
\r
148 dup vertex-array>> [ vertex-array-buffer dispose ] when*
\r
149 dup [ b-rep>> ] [ selected>> value>> ] bi make-b-rep-vertices {
\r
151 static-upload draw-usage vertex-buffer byte-array>buffer
\r
152 over program>> <vertex-array> >>vertex-array
\r
156 [ >>point-indices ]
\r
160 : viewable? ( gml-viewer-world -- ? )
\r
161 { [ b-rep>> ] [ program>> ] } 1&& ;
\r
163 M: gml-viewer-world model-changed
\r
167 [ dup viewable? [ refresh-b-rep-view ] [ drop ] if ] tri ;
\r
169 : init-viewer-model ( gml-viewer-world -- )
\r
170 [ dup model>> add-connection ]
\r
171 [ dup selected>> add-connection ] bi ;
\r
173 : reset-view ( gml-viewer-world -- )
\r
174 { 0.0 0.0 5.0 } 0.0 0.0 set-wasd-view drop ;
\r
176 M: gml-viewer-world begin-game-world
\r
180 T{ point-state { size 5.0 } } set-gpu-state
\r
182 gml-viewer-program <program-instance> >>program
\r
183 dup init-viewer-model
\r
184 refresh-b-rep-view ;
\r
186 M: gml-viewer-world end-game-world
\r
187 [ dup selected>> remove-connection ]
\r
188 [ dup model>> remove-connection ] bi ;
\r
190 M: gml-viewer-world draw-world*
\r
191 system-framebuffer {
\r
192 { default-attachment { 0.0 0.0 0.0 1.0 } }
\r
193 { depth-attachment 1.0 }
\r
194 } clear-framebuffer
\r
197 dup view-faces?>> [
\r
198 T{ depth-state { comparison cmp-less } } set-gpu-state
\r
200 { "primitive-mode" [ drop triangles-mode ] }
\r
201 { "indexes" [ face-indices>> ] }
\r
202 { "uniforms" [ <mvp-uniforms> ] }
\r
203 { "vertex-array" [ vertex-array>> ] }
\r
204 } <render-set> render
\r
205 T{ depth-state { comparison f } } set-gpu-state
\r
208 dup view-edges?>> [
\r
210 { "primitive-mode" [ drop lines-mode ] }
\r
211 { "indexes" [ edge-indices>> ] }
\r
212 { "uniforms" [ <mvp-uniforms> ] }
\r
213 { "vertex-array" [ vertex-array>> ] }
\r
214 } <render-set> render
\r
218 { "primitive-mode" [ drop points-mode ] }
\r
219 { "indexes" [ point-indices>> ] }
\r
220 { "uniforms" [ <mvp-uniforms> ] }
\r
221 { "vertex-array" [ vertex-array>> ] }
\r
222 } <render-set> render
\r
225 TYPED: rotate-view-mode ( world: gml-viewer-world -- )
\r
226 dup view-edges?>> [
\r
228 [ f >>view-faces? ]
\r
229 [ f >>view-edges? t >>view-faces? ] if
\r
230 ] [ t >>view-edges? ] if drop ;
\r
232 CONSTANT: edge-hitbox-radius 0.05
\r
234 :: line-nearest-t ( p0 u q0 v -- tp tq )
\r
243 a c * b b * - :> denom
\r
245 b e * c d * - denom /f
\r
246 a e * b d * - denom /f ;
\r
248 :: intersects-edge-node? ( source direction edge -- ? )
\r
249 edge vertex>> position>> double-4>float-4 :> edge-source
\r
250 edge opposite-edge>> vertex>> position>> double-4>float-4 edge-source v- :> edge-direction
\r
252 source direction edge-source edge-direction line-nearest-t :> ( ray-t edge-t )
\r
254 ray-t 0.0 >= edge-t 0.0 0.5 between? and [
\r
255 source direction ray-t v*n v+
\r
256 edge-source edge-direction edge-t v*n v+ v- norm
\r
257 edge-hitbox-radius <
\r
260 : intersecting-edge-node ( source direction b-rep -- edge/f )
\r
261 edges>> [ intersects-edge-node? ] 2with find nip ;
\r
263 : select-edge ( world -- )
\r
264 [ [ location>> ] [ hand-loc get wasd-pixel-ray ] bi ]
\r
265 [ b-rep>> intersecting-edge-node ]
\r
266 [ '[ _ [ selected>> push-model ] [ refresh-b-rep-view ] bi ] when* ] tri ;
\r
268 gml-viewer-world H{
\r
269 { T{ button-up f f 1 } [ dup drag?>> [ drop ] [ select-edge ] if ] }
\r
270 { T{ drag f 1 } [ t >>drag? drop ] }
\r
271 { T{ key-down f f "RET" } [ reset-view ] }
\r
272 { T{ key-down f f "TAB" } [ rotate-view-mode ] }
\r
275 AFTER: gml-viewer-world tick-game-world
\r
277 read-mouse buttons>>
\r
278 ! FIXME: GTK Mouse buttons are an integer
\r
279 ! MacOSX mouse buttons are an array of bools
\r
280 dup integer? [ 0 bit? ] [ first ] if >>drag?
\r
283 M: gml-viewer-world wasd-mouse-scale drag?>> -1/600. 0.0 ? ;
\r
285 : wrap-in-model ( object -- model )
\r
286 dup model? [ <model> ] unless ;
\r
287 : wrap-in-growable-model ( object -- model )
\r
289 dup growable? [ >vector ] unless
\r
293 : gml-viewer ( b-rep selection -- )
\r
294 [ wrap-in-model ] [ wrap-in-growable-model ] bi*
\r
296 f T{ game-attributes
\r
297 { world-class gml-viewer-world }
\r
298 { title "GML wireframe viewer" }
\r
299 { pixel-format-attributes {
\r
302 T{ depth-bits f 16 }
\r
305 { use-game-input? t }
\r
306 { use-audio-engine? f }
\r
307 { pref-dim { 1024 768 } }
\r
308 { tick-interval-nanos $[ 30 fps ] }
\r