3977e62e1edab68f934fad91587386b49d9fc738
[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 return;
124 struct subworld_sfd *sfd = subworld_sfd();
125 scene_bind( &sfd->mesh );
126
127 shader_scoretext_use();
128 shader_scoretext_uTexGarbage(0);
129 shader_scoretext_uTexGradients(1);
130 shader_link_standard_ub( _shader_scoretext.id, 2 );
131 bind_terrain_textures();
132 vg_tex2d_bind( &tex_scoretext, 1 );
133
134 shader_scoretext_uPv( projection );
135 shader_scoretext_uMdl( transform );
136 shader_scoretext_uCamera( camera );
137
138 for( int y=0;y<display->h; y++ )
139 {
140 for( int x=0; x<display->w; x++ )
141 {
142 float value = display->buffer[display->h*display->w+y*display->w+x];
143 shader_scoretext_uInfo( (v3f){ x,y, value } );
144 scene_draw( &sfd->mesh );
145 }
146 }
147
148 shader_vblend_use();
149 shader_vblend_uTexGarbage(0);
150 shader_vblend_uTexGradients(1);
151 shader_link_standard_ub( _shader_vblend.id, 2 );
152 bind_terrain_textures();
153
154 shader_vblend_uPv( projection );
155 shader_vblend_uMdl( transform );
156 shader_vblend_uCamera( camera );
157
158 mesh_bind( &sfd->temp );
159 mesh_draw( &sfd->temp );
160 }
161
162 static int world_sfd_test( int argc, const char *argv[] )
163 {
164 struct subworld_sfd *sfd = subworld_sfd();
165
166 if( argc == 2 )
167 {
168 int row = vg_min(vg_max(atoi(argv[0]),0),sfd->tester.h);
169 sfd_encode( &sfd->tester, row, argv[1] );
170 }
171
172 return 0;
173 }
174
175 static void world_sfd_init(void)
176 {
177 struct subworld_sfd *sfd = subworld_sfd();
178
179 vg_function_push( (struct vg_cmd){
180 .name = "sfd",
181 .function = world_sfd_test
182 });
183
184 mdl_header *mboard = mdl_load( "models/rs_scoretext.mdl" );
185
186 scene_init( &sfd->mesh );
187
188 mdl_node *pn_card = mdl_node_from_name( mboard, "score_card" );
189 mdl_submesh *card = mdl_submesh_from_id( mboard, pn_card->submesh_start );
190
191 mdl_node *pn_backer = mdl_node_from_name( mboard, "backer" );
192 mdl_submesh *backer = mdl_submesh_from_id( mboard, pn_backer->submesh_start);
193 mdl_unpack_submesh( mboard, &sfd->temp, backer );
194
195 m4x3f identity;
196 m4x3_identity( identity );
197
198 for( int i=0;i<8;i++ )
199 {
200 u32 vert_start = sfd->mesh.vertex_count;
201 scene_add_submesh( &sfd->mesh, mboard, card, identity );
202
203 for( int j=0; j<card->vertex_count; j++ )
204 {
205 mdl_vert *vert = &sfd->mesh.verts[ vert_start+j ];
206
207 float const k_glyph_uvw = 1.0f/64.0f;
208 vert->uv[0] -= k_glyph_uvw * (float)(i-4);
209 vert->colour[0] = 0.0f;
210 vert->colour[1] = i-4;
211 }
212 }
213
214 scene_upload( &sfd->mesh );
215 scene_free_offline_buffers( &sfd->mesh );
216
217 free( mboard );
218 vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 );
219
220 sfd_new( &sfd->tester, 16, 8 );
221 }
222
223 static void world_sfd_register(void)
224 {
225 shader_scoretext_register();
226 }
227
228 static void world_sfd_free(void)
229 {
230 vg_tex2d_free( (vg_tex2d *[]){ &tex_scoretext }, 1 );
231 }
232
233 #endif /* SFD_H */