From: hgn Date: Sun, 19 Oct 2025 22:06:18 +0000 (+0100) Subject: SWITCH TO SDL3 BECAUSE IT ACTUALLY WORKS X-Git-Url: https://skaterift.com/git/?a=commitdiff_plain;h=fee0d3ffbdd95ba18d779ea5c79ef5f9b36b0460;p=vg.git SWITCH TO SDL3 BECAUSE IT ACTUALLY WORKS --- diff --git a/.gitmodules b/.gitmodules index 8fbe57b..693ee81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,9 @@ [submodule "submodules/miniaudio"] path = submodules/miniaudio url = https://github.com/mackron/miniaudio.git +[submodule "SDL"] + path = SDL + url = https://github.com/libsdl-org/SDL.git +[submodule "submodules/SDL"] + path = submodules/SDL + url = https://github.com/libsdl-org/SDL.git diff --git a/async.kv b/async.kv deleted file mode 100644 index 51f5f87..0000000 --- a/async.kv +++ /dev/null @@ -1,7 +0,0 @@ -add source/foundation/async.c - -hook -{ - event START - function _async_init -} diff --git a/bootstrap.sh b/bootstrap.sh index b5cadbc..38805e5 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,7 +1,8 @@ mkdir -p bin/vg.metacompiler-linux-x86_64-zig-cc/ && taskset -c 0-1 zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unused-function -O0 -ggdb \ -std=c11 -D_DEFAULT_SOURCE \ - -include "types.h" \ + -include "source/types.h" \ + -I./source/foundation/ \ source/foundation/options.c \ source/foundation/logging.c \ source/foundation/allocator_heap.c \ @@ -16,6 +17,7 @@ taskset -c 0-1 zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unus source/foundation/io.c \ source/foundation/buffer_operations.c \ source/foundation/temporary.c \ + source/foundation/threads_c11.c \ \ source/tools/metacompiler.c \ -o bin/vg.metacompiler-linux-x86_64-zig-cc/vg.metacompiler diff --git a/build.kv b/build.kv deleted file mode 100644 index bfc604d..0000000 --- a/build.kv +++ /dev/null @@ -1,2 +0,0 @@ -include include/ -include source/ diff --git a/foundation.kv b/foundation.kv deleted file mode 100644 index cd18ebd..0000000 --- a/foundation.kv +++ /dev/null @@ -1,368 +0,0 @@ -event -{ - name OPTIONS - prototype "void" -} -event -{ - name START - prototype "void" -} - -add source/foundation/options.c -add source/foundation/logging.c -{ - hook OPTIONS - function _log_options -} - -add source/foundation/allocator_heap.c -add source/foundation/allocator_stack.c -add source/foundation/allocator_pool.c -add source/foundation/allocator_queue.c -add source/foundation/allocator_stretchy.c -add source/foundation/stream.c -add source/foundation/string.c -add source/foundation/keyvalues.c -add source/foundation/buffer_operations.c -add source/foundation/temporary.c - -{ - if linux - add source/foundation/io.c - add source/foundation/exit.c -} - -{ - if windows - add source/foundation/io_windows.c - add source/foundation/exit_windows.c -} - -{ - if terminal - add source/terminal_main.c -} - -{ - - if game_engine - include source/engine - - { - add source/engine/main.c - hook - { - event OPTIONS - function _engine_options - } - - event - { - name ENGINE_NEW_FRAME - prototype "void" - } - event - { - name ENGINE_FIXED_UPDATE - prototype "void" - } - event - { - name ENGINE_RENDER - prototype "void" - } - event - { - name ENGINE_UI - prototype "void" - } - event - { - name ENGINE_WINDOW_RESIZE - prototype "void" - } - } - - { - add source/engine/ui.c - hook - { - event START - function _engine_ui_init - } - } - - { - add source/engine/input.c - hook - { - event START - function _input_init - } - hook - { - event ENGINE_NEW_FRAME - function _input_update - } - ccmd - { - name bind - function _input_bind_ccmd - description "Bind device input to a button, action or axis" - - parameter - { - description "Device input alias" - } - - parameter - { - description "button,action,axis name" - } - } - ccmd - { - name unbind - description "Unbind all bindings that match" - function _input_unbind_ccmd - - parameter - { - description "binding" - } - } - } - - { - add source/console_core.c - hook - { - event START - function _console_init - } - } - - { - add source/engine/console.c - hook - { - event START - function _engine_console_init - } - hook - { - event ENGINE_NEW_FRAME - function _engine_console_update - } - hook - { - event ENGINE_UI - function _engine_console_ui - affinity 9999 - } - } - - { - add source/engine/vg_framebuffer.c - hook - { - event ENGINE_WINDOW_RESIZE - function _framebuffer_resize - } - } - - add source/engine/shader.c - input_layer - { - name console - } - input_layer - { - name ui - } - input - { - name console - type action - layer_mask console - } - - append async.kv - thread - { - name main - queue_size_m 40 - flag MAIN - flag OPENGL - } - thread - { - name async - queue_size_m 40 - flag ASYNC - } - thread - { - name audio - } - thread - { - name exitor - queue_size_m 1 - } - - append graphics.kv - append glfw3.kv - - ccmd - { - name exec - function _console_exec_ccmd - description "Execute a configuration file" - - parameter - { - description "The path to the config" - } - } - config "bind ALT+GRAVE_ACCENT console" - - config "bind BACKSPACE ui_backspace" - config "bind DELETE ui_delete" - config "bind ENTER ui_enter" - config "bind TAB ui_indent" - config "bind HOME ui_home" - config "bind END ui_end" - config "bind LEFT ui_left" - config "bind RIGHT ui_right" - config "bind UP ui_up" - config "bind DOWN ui_down" - config "bind MOUSE_LEFT ui_click" - - config "bind LEFT_SHIFT ui_select" - config "bind RIGHT_SHIFT ui_select" - - input - { - name ui_delete - type action - layer_mask ui - } - input - { - name ui_backspace - type action - layer_mask ui - } - input - { - name ui_enter - type action - layer_mask ui - } - input - { - name ui_indent - type action - layer_mask ui - } - - input - { - name ui_select - type button - layer_mask ui - } - input - { - name ui_home - type button - layer_mask ui - } - input - { - name ui_end - type button - layer_mask ui - } - input - { - name ui_left - type button - layer_mask ui - } - input - { - name ui_right - type button - layer_mask ui - } - input - { - name ui_up - type button - layer_mask ui - } - input - { - name ui_down - type button - layer_mask ui - } - input - { - name ui_click - type action - layer_mask ui - } - - shader - { - name blit - - subshader - { - type vertex - add shaders/blit.vs - - uniform - { - type vec2 - alias uInverseRatio - } - uniform - { - type int - alias uFlip - } - } - - subshader - { - type fragment - add shaders/blit_tex.fs - - uniform - { - type sampler2D - alias uTexMain - } - } - } - - cvar - { - name test - type u32 - default 5 - cheat 1 - description "This is just a test variable!" - } - - hook - { - event START - function "_shaders_compile" - } -} diff --git a/glfw3.kv b/glfw3.kv deleted file mode 100644 index 37acf90..0000000 --- a/glfw3.kv +++ /dev/null @@ -1,37 +0,0 @@ -include dep/glfw-3.4/src -add dep/glfw-3.4/src/init.c -add dep/glfw-3.4/src/input.c -add dep/glfw-3.4/src/monitor.c -add dep/glfw-3.4/src/platform.c -add dep/glfw-3.4/src/context.c -add dep/glfw-3.4/src/window.c -add dep/glfw-3.4/src/vulkan.c - -add dep/glfw-3.4/src/null_init.c -add dep/glfw-3.4/src/null_joystick.c -add dep/glfw-3.4/src/null_monitor.c -add dep/glfw-3.4/src/null_window.c - -include dep/glad.4.3/ -add dep/glad.4.3/glad.c - -{ - if linux - define _GLFW_X11 - add dep/glfw-3.4/src/posix_thread.c - add dep/glfw-3.4/src/posix_poll.c - add dep/glfw-3.4/src/posix_time.c - add dep/glfw-3.4/src/posix_module.c - add dep/glfw-3.4/src/x11_init.c - add dep/glfw-3.4/src/x11_monitor.c - add dep/glfw-3.4/src/x11_window.c - add dep/glfw-3.4/src/linux_joystick.c - add dep/glfw-3.4/src/glx_context.c - add dep/glfw-3.4/src/egl_context.c - add dep/glfw-3.4/src/osmesa_context.c - add dep/glfw-3.4/src/xkb_unicode.c -} - -{ - if windows -} diff --git a/graphics.kv b/graphics.kv deleted file mode 100644 index f6e2877..0000000 --- a/graphics.kv +++ /dev/null @@ -1,4 +0,0 @@ -add source/graphics/font.c -add source/graphics/ui.c -add source/graphics/graphics.c -add source/graphics/graphics_software.c diff --git a/include/common_api.h b/include/common_api.h deleted file mode 100644 index f504ab8..0000000 --- a/include/common_api.h +++ /dev/null @@ -1,373 +0,0 @@ -/* Voyager common application interface */ -#pragma once - -#define VG_PRE_MAIN \ - _exit_init(); \ - _log_init(); \ - _options_init( argc, argv ); \ - EVENT_CALL( OPTIONS ); \ - _options_check_end(); - -#define BYTES_KB( X ) X*1024 -#define BYTES_MB( X ) X*1024*1024 -#define BYTES_GB( X ) X*1024*1024*1024 -#define ARRAY_COUNT( X ) (sizeof((X))/sizeof((X)[0])) -#define i8_MAX 0x7F -#define u8_MAX 0XFF -#define i16_MAX 0x7FFF -#define u16_MAX 0xFFFF -#define i32_MAX 0x7FFFFFFF -#define u32_MAX 0xFFFFFFFF -#define i64_MAX 0x7FFFFFFFFFFFFFFF -#define u64_MAX 0xFFFFFFFFFFFFFFFF - -#define PAD_TO_4( X ) (((u32)X+0x3) & ~(u32)0x3) -#define PAD_TO_8( X ) (((u32)X+0x7) & ~(u32)0x7) -#define PAD_TO_16( X ) (((u32)X+0xf) & ~(u32)0xf) - -static inline f32 f32_min( f32 a, f32 b ){ return a < b? a: b; } -static inline f32 f32_max( f32 a, f32 b ){ return a > b? a: b; } -static inline i32 i32_min( i32 a, i32 b ){ return a < b? a: b; } -static inline i32 i32_max( i32 a, i32 b ){ return a > b? a: b; } -static inline i32 u32_min( u32 a, u32 b ){ return a < b? a: b; } -static inline i32 u32_max( u32 a, u32 b ){ return a > b? a: b; } -static inline i16 i16_min( i16 a, i16 b ){ return a < b? a: b; } -static inline i16 i16_max( i16 a, i16 b ){ return a > b? a: b; } -static inline f32 f32_clamp( f32 a, f32 min, f32 max ) { return f32_min( max, f32_max( a, min ) ); } -static inline i16 i16_clamp( i16 a, i16 min, i16 max ){ return i16_min( max, i16_max( a, min ) ); } -static inline i16 i32_clamp( i32 a, i32 min, i32 max ){ return i32_min( max, i32_max( a, min ) ); } -static inline f32 f32_sign( f32 a ) { return a < 0.0f? -1.0f: 1.0f; } - -void _exit_init(void); -void _fatal_exit(void); -void _normal_exit(void); -#define ASSERT_CRITICAL( CONDITION ) \ - if( !(CONDITION) ) { $log( $fatal, {"(" $TO_STRING(CONDITION) ")" KRED " == 0" KNRM } ); _fatal_exit(); } - -/* Command line options - * ------------------------------------------------------------------------------------------------------------------ */ -void _options_init( i32 argc, const c8 *argv[] ); -void _options_check_end( void ); -bool _option_flag( c8 c, const c8 *desc ); -const c8 *_option_argument( char c, const c8 *desc ); -bool _option_long( c8 *name, const c8 *desc ); -const c8 *_option_long_argument( char *name, const c8 *desc ); -const c8 *_option(void); - -/* Heap allocation - * ------------------------------------------------------------------------------------------------------------------ */ -void *_heap_allocate( u64 size ); -void *_heap_reallocate( void *buf, u64 size ); -void _heap_free( void *buf ); - -void zero_buffer( void *buffer, u32 length ); - -/* if max_length is 0, the operation runs until a 0 is found in the buffer */ -u32 buffer_djb2( const void *buffer, i32 max_length ); -bool compare_buffers( const void *buffer_a, i32 a_max, const void *buffer_b, i32 b_max ); -i32 buffer_first_index( const void *buffer, u8 match, i32 max_length ); -i32 buffer_last_index( const void *buffer, u8 match, i32 max_length ); -bool buffer_copy( const void *buffer_src, u32 src_length, void *buffer_dest, u32 dest_length ); - -struct stretchy_allocator -{ - i32 count, element_size; - void *segments[26]; -}; -void stretchy_init( struct stretchy_allocator *stretchy, u32 element_size ); -void *stretchy_append( struct stretchy_allocator *stretchy ); -void *stretchy_get( struct stretchy_allocator *stretchy, u32 index ); -void stretchy_delete( struct stretchy_allocator *stretchy, u32 index ); -void stretchy_shrink( struct stretchy_allocator *stretchy ); -u32 stretchy_count( struct stretchy_allocator *stretchy ); -void stretchy_free( struct stretchy_allocator *stretchy ); - -/* Stack - * ------------------------------------------------------------------------------------------------------------------ */ -struct stack_allocator -{ - u32 capacity, offset; /* bytes */ - void *data; - - void *check_pointer; -}; -void stack_init( struct stack_allocator *stack, void *buffer, u32 capacity, const c8 *debug_name ); -void *stack_allocate( struct stack_allocator *stack, u32 size, u32 alignment, const c8 *debug_name ); -void stack_clear( struct stack_allocator *stack ); -void stack_extend_last( struct stack_allocator *stack, void *check_pointer, i32 extra_bytes ); -u32 stack_offset( struct stack_allocator *stack, void *pointer ); -void *stack_pointer( struct stack_allocator *stack, u32 offset ); - -u32 _start_temporary_frame(void); -void _end_temporary_frame( u32 whence ); -void *_temporary_allocate( u32 bytes, u32 alignment ); -struct stack_allocator *_temporary_stack_allocator(void); - -/* Pool - * ------------------------------------------------------------------------------------------------------------------ */ -struct pool_node -{ - u16 l, r, refcount, unused0; -}; -struct pool_chain -{ - u16 head, tail, count, unused0; -}; -struct pool_allocator -{ - struct pool_node *nodes; - u32 count; -}; -void pool_init( struct pool_allocator *pool, struct pool_node *nodes, u16 node_count, struct pool_chain *full_chain ); -u32 pool_index( struct pool_allocator *pool, u16 pool_id ); -u16 pool_reference( struct pool_allocator *pool, u16 pool_id, bool increment ); -u16 pool_next( struct pool_allocator *pool, u16 pool_id, bool right ); -void pool_switch( struct pool_allocator *pool, struct pool_chain *source, struct pool_chain *dest, u16 which ); - -/* Queue - * ------------------------------------------------------------------------------------------------------------------ */ -struct queue_item -{ - u32 alloc_size,prev_size; - u8 data[]; -}; -struct queue_allocator -{ - void *buffer; - u32 size; - u32 head_offset, tail_offset; - u32 allocation_count; -}; -void queue_init( struct queue_allocator *queue, void *buffer, u32 buffer_size ); -void *queue_alloc( struct queue_allocator *queue, u32 size ); -void *queue_data( struct queue_allocator *queue, u32 offset ); -void *queue_tail_data( struct queue_allocator *queue ); -u32 queue_offset( struct queue_allocator *queue, void *pointer ); -/* warning: this is not the size but the allocation size (may be padded) */ -u32 queue_item_size( struct queue_allocator *queue, u32 item_id ); -bool queue_next( struct queue_allocator *queue, u32 item_id, u32 *out_next ); -bool queue_previous( struct queue_allocator *queue, u32 item_id, u32 *out_prev ); -void queue_pop( struct queue_allocator *queue ); -void queue_copy_buffer( struct queue_allocator *queue, void *dst, u32 start, u32 size ); -u32 queue_usage( struct queue_allocator *queue ); -void queue_clear( struct queue_allocator *queue ); - -/* Stream - * ------------------------------------------------------------------------------------------------------------------ */ -enum stream_flag -{ - /* options */ - k_stream_overflow_error = 0x1000, - k_stream_null_terminate = 0x2000, - - /* memory type */ - k_stream_buffer = 0x10, - k_stream_procedural = 0x20, - k_stream_stack = 0x40, - k_stream_posix = 0x80, - k_stream_auto = 0x100, - - /* modes */ - k_stream_write = 0x1, - k_stream_read = 0x2 -}; -struct stream -{ - u32 flags, buffer_length, offset; - union - { - void *posix_stream; - u8 *buffer_write; - const u8 *buffer_read; - u32 (*write_procedure)( struct stream *stream, const void *buffer, u32 length ); - u32 (*read_procedure)( struct stream *stream, void *buffer, u32 length ); - }; - - union - { - struct stack_allocator *stack; - void *procedure_userdata; - }; -}; - -void stream_open_auto( struct stream *stream, u32 flags ); -void stream_open_stack( struct stream *stream, struct stack_allocator *stack, u32 flags ); -void stream_open_buffer_write( struct stream *stream, void *buffer, u32 buffer_length, u32 flags ); -void stream_open_buffer_read( struct stream *stream, const void *buffer, u32 buffer_length, u32 flags ); -bool stream_open_file( struct stream *stream, const c8 *path, u32 flags ); - -void stream_close( struct stream *stream ); -u32 stream_read( struct stream *stream, void *buffer, u32 length ); -u32 stream_write( struct stream *stream, const void *buffer, u32 length ); -u32 stream_offset( struct stream *stream ); -void stream_seek( struct stream *stream, u32 offset ); -bool stream_error( struct stream *stream ); - -/* String (Stream subset) - * ------------------------------------------------------------------------------------------------------------------ */ - -const c8 *string_get( struct stream *string ); -void string_clip( struct stream *string, i32 length ); -void string_append( struct stream *string, const c8 *substring, u32 length ); -void string_append_c8( struct stream *string, c8 c ); -void string_append_i64( struct stream *string, i64 value, u64 base ); -void string_append_i64r( struct stream *string, i64 value, u64 base, u32 width, c8 blank_c8acter ); -void string_append_u64( struct stream *string, u64 value, u64 base ); -void string_append_f64( struct stream *string, f64 value, u64 base, u32 decimal_places ); - -struct v_string_arg -{ - const c8 *_string; - union - { - u64 _u64; - i64 _i64; - f64 _f64; - }; - - u32 type; - u32 base; - union - { - u32 decimals; - u32 length; - }; -}; -void v_string( struct stream *string, struct v_string_arg *argument_list ); - -#define k_$end 99 -#define k_$string 0 -#define k_$unsigned 2 -#define k_$signed 3 -#define k_$float 4 -#define k_$errno 5 - -#define $string( X, ... ) { X, __VA_ARGS__ } -#define $unsigned( X, ... ) { .type=k_$unsigned, ._u64=X, __VA_ARGS__ } -#define $signed( X, ... ) { .type=k_$signed, ._i64=X, __VA_ARGS__ } -#define $float( X, ... ) { .type=k_$float, ._f64=X, __VA_ARGS__ } -#define $errno( ... ) { .type=k_$errno, __VA_ARGS__ } -#define $v_string( STRING, ... ) v_string( STRING, (struct v_string_arg[]){ __VA_ARGS__, {.type=k_$end} } ) - -enum string_parse_result -{ - k_string_parse_ok, - k_string_parse_eof, - k_string_parse_error, - k_string_parse_whitespace -}; -enum string_parse_result string_parse_c8 ( struct stream *string, c8 *c ); -enum string_parse_result string_parse_u64( struct stream *string, u64 *value ); -enum string_parse_result string_parse_i64( struct stream *string, i64 *value ); -enum string_parse_result string_parse_f64( struct stream *string, f64 *value ); -enum string_parse_result string_parse_string( struct stream *string, u32 *out_start, u32 *out_length, c8 delimiter ); - -/* Logging - * ------------------------------------------------------------------------------------------------------------------ */ - -#define KNRM "\x1B[0m" -#define KBLK "\x1B[30m" -#define KRED "\x1B[31m" -#define KGRN "\x1B[32m" -#define KYEL "\x1B[33m" -#define KBLU "\x1B[34m" -#define KMAG "\x1B[35m" -#define KCYN "\x1B[36m" -#define KWHT "\x1B[37m" - -#define $low 0x1 -#define $info 0x2 -#define $ok 0x4 -#define $warning 0x8 -#define $error 0x10 -#define $fatal 0x20 -#define $shell 0x40 -#define $raw 0x80 - -/* One day we will replace this shit with a good pre-processor. */ -#define $TO_STRING( S ) $TO_STRING_1( S ) -#define $TO_STRING_1( S ) #S -#define $line __FILE__ ":" $TO_STRING(__LINE__) -#define $log( C, ... ) { $v_string( _log_event( C, $line ), __VA_ARGS__ ); _log_end_event(); } - -struct stream *_log_event( u32 type, const c8 *code_location ); -void _log_init(void); -void _log_end_event(void); -void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 filter, bool accept_vt_codes ); - -/* Keyvalues - * ------------------------------------------------------------------------------------------------------------------ */ -struct keyvalues -{ - struct stack_allocator *stack; - u32 root_offset; - u32 kv_page_offset, kv_page_count; -}; -void keyvalues_init( struct keyvalues *kvs, struct stack_allocator *stack ); -void keyvalues_parse_stream( struct keyvalues *kvs, u32 root_offset, struct stream *in_stream ); -void keyvalues_write_stream( struct keyvalues *kvs, struct stream *out_stream, u32 node, u32 depth ); - -bool keyvalues_read_file( struct keyvalues *kvs, const char *path, struct stack_allocator *stack ); -bool keyvalues_write_file( struct keyvalues *kvs, const char *path ); - -enum keyvalue_type -{ - k_keyvalue_type_frame = 0, - k_keyvalue_type_pair = 1, - k_keyvalue_type_unused2 = 2, - k_keyvalue_type_unused3 = 3 -}; -u32 keyvalues_type( struct keyvalues *kvs, u32 kv_offset ); -c8 *keyvalues_key( struct keyvalues *kvs, u32 kv_offset, u32 *out_length ); -c8 *keyvalues_value( struct keyvalues *kvs, u32 kv_offset, u32 *out_length ); - -u32 keyvalues_get( struct keyvalues *kvs, u32 root_offset, const c8 *key, bool relative ); -u32 keyvalues_get_next( struct keyvalues *kvs, u32 kv_offset ); -u32 keyvalues_get_child( struct keyvalues *kvs, u32 root_offset, u32 index ); - -const c8 *keyvalues_read_string( struct keyvalues *kvs, u32 root_offset, const c8 *key, const c8 *default_value ); -bool keyvalues_read_i32s( struct keyvalues *kvs, u32 root_offset, const c8 *key, i32 *default_values, i32 *out_values, u32 len ); -bool keyvalues_read_u32s( struct keyvalues *kvs, u32 root_offset, const c8 *key, u32 *default_values, u32 *out_values, u32 len ); -bool keyvalues_read_f32s( struct keyvalues *kvs, u32 root_offset, const c8 *key, f32 *default_values, f32 *out_values, u32 len ); -u32 keyvalues_append_frame( struct keyvalues *kvs, u32 parent_offset, const c8 *key ); -u32 keyvalues_append_string( struct keyvalues *kvs, u32 parent_offset, const c8 *key, const c8 *value ); -u32 keyvalues_append_i32s( struct keyvalues *kvs, u32 parent_offset, const c8 *key, i32 *values, u32 len ); -u32 keyvalues_append_u32s( struct keyvalues *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len ); -u32 keyvalues_append_f32s( struct keyvalues *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len ); - -/* IO */ -struct directory; - -enum directory_entry_type -{ - k_directory_entry_type_unknown, - k_directory_entry_type_file, - k_directory_entry_type_dir -}; - -enum directory_status -{ - k_directory_status_none, - k_directory_status_ok, - k_directory_status_path_too_long, - k_directory_status_invalid_path, - k_directory_status_is_file -}; - -struct directory *directory_open( const c8 *path, struct stack_allocator *stack ); -enum directory_status directory_status( struct directory *directory ); -const c8 *directory_entry_name( struct directory *directory ); -bool directory_next_entry( struct directory *directory ); -enum directory_entry_type directory_entry_type( struct directory *directory ); -void directory_close( struct directory *directory ); - -#define EVENT_CALL( NAME, ... ) \ - for( u32 ev_iter=0; _event_##NAME##_subscribers[ ev_iter ]; ev_iter ++ ) \ - _event_##NAME##_subscribers[ ev_iter ]( __VA_ARGS__ ); - -struct sort_index -{ - u32 index; - i32 value; -}; -void index_sort( struct sort_index *indices, u32 indice_count ); diff --git a/include/common_thread_api.h b/include/common_thread_api.h deleted file mode 100644 index a149aa6..0000000 --- a/include/common_thread_api.h +++ /dev/null @@ -1,41 +0,0 @@ -#include "generated/threads.h" - -struct thread_info -{ - const c8 *name; - u32 queue_size_m; - u32 flags; -}; -struct thread_info *_get_thread_info( enum thread_id thread ); - -#define ASYNC_CRITICAL 0x1 -#define ASYNC_NONBLOCKING 0x2 - -// TODO THIS SHOULD BE PART OF THE METACOMPILER -#define THREAD_FLAG_MAIN 0x1 -#define THREAD_FLAG_ASYNC 0x2 -#define THREAD_FLAG_OPENGL 0x4 - -// TODO THIS SHOULD BE PART OF THE METACOMPILER -#define ASYNC_GROUP_OPENGL 0x1 -#define ASYNC_GROUP_FIRST_LOAD 0x2 - -void _set_thread_id( enum thread_id id ); -enum thread_id _get_thread_id(void); -bool _thread_has_flags( enum thread_id id, u32 flags ); - -struct task *_task_new( enum thread_id thread, u32 buffer_size, u32 async_flags, const c8 *debug_info ); -void task_send( struct task *task, void (*fn)( struct task *task ) ); - -void *task_buffer( struct task *task ); -u32 task_buffer_size( struct task *task ); - -bool _task_queue_process( bool blocking ); -bool _task_queue_can_fit( enum thread_id thread, u32 bytes ); - -void _async_init(void); - -void _async_push_groups( u16 groups, bool exclusive ); -void _async_pop_groups(void); -u16 _async_get_groups(void); -i16 _async_group_count( u16 group ); diff --git a/include/engine_backend.h b/include/engine_backend.h deleted file mode 100644 index 7f1621a..0000000 --- a/include/engine_backend.h +++ /dev/null @@ -1,7 +0,0 @@ -void _engine_console_ui(void); -void _engine_console_init(void); - -void _engine_ui_init(void); -void _engine_ui_pre_render(void); -void _engine_ui_post_render(void); -void _engine_ui_input_character( u32 codepoint ); diff --git a/include/engine_interface.h b/include/engine_interface.h deleted file mode 100644 index a428d99..0000000 --- a/include/engine_interface.h +++ /dev/null @@ -1,21 +0,0 @@ -struct _engine -{ - bool vsync; - f64 framerate_limit; - f64 time, time_delta, time_fixed_extrapolate; - - enum quality_profile - { - k_quality_profile_high = 0, - k_quality_profile_low = 1, - k_quality_profile_min = 2 - } - quality; - - void *window_handle; - i32 w, h; - - i32 native_fbo; -} -extern _engine; -#include "generated/console.h" diff --git a/include/glfw.h b/include/glfw.h deleted file mode 100644 index db755b5..0000000 --- a/include/glfw.h +++ /dev/null @@ -1,2 +0,0 @@ -#define GLFW_INCLUDE_NONE -#include "vg/dep/glfw-3.4/include/GLFW/glfw3.h" diff --git a/include/graphics_api.h b/include/graphics_api.h deleted file mode 100644 index e66096e..0000000 --- a/include/graphics_api.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Basic graphics - * ------------------------------------------------------------------------------------------------------------------ */ - -enum graphics_mode -{ - k_graphics_mode_software, - k_graphics_mode_opengl -}; -struct graphics_target -{ - enum graphics_mode mode; - i16 size[2]; - union - { - u8 *buffer; - }; -}; - -extern struct graphics_target *_graphics_target; - -#pragma pack( push, 1 ) -union colour -{ - struct{ u8 r, g, b, a; }; - u8 channels[4]; - u32 word; -}; -#pragma pack(pop) - -union colour graphics_lerp_colour( union colour c0, union colour c1, i32 d, i32 t ); - -enum blending_mode -{ - k_blending_mode_mix_alpha, - k_blending_mode_set, - k_blending_mode_add, - k_blending_mode_subtract, - k_blending_mode_multiply, - k_blending_mode_pop = -1 -}; - -void _graphics_set_target( struct graphics_target *target ); -void _graphics_viewport( i16 x, i16 y, i16 w, i16 h ); -void _graphics_pixel_unclipped( i16 co[2], union colour colour ); -void _graphics_pixel( i16 co[2], union colour colour ); -void _graphics_push_blendmode( enum blending_mode mode ); - -void _graphics_fill_rect( i16 rect[4], union colour colour ); -void _graphics_line_rect( i16 rect[4], union colour colour ); -void _graphics_line( i16 p0[2], i16 p1[2], union colour colour ); -void _graphics_line2( i16 p0[2], i16 p1[2], union colour c0, union colour c1 ); -void _graphics_line_triangle( i16 p0[2], i16 p1[2], i16 p2[2], union colour colour ); -void _graphics_fill_triangle( i16 in_p0[2], i16 in_p1[2], i16 in_p2[2], union colour colour ); -void _graphics_glyph( i16 co[2], u32 glyph, i16 scale, union colour colour ); - -void rect_clip( i16 child[4], i16 parent[4], i16 clipped[4] ); -void rect_copy( i16 a[4], i16 b[4] ); -void rect_pad( i16 rect[4], i16 padding[2] ); -void rect_split( i16 rect[4], u32 vertical, i16 width, i16 gap, i16 out_left[4], i16 out_right[4] ); -void rect_split_ratio( i16 rect[4], u32 vertical, f32 ratio, i16 gap, i16 out_left[4], i16 out_right[4] ); -bool ui_inside_rect( i16 rect[4], i16 co[2] ); - -/* Font - * ------------------------------------------------------------------------------------------------------------------ */ - -struct font_face_descriptor -{ - i16 cw, ch, sx, sy, baseline; - i16 map[256][2]; -}; - -struct _font -{ - enum font_face - { - k_font_face_normal=0, - k_font_face_larger, - k_font_face_title, - k_font_face_pop = -1 - } - face_stack[8]; - u32 face_stack_depth; - - i16 bitmap_size[2]; - u32 bitmap[]; -} -extern _font; -void _font_push_face( enum font_face face ); -void _font_get_kerning( i16 out_kerning[3] ); -void _font_get_glyph_uvwh( u32 glyph, i16 out_uvwh[5] ); -bool _font_decode_bitmap( i16 uv[2] ); - -/* Immediate mode UI - * ------------------------------------------------------------------------------------------------------------------ */ -void _ui_set_mouse( i16 x, i16 y ); -void _ui_get_mouse_co( i16 out_co[2] ); -void _ui_input_text( const c8 *text ); -bool _ui_want_mouse( i16 area[4] ); - -#define UI_PADDING_PX 8 -#define UI_ROW_PADDING_PX 18 -#define UI_HORIZONTAL 0 -#define UI_VERTICAL 1 -#define MOUSE_LEFT 0x1 -#define MOUSE_RIGHT 0x2 - -#define UI_AUTOFOCUS 0x1 -#define UI_MULTILINE 0x2 - -bool _ui_update(void); -void _ui_draw(void); - -/* Text */ -enum ui_text_encoding -{ - k_ui_text_default, - k_ui_text_utf8 -}; -void _ui_set_encoding( enum ui_text_encoding encoding ); - -enum ui_align -{ - k_ui_align_x_left = 0x1, - k_ui_align_x_right = 0x2, - k_ui_align_x_center = 0x4, - - k_ui_align_y_top = 0x10, - k_ui_align_y_bottom = 0x20, - k_ui_align_y_center = 0x40, - k_ui_align_center = k_ui_align_x_center|k_ui_align_y_center -}; -void _ui_text( i16 rect[4], const c8 *text, enum ui_align align, union colour colour ); - -/* Simple controls - * ------------------------------------------------- */ -i16 _ui_widget_row_height( i16 row_size ); -void _ui_widget_row( i16 inout_panel[4], i16 out_rect[4], i16 row_size ); - -/* Button --------------------------------- */ -enum button_action -{ - k_button_none = 0, - k_button_click = 1, - k_button_repeat = 2, - k_button_hover = 3, -}; -enum button_action _ui_button( i16 rect[4] ); - -/* Checkbox ------------------------------- */ -enum button_action _ui_checkbox( i16 rect[4], i32 *value ); - -/* Dropdown ------------------------------- */ -enum dropdown_action -{ - k_dropdown_none, - k_dropdown_changed -}; -struct ui_dropdown_option -{ - i32 value; - const c8 *display_name; -}; -enum dropdown_action _ui_dropdown( i16 rect[4], struct ui_dropdown_option *options, u32 option_count, i32 *value ); - -/* Slider ---------------------------------- */ -enum button_action _ui_slider( i16 rect[4], i32 vertical, f32 min, f32 max, f32 *value, f32 *out_t ); - -/* Textbox --------------------------------- */ -enum textbox_action -{ - k_textbox_no_action, - k_textbox_enter, - k_textbox_input_up, - k_textbox_input_down, - k_textbox_changed, - k_textbox_escape -}; -enum textbox_action _ui_textbox( i16 rect[4], c8 *text_buffer, u32 text_buffer_length, u32 lines, u32 flags ); diff --git a/include/input_api.h b/include/input_api.h deleted file mode 100644 index e4f21dd..0000000 --- a/include/input_api.h +++ /dev/null @@ -1,34 +0,0 @@ -enum input_type -{ - k_input_type_action, - k_input_type_button, - k_input_type_axis -}; - -enum input_device -{ - k_input_device_none = 0, - k_input_device_keyboard, - k_input_device_controller, - k_input_device_mouse, - k_input_device_modifier, -}; - -struct input_info -{ - const c8 *name; - enum input_type type; - u32 layer_mask; -}; - -enum input_id; - -u8 _input_button_down( enum input_id id, bool allow_repeats ); -u8 _input_button_up( enum input_id id ); -u8 _input_button( enum input_id id ); - -void _input_layer_whitelist( u32 whitelist ); -bool _input_layer_filter( u32 mask ); -void _input_string( struct stream *stream, enum input_id id ); - -#include "generated/input.h" diff --git a/include/maths/common_maths.h b/include/maths/common_maths.h deleted file mode 100644 index b8345d3..0000000 --- a/include/maths/common_maths.h +++ /dev/null @@ -1,1405 +0,0 @@ -#include -#define VG_PIf 3.141592 /* fuck you */ -#define VG_TAUf 6.283 /* fuckk you */ - -static inline u32 f32_raw_bits( f32 a ) { return *((u32 *)(&a)); } -static inline bool f32_is_infinite( f32 a ) { return ((f32_raw_bits(a)) & 0x7FFFFFFFU) == 0x7F800000U; } -static inline bool f32_is_nan( f32 a ) { return !f32_is_infinite(a) && ((f32_raw_bits(a)) & 0x7F800000U) == 0x7F800000U;} -static inline bool f32_is_number( f32 a ) { return ((f32_raw_bits(a)) & 0x7F800000U) != 0x7F800000U; } - -/* Scalars ---------------------------------------------------------------------------------------------------------- */ - -static inline f32 f32_fractional_part( f32 a ) { return a - floorf( a ); } -static inline f64 f64_fractional_part( f64 a ) { return a - floor( a ); } -static inline f32 f32_degrees_to_radians( f32 degrees ) { return degrees * VG_PIf/180.0f; } -static inline f32 f32_friction( f32 velocity, f32 F ) -{ - return -f32_sign(velocity) * f32_min( F, fabsf(velocity) ); -} -static inline f32 f32_lerp( f32 a, f32 b, f32 t ) { return a + t*(b-a); } -static inline f64 f64_lerp( f64 a, f64 b, f64 t ) { return a + t*(b-a); } -static inline void vg_slewf( f32 *a, f32 b, f32 speed ) -{ - f32 d = f32_sign( b-*a ), - c = *a + d*speed; - *a = f32_min( b*d, c*d ) * d; -} -static inline f32 f32_smoothstep( f32 x ) { return x*x*(3.0f - 2.0f*x); } - -static inline f32 f32_radian_difference( f32 a, f32 b ) -{ - f32 d = fmodf(b,VG_TAUf)-fmodf(a,VG_TAUf); - if( fabsf(d) > VG_PIf ) - d = -f32_sign(d) * (VG_TAUf - fabsf(d)); - return d; -} -static inline f32 f32_radian_lerp( f32 a, f32 b, f32 t ) -{ - f32 d = fmodf( b-a, VG_TAUf ), - s = fmodf( 2.0f*d, VG_TAUf ) - d; - return a + s*t; -} - -static inline u32 f32_quantize( f32 a, u32 bits, f32 min, f32 max ) -{ - u32 mask = (0x1 << bits) - 1; - return f32_clamp((a - min) * ((f32)mask/(max-min)), 0.0f, mask ); -} -static inline f32 f32_unquantize( u32 q, u32 bits, f32 min, f32 max ) -{ - return min + (f32)q * ((max-min) / (f32)((0x1 << bits) - 1)); -} -/* https://iquilezles.org/articles/functions/ - * - * Use k to control the stretching of the function. Its maximum, which is 1, - * happens at exactly x = 1/k. - */ -static inline f32 f32_exponential_impulse( f32 x, f32 k ) -{ - f32 h = k*x; - return h*expf(1.0f-h); -} - -/* f32[2] ----------------------------------------------------------------------------------------------------------- */ -static inline void v2_copy( f32 a[2], f32 d[2] ) -{ - d[0] = a[0]; - d[1] = a[1]; -} -static inline void v2_add( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = a[0]+b[0]; - d[1] = a[1]+b[1]; -} -static inline void v2_sub( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = a[0]-b[0]; - d[1] = a[1]-b[1]; -} -static inline void v2_min( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = f32_min(a[0], b[0]); - d[1] = f32_min(a[1], b[1]); -} -static inline void v2_max( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = f32_max(a[0], b[0]); - d[1] = f32_max(a[1], b[1]); -} -static inline f32 v2_dot( f32 a[2], f32 b[2] ) -{ - return a[0] * b[0] + a[1] * b[1]; -} -static inline f32 v2_cross( f32 a[2], f32 b[2] ) -{ - return a[0]*b[1] - a[1]*b[0]; -} -static inline void v2_abs( f32 a[2], f32 d[2] ) -{ - d[0] = fabsf( a[0] ); - d[1] = fabsf( a[1] ); -} -static inline void v2_muls( f32 a[2], f32 s, f32 d[2] ) -{ - d[0] = a[0]*s; - d[1] = a[1]*s; -} -static inline void v2_divs( f32 a[2], f32 s, f32 d[2] ) -{ - d[0] = a[0]/s; - d[1] = a[1]/s; -} -static inline void v2_mul( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = a[0]*b[0]; - d[1] = a[1]*b[1]; -} -static inline void v2_div( f32 a[2], f32 b[2], f32 d[2] ) -{ - d[0] = a[0]/b[0]; - d[1] = a[1]/b[1]; -} -static inline void v2_muladd( f32 a[2], f32 b[2], f32 s[2], f32 d[2] ) -{ - d[0] = a[0]+b[0]*s[0]; - d[1] = a[1]+b[1]*s[1]; -} -static inline void v2_muladds( f32 a[2], f32 b[2], f32 s, f32 d[2] ) -{ - d[0] = a[0]+b[0]*s; - d[1] = a[1]+b[1]*s; -} -static inline f32 v2_length2( f32 a[2] ) -{ - return a[0]*a[0] + a[1]*a[1]; -} -static inline f32 v2_length( f32 a[2] ) -{ - return sqrtf( v2_length2( a ) ); -} -static inline f32 v2_dist2( f32 a[2], f32 b[2] ) -{ - f32 delta[2]; - v2_sub( a, b, delta ); - return v2_length2( delta ); -} -static inline f32 v2_dist( f32 a[2], f32 b[2] ) -{ - return sqrtf( v2_dist2( a, b ) ); -} -static inline void v2_lerp( f32 a[2], f32 b[2], f32 t, f32 d[2] ) -{ - d[0] = a[0] + t*(b[0]-a[0]); - d[1] = a[1] + t*(b[1]-a[1]); -} -static inline void v2_normalize( f32 a[2] ) -{ - v2_muls( a, 1.0f / v2_length( a ), a ); -} -static inline void v2_normalize_clamp( f32 a[2] ) -{ - f32 l2 = v2_length2( a ); - if( l2 > 1.0f ) - v2_muls( a, 1.0f/sqrtf(l2), a ); -} -static inline void v2_floor( f32 a[2], f32 b[2] ) -{ - b[0] = floorf( a[0] ); - b[1] = floorf( a[1] ); -} -static inline void v2_fill( f32 a[2], f32 v ) -{ - a[0] = v; - a[1] = v; -} -static inline void v2_copysign( f32 a[2], f32 b[2] ) -{ - a[0] = copysignf( a[0], b[0] ); - a[1] = copysignf( a[1], b[1] ); -} -/* integer variants */ -static inline void v2i_copy( i32 a[2], i32 b[2] ) -{ - b[0] = a[0]; - b[1] = a[1]; -} -static inline int v2i_eq( i32 a[2], i32 b[2] ) -{ - return ((a[0] == b[0]) && (a[1] == b[1])); -} -static inline void v2i_add( i32 a[2], i32 b[2], i32 d[2] ) -{ - d[0] = a[0]+b[0]; - d[1] = a[1]+b[1]; -} -static inline void v2i_sub( i32 a[2], i32 b[2], i32 d[2] ) -{ - d[0] = a[0]-b[0]; - d[1] = a[1]-b[1]; -} - -/* f32[3] ----------------------------------------------------------------------------------------------------------- */ -static inline bool v3_is_numbers( f32 a[3] ) -{ - return f32_is_number( a[0] ) && f32_is_number( a[1] ) && f32_is_number( a[2] ); -} -static inline void v3_copy( f32 a[3], f32 b[3] ) -{ - b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; -} -static inline void v3_add( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = a[0]+b[0]; - d[1] = a[1]+b[1]; - d[2] = a[2]+b[2]; -} -static inline void v3i_add( i32 a[3], i32 b[3], i32 d[3] ) -{ - d[0] = a[0]+b[0]; - d[1] = a[1]+b[1]; - d[2] = a[2]+b[2]; -} -static inline void v3_sub( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = a[0]-b[0]; - d[1] = a[1]-b[1]; - d[2] = a[2]-b[2]; -} -static inline void v3i_sub( i32 a[3], i32 b[3], i32 d[3] ) -{ - d[0] = a[0]-b[0]; - d[1] = a[1]-b[1]; - d[2] = a[2]-b[2]; -} -static inline void v3_mul( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = a[0]*b[0]; - d[1] = a[1]*b[1]; - d[2] = a[2]*b[2]; -} -static inline void v3_div( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = b[0]!=0.0f? a[0]/b[0]: INFINITY; - d[1] = b[1]!=0.0f? a[1]/b[1]: INFINITY; - d[2] = b[2]!=0.0f? a[2]/b[2]: INFINITY; -} -static inline void v3_muls( f32 a[3], f32 s, f32 d[3] ) -{ - d[0] = a[0]*s; - d[1] = a[1]*s; - d[2] = a[2]*s; -} -static inline void v3_fill( f32 a[3], f32 v ) -{ - a[0] = v; - a[1] = v; - a[2] = v; -} -static inline void v4_fill( f32 a[4], f32 v ) -{ - a[0] = v; - a[1] = v; - a[2] = v; - a[3] = v; -} -static inline void v3_divs( f32 a[3], f32 s, f32 d[3] ) -{ - if( s == 0.0f ) - v3_fill( d, INFINITY ); - else - { - d[0] = a[0]/s; - d[1] = a[1]/s; - d[2] = a[2]/s; - } -} -static inline void v3_muladds( f32 a[3], f32 b[3], f32 s, f32 d[3] ) -{ - d[0] = a[0]+b[0]*s; - d[1] = a[1]+b[1]*s; - d[2] = a[2]+b[2]*s; -} -static inline void v3_muladd( f32 a[3], f32 b[3], f32 s[3], f32 d[3] ) -{ - d[0] = a[0]+b[0]*s[0]; - d[1] = a[1]+b[1]*s[1]; - d[2] = a[2]+b[2]*s[2]; -} -static inline f32 v3_dot( f32 a[3], f32 b[3] ) -{ - return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; -} -static inline void v3_cross( f32 a[3], f32 b[3], f32 dest[3] ) -{ - f32 d[3]; - d[0] = a[1]*b[2] - a[2]*b[1]; - d[1] = a[2]*b[0] - a[0]*b[2]; - d[2] = a[0]*b[1] - a[1]*b[0]; - v3_copy( d, dest ); -} -static inline f32 v3_length2( f32 a[3] ) -{ - return v3_dot( a, a ); -} -static inline f32 v3_length( f32 a[3] ) -{ - return sqrtf( v3_length2( a ) ); -} -static inline f32 v3_dist2( f32 a[3], f32 b[3] ) -{ - f32 delta[3]; - v3_sub( a, b, delta ); - return v3_length2( delta ); -} -static inline f32 v3_dist( f32 a[3], f32 b[3] ) -{ - return sqrtf( v3_dist2( a, b ) ); -} -static inline void v3_normalize( f32 a[3] ) -{ - v3_muls( a, 1.f / v3_length( a ), a ); -} -static inline void v3_lerp( f32 a[3], f32 b[3], f32 t, f32 d[3] ) -{ - d[0] = a[0] + t*(b[0]-a[0]); - d[1] = a[1] + t*(b[1]-a[1]); - d[2] = a[2] + t*(b[2]-a[2]); -} -static inline void v3_min( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = f32_min(a[0], b[0]); - d[1] = f32_min(a[1], b[1]); - d[2] = f32_min(a[2], b[2]); -} -static inline void v3_max( f32 a[3], f32 b[3], f32 d[3] ) -{ - d[0] = f32_max(a[0], b[0]); - d[1] = f32_max(a[1], b[1]); - d[2] = f32_max(a[2], b[2]); -} -static inline f32 v3_min_element( f32 a[3] ) -{ - return f32_min( f32_min( a[0], a[1] ), a[2] ); -} -static inline f32 v3_max_element( f32 a[3] ) -{ - return f32_max( f32_max( a[0], a[1] ), a[2] ); -} -static inline void v3_floor( f32 a[3], f32 b[3] ) -{ - b[0] = floorf( a[0] ); - b[1] = floorf( a[1] ); - b[2] = floorf( a[2] ); -} -static inline void v3_ceil( f32 a[3], f32 b[3] ) -{ - b[0] = ceilf( a[0] ); - b[1] = ceilf( a[1] ); - b[2] = ceilf( a[2] ); -} -static inline void v3_negate( f32 a[3], f32 b[3] ) -{ - b[0] = -a[0]; - b[1] = -a[1]; - b[2] = -a[2]; -} -static inline void v3_rotate( f32 v[3], f32 angle, f32 axis[3], f32 d[3] ) -{ - f32 v1[3], v2[3], k[3], c, s; - c = cosf( angle ); - s = sinf( angle ); - v3_copy( axis, k ); - v3_normalize( k ); - v3_muls( v, c, v1 ); - v3_cross( k, v, v2 ); - v3_muls( v2, s, v2 ); - v3_add( v1, v2, v1 ); - v3_muls( k, v3_dot(k, v) * (1.0f - c), v2); - v3_add( v1, v2, d ); -} -static inline void v3_tangent_basis( f32 n[3], f32 out_tx[3], f32 out_ty[3] ) -{ - /* Compute tangent basis (box2d) */ - if( fabsf( n[0] ) >= 0.57735027f ) - { - out_tx[0] = n[1]; - out_tx[1] = -n[0]; - out_tx[2] = 0.0f; - } - else - { - out_tx[0] = 0.0f; - out_tx[1] = n[2]; - out_tx[2] = -n[1]; - } - v3_normalize( out_tx ); - v3_cross( n, out_tx, out_ty ); -} -static inline void v3_vector_to_angles( f32 v[3], f32 out_angles[3] ) -{ - f32 yaw = atan2f( v[0], -v[2] ), - pitch = atan2f( -v[1], sqrtf( v[0]*v[0] + v[2]*v[2] ) ); - out_angles[0] = yaw; - out_angles[1] = pitch; - out_angles[2] = 0.0f; -} -static inline void v3_angles_to_vector( f32 angles[3], f32 out_vector[3] ) -{ - out_vector[0] = sinf( angles[0] ) * cosf( angles[1] ); - out_vector[1] = -sinf( angles[1] ); - out_vector[2] = -cosf( angles[0] ) * cosf( angles[1] ); -} - -/* f32[4] ----------------------------------------------------------------------------------------------------------- */ -static inline void v4_copy( f32 a[4], f32 d[4] ) -{ - d[0] = a[0]; - d[1] = a[1]; - d[2] = a[2]; - d[3] = a[3]; -} -static inline void v4_add( f32 a[4], f32 b[3], f32 d[4] ) -{ - d[0] = a[0]+b[0]; - d[1] = a[1]+b[1]; - d[2] = a[2]+b[2]; - d[3] = a[3]+b[3]; -} -static inline void v4_muls( f32 a[4], f32 s, f32 d[4] ) -{ - d[0] = a[0]*s; - d[1] = a[1]*s; - d[2] = a[2]*s; - d[3] = a[3]*s; -} -static inline void v4_muladds( f32 a[4], f32 b[4], f32 s, f32 d[4] ) -{ - d[0] = a[0]+b[0]*s; - d[1] = a[1]+b[1]*s; - d[2] = a[2]+b[2]*s; - d[3] = a[3]+b[3]*s; -} -static inline void v4_lerp( f32 a[4], f32 b[4], f32 t, f32 d[4] ) -{ - d[0] = a[0] + t*(b[0]-a[0]); - d[1] = a[1] + t*(b[1]-a[1]); - d[2] = a[2] + t*(b[2]-a[2]); - d[3] = a[3] + t*(b[3]-a[3]); -} -static inline f32 v4_dot( f32 a[4], f32 b[4] ) -{ - return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]; -} -static inline f32 v4_length( f32 a[4] ) -{ - return sqrtf( v4_dot(a,a) ); -} - -/* f32[4] ----------------------------------------------------------------------------------------------------------- */ -static inline void q_identity( f32 q[4] ) -{ - q[0] = 0.0f; - q[1] = 0.0f; - q[2] = 0.0f; - q[3] = 1.0f; -} -static inline void q_axis_angle( f32 q[4], f32 axis[3], f32 angle ) -{ - f32 a = angle*0.5f, - c = cosf(a), - s = sinf(a); - q[0] = s*axis[0]; - q[1] = s*axis[1]; - q[2] = s*axis[2]; - q[3] = c; -} -static inline void q_mul( f32 q[4], f32 q1[4], f32 d[4] ) -{ - f32 t[4]; - t[0] = q[3]*q1[0] + q[0]*q1[3] + q[1]*q1[2] - q[2]*q1[1]; - t[1] = q[3]*q1[1] - q[0]*q1[2] + q[1]*q1[3] + q[2]*q1[0]; - t[2] = q[3]*q1[2] + q[0]*q1[1] - q[1]*q1[0] + q[2]*q1[3]; - t[3] = q[3]*q1[3] - q[0]*q1[0] - q[1]*q1[1] - q[2]*q1[2]; - v4_copy( t, d ); -} -static inline void q_normalize( f32 q[4] ) -{ - f32 l2 = v4_dot(q,q); - if( l2 < 0.00001f ) - q_identity( q ); - else - { - f32 s = 1.0f/sqrtf(l2); - q[0] *= s; - q[1] *= s; - q[2] *= s; - q[3] *= s; - } -} -static inline void q_inv( f32 q[4], f32 d[4] ) -{ - f32 s = 1.0f / v4_dot(q,q); - d[0] = -q[0]*s; - d[1] = -q[1]*s; - d[2] = -q[2]*s; - d[3] = q[3]*s; -} -static inline void q_nlerp( f32 a[4], f32 b[4], f32 t, f32 d[4] ) -{ - if( v4_dot(a,b) < 0.0f ) - { - f32 c[4]; - v4_muls( b, -1.0f, c ); - v4_lerp( a, c, t, d ); - } - else - v4_lerp( a, b, t, d ); - q_normalize( d ); -} -static inline void q_m3x3( f32 q[4], f32 d[3][3] ) -{ - f32 l = v4_length(q), - s = l > 0.0f? 2.0f/l: 0.0f, - xx = s*q[0]*q[0], xy = s*q[0]*q[1], wx = s*q[3]*q[0], - yy = s*q[1]*q[1], yz = s*q[1]*q[2], wy = s*q[3]*q[1], - zz = s*q[2]*q[2], xz = s*q[0]*q[2], wz = s*q[3]*q[2]; - d[0][0] = 1.0f - yy - zz; - d[1][1] = 1.0f - xx - zz; - d[2][2] = 1.0f - xx - yy; - d[0][1] = xy + wz; - d[1][2] = yz + wx; - d[2][0] = xz + wy; - d[1][0] = xy - wz; - d[2][1] = yz - wx; - d[0][2] = xz - wy; -} -static inline void q_mulv( f32 q[4], f32 v[3], f32 d[3] ) -{ - f32 v1[3], v2[3]; - v3_muls( q, 2.0f*v3_dot(q,v), v1 ); - v3_muls( v, q[3]*q[3] - v3_dot(q,q), v2 ); - v3_add( v1, v2, v1 ); - v3_cross( q, v, v2 ); - v3_muls( v2, 2.0f*q[3], v2 ); - v3_add( v1, v2, d ); -} -static inline f32 q_dist( f32 q0[4], f32 q1[4] ) -{ - return acosf( 2.0f * v4_dot(q0,q1) -1.0f ); -} -static inline void q_copy( f32 a[4], f32 b[4] ) -{ - b[0] = a[0]; - b[1] = a[1]; - b[2] = a[2]; - b[3] = a[3]; -} -static inline void m2x2_copy( f32 a[2][2], f32 b[2][2] ) -{ - v2_copy( a[0], b[0] ); - v2_copy( a[1], b[1] ); -} -static inline void m2x2_identity( f32 a[2][2] ) -{ - m2x2_copy( (f32[2][2]){{1,0}, - {0,1}}, a ); -} -static inline void m2x2_create_rotation( f32 a[2][2], f32 theta ) -{ - f32 s = sinf( theta ), - c = cosf( theta ); - a[0][0] = c; - a[0][1] = -s; - a[1][0] = s; - a[1][1] = c; -} -static inline void m2x2_mulv( f32 m[2][2], f32 v[2], f32 d[2] ) -{ - f32 res[2]; - res[0] = m[0][0]*v[0] + m[1][0]*v[1]; - res[1] = m[0][1]*v[0] + m[1][1]*v[1]; - v2_copy( res, d ); -} - -/* f32[3][3] -------------------------------------------------------------------------------------------------------- */ -static inline void euler_m3x3( f32 angles[3], f32 d[3][3] ) -{ - f32 cosY = cosf( angles[0] ), - sinY = sinf( angles[0] ), - cosP = cosf( angles[1] ), - sinP = sinf( angles[1] ), - cosR = cosf( angles[2] ), - sinR = sinf( angles[2] ); - d[2][0] = -sinY * cosP; - d[2][1] = sinP; - d[2][2] = cosY * cosP; - d[0][0] = cosY * cosR; - d[0][1] = sinR; - d[0][2] = sinY * cosR; - v3_cross( d[0], d[2], d[1] ); -} -static inline void m3x3_q( f32 m[3][3], f32 q[4] ) -{ - f32 diag, r, rinv; - diag = m[0][0] + m[1][1] + m[2][2]; - if( diag >= 0.0f ) - { - r = sqrtf( 1.0f + diag ); - rinv = 0.5f / r; - q[0] = rinv * (m[1][2] - m[2][1]); - q[1] = rinv * (m[2][0] - m[0][2]); - q[2] = rinv * (m[0][1] - m[1][0]); - q[3] = r * 0.5f; - } - else if( m[0][0] >= m[1][1] && m[0][0] >= m[2][2] ) - { - r = sqrtf( 1.0f - m[1][1] - m[2][2] + m[0][0] ); - rinv = 0.5f / r; - q[0] = r * 0.5f; - q[1] = rinv * (m[0][1] + m[1][0]); - q[2] = rinv * (m[0][2] + m[2][0]); - q[3] = rinv * (m[1][2] - m[2][1]); - } - else if( m[1][1] >= m[2][2] ) - { - r = sqrtf( 1.0f - m[0][0] - m[2][2] + m[1][1] ); - rinv = 0.5f / r; - q[0] = rinv * (m[0][1] + m[1][0]); - q[1] = r * 0.5f; - q[2] = rinv * (m[1][2] + m[2][1]); - q[3] = rinv * (m[2][0] - m[0][2]); - } - else - { - r = sqrtf( 1.0f - m[0][0] - m[1][1] + m[2][2] ); - rinv = 0.5f / r; - q[0] = rinv * (m[0][2] + m[2][0]); - q[1] = rinv * (m[1][2] + m[2][1]); - q[2] = r * 0.5f; - q[3] = rinv * (m[0][1] - m[1][0]); - } -} -/* a X b == [b]T a == ...*/ -static inline void m3x3_skew_symetric( f32 a[3][3], f32 v[3] ) -{ - a[0][0] = 0.0f; - a[0][1] = v[2]; - a[0][2] = -v[1]; - a[1][0] = -v[2]; - a[1][1] = 0.0f; - a[1][2] = v[0]; - a[2][0] = v[1]; - a[2][1] = -v[0]; - a[2][2] = 0.0f; -} -/* aka kronecker product */ -static inline void m3x3_outer_product( f32 out_m[3][3], f32 a[3], f32 b[3] ) -{ - out_m[0][0] = a[0]*b[0]; - out_m[0][1] = a[0]*b[1]; - out_m[0][2] = a[0]*b[2]; - out_m[1][0] = a[1]*b[0]; - out_m[1][1] = a[1]*b[1]; - out_m[1][2] = a[1]*b[2]; - out_m[2][0] = a[2]*b[0]; - out_m[2][1] = a[2]*b[1]; - out_m[2][2] = a[2]*b[2]; -} -static inline void m3x3_add( f32 a[3][3], f32 b[3][3], f32 d[3][3] ) -{ - v3_add( a[0], b[0], d[0] ); - v3_add( a[1], b[1], d[1] ); - v3_add( a[2], b[2], d[2] ); -} -static inline void m3x3_sub( f32 a[3][3], f32 b[3][3], f32 d[3][3] ) -{ - v3_sub( a[0], b[0], d[0] ); - v3_sub( a[1], b[1], d[1] ); - v3_sub( a[2], b[2], d[2] ); -} -static inline void m3x3_copy( f32 a[3][3], f32 b[3][3] ) -{ - v3_copy( a[0], b[0] ); - v3_copy( a[1], b[1] ); - v3_copy( a[2], b[2] ); -} -static inline void m3x3_identity( f32 a[3][3] ) -{ - m3x3_copy( (f32[3][3]){{1,0,0}, - {0,1,0}, - {0,0,1}}, a ); -} -static inline void m3x3_zero( f32 a[3][3] ) -{ - m3x3_copy( (f32[3][3]){{0,0,0}, - {0,0,0}, - {0,0,0}}, a ); -} -static inline void m3x3_diagonal( f32 out_a[3][3], f32 t ) -{ - m3x3_identity( out_a ); - out_a[0][0] = t; - out_a[1][1] = t; - out_a[2][2] = t; -} -static inline void m3x3_set_diagonal_v3( f32 a[3][3], f32 v[3] ) -{ - a[0][0] = v[0]; - a[1][1] = v[1]; - a[2][2] = v[2]; -} -static inline void m3x3_inv( f32 src[3][3], f32 dest[3][3] ) -{ - f32 a = src[0][0], b = src[0][1], c = src[0][2], - d = src[1][0], e = src[1][1], f = src[1][2], - g = src[2][0], h = src[2][1], i = src[2][2], - det = 1.f / (+a*(e*i-h*f) - -b*(d*i-f*g) - +c*(d*h-e*g)); - dest[0][0] = (e*i-h*f)*det; - dest[0][1] = -(b*i-c*h)*det; - dest[0][2] = (b*f-c*e)*det; - dest[1][0] = -(d*i-f*g)*det; - dest[1][1] = (a*i-c*g)*det; - dest[1][2] = -(a*f-d*c)*det; - dest[2][0] = (d*h-g*e)*det; - dest[2][1] = -(a*h-g*b)*det; - dest[2][2] = (a*e-d*b)*det; -} -static inline f32 m3x3_det( f32 m[3][3] ) -{ - return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) - + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); -} -static inline void m3x3_transpose( f32 src[3][3], f32 dest[3][3] ) -{ - f32 a = src[0][0], b = src[0][1], c = src[0][2], - d = src[1][0], e = src[1][1], f = src[1][2], - g = src[2][0], h = src[2][1], i = src[2][2]; - dest[0][0] = a; - dest[0][1] = d; - dest[0][2] = g; - dest[1][0] = b; - dest[1][1] = e; - dest[1][2] = h; - dest[2][0] = c; - dest[2][1] = f; - dest[2][2] = i; -} -static inline void m3x3_mul( f32 a[3][3], f32 b[3][3], f32 d[3][3] ) -{ - f32 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], - b00 = b[0][0], b01 = b[0][1], b02 = b[0][2], - b10 = b[1][0], b11 = b[1][1], b12 = b[1][2], - b20 = b[2][0], b21 = b[2][1], b22 = b[2][2]; - d[0][0] = a00*b00 + a10*b01 + a20*b02; - d[0][1] = a01*b00 + a11*b01 + a21*b02; - d[0][2] = a02*b00 + a12*b01 + a22*b02; - d[1][0] = a00*b10 + a10*b11 + a20*b12; - d[1][1] = a01*b10 + a11*b11 + a21*b12; - d[1][2] = a02*b10 + a12*b11 + a22*b12; - d[2][0] = a00*b20 + a10*b21 + a20*b22; - d[2][1] = a01*b20 + a11*b21 + a21*b22; - d[2][2] = a02*b20 + a12*b21 + a22*b22; -} -static inline void m3x3_mulv( f32 m[3][3], f32 v[3], f32 d[3] ) -{ - f32 res[3]; - res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2]; - res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2]; - res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2]; - v3_copy( res, d ); -} -static inline void m3x3_projection( f32 d[3][3], f32 left, f32 right, f32 bottom, f32 top ) -{ - f32 rl, tb; - m3x3_zero( d ); - rl = 1.0f / (right - left); - tb = 1.0f / (top - bottom); - d[0][0] = 2.0f * rl; - d[1][1] = 2.0f * tb; - d[2][2] = 1.0f; -} -static inline void m3x3_translate( f32 m[3][3], f32 v[3] ) -{ - m[2][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0]; - m[2][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1]; - m[2][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2]; -} -static inline void m3x3_scale( f32 m[3][3], f32 v[3] ) -{ - v3_muls( m[0], v[0], m[0] ); - v3_muls( m[1], v[1], m[1] ); - v3_muls( m[2], v[2], m[2] ); -} -static inline void m3x3_scalef( f32 m[3][3], f32 f ) -{ - f32 v[3]; - v3_fill( v, f ); - m3x3_scale( m, v ); -} -static inline void m3x3_rotate( f32 m[3][3], f32 angle ) -{ - f32 m00 = m[0][0], m10 = m[1][0], - m01 = m[0][1], m11 = m[1][1], - m02 = m[0][2], m12 = m[1][2], c, s; - s = sinf( angle ); - c = cosf( angle ); - m[0][0] = m00 * c + m10 * s; - m[0][1] = m01 * c + m11 * s; - m[0][2] = m02 * c + m12 * s; - m[1][0] = m00 * -s + m10 * c; - m[1][1] = m01 * -s + m11 * c; - m[1][2] = m02 * -s + m12 * c; -} - -/* f32[4][3] -------------------------------------------------------------------------------------------------------- */ -static inline void m4x3_to_3x3( f32 a[4][3], f32 b[3][3] ) -{ - v3_copy( a[0], b[0] ); - v3_copy( a[1], b[1] ); - v3_copy( a[2], b[2] ); -} -static inline void m4x3_invert_affine( f32 a[4][3], f32 b[4][3] ) -{ - m3x3_transpose( a, b ); - m3x3_mulv( b, a[3], b[3] ); - v3_negate( b[3], b[3] ); -} -static inline void m4x3_invert_full( f32 src[4][3], f32 dst[4][3] ) -{ - f32 t2, t4, t5, - det, - a = src[0][0], b = src[0][1], c = src[0][2], - e = src[1][0], f = src[1][1], g = src[1][2], - i = src[2][0], j = src[2][1], k = src[2][2], - m = src[3][0], n = src[3][1], o = src[3][2]; - t2 = j*o - n*k; - t4 = i*o - m*k; - t5 = i*n - m*j; - - dst[0][0] = f*k - g*j; - dst[1][0] =-(e*k - g*i); - dst[2][0] = e*j - f*i; - dst[3][0] =-(e*t2 - f*t4 + g*t5); - - dst[0][1] =-(b*k - c*j); - dst[1][1] = a*k - c*i; - dst[2][1] =-(a*j - b*i); - dst[3][1] = a*t2 - b*t4 + c*t5; - - t2 = f*o - n*g; - t4 = e*o - m*g; - t5 = e*n - m*f; - - dst[0][2] = b*g - c*f ; - dst[1][2] =-(a*g - c*e ); - dst[2][2] = a*f - b*e ; - dst[3][2] =-(a*t2 - b*t4 + c * t5); - - det = 1.0f / (a * dst[0][0] + b * dst[1][0] + c * dst[2][0]); - v3_muls( dst[0], det, dst[0] ); - v3_muls( dst[1], det, dst[1] ); - v3_muls( dst[2], det, dst[2] ); - v3_muls( dst[3], det, dst[3] ); -} -static inline void m4x3_copy( f32 a[4][3], f32 b[4][3] ) -{ - v3_copy( a[0], b[0] ); - v3_copy( a[1], b[1] ); - v3_copy( a[2], b[2] ); - v3_copy( a[3], b[3] ); -} -static inline void m4x3_identity( f32 a[4][3] ) -{ - m4x3_copy( (f32[4][3]){{1,0,0}, - {0,1,0}, - {0,0,1}, - {0,0,0}}, a ); -} -static inline void m4x3_mul( f32 a[4][3], f32 b[4][3], f32 d[4][3] ) -{ - f32 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], - a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], - b00 = b[0][0], b01 = b[0][1], b02 = b[0][2], - b10 = b[1][0], b11 = b[1][1], b12 = b[1][2], - b20 = b[2][0], b21 = b[2][1], b22 = b[2][2], - b30 = b[3][0], b31 = b[3][1], b32 = b[3][2]; - d[0][0] = a00*b00 + a10*b01 + a20*b02; - d[0][1] = a01*b00 + a11*b01 + a21*b02; - d[0][2] = a02*b00 + a12*b01 + a22*b02; - d[1][0] = a00*b10 + a10*b11 + a20*b12; - d[1][1] = a01*b10 + a11*b11 + a21*b12; - d[1][2] = a02*b10 + a12*b11 + a22*b12; - d[2][0] = a00*b20 + a10*b21 + a20*b22; - d[2][1] = a01*b20 + a11*b21 + a21*b22; - d[2][2] = a02*b20 + a12*b21 + a22*b22; - d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30; - d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31; - d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32; -} -static inline void m4x3_mulv( f32 m[4][3], f32 v[3], f32 d[3] ) -{ - f32 result[3]; - result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]; - result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]; - result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]; - v3_copy( result, d ); -} -static inline void m4x3_mulp( f32 m[4][3], f32 p[4], f32 d[4] ) -{ - f32 o[3]; - v3_muls( p, p[3], o ); - m4x3_mulv( m, o, o ); - m3x3_mulv( m, p, d ); - d[3] = v3_dot( o, d ); -} -static inline void m4x3_translate( f32 m[4][3], f32 v[3] ) -{ - v3_muladds( m[3], m[0], v[0], m[3] ); - v3_muladds( m[3], m[1], v[1], m[3] ); - v3_muladds( m[3], m[2], v[2], m[3] ); -} -static inline void m4x3_rotate_x( f32 m[4][3], f32 angle ) -{ - f32 t[4][3], - c = cosf( angle ), - s = sinf( angle ); - m4x3_identity( t ); - t[1][1] = c; - t[1][2] = s; - t[2][1] = -s; - t[2][2] = c; - m4x3_mul( m, t, m ); -} -static inline void m4x3_rotate_y( f32 m[4][3], f32 angle ) -{ - f32 t[4][3], - c = cosf( angle ), - s = sinf( angle ); - m4x3_identity( t ); - t[0][0] = c; - t[0][2] = -s; - t[2][0] = s; - t[2][2] = c; - m4x3_mul( m, t, m ); -} -static inline void m4x3_rotate_z( f32 m[4][3], f32 angle ) -{ - f32 t[4][3], - c = cosf( angle ), - s = sinf( angle ); - m4x3_identity( t ); - t[0][0] = c; - t[0][1] = s; - t[1][0] = -s; - t[1][1] = c; - m4x3_mul( m, t, m ); -} -static inline void m4x3_expand( f32 m[4][3], f32 d[4][4] ) -{ - v3_copy( m[0], d[0] ); - v3_copy( m[1], d[1] ); - v3_copy( m[2], d[2] ); - v3_copy( m[3], d[3] ); - d[0][3] = 0.0f; - d[1][3] = 0.0f; - d[2][3] = 0.0f; - d[3][3] = 1.0f; -} -static inline void m4x3_decompose( f32 m[4][3], f32 co[3], f32 q[4], f32 s[3] ) -{ - v3_copy( m[3], co ); - s[0] = v3_length(m[0]); - s[1] = v3_length(m[1]); - s[2] = v3_length(m[2]); - f32 rot[3][3]; - v3_divs( m[0], s[0], rot[0] ); - v3_divs( m[1], s[1], rot[1] ); - v3_divs( m[2], s[2], rot[2] ); - m3x3_q( rot, q ); -} -static inline void m4x3_expand_aabb_point( f32 m[4][3], f32 box[2][3], f32 point[3] ) -{ - f32 v[3]; - m4x3_mulv( m, point, v ); - v3_min( box[0], v, box[0] ); - v3_max( box[1], v, box[1] ); -} -static inline void m4x3_expand_aabb_aabb( f32 m[4][3], f32 boxa[2][3], f32 boxb[2][3] ) -{ - f32 a[3]; f32 b[3]; - v3_copy( boxb[0], a ); - v3_copy( boxb[1], b ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ a[0], a[1], a[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ a[0], b[1], a[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ b[0], b[1], a[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ b[0], a[1], a[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ a[0], a[1], b[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ a[0], b[1], b[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ b[0], b[1], b[2] } ); - m4x3_expand_aabb_point( m, boxa, (f32 [3]){ b[0], a[1], b[2] } ); -} -static inline void m4x3_lookat( f32 m[4][3], f32 pos[3], f32 target[3], f32 up[3] ) -{ - f32 dir[3]; - v3_sub( target, pos, dir ); - v3_normalize( dir ); - v3_copy( dir, m[2] ); - v3_cross( up, m[2], m[0] ); - v3_normalize( m[0] ); - v3_cross( m[2], m[0], m[1] ); - v3_copy( pos, m[3] ); -} - -/* f32[4][4] -------------------------------------------------------------------------------------------------------- */ -static inline void m4x4_projection( f32 m[4][4], f32 angle, f32 ratio, f32 fnear, f32 ffar ) -{ - f32 scale = tanf( angle * 0.5f * VG_PIf / 180.0f ) * fnear, - r = ratio * scale, - l = -r, - t = scale, - b = -t; - m[0][0] = 2.0f * fnear / (r - l); - m[0][1] = 0.0f; - m[0][2] = 0.0f; - m[0][3] = 0.0f; - m[1][0] = 0.0f; - m[1][1] = 2.0f * fnear / (t - b); - m[1][2] = 0.0f; - m[1][3] = 0.0f; - m[2][0] = (r + l) / (r - l); - m[2][1] = (t + b) / (t - b); - m[2][2] = -(ffar + fnear) / (ffar - fnear); - m[2][3] = -1.0f; - m[3][0] = 0.0f; - m[3][1] = 0.0f; - m[3][2] = -2.0f * ffar * fnear / (ffar - fnear); - m[3][3] = 0.0f; -} -static inline void m4x4_translate( f32 m[4][4], f32 v[3] ) -{ - v4_muladds( m[3], m[0], v[0], m[3] ); - v4_muladds( m[3], m[1], v[1], m[3] ); - v4_muladds( m[3], m[2], v[2], m[3] ); -} -static inline void m4x4_copy( f32 a[4][4], f32 b[4][4] ) -{ - v4_copy( a[0], b[0] ); - v4_copy( a[1], b[1] ); - v4_copy( a[2], b[2] ); - v4_copy( a[3], b[3] ); -} -static inline void m4x4_identity( f32 a[4][4] ) -{ - m4x4_copy( (f32[4][4]){{1,0,0,0}, - {0,1,0,0}, - {0,0,1,0}, - {0,0,0,1}}, a ); -} -static inline void m4x4_zero( f32 a[4][4] ) -{ - m4x4_copy( (f32[4][4]){{0,0,0,0}, - {0,0,0,0}, - {0,0,0,0}, - {0,0,0,0}}, a ); -} -static inline void m4x4_mul( f32 a[4][4], f32 b[4][4], f32 d[4][4] ) -{ - f32 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3], - a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3], - b00 = b[0][0], b01 = b[0][1], b02 = b[0][2], b03 = b[0][3], - b10 = b[1][0], b11 = b[1][1], b12 = b[1][2], b13 = b[1][3], - b20 = b[2][0], b21 = b[2][1], b22 = b[2][2], b23 = b[2][3], - b30 = b[3][0], b31 = b[3][1], b32 = b[3][2], b33 = b[3][3]; - d[0][0] = a00*b00 + a10*b01 + a20*b02 + a30*b03; - d[0][1] = a01*b00 + a11*b01 + a21*b02 + a31*b03; - d[0][2] = a02*b00 + a12*b01 + a22*b02 + a32*b03; - d[0][3] = a03*b00 + a13*b01 + a23*b02 + a33*b03; - d[1][0] = a00*b10 + a10*b11 + a20*b12 + a30*b13; - d[1][1] = a01*b10 + a11*b11 + a21*b12 + a31*b13; - d[1][2] = a02*b10 + a12*b11 + a22*b12 + a32*b13; - d[1][3] = a03*b10 + a13*b11 + a23*b12 + a33*b13; - d[2][0] = a00*b20 + a10*b21 + a20*b22 + a30*b23; - d[2][1] = a01*b20 + a11*b21 + a21*b22 + a31*b23; - d[2][2] = a02*b20 + a12*b21 + a22*b22 + a32*b23; - d[2][3] = a03*b20 + a13*b21 + a23*b22 + a33*b23; - d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30*b33; - d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31*b33; - d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32*b33; - d[3][3] = a03*b30 + a13*b31 + a23*b32 + a33*b33; -} -static inline void m4x4_mulv( f32 m[4][4], f32 v[4], f32 d[4] ) -{ - f32 res[4]; - res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3]; - res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3]; - res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3]; - res[3] = m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3]; - v4_copy( res, d ); -} -static inline void m4x4_inv( f32 a[4][4], f32 d[4][4] ) -{ - f32 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3], - a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3], - det, - t[6]; - - t[0] = a22*a33 - a32*a23; - t[1] = a21*a33 - a31*a23; - t[2] = a21*a32 - a31*a22; - t[3] = a20*a33 - a30*a23; - t[4] = a20*a32 - a30*a22; - t[5] = a20*a31 - a30*a21; - - d[0][0] = a11*t[0] - a12*t[1] + a13*t[2]; - d[1][0] =-(a10*t[0] - a12*t[3] + a13*t[4]); - d[2][0] = a10*t[1] - a11*t[3] + a13*t[5]; - d[3][0] =-(a10*t[2] - a11*t[4] + a12*t[5]); - - d[0][1] =-(a01*t[0] - a02*t[1] + a03*t[2]); - d[1][1] = a00*t[0] - a02*t[3] + a03*t[4]; - d[2][1] =-(a00*t[1] - a01*t[3] + a03*t[5]); - d[3][1] = a00*t[2] - a01*t[4] + a02*t[5]; - - t[0] = a12*a33 - a32*a13; - t[1] = a11*a33 - a31*a13; - t[2] = a11*a32 - a31*a12; - t[3] = a10*a33 - a30*a13; - t[4] = a10*a32 - a30*a12; - t[5] = a10*a31 - a30*a11; - - d[0][2] = a01*t[0] - a02*t[1] + a03*t[2]; - d[1][2] =-(a00*t[0] - a02*t[3] + a03*t[4]); - d[2][2] = a00*t[1] - a01*t[3] + a03*t[5]; - d[3][2] =-(a00*t[2] - a01*t[4] + a02*t[5]); - - t[0] = a12*a23 - a22*a13; - t[1] = a11*a23 - a21*a13; - t[2] = a11*a22 - a21*a12; - t[3] = a10*a23 - a20*a13; - t[4] = a10*a22 - a20*a12; - t[5] = a10*a21 - a20*a11; - - d[0][3] =-(a01*t[0] - a02*t[1] + a03*t[2]); - d[1][3] = a00*t[0] - a02*t[3] + a03*t[4]; - d[2][3] =-(a00*t[1] - a01*t[3] + a03*t[5]); - d[3][3] = a00*t[2] - a01*t[4] + a02*t[5]; - - det = 1.0f / (a00*d[0][0] + a01*d[1][0] + a02*d[2][0] + a03*d[3][0]); - v4_muls( d[0], det, d[0] ); - v4_muls( d[1], det, d[1] ); - v4_muls( d[2], det, d[2] ); - v4_muls( d[3], det, d[3] ); -} -/* - * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - */ -static inline void m4x4_clip_projection( f32 mat[4][4], f32 plane[4] ) -{ - f32 c[4] = - { - (f32_sign(plane[0]) + mat[2][0]) / mat[0][0], - (f32_sign(plane[1]) + mat[2][1]) / mat[1][1], - -1.0f, - (1.0f + mat[2][2]) / mat[3][2] - }; - v4_muls( plane, 2.0f / v4_dot(plane,c), c ); - mat[0][2] = c[0]; - mat[1][2] = c[1]; - mat[2][2] = c[2] + 1.0f; - mat[3][2] = c[3]; -} -static inline void m4x4_reset_clipping( f32 mat[4][4], f32 far, f32 near ) -{ - mat[0][2] = 0.0f; - mat[1][2] = 0.0f; - mat[2][2] = -(far + near) / (far - near); - mat[3][2] = -2.0f * far * near / (far - near); -} - -/* box -------------------------------------------------------------------------------------------------------------- */ -static inline void box_addpt( f32 a[2][3], f32 pt[3] ) -{ - v3_min( a[0], pt, a[0] ); - v3_max( a[1], pt, a[1] ); -} -static inline void box_concat( f32 a[2][3], f32 b[2][3] ) -{ - v3_min( a[0], b[0], a[0] ); - v3_max( a[1], b[1], a[1] ); -} -static inline void box_copy( f32 a[2][3], f32 b[2][3] ) -{ - v3_copy( a[0], b[0] ); - v3_copy( a[1], b[1] ); -} -static inline bool box_overlap( f32 a[2][3], f32 b[2][3] ) -{ - return ( a[0][0] <= b[1][0] && a[1][0] >= b[0][0] ) && - ( a[0][1] <= b[1][1] && a[1][1] >= b[0][1] ) && - ( a[0][2] <= b[1][2] && a[1][2] >= b[0][2] ); -} -static inline bool box_within_pt( f32 box[2][3], f32 pt[3] ) -{ - return (pt[0] >= box[0][0]) && (pt[1] >= box[0][1]) && (pt[2] >= box[0][2]) && - (pt[0] <= box[1][0]) && (pt[1] <= box[1][1]) && (pt[2] <= box[1][2]); -} -static inline bool box_within( f32 greater[2][3], f32 lesser[2][3] ) -{ - f32 a[3], b[3]; - v3_sub( lesser[0], greater[0], a ); - v3_sub( lesser[1], greater[1], b ); - return (a[0] >= 0.0f) && (a[1] >= 0.0f) && (a[2] >= 0.0f) && - (b[0] <= 0.0f) && (b[1] <= 0.0f) && (b[2] <= 0.0f); -} -static inline void box_init_inf( f32 box[2][3] ) -{ - v3_fill( box[0], INFINITY ); - v3_fill( box[1], -INFINITY ); -} - -/* planes ----------------------------------------------------------------------------------------------------------- */ -static inline void tri_to_plane( f64 a[3], f64 b[3], f64 c[3], f64 p[4] ) -{ - f64 edge0[3]; - f64 edge1[3]; - f64 l; - - edge0[0] = b[0] - a[0]; - edge0[1] = b[1] - a[1]; - edge0[2] = b[2] - a[2]; - - edge1[0] = c[0] - a[0]; - edge1[1] = c[1] - a[1]; - edge1[2] = c[2] - a[2]; - - p[0] = edge0[1] * edge1[2] - edge0[2] * edge1[1]; - p[1] = edge0[2] * edge1[0] - edge0[0] * edge1[2]; - p[2] = edge0[0] * edge1[1] - edge0[1] * edge1[0]; - - l = sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]); - p[3] = (p[0] * a[0] + p[1] * a[1] + p[2] * a[2]) / l; - - p[0] = p[0] / l; - p[1] = p[1] / l; - p[2] = p[2] / l; -} - -// TODO: What is going on here? -static inline bool plane_intersect3( f32 a[4], f32 b[4], f32 c[4], f32 p[3] ) -{ - f32 const epsilon = 1e-6f; - f32 x[3]; - v3_cross( a, b, x ); - f32 d = v3_dot( x, c ); - if( (d < epsilon) && (d > -epsilon) ) - return 0; - - f32 v0[3], v1[3], v2[3]; - v3_cross( b, c, v0 ); - v3_cross( c, a, v1 ); - v3_cross( a, b, v2 ); - - v3_muls( v0, a[3], p ); - v3_muladds( p, v1, b[3], p ); - v3_muladds( p, v2, c[3], p ); - v3_divs( p, d, p ); - return 1; -} -static inline bool plane_intersect2( f32 a[4], f32 b[4], f32 p[3], f32 n[3] ) -{ - f32 const epsilon = 1e-6f; - f32 c[3]; - v3_cross( a, b, c ); - f32 d = v3_length2( c ); - if( (d < epsilon) && (d > -epsilon) ) - return 0; - - f32 v0[3], v1[3], vx[3]; - v3_cross( c, b, v0 ); - v3_cross( a, c, v1 ); - - v3_muls( v0, a[3], vx ); - v3_muladds( vx, v1, b[3], vx ); - v3_divs( vx, d, p ); - v3_copy( c, n ); - return 1; -} -static inline bool plane_segment( f32 plane[4], f32 a[3], f32 b[3], f32 co[3] ) -{ - f32 d0 = v3_dot( a, plane ) - plane[3], - d1 = v3_dot( b, plane ) - plane[3]; - if( d0*d1 < 0.0f ) - { - f32 tot = 1.0f/( fabsf(d0)+fabsf(d1) ); - v3_muls( a, fabsf(d1) * tot, co ); - v3_muladds( co, b, fabsf(d0) * tot, co ); - return 1; - } - else return 0; -} -static inline f64 plane_polarity( f64 p[4], f64 a[3] ) -{ - return (a[0] * p[0] + a[1] * p[1] + a[2] * p[2]) - -(p[0]*p[3] * p[0] + p[1]*p[3] * p[1] + p[2]*p[3] * p[2]); -} -static inline f32 ray_plane( f32 plane[4], f32 co[3], f32 dir[3] ) -{ - f32 d = v3_dot( plane, dir ); - if( fabsf(d) > 1e-6f ) - { - f32 v0[3]; - v3_muls( plane, plane[3], v0 ); - v3_sub( v0, co, v0 ); - return v3_dot( v0, plane ) / d; - } - else return INFINITY; -} - - - -/* - - Time of collision (out t) of line a0 -> a0+b , vs b0->b1 - - a0: line start - b : line trace direction ( non-normalized ) - b0: test segment start - b1: test segment end - bOneSided: One way or double sided colliders - - Returns 1/0 hit - -*/ -static inline bool segment_segment_time_2d( f32 a0[2], f32 b[2], f32 b0[2], f32 d[2], f32 *t, bool one_sided ) -{ - const f32 k_epsilon = 0.00001f; - - f32 c[2]; - f32 det, u; - - /* Interior test */ - det = v2_cross( b, d ); - if( det <= 0 && one_sided ) - return 0; - - v2_sub( b0, a0, c ); - - /* Second edge */ - u = v2_cross( c, b ) / det; - if( u < -k_epsilon || u > 1.0f+k_epsilon ) - return 0; - - /* First edge */ - *t = v2_cross( c, d ) / det; - if( *t < -k_epsilon || *t > 1.0f+k_epsilon ) - return 0; - - return 1; -} - -/* - - Positional collision HELPER. Dont use if in a loop, calculate b/d outside - - a0: line start - a1: line end - b0: line start 2 - b1: line end 2 - dest: collision location - bOneSided: One way or double sided colliders - - returns: 1/0 Hit - -*/ -static inline bool segment_segment_intersect_2d( f32 a0[2], f32 a1[2], f32 b0[2], f32 b1[2], f32 dest[2], bool one_sided ) -{ - f32 b[2]; - f32 d[2]; - f32 t; - - /* Create trace vectors */ - v2_sub( a1, a0, b ); - v2_sub( b1, b0, d ); - - /* Find time */ - if( !segment_segment_time_2d( a0, b, b0, d, &t, one_sided ) ) - return 0; - - /* Calculate position */ - v2_muls( b, t, dest ); - v2_add( a0, dest, dest ); - - return 1; -} - diff --git a/include/maths/rigidbody.h b/include/maths/rigidbody.h deleted file mode 100644 index 10bc05a..0000000 --- a/include/maths/rigidbody.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2021-2025 Mt.ZERO Software - All Rights Reserved - */ - -#define k_friction 0.4f -#define k_damp_linear 0.1f /* scale velocity 1/(1+x) */ -#define k_damp_angular 0.1f /* scale angular 1/(1+x) */ -#define k_penetration_slop 0.01f -#define k_rb_inertia_scale 4.0f -#define k_phys_baumgarte 0.2f -//#define k_gravity 9.6f -#define k_rb_density 8.0f - -extern f32 k_gravity; - -enum rb_shape { - k_rb_shape_none = 0, - k_rb_shape_box = 1, - k_rb_shape_sphere = 2, - k_rb_shape_capsule = 3, -}; - -typedef struct rigidbody rigidbody; -typedef struct rb_capsule rb_capsule; - -struct rb_capsule -{ - f32 h, r; -}; - -struct rigidbody -{ - v3f co, v, w; - v4f q; - - f32 inv_mass; - - m3x3f iI, iIw; /* inertia model and inverse world tensor */ - m4x3f to_world, to_local; -}; - -VG_API void _vg_rigidbody_register(void); - -/* - * Initialize rigidbody inverse mass and inertia tensor with some common shapes - */ -void rb_setbody_capsule( rigidbody *rb, f32 r, f32 h, f32 density, f32 inertia_scale ); -void rb_setbody_box( rigidbody *rb, boxf box, f32 density, f32 inertia_scale ); -void rb_setbody_sphere( rigidbody *rb, f32 r, f32 density, f32 inertia_scale ); - -/* - * Update ALL matrices and tensors on rigidbody - */ -void rb_update_matrices( rigidbody *rb ); - -/* - * Extrapolate rigidbody into a transform based on vg accumulator. - * Useful for rendering - */ -void rb_extrapolate( rigidbody *rb, v3f co, v4f q ); -void rb_iter( rigidbody *rb ); -void rb_solve_gyroscopic( rigidbody *rb, m3x3f I, f32 h ); - -/* - * Creates relative contact velocity vector - */ -void rb_rcv( rigidbody *rba, rigidbody *rbb, v3f ra, v3f rb, v3f rv ); - -/* - * Apply impulse to object - */ -void rb_linear_impulse( rigidbody *rb, v3f delta, v3f impulse ); - -/* - * Effectors - */ -void rb_effect_simple_bouyency( rigidbody *ra, v4f plane, f32 amt, f32 drag ); -void rb_effect_spring_target_vector( rigidbody *rba, v3f ra, v3f rt, f32 spring, f32 dampening, f32 timestep ); - - - -/* TODO: Get rid of this! */ -#define VG_MAX_CONTACTS 256 - -typedef struct rb_ct rb_ct; -struct rb_ct -{ - rigidbody *rba, *rbb; - v3f co, n; - v3f t[2]; - float p, bias, norm_impulse, tangent_impulse[2], - normal_mass, tangent_mass[2]; - - u32 element_id; - - enum contact_type type; -} -extern rb_contact_buffer[VG_MAX_CONTACTS]; -extern int rb_contact_count; - -int rb_capsule__sphere( m4x3f mtxA, rb_capsule *ca, v3f coB, f32 rb, rb_ct *buf ); -int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca, m4x3f mtxB, rb_capsule *cb, rb_ct *buf ); -int rb_capsule__box( m4x3f mtxA, rb_capsule *ca, m4x3f mtxB, m4x3f mtxB_inverse, boxf box, rb_ct *buf ); -int rb_sphere__box( v3f coA, f32 ra, m4x3f mtxB, m4x3f mtxB_inverse, boxf box, rb_ct *buf ); -int rb_sphere__sphere( v3f coA, f32 ra, v3f coB, f32 rb, rb_ct *buf ); -int rb_sphere__triangle( m4x3f mtxA, f32 r, v3f tri[3], rb_ct *buf ); -int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3f tri[3], rb_ct *buf ); -int rb_global_has_space( void ); -rb_ct *rb_global_buffer( void ); -int rb_manifold_apply_filtered( rb_ct *man, int len ); -int rb_box_triangle_sat( v3f extent, v3f center, m4x3f to_local, v3f tri_src[3] ); - -/* - * Merge two contacts if they are within radius(r) of eachother - */ -void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r ); -void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r ); - -/* - * Resolve overlapping pairs - */ -void rb_manifold_filter_pairs( rb_ct *man, int len, float r ); - -/* - * Remove contacts that are facing away from A - */ -void rb_manifold_filter_backface( rb_ct *man, int len ); - -/* - * Filter out duplicate coplanar results. Good for spheres. - */ -void rb_manifold_filter_coplanar( rb_ct *man, int len, float w ); - -void rb_debug_contact( rb_ct *ct ); -void rb_solver_reset(void); -rb_ct *rb_global_ct(void); -void rb_prepare_contact( rb_ct *ct, f32 dt ); -void rb_depenetrate( rb_ct *manifold, int len, v3f dt ); -void rb_presolve_contacts( rb_ct *buffer, f32 dt, int len ); -void rb_contact_restitution( rb_ct *ct, float cr ); -void rb_solve_contacts( rb_ct *buf, int len ); - - - -typedef struct rb_constr_pos rb_constr_pos; -typedef struct rb_constr_swingtwist rb_constr_swingtwist; - -struct rb_constr_pos -{ - rigidbody *rba, *rbb; - v3f lca, lcb; -}; - -struct rb_constr_swingtwist -{ - rigidbody *rba, *rbb; - - v4f conevx, conevy; /* relative to rba */ - v3f view_offset, /* relative to rba */ - coneva, conevxb;/* relative to rbb */ - - int tangent_violation, axis_violation; - v3f axis, tangent_axis, tangent_target, axis_target; - - float conet; - float tangent_mass, axis_mass; - - f32 conv_tangent, conv_axis; -}; - -void rb_debug_position_constraints( rb_constr_pos *buffer, int len ); -void rb_presolve_swingtwist_constraints( rb_constr_swingtwist *buf, int len ); -void rb_debug_swingtwist_constraints( rb_constr_swingtwist *buf, int len ); - -/* - * Solve a list of positional constraints - */ -void rb_solve_position_constraints( rb_constr_pos *buf, int len ); -void rb_solve_swingtwist_constraints( rb_constr_swingtwist *buf, int len ); -void rb_postsolve_swingtwist_constraints( rb_constr_swingtwist *buf, u32 len ); -void rb_solve_constr_angle( rigidbody *rba, rigidbody *rbb, v3f ra, v3f rb ); - -/* - * Correct position constraint drift errors - * [ 0.0 <= amt <= 1.0 ]: the correction amount - */ -void rb_correct_position_constraints( rb_constr_pos *buf, int len, f32 amt ); -void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, int len, float amt ); diff --git a/include/opengl.h b/include/opengl.h deleted file mode 100644 index c59e98d..0000000 --- a/include/opengl.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "vg/dep/glad.4.3/glad/glad.h" -#include "generated/shaders.h" - -GLuint compile_opengl_subshader( GLint type, const c8 *sources[], u32 source_count, bool critical, const c8 *debug_path ); -bool link_opengl_program( GLuint program, bool critical ); - -void _shader_bind( enum shader_id id ); diff --git a/include/types.h b/include/types.h deleted file mode 100644 index 732f839..0000000 --- a/include/types.h +++ /dev/null @@ -1,13 +0,0 @@ -typedef unsigned char u8; -typedef char c8; -typedef unsigned short int u16; -typedef unsigned int u32; -typedef unsigned long int u64; -typedef char i8; -typedef signed short int i16; -typedef signed int i32; -typedef signed long int i64; -typedef float f32; -typedef double f64; -typedef unsigned char bool; -#define NULL 0 diff --git a/shaders/blit.vs b/shaders/blit.vs deleted file mode 100644 index e19a10f..0000000 --- a/shaders/blit.vs +++ /dev/null @@ -1,12 +0,0 @@ -layout (location=0) in vec2 a_co; -out vec2 aUv; - -void main() -{ - gl_Position = vec4(a_co*2.0-1.0,0.0,1.0); - - if( uFlip == 1 ) - aUv = vec2(a_co.x,1.0-a_co.y) * uInverseRatio; - else - aUv = a_co * uInverseRatio; -} diff --git a/shaders/blit_blur.fs b/shaders/blit_blur.fs deleted file mode 100644 index 592c83f..0000000 --- a/shaders/blit_blur.fs +++ /dev/null @@ -1,32 +0,0 @@ -out vec4 FragColor; -uniform sampler2D uTexMain; -uniform sampler2D uTexMotion; -uniform float uBlurStrength; -uniform vec2 uOverrideDir; -uniform vec2 uClampUv; - -in vec2 aUv; - -vec2 rand_hash22( vec2 p ) -{ - vec3 p3 = fract(vec3(p.xyx) * 213.8976123); - p3 += dot(p3, p3.yzx+19.19); - return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); -} - -void main() -{ - vec2 vuv = aUv; - - vec2 vrand = rand_hash22( vuv ) * 2.0 - vec2(1.0); - vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0); - - vec2 vdir = texture( uTexMotion, vuv ).xy * uBlurStrength + uOverrideDir; - - vec4 vcolour0 = texture( uTexMain, min(vuv + vdir*vrand.x,uClampUv) ); - vec4 vcolour1 = texture( uTexMain, min(vuv + vdir*vrand.y,uClampUv) ); - vec4 vcolour2 = texture( uTexMain, min(vuv + vdir*vrand1.x,uClampUv) ); - vec4 vcolour3 = texture( uTexMain, min(vuv + vdir*vrand1.y,uClampUv) ); - - FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25; -} diff --git a/shaders/blit_colour.fs b/shaders/blit_colour.fs deleted file mode 100644 index 7eb290e..0000000 --- a/shaders/blit_colour.fs +++ /dev/null @@ -1,9 +0,0 @@ -out vec4 FragColor; -uniform vec4 uColour; - -in vec2 aUv; - -void main() -{ - FragColor = uColour; -} diff --git a/shaders/blit_tex.fs b/shaders/blit_tex.fs deleted file mode 100644 index 0d39a1b..0000000 --- a/shaders/blit_tex.fs +++ /dev/null @@ -1,7 +0,0 @@ -out vec4 FragColor; -in vec2 aUv; - -void main() -{ - FragColor = texture( uTexMain, aUv ); -} diff --git a/shaders/debug_lines.fs b/shaders/debug_lines.fs deleted file mode 100644 index 1fcc7ad..0000000 --- a/shaders/debug_lines.fs +++ /dev/null @@ -1,8 +0,0 @@ -out vec4 FragColor; - -in vec4 s_colour; - -void main() -{ - FragColor = s_colour; -} diff --git a/shaders/debug_lines.vs b/shaders/debug_lines.vs deleted file mode 100644 index 2fa61e0..0000000 --- a/shaders/debug_lines.vs +++ /dev/null @@ -1,12 +0,0 @@ -uniform mat4 uPv; -layout (location=0) in vec3 a_co; -layout (location=1) in vec4 a_colour; - -out vec4 s_colour; - -void main() -{ - vec4 vert_pos = uPv * vec4( a_co, 1.0 ); - s_colour = a_colour; - gl_Position = vert_pos; -} diff --git a/shaders/loader.fs b/shaders/loader.fs deleted file mode 100644 index dc265dc..0000000 --- a/shaders/loader.fs +++ /dev/null @@ -1,34 +0,0 @@ -out vec4 FragColor; -uniform float uTime; -uniform float uRatio; -uniform float uOpacity; -in vec2 aUv; - -float eval_zero( vec2 uv ) -{ - vec4 vsines = sin( (uTime+uv.y*80.0) * vec4(1.1,2.0234,3.73,2.444) ); - float gradient = min( uv.y, 0.0 ); - float offset = vsines.x*vsines.y*vsines.z*vsines.w*gradient; - - vec2 vpos = uv + vec2( offset, 0.0 ); - float dist = dot( vpos, vpos ); - - float fring = step(0.1*0.1,dist) * step(dist,0.15*0.15); - return max( 0.0, fring * 1.0+gradient*6.0 ); -} - -void main() -{ - vec3 col = 0.5+0.5*sin( uTime + aUv.xyx + vec3(0.0,2.0,4.0) ); - - vec2 uvx = aUv - vec2( 0.5 ); - uvx.x *= uRatio; - uvx.y *= 0.75; - - float zero = eval_zero( uvx ); - - float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5; - float fmt1 = step( 0.5, zero*zero + dither )*0.8+0.2; - - FragColor = vec4(vec3(fmt1),uOpacity); -} diff --git a/shaders/motion_vectors_common.glsl b/shaders/motion_vectors_common.glsl deleted file mode 100644 index 7e6c114..0000000 --- a/shaders/motion_vectors_common.glsl +++ /dev/null @@ -1 +0,0 @@ -const float k_motion_lerp_amount = 0.01; diff --git a/shaders/motion_vectors_fs.glsl b/shaders/motion_vectors_fs.glsl deleted file mode 100644 index b92ae2d..0000000 --- a/shaders/motion_vectors_fs.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#include "../vg/shaders/motion_vectors_common.glsl" - -layout (location = 1) out vec4 oMotionVec; - -in vec3 aMotionVec0; -in vec3 aMotionVec1; - -void compute_motion_vectors() -{ - // Write motion vectors - vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z; - vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z; - vec2 vmotion = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount); - - oMotionVec = vec4( vmotion, 0.0, 1.0 ); -} diff --git a/shaders/motion_vectors_vs.glsl b/shaders/motion_vectors_vs.glsl deleted file mode 100644 index 4eee0a6..0000000 --- a/shaders/motion_vectors_vs.glsl +++ /dev/null @@ -1,14 +0,0 @@ -#include "../vg/shaders/motion_vectors_common.glsl" - -out vec3 aMotionVec0; -out vec3 aMotionVec1; - -void vs_motion_out( vec4 vproj0, vec4 vproj1 ) -{ - // This magically solves some artifacting errors! - // - vproj1 = vproj0*(1.0-k_motion_lerp_amount) + vproj1*k_motion_lerp_amount; - - aMotionVec0 = vec3( vproj0.xy, vproj0.w ); - aMotionVec1 = vec3( vproj1.xy, vproj1.w ); -} diff --git a/shaders/rigidbody_view.fs b/shaders/rigidbody_view.fs deleted file mode 100644 index a47829b..0000000 --- a/shaders/rigidbody_view.fs +++ /dev/null @@ -1,48 +0,0 @@ -out vec4 FragColor; -uniform vec4 uColour; - -in vec3 aNorm; -in vec3 aCo; -// The MIT License -// Copyright © 2017 Inigo Quilez -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the Software), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. THE SOFTWARE IS -// PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// Info: https://iquilezles.org/articles/filterableprocedurals -// -// More filtered patterns: https://www.shadertoy.com/playlist/l3KXR1 - -vec3 tri( in vec3 x ) -{ - return 1.0-abs(2.0*fract(x/2.0)-1.0); -} - -float checkersTextureGrad( in vec3 p, in vec3 ddx, in vec3 ddy ) -{ - vec3 w = max(abs(ddx), abs(ddy)) + 0.0001; // filter kernel - vec3 i = (tri(p+0.5*w)-tri(p-0.5*w))/w; // analytical integral (box filter) - return 0.5 - 0.5*i.x*i.y*i.z; // xor pattern -} - -void main() -{ - vec3 uvw = aCo; - vec3 ddx_uvw = dFdx( uvw ); - vec3 ddy_uvw = dFdy( uvw ); - float diffuse = checkersTextureGrad( uvw, ddx_uvw, ddy_uvw )*0.5+0.4; - float light = dot( vec3(0.8017,0.5345,-0.2672), aNorm )*0.5 + 0.5; - FragColor = light * diffuse * uColour; -} diff --git a/shaders/rigidbody_view.vs b/shaders/rigidbody_view.vs deleted file mode 100644 index 08fc744..0000000 --- a/shaders/rigidbody_view.vs +++ /dev/null @@ -1,20 +0,0 @@ -uniform mat4 uPv; -uniform mat4x3 uMdl; -uniform mat4x3 uMdl1; -layout (location=0) in vec4 a_co; -layout (location=1) in vec3 a_norm; -out vec3 aNorm; -out vec3 aCo; - -void main() -{ - vec3 world_pos0 = uMdl * vec4( a_co.xyz, 1.0 ); - vec3 world_pos1 = uMdl1 * vec4( a_co.xyz, 1.0 ); - vec3 co = mix( world_pos0, world_pos1, a_co.w ); - vec4 vert_pos = uPv * vec4( co, 1.0 ); - - gl_Position = vert_pos; - vec3 l = vec3(length(uMdl[0]),length(uMdl[1]),length(uMdl[2])); - aNorm = (mat3(uMdl) * a_norm)/l; - aCo = a_co.xyz*l; -} diff --git a/shaders/ui.fs b/shaders/ui.fs deleted file mode 100644 index bf8525d..0000000 --- a/shaders/ui.fs +++ /dev/null @@ -1,48 +0,0 @@ -uniform sampler2D uTexGlyphs; -uniform sampler2D uTexBG; -uniform vec4 uColour; -uniform float uSpread; -out vec4 FragColor; - -in vec4 aTexCoords; -in vec4 aColour; - -vec2 rand_hash22( vec2 p ) -{ - vec3 p3 = fract(vec3(p.xyx) * 213.8976123); - p3 += dot(p3, p3.yzx+19.19); - return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); -} - -void main() -{ - vec4 diffuse = aColour; - - vec4 avg = vec4(0.0); - - if( aColour.a == 0.0 ) - { - avg = aColour; - avg.a = texture( uTexGlyphs, aTexCoords.xy ).r; - } - else - { - if( uSpread > 0.0001 ) - { - for( int i=0; i<4; i ++ ) - { - vec2 spread = rand_hash22(aTexCoords.zw+vec2(float(i))); - avg += texture( uTexBG, aTexCoords.zw + (spread-0.5)*uSpread ); - } - avg *= 0.25; - avg.a = 1.0; - avg.rgb = mix( avg.rgb, aColour.rgb, aColour.a ); - } - else - { - avg = aColour; - } - } - - FragColor = avg * uColour; -} diff --git a/shaders/ui.vs b/shaders/ui.vs deleted file mode 100644 index 37f8b3b..0000000 --- a/shaders/ui.vs +++ /dev/null @@ -1,17 +0,0 @@ -layout (location=0) in vec2 a_co; -layout (location=1) in vec2 a_uv; -layout (location=2) in vec4 a_colour; -uniform mat3 uPv; -uniform vec2 uBGInverseRatio; -uniform vec2 uInverseFontSheet; - -out vec4 aTexCoords; -out vec4 aColour; - -void main() -{ - vec4 proj_pos = vec4( uPv * vec3( a_co, 1.0 ), 1.0 ); - gl_Position = proj_pos; - aTexCoords = vec4( a_uv * uInverseFontSheet, (proj_pos.xy*0.5+0.5) * uBGInverseRatio ); - aColour = a_colour; -} diff --git a/shaders/ui_image.fs b/shaders/ui_image.fs deleted file mode 100644 index 5d45c1d..0000000 --- a/shaders/ui_image.fs +++ /dev/null @@ -1,13 +0,0 @@ -uniform sampler2D uTexImage; -uniform vec4 uColour; -out vec4 FragColor; - -in vec2 aTexCoords; -in vec4 aColour; -in vec2 aWsp; - -void main() -{ - vec4 colour = texture( uTexImage, aTexCoords ); - FragColor = colour * aColour * uColour; -} diff --git a/shaders/ui_image.vs b/shaders/ui_image.vs deleted file mode 100644 index 47f1704..0000000 --- a/shaders/ui_image.vs +++ /dev/null @@ -1,17 +0,0 @@ -layout (location=0) in vec2 a_co; -layout (location=1) in vec2 a_uv; -layout (location=2) in vec4 a_colour; -uniform mat3 uPv; - -out vec2 aTexCoords; -out vec4 aColour; -out vec2 aWsp; - -void main() -{ - gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 ); - aTexCoords = a_uv * 0.00390625; - aColour = a_colour; - - aWsp = a_co; -} diff --git a/shaders/ui_image_grad.fs b/shaders/ui_image_grad.fs deleted file mode 100644 index 3201908..0000000 --- a/shaders/ui_image_grad.fs +++ /dev/null @@ -1,22 +0,0 @@ -uniform sampler2D uTexImage; -uniform vec4 uColour; -uniform int uLog; -uniform float uScale; - -out vec4 FragColor; - -in vec2 aTexCoords; -in vec4 aColour; -in vec2 aWsp; - -void main() -{ - vec4 colour = texture( uTexImage, aTexCoords ); - float v = colour.r; - if( uLog == 1 ) - { - v = log(v); - } - v *= uScale; - FragColor = vec4(vec3(v)*uColour.rgb,1.0); -} diff --git a/shaders/ui_image_hsv.fs b/shaders/ui_image_hsv.fs deleted file mode 100644 index e98838c..0000000 --- a/shaders/ui_image_hsv.fs +++ /dev/null @@ -1,15 +0,0 @@ -uniform float uHue; -out vec4 FragColor; - -in vec2 aTexCoords; -in vec4 aColour; -in vec2 aWsp; - -void main() -{ - vec3 c = vec3( uHue, aTexCoords ); - vec4 K = vec4(1.0,2.0/3.0,1.0/3.0,3.0); - vec3 p = abs(fract(c.xxx+K.xyz)*6.0 - K.www); - vec3 colour = c.z*mix(K.xxx,clamp(p-K.xxx,0.0,1.0),c.y); - FragColor = vec4( colour, 1.0 ); -} diff --git a/source/async/async.kv b/source/async/async.kv new file mode 100644 index 0000000..dfab494 --- /dev/null +++ b/source/async/async.kv @@ -0,0 +1,13 @@ +include "" + +{ + if SDL + add sdl_async.c +} + +hook +{ + affinity -20000 + event START + function _async_init +} diff --git a/source/async/sdl_async.c b/source/async/sdl_async.c new file mode 100644 index 0000000..c1aa445 --- /dev/null +++ b/source/async/sdl_async.c @@ -0,0 +1,295 @@ +#include "foundation.h" +#include "vg_async.h" +#include "generated/threads.c" +#include "SDL3/SDL.h" + +#define ASYNC_DEBUG_GROUP_COUNTS + +struct thread_context +{ + u16 async_groups[ 8 ]; + u32 async_group_depth; +} +_thread_contexts[ k_thread_count ]; + +struct thread_info *_get_thread_info( enum thread_id thread ) +{ + ASSERT_CRITICAL( thread < k_thread_count ); + return &_thread_infos[ thread ]; +} + +b8 _thread_has_flags( enum thread_id thread, u32 flags ) +{ + return (_get_thread_info( thread )->flags & flags) == flags; +} + +void _async_push_groups( u16 groups, b8 exclusive ) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + + ASSERT_CRITICAL( context->async_group_depth < ARRAY_COUNT( context->async_groups ) ); + context->async_group_depth ++; + if( !exclusive ) + groups |= context->async_groups[ context->async_group_depth-1 ]; + context->async_groups[ context->async_group_depth ] = groups; +} + +void _async_pop_groups(void) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + ASSERT_CRITICAL( context->async_group_depth ); + context->async_group_depth --; +} + +u16 _async_get_groups(void) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + return context->async_groups[ context->async_group_depth ]; +} + +struct +{ + i16 group_counts[ 16 ]; + SDL_Mutex *count_lock; +} +_async; + +struct task_queue +{ + u32 count; + + SDL_Condition *blocking_signal, *work_signal; + SDL_Mutex *lock, *data_lock; + struct queue_allocator queue; + + struct task *allocating_task; +} +static _task_queues[ k_thread_count ]; + +struct task +{ + const c8 *alloc_debug_info; + + union + { + void (*fn)( struct task *task ); + enum thread_id target_thread; + }; + + u32 buffer_size; + u16 groups, unused0; + + union + { + u64 _force_8byte_align[]; + u8 buffer[]; + }; +}; + +_Thread_local enum thread_id _thread_id; + +void _set_thread_id( enum thread_id id ) +{ + _thread_id = id; +} + +enum thread_id _get_thread_id(void) +{ + return _thread_id; +} +void _async_init( void ) +{ + $log( $info, {"[INIT] _async_init"} ); + _async.count_lock = SDL_CreateMutex(); + ASSERT_CRITICAL( _async.count_lock ); + + for( u32 i=0; iqueue_size_m ) + { + struct task_queue *queue = &_task_queues[ i ]; + queue->lock = SDL_CreateMutex(); + queue->data_lock = SDL_CreateMutex(); + queue->blocking_signal = SDL_CreateCondition(); + queue->work_signal = SDL_CreateCondition(); + ASSERT_CRITICAL( queue->lock && queue->data_lock && queue->blocking_signal && queue->work_signal ); + + u32 bytes = BYTES_MB(thread_info->queue_size_m); + queue->queue.buffer = _heap_allocate( bytes ); + queue->queue.size = bytes; + } + } +} + +static void _async_group_increment( u16 groups, i16 dir, const c8 *who ) +{ + if( !groups ) + return; + + SDL_LockMutex( _async.count_lock ); + for( u16 i=0; i<16; i ++ ) + { + if( (groups >> i) & 0x1 ) + { + _async.group_counts[i] += dir; + ASSERT_CRITICAL( _async.group_counts[i] >= 0 ); + ASSERT_CRITICAL( _async.group_counts[i] <= 2048 ); + +#if defined( ASYNC_DEBUG_GROUP_COUNTS ) + $log( $warning, {"The task count for group "}, $unsigned(i), {" has "}, {dir>0? "increased": "decreased"}, + {" to "}, $unsigned(_async.group_counts[i]), {" ("}, {who}, {")"} ); +#endif + } + } + SDL_UnlockMutex( _async.count_lock ); +} + +i16 _async_group_count( u16 group ) +{ + ASSERT_CRITICAL( group ); + u32 index = __builtin_ctz( (u32)group ); + + SDL_LockMutex( _async.count_lock ); + i16 count = _async.group_counts[ index ]; + SDL_UnlockMutex ( _async.count_lock ); + return count; +} + +static struct task_queue *_get_thread_task_queue( enum thread_id thread ) +{ + ASSERT_CRITICAL( thread < k_thread_count ); + return &_task_queues[ thread ]; +} + +b8 _task_queue_can_fit( enum thread_id thread, u32 bytes ) +{ + struct task_queue *queue = _get_thread_task_queue( thread ); + u32 total_size = sizeof(struct task) + bytes; + return total_size <= queue->queue.size; +} + +struct task *_task_new( enum thread_id target_thread, u32 buffer_size, u32 async_flags, const c8 *debug_info ) +{ + ASSERT_CRITICAL( target_thread != _get_thread_id() ); + + struct task_queue *queue = _get_thread_task_queue( target_thread ); + struct queue_allocator *ring = &queue->queue; + u32 total_size = sizeof(struct task) + buffer_size; + ASSERT_CRITICAL( total_size <= queue->queue.size ); + + SDL_LockMutex( queue->data_lock ); + if( queue->allocating_task ) + { + $log( $fatal, {"Overlapping async allocations. \n" + " Previous allocation began at: "}, {queue->allocating_task->alloc_debug_info}, {"\n" + " Overlapping call at: "}, {debug_info} ); + _fatal_exit(); + } + SDL_LockMutex( queue->lock ); + + struct task *task = queue_alloc( ring, total_size ); + while( ((async_flags & ASYNC_CRITICAL) || !(async_flags & ASYNC_NONBLOCKING)) && !task ) + { + if( async_flags & ASYNC_CRITICAL ) + { + $log( $fatal, { "Too many tasks allocated on this queue, so we cant make this (critical allocation)"} ); + _fatal_exit(); + } + + SDL_WaitCondition( queue->blocking_signal, queue->lock ); + task = queue_alloc( ring, total_size ); + } + + if( task ) + { + queue->allocating_task = task; + task->target_thread = target_thread; + task->alloc_debug_info = debug_info; + task->buffer_size = buffer_size; + task->groups = _async_get_groups(); + _async_group_increment( task->groups, +1, task->alloc_debug_info ); + + SDL_UnlockMutex( queue->lock ); + return task; + } + else + { + SDL_UnlockMutex( queue->lock ); + return NULL; + } +} + +void *task_buffer( struct task *task ) +{ + return task->buffer; +} + +u32 task_buffer_size( struct task *task ) +{ + return task->buffer_size; +} + +void task_send( struct task *task, void (*fn)( struct task *task ) ) +{ + struct task_queue *queue = _get_thread_task_queue( task->target_thread ); + + ASSERT_CRITICAL( task ); + ASSERT_CRITICAL( queue->allocating_task == task ); + + if( fn ) task->fn = fn; + else _async_group_increment( task->groups, -1, task->alloc_debug_info ); + queue->allocating_task = NULL; + + SDL_LockMutex( queue->lock ); + queue->count ++; + SDL_UnlockMutex( queue->lock ); + SDL_UnlockMutex( queue->data_lock ); + SDL_SignalCondition( queue->work_signal ); +} + +b8 _task_queue_process( b8 blocking ) +{ + struct task_queue *queue = _get_thread_task_queue( _get_thread_id() ); + SDL_LockMutex( queue->lock ); + + if( blocking ) + { + while( queue->count == 0 ) + SDL_WaitCondition( queue->work_signal, queue->lock ); + } + else + { + if( queue->count == 0) + { + SDL_UnlockMutex( queue->lock ); + return 0; + } + } + + struct task *task = queue_tail_data( &queue->queue ); + SDL_UnlockMutex( queue->lock ); + + if( task ) + { + /* task fn can be NULL if it was cancelled (so this is a NOP). Makes code easier if we do this instead of + * reverting the queue to cancel. */ + if( task->fn ) + { + _async_push_groups( task->groups, 0 ); + task->fn( task ); + _async_pop_groups(); + _async_group_increment( task->groups, -1, task->alloc_debug_info ); + } + + SDL_LockMutex( queue->lock ); + queue_pop( &queue->queue ); + queue->count --; + SDL_UnlockMutex( queue->lock ); + SDL_SignalCondition( queue->blocking_signal ); + return 1; + } + else + return 0; +} diff --git a/source/async/vg_async.c b/source/async/vg_async.c new file mode 100644 index 0000000..c52183b --- /dev/null +++ b/source/async/vg_async.c @@ -0,0 +1,293 @@ +#include "vg_async.h" +#include "generated/threads.c" + +#include + +#define ASYNC_DEBUG_GROUP_COUNTS + +struct thread_context +{ + u16 async_groups[ 8 ]; + u32 async_group_depth; +} +_thread_contexts[ k_thread_count ]; + +struct thread_info *_get_thread_info( enum thread_id thread ) +{ + ASSERT_CRITICAL( thread < k_thread_count ); + return &_thread_infos[ thread ]; +} + +bool _thread_has_flags( enum thread_id thread, u32 flags ) +{ + return (_get_thread_info( thread )->flags & flags) == flags; +} + +void _async_push_groups( u16 groups, bool exclusive ) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + + ASSERT_CRITICAL( context->async_group_depth < ARRAY_COUNT( context->async_groups ) ); + context->async_group_depth ++; + if( !exclusive ) + groups |= context->async_groups[ context->async_group_depth-1 ]; + context->async_groups[ context->async_group_depth ] = groups; +} + +void _async_pop_groups(void) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + ASSERT_CRITICAL( context->async_group_depth ); + context->async_group_depth --; +} + +u16 _async_get_groups(void) +{ + struct thread_context *context = &_thread_contexts[ _get_thread_id() ]; + return context->async_groups[ context->async_group_depth ]; +} + +struct +{ + i16 group_counts[ 16 ]; + mtx_t count_lock; +} +_async; + +struct task_queue +{ + u32 count; + + cnd_t blocking_signal, work_signal; + mtx_t lock, data_lock; + struct queue_allocator queue; + + struct task *allocating_task; +} +static _task_queues[ k_thread_count ]; + +struct task +{ + const c8 *alloc_debug_info; + + union + { + void (*fn)( struct task *task ); + enum thread_id target_thread; + }; + + u32 buffer_size; + u16 groups, unused0; + + union + { + u64 _force_8byte_align[]; + u8 buffer[]; + }; +}; + +_Thread_local enum thread_id _thread_id; + +void _set_thread_id( enum thread_id id ) +{ + _thread_id = id; +} + +enum thread_id _get_thread_id(void) +{ + return _thread_id; +} +void _async_init( void ) +{ + ASSERT_CRITICAL( mtx_init( &_async.count_lock, mtx_plain ) == thrd_success ); + + for( u32 i=0; iqueue_size_m ) + { + struct task_queue *queue = &_task_queues[ i ]; + ASSERT_CRITICAL( mtx_init( &queue->lock, mtx_plain ) == thrd_success ); + ASSERT_CRITICAL( mtx_init( &queue->data_lock, mtx_plain ) == thrd_success ); + ASSERT_CRITICAL( cnd_init( &queue->blocking_signal ) == thrd_success ); + ASSERT_CRITICAL( cnd_init( &queue->work_signal ) == thrd_success ); + u32 bytes = BYTES_MB(thread_info->queue_size_m); + queue->queue.buffer = _heap_allocate( bytes ); + queue->queue.size = bytes; + } + } +} + +static void _async_group_increment( u16 groups, i16 dir, const c8 *who ) +{ + if( !groups ) + return; + + ASSERT_CRITICAL( mtx_lock( &_async.count_lock ) == thrd_success ); + for( u16 i=0; i<16; i ++ ) + { + if( (groups >> i) & 0x1 ) + { + _async.group_counts[i] += dir; + ASSERT_CRITICAL( _async.group_counts[i] >= 0 ); + ASSERT_CRITICAL( _async.group_counts[i] <= 2048 ); + +#if defined( ASYNC_DEBUG_GROUP_COUNTS ) + $log( $warning, {"The task count for group "}, $unsigned(i), {" has "}, {dir>0? "increased": "decreased"}, + {" to "}, $unsigned(_async.group_counts[i]), {" ("}, {who}, {")"} ); +#endif + } + } + ASSERT_CRITICAL( mtx_unlock( &_async.count_lock ) == thrd_success ); +} + +i16 _async_group_count( u16 group ) +{ + ASSERT_CRITICAL( group ); + u32 index = __builtin_ctz( (u32)group ); + ASSERT_CRITICAL( mtx_lock( &_async.count_lock ) == thrd_success ); + i16 count = _async.group_counts[ index ]; + ASSERT_CRITICAL( mtx_unlock( &_async.count_lock ) == thrd_success ); + return count; +} + +static struct task_queue *_get_thread_task_queue( enum thread_id thread ) +{ + ASSERT_CRITICAL( thread < k_thread_count ); + + return &_task_queues[ thread ]; +} + +bool _task_queue_can_fit( enum thread_id thread, u32 bytes ) +{ + struct task_queue *queue = _get_thread_task_queue( thread ); + u32 total_size = sizeof(struct task) + bytes; + return total_size <= queue->queue.size; +} + +struct task *_task_new( enum thread_id target_thread, u32 buffer_size, u32 async_flags, const c8 *debug_info ) +{ + ASSERT_CRITICAL( target_thread != _get_thread_id() ); + + struct task_queue *queue = _get_thread_task_queue( target_thread ); + struct queue_allocator *ring = &queue->queue; + u32 total_size = sizeof(struct task) + buffer_size; + ASSERT_CRITICAL( total_size <= queue->queue.size ); + + ASSERT_CRITICAL( mtx_lock( &queue->data_lock ) == thrd_success ); + if( queue->allocating_task ) + { + $log( $fatal, {"Overlapping async allocations. \n" + " Previous allocation began at: "}, {queue->allocating_task->alloc_debug_info}, {"\n" + " Overlapping call at: "}, {debug_info} ); + _fatal_exit(); + } + ASSERT_CRITICAL( mtx_lock( &queue->lock ) == thrd_success ); + + struct task *task = queue_alloc( ring, total_size ); + while( ((async_flags & ASYNC_CRITICAL) || !(async_flags & ASYNC_NONBLOCKING)) && !task ) + { + if( async_flags & ASYNC_CRITICAL ) + { + $log( $fatal, { "Too many tasks allocated on this queue, so we cant make this (critical allocation)"} ); + _fatal_exit(); + } + + ASSERT_CRITICAL( cnd_wait( &queue->blocking_signal, &queue->lock ) == thrd_success ); + task = queue_alloc( ring, total_size ); + } + + if( task ) + { + queue->allocating_task = task; + task->target_thread = target_thread; + task->alloc_debug_info = debug_info; + task->buffer_size = buffer_size; + task->groups = _async_get_groups(); + _async_group_increment( task->groups, +1, task->alloc_debug_info ); + + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + return task; + } + else + { + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + return NULL; + } +} + +void *task_buffer( struct task *task ) +{ + return task->buffer; +} + +u32 task_buffer_size( struct task *task ) +{ + return task->buffer_size; +} + +void task_send( struct task *task, void (*fn)( struct task *task ) ) +{ + struct task_queue *queue = _get_thread_task_queue( task->target_thread ); + + ASSERT_CRITICAL( task ); + ASSERT_CRITICAL( queue->allocating_task == task ); + + if( fn ) task->fn = fn; + else _async_group_increment( task->groups, -1, task->alloc_debug_info ); + queue->allocating_task = NULL; + + ASSERT_CRITICAL( mtx_lock( &queue->lock ) == thrd_success ); + queue->count ++; + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + + ASSERT_CRITICAL( mtx_unlock( &queue->data_lock ) == thrd_success ); + ASSERT_CRITICAL( cnd_signal( &queue->work_signal ) == thrd_success ); +} + +bool _task_queue_process( bool blocking ) +{ + struct task_queue *queue = _get_thread_task_queue( _get_thread_id() ); + ASSERT_CRITICAL( mtx_lock( &queue->lock ) == thrd_success ); + + if( blocking ) + { + while( queue->count == 0 ) + ASSERT_CRITICAL( cnd_wait( &queue->work_signal, &queue->lock ) == thrd_success ); + } + else + { + if( queue->count == 0) + { + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + return 0; + } + } + + struct task *task = queue_tail_data( &queue->queue ); + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + + if( task ) + { + /* task fn can be NULL if it was cancelled (so this is a NOP). Makes code easier if we do this instead of + * reverting the queue to cancel. */ + if( task->fn ) + { + _async_push_groups( task->groups, 0 ); + task->fn( task ); + _async_pop_groups(); + _async_group_increment( task->groups, -1, task->alloc_debug_info ); + } + + ASSERT_CRITICAL( mtx_lock( &queue->lock ) == thrd_success ); + queue_pop( &queue->queue ); + queue->count --; + ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success ); + + ASSERT_CRITICAL( cnd_signal( &queue->blocking_signal ) == thrd_success ); + return 1; + } + else + return 0; +} diff --git a/source/async/vg_async.h b/source/async/vg_async.h new file mode 100644 index 0000000..fd3a412 --- /dev/null +++ b/source/async/vg_async.h @@ -0,0 +1,42 @@ +#pragma once +#include "generated/threads.h" + +struct thread_info +{ + const c8 *name; + u32 queue_size_m; + u32 flags; +}; +struct thread_info *_get_thread_info( enum thread_id thread ); + +#define ASYNC_CRITICAL 0x1 +#define ASYNC_NONBLOCKING 0x2 + +// TODO THIS SHOULD BE PART OF THE METACOMPILER +#define THREAD_FLAG_MAIN 0x1 +#define THREAD_FLAG_ASYNC 0x2 +#define THREAD_FLAG_OPENGL 0x4 + +// TODO THIS SHOULD BE PART OF THE METACOMPILER +#define ASYNC_GROUP_OPENGL 0x1 +#define ASYNC_GROUP_FIRST_LOAD 0x2 + +void _set_thread_id( enum thread_id id ); +enum thread_id _get_thread_id(void); +b8 _thread_has_flags( enum thread_id id, u32 flags ); + +struct task *_task_new( enum thread_id thread, u32 buffer_size, u32 async_flags, const c8 *debug_info ); +void task_send( struct task *task, void (*fn)( struct task *task ) ); + +void *task_buffer( struct task *task ); +u32 task_buffer_size( struct task *task ); + +b8 _task_queue_process( b8 blocking ); +b8 _task_queue_can_fit( enum thread_id thread, u32 bytes ); + +void _async_init(void); + +void _async_push_groups( u16 groups, b8 exclusive ); +void _async_pop_groups(void); +u16 _async_get_groups(void); +i16 _async_group_count( u16 group ); diff --git a/source/console/console_system.c b/source/console/console_system.c new file mode 100644 index 0000000..c30470f --- /dev/null +++ b/source/console/console_system.c @@ -0,0 +1,123 @@ +#include "foundation.h" +#include "console_system.h" + +struct console_command +{ + const c8 *alias; + i32 (*fn)( struct console_arguments *args ); +}; + +#include "generated/console.c" + +i32 _console_exec_ccmd( struct console_arguments *args ) +{ + const c8 *path = console_get_argument( args, 0 ); + if( !path ) + { + $log( $error, {"Usage: exec "} ); + return -1; + } + + struct stream file; + if( !stream_open_file( &file, path, k_stream_read ) ) + return -1; + + b8 more_to_go = 1; + while( more_to_go ) + { + u32 temp_frame = _start_temporary_frame(); + + struct stream line; + stream_open_stack( &line, _temporary_stack_allocator(), k_stream_null_terminate ); + + c8 c; + more_to_go = 0; + while( stream_read( &file, &c, 1 ) ) + { + if( c == '\n' ) + { + more_to_go = 1; + break; + } + string_append_c8( &line, c ); + } + + if( stream_offset( &line ) ) + _console_execute( string_get( &line ), 1, 0 ); + + _end_temporary_frame( temp_frame ); + } + + return 0; +} + +void _console_execute( const c8 *command, b8 silent, b8 cheat_allowed ) +{ + if( !silent ) + $log( $shell, {command} ); + + struct stream string; + stream_open_buffer_read( &string, command, buffer_last_index( command, 0, 0 )+1, 0 ); + + struct console_arguments args; + args.count = 0; + + u32 temp_frame = _start_temporary_frame(); + struct console_command *target_command = NULL; + + // TODO: warning if we put to many or to few arguments & required ones. + for( u32 i=0; ialias, 0, command+start, length ) ) + { + target_command = cmd; + break; + } + } + + if( !target_command ) + { + $log( $error, {"There is no command called '"}, $string( command+start, .length=length ), {"'"} ); + return; + } + } + else + { + c8 *buffer = _temporary_allocate( length + 1, 4 ); + buffer_copy( command + start, length, buffer, length ); + buffer[ length ] = 0; + + args.arguments[ args.count ] = buffer; + args.count ++; + } + } + else break; + } + + if( target_command ) + target_command->fn( &args ); + + _end_temporary_frame( temp_frame ); +} + +const c8 *console_get_argument( struct console_arguments *args, u32 index ) +{ + if( index < args->count ) + return args->arguments[ index ]; + else + return NULL; +} + +void _console_init(void) +{ + _console_execute( "exec cfg/default.cfg", 1, 0 ); +} diff --git a/source/console/console_system.h b/source/console/console_system.h new file mode 100644 index 0000000..f2b2329 --- /dev/null +++ b/source/console/console_system.h @@ -0,0 +1,11 @@ +#include "generated/console.h" + +void _console_init(void); +void _console_execute( const c8 *command, b8 silent, b8 cheat_allowed ); + +struct console_arguments +{ + const c8 *arguments[ 32 ]; + u32 count; +}; +const c8 *console_get_argument( struct console_arguments *args, u32 index ); diff --git a/source/console/console_system.kv b/source/console/console_system.kv new file mode 100644 index 0000000..8dd9a96 --- /dev/null +++ b/source/console/console_system.kv @@ -0,0 +1,8 @@ +include "" +add console_system.c + +hook +{ + event START + function _console_init +} diff --git a/source/console_core.c b/source/console_core.c deleted file mode 100644 index 5ff9660..0000000 --- a/source/console_core.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "common_api.h" -#include "console_core.h" - -struct console_command -{ - const c8 *alias; - i32 (*fn)( struct console_arguments *args ); -}; - -#include "generated/console.c" - -i32 _console_exec_ccmd( struct console_arguments *args ) -{ - const c8 *path = console_get_argument( args, 0 ); - if( !path ) - { - $log( $error, {"Usage: exec "} ); - return -1; - } - - struct stream file; - if( !stream_open_file( &file, path, k_stream_read ) ) - return -1; - - bool more_to_go = 1; - while( more_to_go ) - { - u32 temp_frame = _start_temporary_frame(); - - struct stream line; - stream_open_stack( &line, _temporary_stack_allocator(), k_stream_null_terminate ); - - c8 c; - more_to_go = 0; - while( stream_read( &file, &c, 1 ) ) - { - if( c == '\n' ) - { - more_to_go = 1; - break; - } - string_append_c8( &line, c ); - } - - if( stream_offset( &line ) ) - _console_execute( string_get( &line ), 1, 0 ); - - _end_temporary_frame( temp_frame ); - } - - return 0; -} - -void _console_execute( const c8 *command, bool silent, bool cheat_allowed ) -{ - if( !silent ) - $log( $shell, {command} ); - - struct stream string; - stream_open_buffer_read( &string, command, buffer_last_index( command, 0, 0 )+1, 0 ); - - struct console_arguments args; - args.count = 0; - - u32 temp_frame = _start_temporary_frame(); - struct console_command *target_command = NULL; - - // TODO: warning if we put to many or to few arguments & required ones. - for( u32 i=0; ialias, 0, command+start, length ) ) - { - target_command = cmd; - break; - } - } - - if( !target_command ) - { - $log( $error, {"There is no command called '"}, $string( command+start, .length=length ), {"'"} ); - return; - } - } - else - { - c8 *buffer = _temporary_allocate( length + 1, 4 ); - buffer_copy( command + start, length, buffer, length ); - buffer[ length ] = 0; - - args.arguments[ args.count ] = buffer; - args.count ++; - } - } - else break; - } - - if( target_command ) - target_command->fn( &args ); - - _end_temporary_frame( temp_frame ); -} - -const c8 *console_get_argument( struct console_arguments *args, u32 index ) -{ - if( index < args->count ) - return args->arguments[ index ]; - else - return NULL; -} - -void _console_init(void) -{ - _console_execute( "exec cfg/default.cfg", 1, 0 ); -} diff --git a/source/console_core.h b/source/console_core.h deleted file mode 100644 index 91928ac..0000000 --- a/source/console_core.h +++ /dev/null @@ -1,11 +0,0 @@ -#include "generated/console.h" - -void _console_init(void); -void _console_execute( const c8 *command, bool silent, bool cheat_allowed ); - -struct console_arguments -{ - const c8 *arguments[ 32 ]; - u32 count; -}; -const c8 *console_get_argument( struct console_arguments *args, u32 index ); diff --git a/source/engine/array_file.c b/source/engine/array_file.c new file mode 100644 index 0000000..74df834 --- /dev/null +++ b/source/engine/array_file.c @@ -0,0 +1,333 @@ +#include "foundation.h" +#include "array_file.h" + +u32 af_str_hash( const void *packed_strings, u32 pstr ) +{ + if( pstr & 0x3 ) + { + $log( $fatal, {"ALIGNMENT ERROR, PSTR INDEX: "}, $unsigned(pstr) ); + } + return *((u32 *)(packed_strings + pstr)); +} + +const c8 *af_str( const void *packed_strings, u32 pstr ) +{ + return packed_strings + pstr + 4; +} + +b8 af_str_eq( const void *packed_strings, u32 pstr, const c8 *str, u32 str_hash ) +{ + if( af_str_hash( packed_strings, pstr ) == str_hash ) + if( compare_buffers( str, 0, af_str( packed_strings, pstr ), 0 )) + return 1; + return 0; +} + +void af_load_array_file_buffer( struct array_file_context *ctx, struct array_file_meta *arr, void *buffer, u32 stride ) +{ + if( arr->item_count ) + { + zero_buffer( buffer, stride*arr->item_count ); + u32 read_size = u32_min( stride, arr->item_size ); + for( u32 i=0; iitem_count; i++ ) + { + stream_seek( ctx->stream, arr->file_offset + i*arr->item_size ); + stream_read( ctx->stream, buffer+i*stride, read_size ); + } + } +} + +void af_load_array_file( struct array_file_context *ctx, struct array_file_ptr *out_ptr, + struct array_file_meta *arr, struct stack_allocator *stack, u32 stride ) +{ + if( arr->item_count ) + { + u32 size = stride*arr->item_count; + out_ptr->data = stack_allocate( stack, size, 8, NULL ); + af_load_array_file_buffer( ctx, arr, out_ptr->data, stride ); + } + else + out_ptr->data = NULL; + + out_ptr->stride = stride; + out_ptr->count = arr->item_count; +} + +void *af_arritm( struct array_file_ptr *arr, u32 index ) +{ + if( index >= arr->count ) + { + $log( $fatal, {"Index out of range"}, $unsigned(index), {" >= "}, $unsigned( arr->count ) ); + _fatal_exit(); + } + + return ((u8 *)arr->data) + index*arr->stride; +} + +u32 af_arrcount( struct array_file_ptr *arr ) +{ + return arr->count; +} + +struct array_file_meta *af_find_array( struct array_file_context *ctx, const c8 *name ) +{ + for( u32 i=0; iindex); i++ ) + { + struct array_file_meta *arr = af_arritm( &ctx->index, i ); + if( compare_buffers( arr->name, 0, name, 0 ) ) + return arr; + } + + return NULL; +} + +b8 af_load_array( struct array_file_context *ctx, struct array_file_ptr *ptr, const c8 *name, + struct stack_allocator *stack, u32 stride ) +{ + struct array_file_meta *arr = af_find_array( ctx, name ); + + if( arr ) + { + af_load_array_file( ctx, ptr, arr, stack, stride ); + return 1; + } + else + { + ptr->data = NULL; + ptr->count = 0; + ptr->stride = 0; + return 0; + } +} + +b8 af_open_stream( struct array_file_context *afc, struct stream *stream, u32 min_version, u32 max_version, + struct stack_allocator *stack ) +{ + afc->stream = stream; + if( stream_read( stream, &afc->header, sizeof(struct array_file_header)) != sizeof(struct array_file_header) ) + { + $log( $error, {"Array file not large enough to contain header."} ); + return 0; + } + + if( (afc->header.version < min_version) || (afc->header.version > max_version) ) + { + $log( $error, {"Array file version is out of range ("}, $unsigned( afc->header.version ), + {"\nAccepted: "}, $unsigned( min_version ), {" -> "}, $unsigned( max_version ) ); + return 0; + } + + af_load_array_file( afc, &afc->index, &afc->header.index, stack, sizeof(struct array_file_meta) ); + return 1; +} + +/* compiler + * ---------------------------------------------------------------------- */ +struct af_compiler_iter +{ + u32 i, j; + struct af_compiler_index *index; + struct af_compiler_item *current_item; + void *data; +}; + +static void af_init_iterator( struct af_compiler_iter *iter, struct af_compiler_index *index ) +{ + iter->i = 0; + iter->j = 0; + iter->index = index; + iter->current_item = NULL; + iter->data = NULL; +} + +static b8 af_next( struct af_compiler_iter *iter ) +{ + if( iter->i == 0 ) + { + if( iter->index->first == NULL ) + return 0; + iter->current_item = iter->index->first; + } + + if( iter->j >= iter->current_item->count ) + { + if( iter->current_item->next == NULL ) + return 0; + + iter->current_item = iter->current_item->next; + iter->j = 0; + } + + iter->data = iter->current_item->data + (iter->j * iter->index->element_size); + iter->j ++; + iter->i ++; + return 1; +} + +struct af_compiler_item *af_compiler_allocate_items( struct af_compiler *compiler, struct af_compiler_index *index, u32 count ) +{ + struct af_compiler_item *entry = stack_allocate( compiler->stack, sizeof(struct af_compiler_item), 1, "Compiler item" ); + entry->next = NULL; + + u32 data_size = count * index->element_size; + index->element_count += count; + + entry->data = stack_allocate( compiler->stack, data_size, 8, NULL ); + entry->count = count; + + for( u32 i=0; idata)[i] = 0xab; + + if( index->last ) + index->last->next = entry; + index->last = entry; + + if( !index->first ) + index->first = entry; + + return entry; +} + +static void af_compiler_init_index( struct af_compiler_index *index, const c8 *alias, u32 element_size ) +{ + ASSERT_CRITICAL( element_size ); + if( !buffer_copy( alias, 0, index->name, sizeof(index->name) ) ) + { + $log( $fatal, {"Index name overflowed: "}, {alias} ); + _fatal_exit(); + } + index->element_size = element_size; + index->element_count = 0; + index->first = NULL; + index->last = NULL; +} + +struct af_compiler_index *af_compiler_create_index( struct af_compiler *compiler, const c8 *alias, u32 element_size ) +{ + struct af_compiler_item *item = af_compiler_allocate_items( compiler, &compiler->index, 1 ); + struct af_compiler_index *index = item->data; + af_compiler_init_index( index, alias, element_size ); + return index; +} + +u32 af_compile_string( struct af_compiler *compiler, const c8 *string ) +{ + u32 string_hash = buffer_djb2( string, 0 ); + + // TODO: Hash table against existing strings (low priority) + u32 offset = offset = compiler->strings_index->element_count; + u32 bytes = PAD_TO_4( buffer_first_index( string, 0,0 )+1 + 4 ); + struct af_compiler_item *item = af_compiler_allocate_items( compiler, compiler->strings_index, bytes ); + *((u32 *)item->data) = string_hash; + buffer_copy( string, 0, item->data+4, 0 ); + return offset; +} + +void af_compiler_init( struct af_compiler *compiler, struct stack_allocator *stack ) +{ + compiler->stack = stack; + af_compiler_init_index( &compiler->index, "index", sizeof(struct af_compiler_index) ); + compiler->strings_index = af_compiler_create_index( compiler, "strings", 1 ); + af_compile_string( compiler, "nul" ); +} + +static void af_write_bin( struct af_compiler *compiler, void *data, u32 data_len, u32 padding ) +{ + if( data ) + { + stream_write( &compiler->stream, data, data_len ); + compiler->file_offset += data_len; + } + + if( padding ) + { + while( compiler->file_offset % padding ) + { + const u8 pad_byte = 0xac; + stream_write( &compiler->stream, &pad_byte, 1 ); + compiler->file_offset ++; + } + } +} + +struct af_compiler_index *af_get_or_make_index( struct af_compiler *compiler, const c8 *alias, u32 element_size ) +{ + struct af_compiler_iter iter; + af_init_iterator( &iter, &compiler->index ); + while( af_next( &iter ) ) + { + struct af_compiler_index *index = iter.data; + if( compare_buffers( index->name, 0, alias, 0 ) ) + return index; + } + + return af_compiler_create_index( compiler, alias, element_size ); +} + +b8 af_write( struct af_compiler *compiler, const c8 *path, u32 version ) +{ + u32 indices_to_write = 0; + + struct af_compiler_iter iter; + af_init_iterator( &iter, &compiler->index ); + while( af_next( &iter ) ) + { + struct af_compiler_index *index = iter.data; + if( index->element_count ) + indices_to_write ++; + } + + u32 header_size = PAD_TO_8( sizeof( struct array_file_header ) ); + u32 index_size = PAD_TO_8( sizeof( struct array_file_meta ) * indices_to_write ); + + if( !stream_open_file( &compiler->stream, path, k_stream_write ) ) + return 0; + + compiler->file_offset = 0; + + struct array_file_header header; + header.version = version; + header.index.file_offset = header_size; + header.index.item_count = indices_to_write; + header.index.item_size = sizeof(struct array_file_meta); + buffer_copy( "index", 0, header.index.name, sizeof(header.index.name) ); + af_write_bin( compiler, &header, sizeof(struct array_file_header), 8 ); + + /* write index */ + u32 file_offset = header_size + index_size; + af_init_iterator( &iter, &compiler->index ); + while( af_next( &iter ) ) + { + struct af_compiler_index *index = iter.data; + if( index->element_count ) + { + struct array_file_meta meta; + buffer_copy( index->name, sizeof(index->name), meta.name, sizeof(meta.name) ); + meta.item_count = index->element_count; + meta.item_size = index->element_size; + meta.file_offset = file_offset; + file_offset += PAD_TO_8( meta.item_size*meta.item_count ); + af_write_bin( compiler, &meta, sizeof(struct array_file_meta), 0 ); + } + } + af_write_bin( compiler, NULL, 0, 8 ); + + af_init_iterator( &iter, &compiler->index ); + while( af_next( &iter ) ) + { + struct af_compiler_index *index = iter.data; + + if( index->element_count ) + { + struct af_compiler_iter item_iter; + af_init_iterator( &item_iter, index ); + + while( af_next( &item_iter ) ) + af_write_bin( compiler, item_iter.data, index->element_size, 0 ); + af_write_bin( compiler, NULL, 0, 8 ); + } + } + + stream_close( &compiler->stream ); + return 1; +} diff --git a/source/engine/array_file.h b/source/engine/array_file.h new file mode 100644 index 0000000..68f9739 --- /dev/null +++ b/source/engine/array_file.h @@ -0,0 +1,89 @@ +#pragma once + +struct array_file_ptr +{ + void *data; + u32 count, stride; +}; + +struct array_file_meta +{ + u32 file_offset, + item_count, + item_size; + + c8 name[16]; +}; + +struct array_file_header +{ + u32 version; + struct array_file_meta index; +}; + +struct array_file_context +{ + struct stream *stream; + struct array_file_header header; + struct array_file_ptr index; +}; + +/* array loading */ +struct array_file_meta *af_find_array( struct array_file_context *ctx, const c8 *name ); + +void af_load_array_file( struct array_file_context *ctx, struct array_file_ptr *out_ptr, + struct array_file_meta *arr, struct stack_allocator *stack, u32 stride ); + +b8 af_load_array( struct array_file_context *ctx, struct array_file_ptr *ptr, const c8 *name, + struct stack_allocator *stack, u32 stride ); +void af_load_array_file_buffer( struct array_file_context *ctx, struct array_file_meta *arr, void *buffer, u32 stride ); + +/* array access */ +void *af_arritm( struct array_file_ptr *arr, u32 index ); +u32 af_arrcount( struct array_file_ptr *arr ); + +/* packed string buffer access (with djb2 hash prefix) */ +const c8 *af_str( const void *packed_strings, u32 pstr ); +u32 af_str_hash( const void *packed_strings, u32 pstr ); +b8 af_str_eq( const void *packed_strings, u32 pstr, const char *str, u32 str_hash ); + +#define AF_STR_EQ( CTX, PSTR, CONSTR ) \ + af_str_eq( CTX, PSTR, CONSTR, vg_strdjb2( CONSTR ) ) + +/* COmpiler + * ------------------------------------ */ + +struct af_compiler_item +{ + void *data; + u32 count; + struct af_compiler_item *next; +}; + +struct af_compiler_index +{ + c8 name[16]; + u32 element_size, element_count; + struct af_compiler_item *first, *last; +}; + +struct af_compiler +{ + struct stack_allocator *stack; + struct af_compiler_index index, + *strings_index; + struct af_compiler_item *most_recent_item; + + struct stream stream; + u32 file_offset; +}; + +void af_compiler_init( struct af_compiler *compiler, struct stack_allocator *stack ); +struct af_compiler_item *af_compiler_allocate_items( struct af_compiler *compiler, struct af_compiler_index *index, u32 count ); +struct af_compiler_index *af_compiler_create_index( struct af_compiler *compiler, const c8 *alias, u32 element_size ); +b8 af_write( struct af_compiler *compiler, const c8 *path, u32 version ); +struct af_compiler_index *af_get_or_make_index( struct af_compiler *compiler, const c8 *alias, u32 element_size ); +u32 af_compile_string( struct af_compiler *compiler, const c8 *string ); + +b8 af_open_stream( struct array_file_context *afc, struct stream *stream, u32 min_version, u32 max_version, + struct stack_allocator *stack ); diff --git a/source/engine/audio_mixer.c b/source/engine/audio_mixer.c index 56aee24..0209e62 100644 --- a/source/engine/audio_mixer.c +++ b/source/engine/audio_mixer.c @@ -4,7 +4,7 @@ struct vg_audio _vg_audio = .dsp_enabled_ui = 1 }; -_Thread_local static bool _vg_audio_thread_has_lock = 0; +_Thread_local static b8 _vg_audio_thread_has_lock = 0; void vg_audio_lock(void) { @@ -30,7 +30,7 @@ static void vg_audio_assert_lock(void) /* clip loading from disk * ------------------------------------------------------------------------------- */ -VG_TIER_2 bool vg_audio_clip_load( audio_clip *clip, vg_stack_allocator *stack ) +VG_TIER_2 b8 vg_audio_clip_load( audio_clip *clip, vg_stack_allocator *stack ) { VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) ); @@ -333,7 +333,7 @@ void vg_audio_sync_ui_master_controls(void) _vg_audio.controls.dsp_enabled = _vg_audio.dsp_enabled_ui; } -void vg_audio_set_channel_volume( audio_channel_id id, f64 volume, bool instant ) +void vg_audio_set_channel_volume( audio_channel_id id, f64 volume, b8 instant ) { vg_audio_assert_lock(); @@ -358,7 +358,7 @@ void vg_audio_set_channel_volume_slew_duration( audio_channel_id id, f64 length_ controls->volume_slew_rate_per_sample = (f64)AUDIO_VOLUME_100 / (length_seconds * 44100.0); } -void vg_audio_set_channel_pan( audio_channel_id id, f64 pan, bool instant ) +void vg_audio_set_channel_pan( audio_channel_id id, f64 pan, b8 instant ) { vg_audio_assert_lock(); @@ -431,7 +431,7 @@ audio_channel_id vg_audio_crossfade( audio_channel_id id, audio_clip *new_clip, return new_id; } -bool vg_audio_is_channel_using_clip( audio_channel_id id, audio_clip *clip ) +b8 vg_audio_is_channel_using_clip( audio_channel_id id, audio_clip *clip ) { vg_audio_assert_lock(); audio_channel *channel = get_audio_channel( id ); @@ -460,7 +460,7 @@ void vg_audio_fadeout_flagged_audio( u32 flag, f32 length ) } } -bool vg_audio_flagged_stopped( u32 flag ) +b8 vg_audio_flagged_stopped( u32 flag ) { vg_audio_lock(); for( u32 id=1; id<=AUDIO_CHANNELS; id ++ ) @@ -480,14 +480,14 @@ bool vg_audio_flagged_stopped( u32 flag ) return 1; } -void vg_audio_set_channel_pause( audio_channel_id id, bool pause ) +void vg_audio_set_channel_pause( audio_channel_id id, b8 pause ) { vg_audio_assert_lock(); struct audio_channel_controls *controls = get_audio_channel_controls( id ); controls->pause = pause; } -void vg_audio_set_flagged_pause( u32 flag, bool pause ) +void vg_audio_set_flagged_pause( u32 flag, b8 pause ) { vg_audio_assert_lock(); for( u32 id=1; id<=AUDIO_CHANNELS; id ++ ) @@ -747,8 +747,8 @@ static void audio_channel_mix( audio_channel_id id, { struct audio_channel_state *state = get_audio_channel_state( id ); - bool is_3d = controls->flags & AUDIO_FLAG_SPACIAL_3D? 1: 0; - bool use_doppler = controls->flags & AUDIO_FLAG_NO_DOPPLER? 0: 1; + b8 is_3d = controls->flags & AUDIO_FLAG_SPACIAL_3D? 1: 0; + b8 use_doppler = controls->flags & AUDIO_FLAG_NO_DOPPLER? 0: 1; f32 frame_sample_rate = controls->sampling_rate_multiplier; @@ -1103,7 +1103,7 @@ static void _vg_audio_mixer( void *user, u8 *stream, int byte_count ) if( controls->flags & AUDIO_FLAG_RELINQUISHED ) { - bool die = 0; + b8 die = 0; if( state->activity == k_channel_activity_end ) die = 1; if( state->activity == k_channel_activity_error ) die = 1; if( state->volume == 0 ) die = 1; @@ -1153,7 +1153,7 @@ static void cb_vg_audio_view( ui_context *ctx, ui_rect rect, struct vg_magi_pane ui_rect row; ui_split( panel, k_ui_axis_h, 18, 1, row, panel ); - bool show_row = ui_clip( rect, row, row ); + b8 show_row = ui_clip( rect, row, row ); if( channel->stage == k_channel_stage_none ) { @@ -1445,7 +1445,7 @@ VG_API void _vg_audio_init(void) void vg_audio_preupdate(void) { - bool before_working = _vg_audio.working; + b8 before_working = _vg_audio.working; _vg_audio.working = 1; if( _vg_audio.sdl_output_device == 0 ) _vg_audio.working = 0; diff --git a/source/engine/console.c b/source/engine/console.c index f493c3a..735580f 100644 --- a/source/engine/console.c +++ b/source/engine/console.c @@ -1,13 +1,13 @@ -#include "common_api.h" -#include "console_core.h" -#include "graphics_api.h" -#include "engine_interface.h" -#include "input_api.h" +#include "foundation.h" +#include "console_system.h" +#include "vg_graphics.h" +#include "vg_engine.h" +#include "vg_input.h" struct { struct queue_allocator input_history, log_history; - bool open; + b8 open; } _console; diff --git a/source/engine/engine.kv b/source/engine/engine.kv new file mode 100644 index 0000000..0c66c16 --- /dev/null +++ b/source/engine/engine.kv @@ -0,0 +1,399 @@ +include "" +append ../maths/maths.kv + +include ../../submodules/SDL/include +include ../../dep/glad.4.3/ +add ../../dep/glad.4.3/glad.c + +enable SDL +append ../foundation/foundation.kv + +{ + add vg_engine.c + hook + { + event OPTIONS + function _engine_options + } + event + { + name ENGINE_NEW_FRAME + prototype "void" + } + event + { + name ENGINE_FIXED_UPDATE + prototype "void" + } + event + { + name ENGINE_RENDER + prototype "void" + } + event + { + name ENGINE_UI + prototype "void" + } + event + { + name ENGINE_WINDOW_RESIZE + prototype "void" + } +} + +{ + add vg_ui.c + hook + { + event START + function _engine_ui_init + } +} + +{ + add vg_input.c + hook + { + event START + function _input_init + } + hook + { + event ENGINE_NEW_FRAME + function _input_update + } + ccmd + { + name bind + function _input_bind_ccmd + description "Bind device input to a button, action or axis" + + parameter + { + description "Device input alias" + } + + parameter + { + description "button,action,axis name" + } + } + ccmd + { + name unbind + description "Unbind all bindings that match" + function _input_unbind_ccmd + + parameter + { + description "binding" + } + } +} + +append ../console/console_system.kv +{ + add console.c + hook + { + event START + function _engine_console_init + } + hook + { + event ENGINE_NEW_FRAME + function _engine_console_update + } + hook + { + event ENGINE_UI + function _engine_console_ui + affinity 9999 + } +} + +{ + add vg_framebuffer.c + hook + { + event ENGINE_WINDOW_RESIZE + function _framebuffer_resize + } +} + +{ + add vg_render.c + hook + { + event START + function _vg_render_init + } +} + +add vg_shader.c + +input_layer +{ + name console +} +input_layer +{ + name ui +} +input +{ + name console + type action + layer_mask console +} + +append ../async/async.kv +thread +{ + name main + queue_size_m 40 + flag MAIN + flag OPENGL +} +thread +{ + name async + queue_size_m 40 + flag ASYNC +} +thread +{ + name audio +} +thread +{ + name exitor + queue_size_m 1 +} + +append ../graphics/graphics.kv + +ccmd +{ + name exec + function _console_exec_ccmd + description "Execute a configuration file" + + parameter + { + description "The path to the config" + } +} +config "bind ALT+GRAVE_ACCENT console" + +config "bind BACKSPACE ui_backspace" +config "bind DELETE ui_delete" +config "bind ENTER ui_enter" +config "bind TAB ui_indent" +config "bind HOME ui_home" +config "bind END ui_end" +config "bind LEFT ui_left" +config "bind RIGHT ui_right" +config "bind UP ui_up" +config "bind DOWN ui_down" +config "bind MOUSE_LEFT ui_click" + +config "bind LEFT_SHIFT ui_select" +config "bind RIGHT_SHIFT ui_select" + +input +{ + name ui_delete + type action + layer_mask ui +} +input +{ + name ui_backspace + type action + layer_mask ui +} +input +{ + name ui_enter + type action + layer_mask ui +} +input +{ + name ui_indent + type action + layer_mask ui +} + +input +{ + name ui_select + type button + layer_mask ui +} +input +{ + name ui_home + type button + layer_mask ui +} +input +{ + name ui_end + type button + layer_mask ui +} +input +{ + name ui_left + type button + layer_mask ui +} +input +{ + name ui_right + type button + layer_mask ui +} +input +{ + name ui_up + type button + layer_mask ui +} +input +{ + name ui_down + type button + layer_mask ui +} +input +{ + name ui_click + type action + layer_mask ui +} + +shader +{ + name blit + + subshader + { + type vertex + add shaders/blit.vs + + uniform + { + type vec2 + alias uInverseRatio + } + uniform + { + type int + alias uFlip + } + } + + subshader + { + type fragment + add shaders/blit_tex.fs + + uniform + { + type sampler2D + alias uTexMain + } + } +} + +cvar +{ + name test + type u32 + default 5 + cheat 1 + description "This is just a test variable!" +} + +hook +{ + event START + function "_shaders_compile" +} +} + + + + + + +add vg_camera.c + + +add vg_tex.c +hook +{ + event START + function _vg_tex_init +} + + +add vg_lines.c +hook +{ + event START + function _vg_lines_init +} +cvar +{ + name debug_lines + type u32 + default 0 + cheat 1 + description "Show line debuggers" +} +shader +{ + name debug_lines + subshader + { + type vertex + add shaders/debug_lines.vs + uniform + { + type mat4 + alias uPv + } + } + subshader + { + type fragment + add shaders/debug_lines.fs + } +} + + +add vg_audio.c +add vg_audio_dsp.c +add vg_audio_vorbis.c +hook +{ + affinity -3008 + event START + function _audio_init +} +hook +{ + affinity -6004 + event START + function _dsp_init +} + + +add model.c +add metascene.c +add array_file.c diff --git a/source/engine/input.c b/source/engine/input.c deleted file mode 100644 index 533d1dc..0000000 --- a/source/engine/input.c +++ /dev/null @@ -1,450 +0,0 @@ -#include "common_api.h" -#include "glfw.h" -#include "engine_interface.h" -#include "input_api.h" -#include "console_core.h" -#include "generated/input.c" - -struct input_alias -{ - const c8 *alias; - u8 device_type; - u32 key; - u32 alias_hash; -} -_input_aliases[] = -{ - { "MOUSE_LEFT", k_input_device_mouse, .key = GLFW_MOUSE_BUTTON_1 }, - { "MOUSE_RIGHT", k_input_device_mouse, .key = GLFW_MOUSE_BUTTON_2 }, - { "MOUSE_MIDDLE", k_input_device_mouse, .key = GLFW_MOUSE_BUTTON_3 }, - { "SPACE", k_input_device_keyboard, .key = GLFW_KEY_SPACE }, - { "APOSTROPHE", k_input_device_keyboard, .key = GLFW_KEY_APOSTROPHE }, - { "COMMA", k_input_device_keyboard, .key = GLFW_KEY_COMMA }, - { "MINUS", k_input_device_keyboard, .key = GLFW_KEY_MINUS }, - { "PERIOD", k_input_device_keyboard, .key = GLFW_KEY_PERIOD }, - { "SLASH", k_input_device_keyboard, .key = GLFW_KEY_SLASH }, - { "0", k_input_device_keyboard, .key = GLFW_KEY_0 }, - { "1", k_input_device_keyboard, .key = GLFW_KEY_1 }, - { "2", k_input_device_keyboard, .key = GLFW_KEY_2 }, - { "3", k_input_device_keyboard, .key = GLFW_KEY_3 }, - { "4", k_input_device_keyboard, .key = GLFW_KEY_4 }, - { "5", k_input_device_keyboard, .key = GLFW_KEY_5 }, - { "6", k_input_device_keyboard, .key = GLFW_KEY_6 }, - { "7", k_input_device_keyboard, .key = GLFW_KEY_7 }, - { "8", k_input_device_keyboard, .key = GLFW_KEY_8 }, - { "9", k_input_device_keyboard, .key = GLFW_KEY_9 }, - { "SEMICOLON", k_input_device_keyboard, .key = GLFW_KEY_SEMICOLON }, - { "EQUAL", k_input_device_keyboard, .key = GLFW_KEY_EQUAL }, - { "A", k_input_device_keyboard, .key = GLFW_KEY_A }, - { "B", k_input_device_keyboard, .key = GLFW_KEY_B }, - { "C", k_input_device_keyboard, .key = GLFW_KEY_C }, - { "D", k_input_device_keyboard, .key = GLFW_KEY_D }, - { "E", k_input_device_keyboard, .key = GLFW_KEY_E }, - { "F", k_input_device_keyboard, .key = GLFW_KEY_F }, - { "G", k_input_device_keyboard, .key = GLFW_KEY_G }, - { "H", k_input_device_keyboard, .key = GLFW_KEY_H }, - { "I", k_input_device_keyboard, .key = GLFW_KEY_I }, - { "J", k_input_device_keyboard, .key = GLFW_KEY_J }, - { "K", k_input_device_keyboard, .key = GLFW_KEY_K }, - { "L", k_input_device_keyboard, .key = GLFW_KEY_L }, - { "M", k_input_device_keyboard, .key = GLFW_KEY_M }, - { "N", k_input_device_keyboard, .key = GLFW_KEY_N }, - { "O", k_input_device_keyboard, .key = GLFW_KEY_O }, - { "P", k_input_device_keyboard, .key = GLFW_KEY_P }, - { "Q", k_input_device_keyboard, .key = GLFW_KEY_Q }, - { "R", k_input_device_keyboard, .key = GLFW_KEY_R }, - { "S", k_input_device_keyboard, .key = GLFW_KEY_S }, - { "T", k_input_device_keyboard, .key = GLFW_KEY_T }, - { "U", k_input_device_keyboard, .key = GLFW_KEY_U }, - { "V", k_input_device_keyboard, .key = GLFW_KEY_V }, - { "W", k_input_device_keyboard, .key = GLFW_KEY_W }, - { "X", k_input_device_keyboard, .key = GLFW_KEY_X }, - { "Y", k_input_device_keyboard, .key = GLFW_KEY_Y }, - { "Z", k_input_device_keyboard, .key = GLFW_KEY_Z }, - { "LEFT_BRACKET", k_input_device_keyboard, .key = GLFW_KEY_LEFT_BRACKET }, - { "BACKSLASH", k_input_device_keyboard, .key = GLFW_KEY_BACKSLASH }, - { "RIGHT_BRACKET", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_BRACKET }, - { "GRAVE_ACCENT", k_input_device_keyboard, .key = GLFW_KEY_GRAVE_ACCENT }, - { "WORLD_1", k_input_device_keyboard, .key = GLFW_KEY_WORLD_1 }, - { "WORLD_2", k_input_device_keyboard, .key = GLFW_KEY_WORLD_2 }, - { "ESCAPE", k_input_device_keyboard, .key = GLFW_KEY_ESCAPE }, - { "ENTER", k_input_device_keyboard, .key = GLFW_KEY_ENTER }, - { "TAB", k_input_device_keyboard, .key = GLFW_KEY_TAB }, - { "BACKSPACE", k_input_device_keyboard, .key = GLFW_KEY_BACKSPACE }, - { "INSERT", k_input_device_keyboard, .key = GLFW_KEY_INSERT }, - { "DELETE", k_input_device_keyboard, .key = GLFW_KEY_DELETE }, - { "RIGHT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT }, - { "LEFT", k_input_device_keyboard, .key = GLFW_KEY_LEFT }, - { "DOWN", k_input_device_keyboard, .key = GLFW_KEY_DOWN }, - { "UP", k_input_device_keyboard, .key = GLFW_KEY_UP }, - { "PAGE_UP", k_input_device_keyboard, .key = GLFW_KEY_PAGE_UP }, - { "PAGE_DOWN", k_input_device_keyboard, .key = GLFW_KEY_PAGE_DOWN }, - { "HOME", k_input_device_keyboard, .key = GLFW_KEY_HOME }, - { "END", k_input_device_keyboard, .key = GLFW_KEY_END }, - { "CAPS_LOCK", k_input_device_keyboard, .key = GLFW_KEY_CAPS_LOCK }, - { "SCROLL_LOCK", k_input_device_keyboard, .key = GLFW_KEY_SCROLL_LOCK }, - { "NUM_LOCK", k_input_device_keyboard, .key = GLFW_KEY_NUM_LOCK }, - { "PRINT_SCREEN", k_input_device_keyboard, .key = GLFW_KEY_PRINT_SCREEN }, - { "PAUSE", k_input_device_keyboard, .key = GLFW_KEY_PAUSE }, - { "F1", k_input_device_keyboard, .key = GLFW_KEY_F1 }, - { "F2", k_input_device_keyboard, .key = GLFW_KEY_F2 }, - { "F3", k_input_device_keyboard, .key = GLFW_KEY_F3 }, - { "F4", k_input_device_keyboard, .key = GLFW_KEY_F4 }, - { "F5", k_input_device_keyboard, .key = GLFW_KEY_F5 }, - { "F6", k_input_device_keyboard, .key = GLFW_KEY_F6 }, - { "F7", k_input_device_keyboard, .key = GLFW_KEY_F7 }, - { "F8", k_input_device_keyboard, .key = GLFW_KEY_F8 }, - { "F9", k_input_device_keyboard, .key = GLFW_KEY_F9 }, - { "F10", k_input_device_keyboard, .key = GLFW_KEY_F10 }, - { "F11", k_input_device_keyboard, .key = GLFW_KEY_F11 }, - { "F12", k_input_device_keyboard, .key = GLFW_KEY_F12 }, - { "F13", k_input_device_keyboard, .key = GLFW_KEY_F13 }, - { "F14", k_input_device_keyboard, .key = GLFW_KEY_F14 }, - { "F15", k_input_device_keyboard, .key = GLFW_KEY_F15 }, - { "F16", k_input_device_keyboard, .key = GLFW_KEY_F16 }, - { "F17", k_input_device_keyboard, .key = GLFW_KEY_F17 }, - { "F18", k_input_device_keyboard, .key = GLFW_KEY_F18 }, - { "F19", k_input_device_keyboard, .key = GLFW_KEY_F19 }, - { "F20", k_input_device_keyboard, .key = GLFW_KEY_F20 }, - { "F21", k_input_device_keyboard, .key = GLFW_KEY_F21 }, - { "F22", k_input_device_keyboard, .key = GLFW_KEY_F22 }, - { "F23", k_input_device_keyboard, .key = GLFW_KEY_F23 }, - { "F24", k_input_device_keyboard, .key = GLFW_KEY_F24 }, - { "F25", k_input_device_keyboard, .key = GLFW_KEY_F25 }, - { "KP_0", k_input_device_keyboard, .key = GLFW_KEY_KP_0 }, - { "KP_1", k_input_device_keyboard, .key = GLFW_KEY_KP_1 }, - { "KP_2", k_input_device_keyboard, .key = GLFW_KEY_KP_2 }, - { "KP_3", k_input_device_keyboard, .key = GLFW_KEY_KP_3 }, - { "KP_4", k_input_device_keyboard, .key = GLFW_KEY_KP_4 }, - { "KP_5", k_input_device_keyboard, .key = GLFW_KEY_KP_5 }, - { "KP_6", k_input_device_keyboard, .key = GLFW_KEY_KP_6 }, - { "KP_7", k_input_device_keyboard, .key = GLFW_KEY_KP_7 }, - { "KP_8", k_input_device_keyboard, .key = GLFW_KEY_KP_8 }, - { "KP_9", k_input_device_keyboard, .key = GLFW_KEY_KP_9 }, - { "KP_DECIMAL", k_input_device_keyboard, .key = GLFW_KEY_KP_DECIMAL }, - { "KP_DIVIDE", k_input_device_keyboard, .key = GLFW_KEY_KP_DIVIDE }, - { "KP_MULTIPLY", k_input_device_keyboard, .key = GLFW_KEY_KP_MULTIPLY }, - { "KP_SUBTRACT", k_input_device_keyboard, .key = GLFW_KEY_KP_SUBTRACT }, - { "KP_ADD", k_input_device_keyboard, .key = GLFW_KEY_KP_ADD }, - { "KP_ENTER", k_input_device_keyboard, .key = GLFW_KEY_KP_ENTER }, - { "KP_EQUAL", k_input_device_keyboard, .key = GLFW_KEY_KP_EQUAL }, - { "LEFT_SHIFT", k_input_device_keyboard, .key = GLFW_KEY_LEFT_SHIFT }, - { "LEFT_CONTROL", k_input_device_keyboard, .key = GLFW_KEY_LEFT_CONTROL }, - { "LEFT_ALT", k_input_device_keyboard, .key = GLFW_KEY_LEFT_ALT }, - { "LEFT_SUPER", k_input_device_keyboard, .key = GLFW_KEY_LEFT_SUPER }, - { "RIGHT_SHIFT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_SHIFT }, - { "RIGHT_CONTROL", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_CONTROL }, - { "RIGHT_ALT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_ALT }, - { "RIGHT_SUPER", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_SUPER }, - { "MENU", k_input_device_keyboard, .key = GLFW_KEY_MENU }, - { "SHIFT", k_input_device_modifier, .key = GLFW_MOD_SHIFT }, - { "CONTROL", k_input_device_modifier, .key = GLFW_MOD_CONTROL }, - { "ALT", k_input_device_modifier, .key = GLFW_MOD_ALT }, - { "SUPER", k_input_device_modifier, .key = GLFW_MOD_SUPER }, -}; - -static struct input_alias *_input_alias_find( const c8 *alias, u32 alias_length ) -{ - u32 hash = buffer_djb2( alias, alias_length ); - for( u32 i=0; ialias_hash == hash ) - if( compare_buffers( alias_i->alias, 0, alias, alias_length ) ) - return alias_i; - } - return NULL; -} - -static i32 _input_page = 0; - -union input_state -{ - struct - { - u8 hold_count, activation_count, release_count, repeat_count; - } - button; - - struct - { - f32 value; - } - axis; -} -static _input_states[2][k_input_count]; - -struct bind -{ - u16 device, input_index; - u32 id; - u32 modifiers; -}; -struct stretchy_allocator _bind_allocator; - -i32 _input_bind_ccmd( struct console_arguments *args ) -{ - const c8 *buttons = console_get_argument( args, 0 ); - if( !buttons ) - { - $log( $error, {"Usage: bind