X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=fishladder.c;h=f6673f77aeda5c4c920682daa231c419fd81a79f;hb=49a2d3825e61f53012816135ac4c4278c0b27632;hp=7f49563a4e819977c5524caf71acde04f267e5e5;hpb=56d6d59869fcdd9d23b0135e3262d9d29c218e05;p=fishladder.git diff --git a/fishladder.c b/fishladder.c index 7f49563..f6673f7 100644 --- a/fishladder.c +++ b/fishladder.c @@ -7,11 +7,12 @@ SHADER_DEFINE( colour_shader, // VERTEX "layout (location=0) in vec3 a_co;" - "uniform mat4 uPvm;" + "uniform mat4 uPv;" + "uniform mat4 uMdl;" "" "void main()" "{" - " vec4 vert_pos = uPvm * vec4( a_co, 1.0 );" + " vec4 vert_pos = uPv * uMdl * vec4( a_co, 1.0 );" " gl_Position = vert_pos;" "}", @@ -24,18 +25,207 @@ SHADER_DEFINE( colour_shader, " FragColor = uColour;" "}" , - UNIFORMS({ "uPvm", "uColour" }) + UNIFORMS({ "uPv", "uMdl", "uColour" }) ) mat4 m_projection; mat4 m_view; mat4 m_pv; +mat4 m_mdl; int main( int argc, char *argv[] ) { vg_init( argc, argv, "FishLadder" ); } +#define CELL_FLAG_INPUT 0x1 +#define CELL_FLAG_OUTPUT 0x2 + #define CELL_FLAG_IO (CELL_FLAG_INPUT|CELL_FLAG_OUTPUT) +#define CELL_FLAG_WALL 0x4 +#define CELL_FLAG_HOVER 0x8 +#define CELL_FLAG_ITER 0x10 +#define CELL_FLAG_CANAL 0x20 + +static struct +{ + u32 x,y; + + struct cell + { + u32 flags; + u32 model_id; + + char *conditions; + } + * cells; + + vec3 origin; + struct cell *selected; + int select_valid; + + u32 *io; + + struct vstack + { + struct vframe + { + int x, y; + int i; + } + frames[ 64 ]; + + int level; + u32 flags; + } + stack; +} +map; + +static void map_free(void) +{ + for( int i = 0; i < arrlen( map.io ); i ++ ) + { + arrfree( map.cells[ map.io[i] ].conditions ); + } + + arrfree( map.cells ); + arrfree( map.io ); + map.x = 0; + map.y = 0; + map.cells = NULL; + map.io = NULL; +} + +static struct cell *map_tile_at( int pos[2] ) +{ + if( pos[0] >= 0 && pos[0] < map.x && pos[1] >= 0 && pos[1] < map.y ) + return map.cells + pos[1]*map.x + pos[0]; + return NULL; +} + +static int map_load( const char *str ) +{ + map_free(); + + char *c = str; + + // Scan for width + for(;; map.x ++) + { + if( str[map.x] == ';' ) + break; + else if( !str[map.x] ) + { + vg_error( "Unexpected EOF when parsing level!\n" ); + return 0; + } + } + + struct cell *row = arraddnptr( map.cells, map.x ); + int cx = 0; + int reg_start = 0, reg_end = 0; + + for(;;) + { + if( !*c ) + break; + + if( *c == ';' ) + { + c ++; + + // Parse attribs + if( *c != '\n' ) + { + while( *c ) + { + if( reg_start < reg_end ) + { + if( *c >= 'a' && *c <= 'z' ) + { + arrpush( map.cells[ map.io[ reg_start ] ].conditions, *c ); + } + else + { + if( *c == ',' || *c == '\n' ) + { + reg_start ++; + + if( *c == '\n' ) + break; + } + else + { + vg_error( "Unkown attrib '%c' (row: %u)\n", *c, map.y ); + return 0; + } + } + } + else + { + vg_error( "Over-assigned values (row: %u)\n", map.y ); + return 0; + } + + c ++; + } + } + + if( reg_start != reg_end ) + { + vg_error( "Not enough values assigned (row: %u, %u of %u)\n", map.y, reg_start, reg_end ); + return 0; + } + + if( cx != map.x ) + { + vg_error( "Map row underflow (row: %u, %u<%u)\n", map.y, cx, map.x ); + return 0; + } + + row = arraddnptr( map.cells, map.x ); + cx = 0; + map.y ++; + reg_end = reg_start = arrlen( map.io ); + } + else + { + if( cx == map.x ) + { + vg_error( "Map row overflow (row: %u, %u>%u)\n", map.y, cx, map.x ); + return 0; + } + + row[ cx ].conditions = NULL; + + // Parse the various cell types + if( *c == '+' || *c == '-' ) + { + arrpush( map.io, cx + map.y*map.x ); + row[ cx ++ ].flags = *c == '+'? CELL_FLAG_INPUT: CELL_FLAG_OUTPUT; + reg_end ++; + } + else if( *c == '#' ) + { + row[ cx ++ ].flags = CELL_FLAG_WALL; + } + else + { + row[ cx ++ ].flags = 0x00; + } + } + + c ++; + } + + // Origin top left corner + map.origin[0] = -((float)map.x) * 0.5f; + map.origin[2] = -((float)map.y) * 0.5f; + + vg_success( "Map loaded! (%u:%u)\n", map.x, map.y ); + return 1; +} + void vg_update(void) { // Update camera @@ -45,9 +235,33 @@ void vg_update(void) glm_mat4_identity( m_view ); glm_translate_z( m_view, -10.f ); - glm_rotate_x( m_view, -1.0f, m_view ); + glm_rotate_x( m_view, 1.0f, m_view ); glm_mat4_mul( m_projection, m_view, m_pv ); + + // Get mouse ray + vec3 ray_origin; + vec3 ray_dir; + + mat4 pv_inverse; + vec4 vp = { 0.f, 0.f, vg_window_x, vg_window_y }; + glm_mat4_inv( m_pv, pv_inverse ); + glm_unprojecti( (vec3){ vg_mouse_x, vg_window_y-vg_mouse_y, -1.f }, pv_inverse, vp, ray_dir ); + glm_unprojecti( (vec3){ vg_mouse_x, vg_window_y-vg_mouse_y, 0.f }, pv_inverse, vp, ray_origin ); + glm_vec3_sub( ray_dir, ray_origin, ray_dir ); + + // Get floor tile intersection + float ray_t = -ray_origin[1] / ray_dir[1]; + + vec3 tile_pos; + glm_vec3_copy( ray_origin, tile_pos ); + glm_vec3_muladds( ray_dir, ray_t, tile_pos ); + glm_vec3_sub( tile_pos, map.origin, tile_pos ); + + int tile_x = floorf( tile_pos[0] ); + int tile_y = floorf( tile_pos[2] ); + + map.selected = map_tile_at( (int [2]){tile_x, tile_y} ); } GLuint tile_vao; @@ -55,16 +269,51 @@ GLuint tile_vbo; void vg_render(void) { + glViewport( 0,0, vg_window_x, vg_window_y ); + glEnable( GL_DEPTH_TEST ); glClearColor( 0.94f, 0.94f, 0.94f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); SHADER_USE( colour_shader ); - glUniformMatrix4fv( SHADER_UNIFORM( colour_shader, "uPvm" ), 1, GL_FALSE, (float *)m_pv ); - glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), 0.5f, 0.5f, 0.5f, 1.0f ); + glUniformMatrix4fv( SHADER_UNIFORM( colour_shader, "uPv" ), 1, GL_FALSE, (float *)m_pv ); - glBindVertexArray( tile_vao ); - glDrawArrays( GL_TRIANGLES, 0, 6 ); + for( int y = 0; y < map.y; y ++ ) + { + for( int x = 0; x < map.x; x ++ ) + { + glm_mat4_identity( m_mdl ); + glm_translate( m_mdl, + (vec3){ + map.origin[0] + (float)x + 0.5f, + 0.f, + map.origin[2] + (float)y + 0.5f + } + ); + glUniformMatrix4fv( SHADER_UNIFORM( colour_shader, "uMdl" ), 1, GL_FALSE, (float *)m_mdl ); + + struct cell *cell = &map.cells[ y*map.x+x ]; + + if( map.selected != cell ) + { + if( cell->flags & CELL_FLAG_INPUT ) + glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), 0.9f, 0.5f, 0.5f, 1.0f ); + else if( cell->flags & CELL_FLAG_OUTPUT ) + glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), 0.5f, 0.9f, 0.5f, 1.0f ); + else if( cell->flags & CELL_FLAG_WALL ) + glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), 0.1f, 0.1f, 0.1f, 1.0f ); + else + glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), 0.7f, 0.7f, 0.7f, 1.0f ); + } + else + { + float flash = sinf( vg_time*2.5f ) * 0.25f + 0.75f; + glUniform4f( SHADER_UNIFORM( colour_shader, "uColour" ), flash,flash,flash, 1.0f ); + } + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + } + } } void vg_start(void) @@ -98,11 +347,22 @@ void vg_start(void) glEnableVertexAttribArray( 0 ); VG_CHECK_GL(); + + map_load + ( + "#####-#####;aa\n" + "# #;\n" + "# #;\n" + "# -;bb\n" + "# #;\n" + "# #;\n" + "#####+#####;abab\n" + ); } void vg_free(void) { - + map_free(); } void vg_ui(void)