full request roundtrip
[carveJwlIkooP6JGAAIwe30JlM.git] / world_sfd.c
1 #ifndef SFD_C
2 #define SFD_C
3
4 #include "world_sfd.h"
5 #include "shaders/scene_scoretext.h"
6 #include "shaders/scene_vertex_blend.h"
7 #include "network.h"
8 #include "entity.h"
9
10 static f32 sfd_encode_glyph( char c ){
11 int value = 0;
12 if( c >= 'a' && c <= 'z' )
13 value = c-'a'+11;
14 else if( c >= '0' && c <= '9' )
15 value = c-'0'+1;
16 else if( c >= 'A' && c <= 'Z' )
17 value = c-'A'+11;
18 else if( c >= '\x01' && c <= '\x01'+10 )
19 value = 63-c;
20 else{
21 int base = 11+26;
22
23 switch( c ){
24 case '!': value=base+0; break;
25 case '?': value=base+1; break;
26 case ',': value=base+2; break;
27 case '.': value=base+3; break;
28 case '#': value=base+4; break;
29 case '$': value=base+5; break;
30 case '%': value=base+6; break;
31 case '*': value=base+7; break;
32 case '+': value=base+8; break;
33 case '-': value=base+9; break;
34 case '/': value=base+10; break;
35 case ':': value=base+11; break;
36 default: value=0; break;
37 }
38 }
39
40 return (float)value;
41 }
42
43 static void sfd_encode( u32 row, const char *str )
44 {
45 int end=0;
46 u32 row_h = world_sfd.h -1 -row;
47
48 for( int i=0; i<world_sfd.w; i++ ){
49 u32 idx = (world_sfd.w*row_h + i) * 2;
50
51 if( end ){
52 world_sfd.buffer[idx] = 0.0f;
53 }
54 else{
55 if( !str[i] )
56 end = 1;
57
58 world_sfd.buffer[idx] = sfd_encode_glyph( str[i] );
59 }
60 }
61 }
62
63 static void world_sfd_update( world_instance *world, v3f pos ){
64 if( mdl_arrcount( &world->ent_route ) ){
65 u32 closest = 0;
66 float min_dist = INFINITY;
67
68 for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
69 ent_route *route = mdl_arritm( &world->ent_route, i );
70 float dist = v3_dist2( route->board_transform[3], pos );
71
72 if( dist < min_dist ){
73 min_dist = dist;
74 closest = i;
75 }
76 }
77
78 if( (world_sfd.active_route_board != closest) || network_scores_updated ){
79 network_scores_updated = 0;
80 world_sfd.active_route_board = closest;
81 ent_route *route = mdl_arritm( &world->ent_route, closest );
82
83 addon_reg *world_reg = world_static.addon_hub;
84 if( world_static.active_instance )
85 world_reg = world_static.addon_client;
86
87 char mod_uid[ ADDON_UID_MAX ];
88 addon_alias_uid( &world_reg->alias, mod_uid );
89
90 network_request_scoreboard(
91 mod_uid,
92 mdl_pstr( &world->meta, route->pstr_name ),
93 0 );
94 #if 0
95 u32 id = route->anon.official_track_id;
96
97 if( id != 0xffffffff ){
98 struct netmsg_board *local_board =
99 &scoreboard_client_data.boards[id];
100
101 for( int i=0; i<13; i++ ){
102 sfd_encode( i, &local_board->data[27*i] );
103 }
104 }else{
105 sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
106 sfd_encode( 1, "No data" );
107 }
108 #endif
109 }
110 }
111
112 for( int i=0; i<world_sfd.w*world_sfd.h; i++ ){
113 float *target = &world_sfd.buffer[i*2+0],
114 *cur = &world_sfd.buffer[i*2+1];
115
116 float const rate = vg.time_delta * 15.2313131414f;
117 float d1 = *target-*cur;
118
119 if( fabsf(d1) > rate ){
120 *cur += rate;
121 if( *cur > 60.0f )
122 *cur -= 60.0f;
123 }
124 else
125 *cur = *target;
126 }
127 }
128
129 static void bind_terrain_noise(void);
130 static void sfd_render( world_instance *world, camera *cam, m4x3f transform ){
131 mesh_bind( &world_sfd.mesh_display );
132 shader_scene_scoretext_use();
133 shader_scene_scoretext_uTexMain(1);
134 WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_scoretext );
135
136 bind_terrain_noise();
137
138 glActiveTexture( GL_TEXTURE1 );
139 glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
140
141 m4x4f pvm_prev;
142 m4x3_expand( transform, pvm_prev );
143 m4x4_mul( cam->mtx_prev.pv, pvm_prev, pvm_prev );
144
145 shader_scene_scoretext_uPv( cam->mtx.pv );
146 shader_scene_scoretext_uPvmPrev( pvm_prev );
147 shader_scene_scoretext_uMdl( transform );
148 shader_scene_scoretext_uCamera( cam->transform[3] );
149
150 for( int y=0;y<world_sfd.h; y++ ){
151 for( int x=0; x<world_sfd.w; x++ ){
152 float value = world_sfd.buffer[(y*world_sfd.w+x)*2+1];
153 shader_scene_scoretext_uInfo( (v3f){ x,y, value } );
154 mesh_draw( &world_sfd.mesh_display );
155 }
156 }
157
158 shader_scene_vertex_blend_use();
159 shader_scene_vertex_blend_uTexGarbage(0);
160 shader_scene_vertex_blend_uTexGradients(1);
161 WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
162
163 bind_terrain_noise();
164 glActiveTexture( GL_TEXTURE1 );
165 glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
166
167 shader_scene_vertex_blend_uPv( cam->mtx.pv );
168 shader_scene_vertex_blend_uPvmPrev( pvm_prev );
169 shader_scene_vertex_blend_uMdl( transform );
170 shader_scene_vertex_blend_uCamera( cam->transform[3] );
171
172 mesh_bind( &world_sfd.mesh_base );
173 mdl_draw_submesh( &world_sfd.sm_base );
174 }
175
176 static int world_sfd_test( int argc, const char *argv[] ){
177 if( argc == 2 ){
178 int row = vg_min( vg_max(atoi(argv[0]),0), world_sfd.h);
179 sfd_encode( row, argv[1] );
180 }
181
182 return 0;
183 }
184
185 static void world_sfd_init(void){
186 vg_info( "world_sfd_init\n" );
187 shader_scene_scoretext_register();
188 vg_console_reg_cmd( "sfd", world_sfd_test, NULL );
189
190 vg_linear_clear( vg_mem.scratch );
191
192 mdl_context mscoreboard;
193 mdl_open( &mscoreboard, "models/rs_scoretext.mdl", vg_mem.scratch );
194 mdl_load_metadata_block( &mscoreboard, vg_mem.scratch );
195 mdl_async_load_glmesh( &mscoreboard, &world_sfd.mesh_base );
196
197 mdl_load_mesh_block( &mscoreboard, vg_mem.scratch );
198
199 scene_context *scene = &world_sfd.scene;
200 vg_async_item *call = scene_alloc_async( scene, &world_sfd.mesh_display,
201 3000, 8000 );
202
203
204 mdl_mesh *m_backer = mdl_find_mesh( &mscoreboard, "backer" ),
205 *m_card = mdl_find_mesh( &mscoreboard, "score_card" );
206
207 mdl_submesh
208 *sm_backer = mdl_arritm( &mscoreboard.submeshs, m_backer->submesh_start ),
209 *sm_card = mdl_arritm( &mscoreboard.submeshs, m_card->submesh_start );
210 world_sfd.sm_base = *sm_backer;
211
212 m4x3f identity;
213 m4x3_identity( identity );
214
215 for( int i=0;i<4;i++ ){
216 u32 vert_start = scene->vertex_count;
217 scene_add_mdl_submesh( scene, &mscoreboard, sm_card, identity );
218
219 for( int j=0; j<sm_card->vertex_count; j++ ){
220 scene_vert *vert = &scene->arrvertices[ vert_start+j ];
221
222 float const k_glyph_uvw = 1.0f/64.0f;
223 vert->uv[0] -= k_glyph_uvw * (float)(i-1);
224 vert->norm[3] = i*42;
225 }
226 }
227
228 vg_async_dispatch( call, async_scene_upload );
229 vg_tex2d_load_qoi_async_file( "textures/scoretext.qoi",
230 VG_TEX2D_CLAMP|VG_TEX2D_NEAREST,
231 &world_sfd.tex_scoretex );
232
233 mdl_close( &mscoreboard );
234
235 int w = 27,
236 h = 13;
237
238 world_sfd.w = w;
239 world_sfd.h = h;
240 world_sfd.buffer = vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
241
242 for( int i=0; i<w*h*2; i++ )
243 world_sfd.buffer[i] = 0.0f;
244 }
245
246 #endif /* WORLD_SFD_C */