whole
[carveJwlIkooP6JGAAIwe30JlM.git] / world_sfd.h
1 #ifndef SFD_H
2 #define SFD_H
3
4 #include "common.h"
5 #include "model.h"
6 #include "world.h"
7
8 #include "shaders/scoretext.h"
9 #include "shaders/vblend.h"
10
11 vg_tex2d tex_scoretext = { .path = "textures/scoretext.qoi",
12 .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
13
14 struct sfd_instance
15 {
16 float *buffer;
17
18 u32 w,h;
19 };
20
21
22 struct subworld_sfd
23 {
24 scene mesh;
25 mdl_submesh *sm_module, *sm_card;
26 glmesh temp;
27
28 struct sfd_instance tester;
29 };
30
31 static struct subworld_sfd *subworld_sfd(void);
32
33
34 float sfd_encode_glyph( char c )
35 {
36 int value = 0;
37 if( c >= 'a' && c <= 'z' )
38 value = c-'a'+11;
39 else if( c >= '0' && c <= '9' )
40 value = c-'0'+1;
41 else if( c >= 'A' && c <= 'Z' )
42 value = c-'A'+11;
43 else if( c >= '\x01' && c <= '\x01'+10 )
44 value = 63-c;
45 else
46 {
47 int base = 11+26;
48
49 switch( c )
50 {
51 case '!': value=base+0; break;
52 case '?': value=base+1; break;
53 case ',': value=base+2; break;
54 case '.': value=base+3; break;
55 case '#': value=base+4; break;
56 case '$': value=base+5; break;
57 case '%': value=base+6; break;
58 case '*': value=base+7; break;
59 case '+': value=base+8; break;
60 case '-': value=base+9; break;
61 case '/': value=base+10; break;
62 case ':': value=base+11; break;
63 default: value=0; break;
64 }
65 }
66
67 return (float)value;
68 }
69
70 static void sfd_encode( struct sfd_instance *display, u32 row, const char *str )
71 {
72 int end=0;
73 for( int i=0; i<display->w; i++ )
74 {
75 if( end )
76 {
77 display->buffer[display->w*row + i] = 0.0f;
78 }
79 else
80 {
81 if( !str[i] )
82 end = 1;
83
84 display->buffer[display->w*row + i] = sfd_encode_glyph( str[i] );
85 }
86 }
87 }
88
89 static void sfd_new( struct sfd_instance *display, u32 w, u32 h )
90 {
91 display->w = w;
92 display->h = h;
93 display->buffer = malloc( w*h*sizeof(float)*2 );
94
95 for( int i=0; i<w*h*2; i++ )
96 display->buffer[i] = 0.0f;
97 }
98
99 static void sfd_update( struct sfd_instance *display )
100 {
101 for( int i=0; i<display->w*display->h; i++ )
102 {
103 float *target = &display->buffer[i],
104 *cur = target+display->w*display->h;
105
106 float const rate = ktimestep*15.2313131414f;
107 float d1 = *target-*cur;
108
109 if( fabsf(d1) > rate )
110 {
111 *cur += rate;
112 if( *cur > 60.0f )
113 *cur -= 60.0f;
114 }
115 else
116 *cur = *target;
117 }
118 }
119
120 static void sfd_render( struct sfd_instance *display,
121 m4x4f projection, v3f camera, m4x3f transform )
122 {
123 struct subworld_sfd *sfd = subworld_sfd();
124 scene_bind( &sfd->mesh );
125
126 shader_scoretext_use();
127 shader_scoretext_uTexGarbage(0);
128 shader_scoretext_uTexGradients(1);
129 shader_link_standard_ub( _shader_scoretext.id, 2 );
130 bind_terrain_textures();
131 vg_tex2d_bind( &tex_scoretext, 1 );
132
133 shader_scoretext_uPv( projection );
134 shader_scoretext_uMdl( transform );
135 shader_scoretext_uCamera( camera );
136
137 for( int y=0;y<display->h; y++ )
138 {
139 for( int x=0; x<display->w; x++ )
140 {
141 float value = display->buffer[display->h*display->w+y*display->w+x];
142 shader_scoretext_uInfo( (v3f){ x,y, value } );
143 scene_draw( &sfd->mesh );
144 }
145 }
146
147 shader_vblend_use();
148 shader_vblend_uTexGarbage(0);
149 shader_vblend_uTexGradients(1);
150 shader_link_standard_ub( _shader_vblend.id, 2 );
151 bind_terrain_textures();
152
153 shader_vblend_uPv( projection );
154 shader_vblend_uMdl( transform );
155 shader_vblend_uCamera( camera );
156
157 mesh_bind( &sfd->temp );
158 mesh_draw( &sfd->temp );
159 }
160
161 static int world_sfd_test( int argc, const char *argv[] )
162 {
163 struct subworld_sfd *sfd = subworld_sfd();
164
165 if( argc == 2 )
166 {
167 int row = vg_min(vg_max(atoi(argv[0]),0),sfd->tester.h);
168 sfd_encode( &sfd->tester, row, argv[1] );
169 }
170
171 return 0;
172 }
173
174 static void world_sfd_init(void)
175 {
176 struct subworld_sfd *sfd = subworld_sfd();
177
178 vg_function_push( (struct vg_cmd){
179 .name = "sfd",
180 .function = world_sfd_test
181 });
182
183 mdl_header *mboard = mdl_load( "models/rs_scoretext.mdl" );
184
185 scene_init( &sfd->mesh );
186
187 mdl_node *pn_card = mdl_node_from_name( mboard, "score_card" );
188 mdl_submesh *card = mdl_submesh_from_id( mboard, pn_card->submesh_start );
189
190 mdl_node *pn_backer = mdl_node_from_name( mboard, "backer" );
191 mdl_submesh *backer = mdl_submesh_from_id( mboard, pn_backer->submesh_start);
192 mdl_unpack_submesh( mboard, &sfd->temp, backer );
193
194 m4x3f identity;
195 m4x3_identity( identity );
196
197 for( int i=0;i<8;i++ )
198 {
199 u32 vert_start = sfd->mesh.vertex_count;
200 scene_add_submesh( &sfd->mesh, mboard, card, identity );
201
202 for( int j=0; j<card->vertex_count; j++ )
203 {
204 mdl_vert *vert = &sfd->mesh.verts[ vert_start+j ];
205
206 float const k_glyph_uvw = 1.0f/64.0f;
207 vert->uv[0] -= k_glyph_uvw * (float)(i-4);
208 vert->colour[0] = 0.0f;
209 vert->colour[1] = i*36;
210 }
211 }
212
213 scene_upload( &sfd->mesh );
214 scene_free_offline_buffers( &sfd->mesh );
215
216 free( mboard );
217 vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 );
218
219 sfd_new( &sfd->tester, 16, 8 );
220 }
221
222 static void world_sfd_register(void)
223 {
224 shader_scoretext_register();
225 }
226
227 static void world_sfd_free(void)
228 {
229 vg_tex2d_free( (vg_tex2d *[]){ &tex_scoretext }, 1 );
230 }
231
232 #endif /* SFD_H */