]> gitweb.factorcode.org Git - factor.git/blob - extra/model-viewer/model-viewer.factor
ui.tools.listener.completion: change history completion popup to preserve newlines
[factor.git] / extra / model-viewer / model-viewer.factor
1 ! Copyright (C) 2010 Erik Charlebois
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types arrays combinators game.loop
4 game.models.loader game.worlds gpu gpu.buffers gpu.render
5 gpu.shaders gpu.state gpu.textures gpu.util.wasd images
6 images.loader kernel literals opengl.gl sequences
7 specialized-arrays specialized-vectors ui ui.gadgets.worlds
8 ui.pixel-formats ;
9 FROM: alien.c-types => float ;
10 SPECIALIZED-ARRAY: float
11 SPECIALIZED-VECTOR: uint
12 IN: model-viewer
13
14 GLSL-SHADER: obj-vertex-shader vertex-shader
15 uniform mat4 mv_matrix;
16 uniform mat4 p_matrix;
17
18 attribute vec3 POSITION;
19 attribute vec3 TEXCOORD;
20 attribute vec3 NORMAL;
21
22 varying vec2 texcoord_fs;
23 varying vec3 normal_fs;
24 varying vec3 world_pos_fs;
25
26 void main()
27 {
28     vec4 position = mv_matrix * vec4(POSITION, 1.0);
29     gl_Position   = p_matrix * position;
30     world_pos_fs  = POSITION;
31     texcoord_fs   = TEXCOORD;
32     normal_fs     = NORMAL;
33 }
34 ;
35
36 GLSL-SHADER: obj-fragment-shader fragment-shader
37 uniform mat4 mv_matrix, p_matrix;
38 uniform sampler2D map_Ka;
39 uniform sampler2D map_bump;
40 uniform vec3 Ka;
41 uniform vec3 view_pos;
42 uniform vec3 light;
43 varying vec2 texcoord_fs;
44 varying vec3 normal_fs;
45 varying vec3 world_pos_fs;
46 void main()
47 {
48     vec4 d = texture2D(map_Ka, texcoord_fs.xy);
49     vec3 b = texture2D(map_bump, texcoord_fs.xy).xyz;
50     vec3 n = normal_fs;
51     vec3 v = normalize(view_pos - world_pos_fs);
52     vec3 l = normalize(light);
53     vec3 h = normalize(v + l);
54     float cosTh = saturate(dot(n, l));
55     gl_FragColor = d * cosTh
56                  + d * 0.5 * cosTh * pow(saturate(dot(n, h)), 10.0) ;
57 }
58 ;
59
60 GLSL-PROGRAM: obj-program
61     obj-vertex-shader obj-fragment-shader ;
62
63 UNIFORM-TUPLE: model-uniforms < mvp-uniforms
64     { "map_Ka"    texture-uniform   f }
65     { "map_bump"  texture-uniform   f }
66     { "Ka"        vec3-uniform      f }
67     { "light"     vec3-uniform      f }
68     { "view_pos"  vec3-uniform      f }
69     ;
70
71 TUPLE: model-state
72     models
73     vertex-arrays
74     index-vectors
75     textures
76     bumps
77     kas ;
78
79 TUPLE: model-world < wasd-world model-path model-state ;
80
81 TUPLE: vbo
82     vertex-buffer
83     index-buffer index-count vertex-format texture bump ka ;
84
85 : white-image ( -- image )
86     <image>
87         { 1 1 } >>dim
88         BGR >>component-order
89         ubyte-components >>component-type
90         B{ 255 255 255 } >>bitmap ;
91
92 : up-image ( -- image )
93     <image>
94         { 1 1 } >>dim
95         BGR >>component-order
96         ubyte-components >>component-type
97         B{ 0 0 0 } >>bitmap ;
98
99 : make-texture ( pathname alt -- texture )
100     swap [ nip load-image ] when*
101     [
102         [ component-order>> ]
103         [ component-type>> ] bi
104         T{ texture-parameters
105            { wrap repeat-texcoord }
106            { min-filter filter-linear }
107            { min-mipmap-filter f } }
108         <texture-2d>
109     ]
110     [
111         0 swap [ allocate-texture-image ] keepdd
112     ] bi ;
113
114 : <model-buffers> ( models -- buffers )
115     [
116         {
117             [ attribute-buffer>> underlying>> static-upload draw-usage vertex-buffer byte-array>buffer ]
118             [ index-buffer>> underlying>> static-upload draw-usage index-buffer byte-array>buffer ]
119             [ index-buffer>> length ]
120             [ vertex-format>> ]
121             [ material>> ambient-map>> white-image make-texture ]
122             [ material>> bump-map>> up-image make-texture ]
123             [ material>> ambient-reflectivity>> ]
124         } cleave vbo boa
125     ] map ;
126
127 : fill-model-state ( model-state -- )
128     dup models>> <model-buffers>
129     {
130         [
131             [
132                 [ vertex-buffer>> obj-program <program-instance> ]
133                 [ vertex-format>> ] bi <vertex-array*>
134             ] map >>vertex-arrays drop
135         ]
136         [
137             [
138                 [ index-buffer>> ] [ index-count>> ] bi
139                 '[ _ 0 <buffer-ptr> _ uint-indexes <index-elements> ] call
140             ] map >>index-vectors drop
141         ]
142         [ [ texture>> ] map >>textures drop ]
143         [ [ bump>> ] map >>bumps drop ]
144         [ [ ka>> ] map >>kas drop ]
145     } 2cleave ;
146
147 : <model-state> ( model-world -- model-state )
148     model-path>> 1array model-state new swap
149     [ load-models ] [ append ] map-reduce >>models ;
150
151 :: <model-uniforms> ( world -- uniforms )
152     world model-state>>
153     [ textures>> ] [ bumps>> ] [ kas>> ] tri
154     [| texture bump ka |
155         world wasd-mv-matrix
156         world wasd-p-matrix
157         texture bump ka
158         { 0.5 0.5 0.5 }
159         world location>>
160         model-uniforms boa
161     ] 3map ;
162
163 : clear-screen ( -- )
164     0 0 0 0 glClearColor
165     1 glClearDepth
166     0xffffffff glClearStencil
167     flags{ GL_COLOR_BUFFER_BIT
168       GL_DEPTH_BUFFER_BIT
169       GL_STENCIL_BUFFER_BIT } glClear ;
170
171 : draw-model ( world -- )
172     clear-screen
173     face-ccw cull-back <triangle-cull-state> set-gpu-state
174     cmp-less <depth-state> set-gpu-state
175     [ model-state>> vertex-arrays>> ]
176     [ model-state>> index-vectors>> ]
177     [ <model-uniforms> ]
178     tri
179     [
180         {
181             { "primitive-mode"     [ 3drop triangles-mode ] }
182             { "uniforms"           [ 2nip ] }
183             { "vertex-array"       [ 2drop ] }
184             { "indexes"            [ drop nip ] }
185         } 3<render-set> render
186     ] 3each ;
187
188 TUPLE: model-attributes < game-attributes model-path ;
189
190 M: model-world draw-world* draw-model ;
191 M: model-world wasd-movement-speed drop 1/4. ;
192 M: model-world wasd-near-plane drop 1/32. ;
193 M: model-world wasd-far-plane drop 1024.0 ;
194 M: model-world begin-game-world
195     init-gpu
196     { 0.0 0.0 2.0 } 0 0 set-wasd-view
197     [ <model-state> [ fill-model-state ] keep ] [ model-state<< ] bi ;
198 M: model-world apply-world-attributes
199     {
200         [ model-path>> >>model-path ]
201         [ call-next-method ]
202     } cleave ;
203
204 :: open-model-viewer ( model-path -- )
205     [
206         f
207         T{ model-attributes
208            { world-class model-world }
209            { grab-input? t }
210            { title "Model Viewer" }
211            { pixel-format-attributes
212              { windowed double-buffered }
213            }
214            { pref-dim { 1024 768 } }
215            { tick-interval-nanos $[ 60 fps ] }
216            { use-game-input? t }
217            { model-path model-path }
218         }
219         clone
220         open-window
221     ] with-ui ;