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