1 // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
6 SHADER_DEFINE( colour_shader
,
9 "layout (location=0) in vec3 a_co;"
15 " vec4 vert_pos = uPv * uMdl * vec4( a_co, 1.0 );"
16 " gl_Position = vert_pos;"
21 "uniform vec4 uColour;"
25 " FragColor = uColour;"
28 UNIFORMS({ "uPv", "uMdl", "uColour" })
36 int main( int argc
, char *argv
[] )
38 vg_init( argc
, argv
, "FishLadder" );
41 #define CELL_FLAG_INPUT 0x1
42 #define CELL_FLAG_OUTPUT 0x2
43 #define CELL_FLAG_IO (CELL_FLAG_INPUT|CELL_FLAG_OUTPUT)
44 #define CELL_FLAG_WALL 0x4
45 #define CELL_FLAG_HOVER 0x8
46 #define CELL_FLAG_ITER 0x10
47 #define CELL_FLAG_CANAL 0x20
63 struct cell
*selected
;
84 static void map_free(void)
86 for( int i
= 0; i
< arrlen( map
.io
); i
++ )
88 arrfree( map
.cells
[ map
.io
[i
] ].conditions
);
99 static struct cell
*map_tile_at( int pos
[2] )
101 if( pos
[0] >= 0 && pos
[0] < map
.x
&& pos
[1] >= 0 && pos
[1] < map
.y
)
102 return map
.cells
+ pos
[1]*map
.x
+ pos
[0];
106 static int map_load( const char *str
)
115 if( str
[map
.x
] == ';' )
117 else if( !str
[map
.x
] )
119 vg_error( "Unexpected EOF when parsing level!\n" );
124 struct cell
*row
= arraddnptr( map
.cells
, map
.x
);
126 int reg_start
= 0, reg_end
= 0;
142 if( reg_start
< reg_end
)
144 if( *c
>= 'a' && *c
<= 'z' )
146 arrpush( map
.cells
[ map
.io
[ reg_start
] ].conditions
, *c
);
150 if( *c
== ',' || *c
== '\n' )
159 vg_error( "Unkown attrib '%c' (row: %u)\n", *c
, map
.y
);
166 vg_error( "Over-assigned values (row: %u)\n", map
.y
);
174 if( reg_start
!= reg_end
)
176 vg_error( "Not enough values assigned (row: %u, %u of %u)\n", map
.y
, reg_start
, reg_end
);
182 vg_error( "Map row underflow (row: %u, %u<%u)\n", map
.y
, cx
, map
.x
);
186 row
= arraddnptr( map
.cells
, map
.x
);
189 reg_end
= reg_start
= arrlen( map
.io
);
195 vg_error( "Map row overflow (row: %u, %u>%u)\n", map
.y
, cx
, map
.x
);
199 row
[ cx
].conditions
= NULL
;
201 // Parse the various cell types
202 if( *c
== '+' || *c
== '-' )
204 arrpush( map
.io
, cx
+ map
.y
*map
.x
);
205 row
[ cx
++ ].flags
= *c
== '+'? CELL_FLAG_INPUT
: CELL_FLAG_OUTPUT
;
210 row
[ cx
++ ].flags
= CELL_FLAG_WALL
;
214 row
[ cx
++ ].flags
= 0x00;
221 // Origin top left corner
222 map
.origin
[0] = -((float)map
.x
) * 0.5f
;
223 map
.origin
[2] = -((float)map
.y
) * 0.5f
;
225 vg_success( "Map loaded! (%u:%u)\n", map
.x
, map
.y
);
232 float ratio
= (float)vg_window_y
/ (float)vg_window_x
;
233 float const size
= 7.5f
;
234 glm_ortho( -size
, size
, -size
*ratio
, size
*ratio
, 0.1f
, 100.f
, m_projection
);
236 glm_mat4_identity( m_view
);
237 glm_translate_z( m_view
, -10.f
);
238 glm_rotate_x( m_view
, 1.0f
, m_view
);
240 glm_mat4_mul( m_projection
, m_view
, m_pv
);
247 vec4 vp
= { 0.f
, 0.f
, vg_window_x
, vg_window_y
};
248 glm_mat4_inv( m_pv
, pv_inverse
);
249 glm_unprojecti( (vec3
){ vg_mouse_x
, vg_window_y
-vg_mouse_y
, -1.f
}, pv_inverse
, vp
, ray_dir
);
250 glm_unprojecti( (vec3
){ vg_mouse_x
, vg_window_y
-vg_mouse_y
, 0.f
}, pv_inverse
, vp
, ray_origin
);
251 glm_vec3_sub( ray_dir
, ray_origin
, ray_dir
);
253 // Get floor tile intersection
254 float ray_t
= -ray_origin
[1] / ray_dir
[1];
257 glm_vec3_copy( ray_origin
, tile_pos
);
258 glm_vec3_muladds( ray_dir
, ray_t
, tile_pos
);
259 glm_vec3_sub( tile_pos
, map
.origin
, tile_pos
);
261 int tile_x
= floorf( tile_pos
[0] );
262 int tile_y
= floorf( tile_pos
[2] );
264 map
.selected
= map_tile_at( (int [2]){tile_x
, tile_y
} );
272 glViewport( 0,0, vg_window_x
, vg_window_y
);
274 glEnable( GL_DEPTH_TEST
);
275 glClearColor( 0.94f
, 0.94f
, 0.94f
, 1.0f
);
276 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
278 SHADER_USE( colour_shader
);
279 glUniformMatrix4fv( SHADER_UNIFORM( colour_shader
, "uPv" ), 1, GL_FALSE
, (float *)m_pv
);
281 for( int y
= 0; y
< map
.y
; y
++ )
283 for( int x
= 0; x
< map
.x
; x
++ )
285 glm_mat4_identity( m_mdl
);
286 glm_translate( m_mdl
,
288 map
.origin
[0] + (float)x
+ 0.5f
,
290 map
.origin
[2] + (float)y
+ 0.5f
293 glUniformMatrix4fv( SHADER_UNIFORM( colour_shader
, "uMdl" ), 1, GL_FALSE
, (float *)m_mdl
);
295 struct cell
*cell
= &map
.cells
[ y
*map
.x
+x
];
297 if( map
.selected
!= cell
)
299 if( cell
->flags
& CELL_FLAG_INPUT
)
300 glUniform4f( SHADER_UNIFORM( colour_shader
, "uColour" ), 0.9f
, 0.5f
, 0.5f
, 1.0f
);
301 else if( cell
->flags
& CELL_FLAG_OUTPUT
)
302 glUniform4f( SHADER_UNIFORM( colour_shader
, "uColour" ), 0.5f
, 0.9f
, 0.5f
, 1.0f
);
303 else if( cell
->flags
& CELL_FLAG_WALL
)
304 glUniform4f( SHADER_UNIFORM( colour_shader
, "uColour" ), 0.1f
, 0.1f
, 0.1f
, 1.0f
);
306 glUniform4f( SHADER_UNIFORM( colour_shader
, "uColour" ), 0.7f
, 0.7f
, 0.7f
, 1.0f
);
310 float flash
= sinf( vg_time
*2.5f
) * 0.25f
+ 0.75f
;
311 glUniform4f( SHADER_UNIFORM( colour_shader
, "uColour" ), flash
,flash
,flash
, 1.0f
);
314 glDrawArrays( GL_TRIANGLES
, 0, 6 );
321 SHADER_INIT( colour_shader
);
323 glGenVertexArrays( 1, &tile_vao
);
324 glGenBuffers( 1, &tile_vbo
);
336 glBindVertexArray( tile_vao
);
337 glBindBuffer( GL_ARRAY_BUFFER
, tile_vbo
);
346 glVertexAttribPointer( 0, 3, GL_FLOAT
, GL_FALSE
, 3 * sizeof(float), (void*)0 );
347 glEnableVertexAttribArray( 0 );