From ba6d14a7737ef7cd02b61586e39ca2162df3018d Mon Sep 17 00:00:00 2001 From: Kasullian Date: Mon, 8 Sep 2025 23:20:06 -0400 Subject: glew, map parsing for windows --- .gitignore | 3 ++ CMakeLists.txt | 39 ++++++++++++---- assets/shaders/2d_texcoord.fsh | 7 +-- src/game.h | 2 +- src/game/raycast.cpp | 2 +- src/game/world/draw.cpp | 2 +- src/main.cpp | 2 +- src/render/gl.cpp | 61 ++++++++++++++++-------- src/render/gl.h | 5 +- src/render/gl_2d.cpp | 68 ++++++++++++++++++++------- src/render/gl_2d_font.cpp | 43 ++++++++++++----- src/render/gl_3d.cpp | 13 ++++-- src/render/gl_3d.h | 4 +- src/util/config/config.cpp | 103 +++++++++++++++++++++++++++++++---------- 14 files changed, 258 insertions(+), 96 deletions(-) diff --git a/.gitignore b/.gitignore index d53f885..c332cef 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ cmake_install.cmake Makefile .cache/clangd/index compile_commands.json +build/* +settings.json +c_cpp_properties.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 3931ec5..e99269a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,26 +7,46 @@ set(CMAKE_CXX_STANDARD 17) file(GLOB_RECURSE SRC_FILES ./src/*.cpp ./src/game/*.cpp ./src/util/config/*.cpp) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) +if(UNIX) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) +else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() add_executable(app ${SRC_FILES}) find_package(PkgConfig REQUIRED) -pkg_check_modules(GL REQUIRED gl) pkg_check_modules(SDL2 REQUIRED sdl2) pkg_check_modules(FREETYPE REQUIRED freetype2) +pkg_check_modules(GLEW REQUIRED glew) + +find_package(OpenGL REQUIRED) target_compile_options(app PRIVATE -Wall) target_include_directories(app PRIVATE ${SDL2_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS} - ${GL_INCLUDE_DIRS} -) -target_link_libraries(app PRIVATE - ${SDL2_LIBRARIES} - ${FREETYPE_LIBRARIES} - ${GL_LIBRARIES} + ${GLEW_INCLUDE_DIRS} + ${OPENGL_INCLUDE_DIR} ) +# Platform-specific linking +if(WIN32) + target_link_libraries(app PRIVATE + ${SDL2_LIBRARIES} + ${FREETYPE_LIBRARIES} + ${GLEW_LIBRARIES} + ${OPENGL_LIBRARIES} + winmm # For timeGetDevCaps, timeBeginPeriod, timeEndPeriod + ) +else() + target_link_libraries(app PRIVATE + ${SDL2_LIBRARIES} + ${FREETYPE_LIBRARIES} + ${GLEW_LIBRARIES} + ${OPENGL_LIBRARIES} + ) +endif() + # release build settings set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-nontrivial-memcall") # debug build settings @@ -43,5 +63,4 @@ add_custom_target(release COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Building ~~**RELEASE**~~" -) - +) \ No newline at end of file diff --git a/assets/shaders/2d_texcoord.fsh b/assets/shaders/2d_texcoord.fsh index 276f305..fabbb2f 100644 --- a/assets/shaders/2d_texcoord.fsh +++ b/assets/shaders/2d_texcoord.fsh @@ -11,8 +11,9 @@ flat in uint g_sampler; void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { - color = texture2D( g_samplers[g_sampler], g_texcoord ); - color *= g_color; + vec4 tex_color = texture2D( g_samplers[g_sampler], g_texcoord ); + color.a = g_color.a * tex_color.a; + if (color.a < 0.01) discard; } gl_FragColor = color; -} +} \ No newline at end of file diff --git a/src/game.h b/src/game.h index b0307a1..653eb91 100644 --- a/src/game.h +++ b/src/game.h @@ -19,7 +19,7 @@ typedef struct { GL_SHADER_PROGRAM* gl2d; GL_SHADER_PROGRAM* gl2d_texcoord; - struct GL_3D* gl3d; + struct GL3D* gl3d; } GAME_SHADERS; typedef struct { diff --git a/src/game/raycast.cpp b/src/game/raycast.cpp index c82a3ed..d38eb0a 100644 --- a/src/game/raycast.cpp +++ b/src/game/raycast.cpp @@ -126,7 +126,7 @@ U32 ray_trace( TRACE* tr, VEC3 end ) { } void draw_player( GAME_DATA* game, PLAYER* pl ) { - GL_PROGRAM* gl2d = game->shaders.gl2d; + GL_SHADER_PROGRAM* gl2d = game->shaders.gl2d; VEC2 xy = { pl->pos.x, pl->pos.y }; gl_2d_frect( gl2d, xy - VEC2{ 5.f, 5.f }, { 10.f, 10.f }, CLR::RED() ); diff --git a/src/game/world/draw.cpp b/src/game/world/draw.cpp index 9269a21..aad4d09 100644 --- a/src/game/world/draw.cpp +++ b/src/game/world/draw.cpp @@ -11,7 +11,7 @@ VEC2 world_project_pos( GAME_DATA* game, VEC3 pos ) { - GL_3D* gl3d = (GL_3D*)game->shaders.gl3d; + GL3D* gl3d = (GL3D*)game->shaders.gl3d; VEC4 clip = { pos.x, pos.z, pos.y, 1.f }; VEC4 ndc; diff --git a/src/main.cpp b/src/main.cpp index 28886fa..5d70ef8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,7 +33,7 @@ void loop() { game_main_loop( game ); } -int main() { +int main(int argc, char* argv[]) { if( !canvas ) canvas = (I32*)malloc( sizeof(I32) * 2 ); diff --git a/src/render/gl.cpp b/src/render/gl.cpp index 915722e..6654dd4 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -29,7 +29,7 @@ GL_DATA* gl_create( I32* _canvas ) { return 0; } - SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); @@ -43,8 +43,8 @@ GL_DATA* gl_create( I32* _canvas ) { GL_DATA* gl = new GL_DATA; gl->window = SDL_CreateWindow( "game", - 0, - 0, + SDL_WINDOWPOS_CENTERED, // Use centered position + SDL_WINDOWPOS_CENTERED, _canvas[0], _canvas[1], SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN @@ -52,22 +52,40 @@ GL_DATA* gl_create( I32* _canvas ) { if( !gl->window ) { dlog( "gl_init() could not create window: %s\n", SDL_GetError() ); - return 0; - } - - U32 renderer_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; - gl->renderer = SDL_CreateRenderer( gl->window, -1, renderer_flags ); - if( !gl->renderer ) { - dlog( "gl_init() could not create renderer: %s\n", SDL_GetError() ); + delete gl; return 0; } gl->ctx = SDL_GL_CreateContext( gl->window ); if( !gl->ctx ) { dlog( "gl_init() could not create context: %s\n", SDL_GetError() ); + SDL_DestroyWindow( gl->window ); + delete gl; + return 0; + } + + SDL_GL_MakeCurrent( gl->window, gl->ctx ); + + GLenum glewError = glewInit(); + if( glewError != GLEW_OK ) { + dlog( "gl_create() : Failed to initialize GLEW: %s\n", glewGetErrorString(glewError) ); + SDL_GL_DeleteContext( gl->ctx ); + SDL_DestroyWindow( gl->window ); + delete gl; return 0; } + dlog( "OpenGL Version: %s\n", glGetString(GL_VERSION) ); + dlog( "GLSL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) ); + dlog( "Renderer: %s\n", glGetString(GL_RENDERER) ); + dlog( "Vendor: %s\n", glGetString(GL_VENDOR) ); + + // Set up V-Sync (0 = off, 1 = on, -1 = adaptive) + SDL_GL_SetSwapInterval(1); + + // Clear any OpenGL errors that might have occurred during initialization + while( glGetError() != GL_NO_ERROR ); + glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, &gl->shader_texture_limit ); if( gl->shader_texture_limit > 255 ) gl->shader_texture_limit = 255; @@ -78,18 +96,28 @@ GL_DATA* gl_create( I32* _canvas ) { memcpy( gl->canvas_size, _canvas, sizeof(I32) * 2 ); gl->clip_start = { 0, 0 }; gl->clip_dim = { (F32)gl->canvas_size[0], (F32)gl->canvas_size[1] }; + + // Set initial viewport + glViewport( 0, 0, gl->canvas_size[0], gl->canvas_size[1] ); + + // Set initial clear color (so you can see if clearing is working) + glClearColor( 0.2f, 0.2f, 0.2f, 1.0f ); gl_inst = gl; return gl; } void gl_gen_buffers( GL_DATA* gl ) { + // Generate and bind VAO first + glGenVertexArrays( 1, &gl->vao ); + glBindVertexArray( gl->vao ); + glGenBuffers( 1, &gl->vbuffer ); - glBindBuffer( GL_ARRAY_BUFFER, gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, 8192, 0, GL_STATIC_DRAW ); - glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glBindVertexArray( 0 ); // Unbind VAO } void gl_destroy( GL_DATA *gl ) { @@ -131,7 +159,7 @@ void gl_update_window( GL_DATA* gl, I32* size ) { glUseProgram( 0 ); } -STAT gl_shader_compile( GL_DATA* gl, GL_SHADER* shader ) { +STAT gl_shader_compile( GL_DATA* gl, GL_SHADER_DEF* shader ) { static char* log_buf = 0; if( !log_buf ) log_buf = (char*)malloc( 8192 ); @@ -154,7 +182,7 @@ STAT gl_shader_compile( GL_DATA* gl, GL_SHADER* shader ) { return STAT_OK; } -void gl_shader_destroy( GL_DATA* gl, GL_SHADER* shader ) { +void gl_shader_destroy( GL_DATA* gl, GL_SHADER_DEF* shader ) { if( shader->code ) free( (void*)shader->code ); } @@ -287,7 +315,6 @@ GL_TEX2D* gl_texture_from_bitmap( GL_DATA* gl, const char* name, U8* bitmap, U32 return tex; } - GL_TEX2D* gl_texture_create( GL_DATA* gl, const char* name ) { GL_TEX2D* tex = (GL_TEX2D*)malloc( sizeof(GL_TEX2D) ); strcpy( tex->name, name ); @@ -307,10 +334,6 @@ void gl_texture_destroy( GL_DATA* gl, GL_TEX2D* tex ) { } STAT gl_beginframe( GL_DATA* gl ) { - SDL_SetRenderTarget( gl->renderer, 0 ); - SDL_SetRenderDrawColor( gl->renderer, 0, 0, 0, 255 ); - SDL_RenderClear( gl->renderer ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); gl->last_tick = u_tick(); return STAT_OK; diff --git a/src/render/gl.h b/src/render/gl.h index cf2b5dd..e4e2d5a 100644 --- a/src/render/gl.h +++ b/src/render/gl.h @@ -1,7 +1,8 @@ #pragma once #include -#include +// #include +#include #include "../util.h" #include "../util/matrix.h" @@ -68,6 +69,8 @@ typedef struct GL_DATA { VEC2 viewport_dim; MAT4* proj_matrix; + + GLuint vao; } *PGL_DATA; GL_DATA* gl_instance(); diff --git a/src/render/gl_2d.cpp b/src/render/gl_2d.cpp index 44e7e00..ca3a338 100644 --- a/src/render/gl_2d.cpp +++ b/src/render/gl_2d.cpp @@ -1,8 +1,8 @@ #include "gl_2d.h" #include "../util.h" -GL_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { - GL_PROGRAM* program = gl_program_create( gl, shadername ); +GL_SHADER_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { + GL_SHADER_PROGRAM* program = gl_program_create( gl, shadername ); if( !OK( gl_program_compile( gl, program ) ) ) dlog( "gl_2d_init() : error compiling shader %s\n", shadername ); @@ -26,10 +26,11 @@ GL_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { return program; } -void gl_2d_line( GL_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { +void gl_2d_line( GL_SHADER_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { static const U16 order[] = { 0, 1 }; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { .pos = { start.x, start.y }, .clr = col }, @@ -47,12 +48,15 @@ void gl_2d_line( GL_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_LINES, 2, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); } -void gl_2d_rect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { +void gl_2d_rect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { static const U16 order[] = { 0, 1, 2, 3, 4 }; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { .pos = { origin.x , origin.y }, .clr = col }, @@ -73,12 +77,16 @@ void gl_2d_rect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); } -void gl_2d_textured_frect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* texture, CLR col, VEC2* uv, F32 rotation ) { +void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* texture, CLR col, VEC2* uv, F32 rotation ) { static const U16 order[] = { 0, 1, 2, 3 }; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); + VERTEX vertices[] = { { { origin.x, origin.y }, uv? uv[0] : VEC2{ 0.f, 0.f }, col, 0 }, { { origin.x + dim.x, origin.y }, uv? uv[1] : VEC2{ 1.f, 0.f }, col, 0 }, @@ -125,12 +133,16 @@ void gl_2d_textured_frect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* te glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); glBindTexture( GL_TEXTURE_2D, 0 ); + + glBindVertexArray( 0 ); } -void gl_2d_frect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { +void gl_2d_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { static const U16 order[] = { 0, 1, 2, 3 }; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); + VERTEX vertices[] = { { .pos = { origin.x, origin.y }, .uv = { 0.f, 0.f }, .clr = col }, { .pos = { origin.x + dim.x, origin.y }, .uv = { 1.f, 0.f }, .clr = col }, @@ -140,25 +152,38 @@ void gl_2d_frect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_DYNAMIC_DRAW ); + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); - glEnableVertexAttribArray( position ); - glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); I32 color = glGetAttribLocation( gl2d->id, "in_col" ); - glEnableVertexAttribArray( color ); - glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + + if (position >= 0) { + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + } + + if (color >= 0) { + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + } + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); - glEnableVertexAttribArray( texcoord ); - glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + if (texcoord >= 0) { + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + } glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); // Unbind VAO } -void gl_2d_circle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { +void gl_2d_circle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { static U16* order = 0; const F32 step = 360.f / (F32)res; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); if( !order ) { order = (U16*)malloc( sizeof( U16 ) * (res + 1) ); @@ -193,13 +218,16 @@ void gl_2d_circle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) glDrawElements( GL_LINE_STRIP, res + 1, GL_UNSIGNED_SHORT, order ); free( vertices ); + + glBindVertexArray( 0 ); } -void gl_2d_fcircle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { +void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { static U16* order = 0; const F32 step = 360.f / (F32)res; glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); if( !order ) { order = (U16*)malloc( sizeof( U16 ) * (res * 2) ); @@ -246,10 +274,13 @@ void gl_2d_fcircle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res glDrawElements( GL_TRIANGLE_STRIP, res + 2, GL_UNSIGNED_SHORT, order ); free( vertices ); + + glBindVertexArray( 0 ); } -void gl_polygon( GL_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { +void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * vertices_count, vertices, GL_STATIC_DRAW ); @@ -271,15 +302,18 @@ void gl_polygon( GL_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { order[i] = i; glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); } void gl_textured_polygon( - GL_PROGRAM *gl2d, + GL_SHADER_PROGRAM *gl2d, VERTEX *vertices, U32 vertices_count, GL_TEX2D *tex ) { glUseProgram( gl2d->id ); + glBindVertexArray( gl2d->gl->vao ); for( U32 i = 0; i < vertices_count; ++i ) vertices[i].sampler = 0; @@ -311,4 +345,6 @@ void gl_textured_polygon( order[i] = i; glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); } diff --git a/src/render/gl_2d_font.cpp b/src/render/gl_2d_font.cpp index 1dc498b..a104124 100644 --- a/src/render/gl_2d_font.cpp +++ b/src/render/gl_2d_font.cpp @@ -207,24 +207,38 @@ void gl_font_draw( GL_FONT* font, GL_SHADER_PROGRAM* shader, VEC2 origin, const gl_font_calc_vertices_uvs( font, origin, text, _scale, vertices, indices, coords, clr ); glUseProgram( shader->id ); + glBindVertexArray( shader->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, shader->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * 6 * len, vertices, GL_STATIC_DRAW ); + I32 position = glGetAttribLocation( shader->id, "in_pos" ); - glEnableVertexAttribArray( position ); - glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->pos ); - I32 color = glGetAttribLocation( shader->id, "in_clr" ); - glEnableVertexAttribArray( color ); - glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); - I32 texcoord = glGetAttribLocation( shader->id, "in_texcoord" ); - glEnableVertexAttribArray( texcoord ); - glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); - I32 sampler = glGetAttribLocation( shader->id, "in_sampler" ); - glEnableVertexAttribArray( sampler ); - glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + + if (position >= 0) { + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->pos ); + } + + if (color >= 0) { + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + } + + if (texcoord >= 0) { + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + } + + if (sampler >= 0) { + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + } + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, font->atlas->id ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); @@ -234,10 +248,12 @@ void gl_font_draw( GL_FONT* font, GL_SHADER_PROGRAM* shader, VEC2 origin, const glDrawElements( GL_TRIANGLES, len * 6, GL_UNSIGNED_SHORT, indices ); glBindTexture( GL_TEXTURE_2D, 0 ); - + free( vertices ); free( indices ); free( coords ); + + glBindVertexArray( 0 ); } void gl_font_textured( @@ -272,6 +288,7 @@ void gl_font_textured( } glUseProgram( shader->id ); + glBindVertexArray( shader->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, shader->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(FONT_CUSTOM_VERTEX) * 6 * len, custom_vertices, GL_STATIC_DRAW ); @@ -303,6 +320,8 @@ void gl_font_textured( free( indices ); free( coords ); free( custom_vertices ); + + glBindVertexArray( 0 ); } diff --git a/src/render/gl_3d.cpp b/src/render/gl_3d.cpp index 78e7f5e..7209f61 100644 --- a/src/render/gl_3d.cpp +++ b/src/render/gl_3d.cpp @@ -3,8 +3,8 @@ #include "gl.h" #include "gl_batch.h" -GL_3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { - GL_3D *gl3d = (GL_3D*)gl_program_create( gl, shadername, sizeof(GL_3D) ); +GL3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { + GL3D *gl3d = (GL3D*)gl_program_create( gl, shadername, sizeof(GL3D) ); if( !OK( gl_program_compile( gl, gl3d ) ) ) dlog( "gl_2d_init() : error compiling shader %s\n", shadername ); @@ -17,8 +17,8 @@ GL_3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { return gl3d; } -void gl_3d_projection_setup( GL_PROGRAM *_gl3d, VEC3 pos, F32 fov_deg, F32 yaw, F32 pitch, F32 near, F32 far, VEC2 winsize ) { - GL_3D* gl3d = (GL_3D*)_gl3d; +void gl_3d_projection_setup( GL_SHADER_PROGRAM *_gl3d, VEC3 pos, F32 fov_deg, F32 yaw, F32 pitch, F32 near, F32 far, VEC2 winsize ) { + GL3D* gl3d = (GL3D*)_gl3d; MAT4 proj, yaw_rot, pitch_rot, view, transl, tmp; F32 fov_rad = m_deg2rad( fov_deg ); @@ -63,12 +63,13 @@ void gl_3d_batch_setup( GL_BATCH3D *batch ) { } void gl_3d_polygon( - GL_PROGRAM* gl3d, + GL_SHADER_PROGRAM* gl3d, VERTEX3D* vertices, U32 vertices_count, GL_TEX2D* tex ) { glUseProgram( gl3d->id ); + glBindVertexArray( gl3d->gl->vao ); if( !!tex ) { glActiveTexture( GL_TEXTURE0 ); @@ -99,6 +100,8 @@ void gl_3d_polygon( glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); + + glBindVertexArray( 0 ); } void gl_3d_polygon_fan( diff --git a/src/render/gl_3d.h b/src/render/gl_3d.h index 531c3a3..69f171a 100644 --- a/src/render/gl_3d.h +++ b/src/render/gl_3d.h @@ -13,7 +13,7 @@ struct VERTEX3D { }; using GL_BATCH3D = GL_BATCH; -struct GL_3D : GL_SHADER_PROGRAM { +struct GL3D : GL_SHADER_PROGRAM { F32 aspect; MAT4 projmat; @@ -21,7 +21,7 @@ struct GL_3D : GL_SHADER_PROGRAM { }; // shader init ----------------------------------------------------------- -extern GL_3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ); +extern GL3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ); // sets up projection matrix and sends it to the gpu ------------------------------------------------------------ extern void gl_3d_projection_setup( GL_SHADER_PROGRAM* gl3d, VEC3 pos, F32 fov_deg, F32 yaw, F32 pitch, F32 near, F32 far, VEC2 winsize ); extern void gl_3d_batch_setup( GL_BATCH3D* batch ); diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp index 1601afe..6c2d021 100644 --- a/src/util/config/config.cpp +++ b/src/util/config/config.cpp @@ -12,20 +12,24 @@ void cfg_seterr( CFG_PARSER* p, const char* fmt, ... ) { } inline U8 is_whitespace( char c ) { - return c == ' ' || c == '\t' || c == '\n'; + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; // Added \r } inline void trim_whitespace( char* buf ) { - U32 i; - for( i = 0; !!buf[i]; ++i ) - if( !is_whitespace( buf[i] ) ) break; - for( U32 i2 = i; !!buf[i2]; ++i2 ) { - if( is_whitespace( buf[i2] ) ) { - buf[i2 - i] = 0; - return; - } - buf[i2 - i] = buf[i2]; - } + if (!buf || !*buf) return; + + // Find first non-whitespace character + U32 start = 0; + while( buf[start] && is_whitespace( buf[start] ) ) start++; + + // Find last non-whitespace character + U32 end = strlen( buf ); + while( end > start && is_whitespace( buf[end - 1] ) ) end--; + + // Move string to beginning and null-terminate + U32 len = end - start; + memmove( buf, buf + start, len ); + buf[len] = '\0'; } inline void init_cfg_node( CFG_NODE* node, const char* name, CFG_NODE* parent, U8 type ) { @@ -179,65 +183,116 @@ void parse_section( CFG_PARSER* parser, CFG_SECTION* current_section ) { char* next_token; while( fgets( line, sizeof(line), parser->file ) ) { - token = strtok( line, " \t\n" ); + parser->linen++; + + // Remove all whitespace including \r\n + trim_whitespace( line ); + + // Skip empty lines + if( strlen(line) == 0 ) continue; + + // Use a copy for tokenization to preserve original + char line_copy[8192]; + strcpy( line_copy, line ); + + token = strtok( line_copy, " \t\r\n" ); // Added \r if( !token ) continue; - if( strcmp( token, "{" ) == 0 ) + + if( strcmp( token, "{" ) == 0 ) { continue; - else if( strcmp( token, "}" ) == 0 ) { + } else if( strcmp( token, "}" ) == 0 ) { return; } else if( strcmp( token, cfg_types[CFGT_SECTION].def ) == 0 ) { - next_token = strtok( NULL, " \t\n" ); + next_token = strtok( NULL, " \t\r\n" ); + if( !next_token ) { + cfg_seterr( parser, "Missing section name at line %d", parser->linen ); + return; + } + char sectname[64]; - strcpy( sectname, next_token ); + strncpy( sectname, next_token, sizeof(sectname) - 1 ); + sectname[sizeof(sectname) - 1] = '\0'; trim_whitespace( sectname ); CFG_SECTION* new_section = cfg_section_new( sectname, (CFG_NODE*)current_section ); - strtok( NULL, " \t\n" ); + + // Look for opening brace + char* brace = strtok( NULL, " \t\r\n" ); + if( !brace || strcmp( brace, "{" ) != 0 ) { + cfg_seterr( parser, "Expected '{' after section name at line %d", parser->linen ); + return; + } + parse_section( parser, new_section ); } else { + // Parse variable declaration char name[64]; - strcpy( name, token ); + strncpy( name, token, sizeof(name) - 1 ); + name[sizeof(name) - 1] = '\0'; trim_whitespace( name ); + // Find the variable name (between type and =) token = strtok( NULL, "=[" ); - if( !token ) + if( !token ) { + cfg_seterr( parser, "Invalid variable declaration at line %d", parser->linen ); continue; + } char varname[64]; - strcpy( varname, token ); + strncpy( varname, token, sizeof(varname) - 1 ); + varname[sizeof(varname) - 1] = '\0'; trim_whitespace( varname ); + // Find matching parser + bool found = false; for( I32 i = 0; i < sizeof(cfg_types) / sizeof(CFG_TYPE); ++i ) { const CFG_TYPE* fn = &cfg_types[i]; - if( strncmp( name, fn->def, strlen( fn->def ) ) == 0 ) { + if( strcmp( name, fn->def ) == 0 ) { + // Reset strtok to work on original line for parser + strcpy( line_copy, line ); + strtok( line_copy, " \t\r\n" ); // Skip type + strtok( NULL, "=[" ); // Skip variable name + fn->parser( parser, current_section, varname ); + found = true; break; } } + + if( !found ) { + cfg_seterr( parser, "Unknown type '%s' at line %d", name, parser->linen ); + return; + } if( parser->iserr ) { dlog( "parse_section() : %s parse error:\n - %s\n", name, parser->err ); return; } } - - parser->linen++; } } CFG_SECTION* cfg_load( const char* path ) { - FILE* f = fopen( path, "rb" ); + FILE* f = fopen( path, "r" ); // Changed from "rb" to "r" for text mode if( !f ) return 0; CFG_PARSER p; + memset( &p, 0, sizeof(p) ); // Initialize all fields p.iserr = 0; p.file = f; p.linen = 0; p.root = cfg_section_new( "root", 0 ); + parse_section( &p, p.root ); fclose( f ); + + if( p.iserr ) { + cfg_free( (CFG_NODE*)p.root ); + return 0; + } + return p.root; } -- cgit v1.2.3 From 8be4ca70798fafd57dba947edfb18d0de594013d Mon Sep 17 00:00:00 2001 From: Kasullian Date: Tue, 9 Sep 2025 01:19:12 -0400 Subject: fix font rendering --- assets/shaders/2d_texcoord.fsh | 7 ++++--- assets/shaders/2d_texcoord.vsh | 4 ++-- assets/shaders/3d.fsh | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/assets/shaders/2d_texcoord.fsh b/assets/shaders/2d_texcoord.fsh index fabbb2f..cf94a68 100644 --- a/assets/shaders/2d_texcoord.fsh +++ b/assets/shaders/2d_texcoord.fsh @@ -2,16 +2,17 @@ uniform sampler2D g_samplers[255]; -const uint SAMPLER_ID_NONE = 255u; +const int SAMPLER_ID_NONE = 255; in vec2 g_texcoord; in vec4 g_color; -flat in uint g_sampler; +flat in int g_sampler; void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { - vec4 tex_color = texture2D( g_samplers[g_sampler], g_texcoord ); + // Always use sampler 0 to avoid dynamic indexing issues + vec4 tex_color = texture2D( g_samplers[0], g_texcoord ); color.a = g_color.a * tex_color.a; if (color.a < 0.01) discard; } diff --git a/assets/shaders/2d_texcoord.vsh b/assets/shaders/2d_texcoord.vsh index 3ccc8e7..80c7597 100644 --- a/assets/shaders/2d_texcoord.vsh +++ b/assets/shaders/2d_texcoord.vsh @@ -9,7 +9,7 @@ in float in_sampler; out vec2 g_texcoord; out vec4 g_color; -flat out uint g_sampler; +flat out int g_sampler; uniform vec4 g_screenratio; @@ -23,6 +23,6 @@ void main() { g_texcoord = in_texcoord; g_color = in_clr; - g_sampler = uint(in_sampler * 255 + 0.5); + g_sampler = int(in_sampler * 255.0 + 0.5); gl_Position = ( pos ) * g_screenratio; } diff --git a/assets/shaders/3d.fsh b/assets/shaders/3d.fsh index ee1208c..7660204 100644 --- a/assets/shaders/3d.fsh +++ b/assets/shaders/3d.fsh @@ -11,8 +11,9 @@ flat in uint g_sampler; void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { - color = texture2D( g_samplers[int(g_sampler)], g_texcoord ); + // Always use sampler 0 for fonts + color = texture2D( g_samplers[0], g_texcoord ); color *= g_color; } gl_FragColor = color; -} +} \ No newline at end of file -- cgit v1.2.3 From 235926dadb686589f0b5480162c3ab929159e570 Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 10 Sep 2025 12:25:00 +0200 Subject: unfuck --- CMakeLists.txt | 13 ++++---- assets/shaders/2d_texcoord.fsh | 5 ++-- assets/shaders/3d.fsh | 5 ++-- src/render/gl.cpp | 26 ++++------------ src/render/gl_2d_font.cpp | 28 +++++++----------- src/util/allocator.h | 12 ++++++++ src/util/config/config.cpp | 67 ++++++++++++++++++------------------------ 7 files changed, 67 insertions(+), 89 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e99269a..fc2ce17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,8 +20,11 @@ pkg_check_modules(FREETYPE REQUIRED freetype2) pkg_check_modules(GLEW REQUIRED glew) find_package(OpenGL REQUIRED) +# release build settings +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-nontrivial-memcall") +# debug build settings +set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG=1 -fsanitize=address -Wno-nontrivial-memcall") -target_compile_options(app PRIVATE -Wall) target_include_directories(app PRIVATE ${SDL2_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS} @@ -47,10 +50,8 @@ else() ) endif() -# release build settings -set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-nontrivial-memcall") -# debug build settings -set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG=1 -fsanitize=address -Wno-nontrivial-memcall") +target_compile_options(app PRIVATE -Wall) +target_compile_options(app PRIVATE -Wno-nontrivial-memcall) add_custom_target(debug COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_BINARY_DIR} @@ -63,4 +64,4 @@ add_custom_target(release COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Building ~~**RELEASE**~~" -) \ No newline at end of file +) diff --git a/assets/shaders/2d_texcoord.fsh b/assets/shaders/2d_texcoord.fsh index cf94a68..cbb9be0 100644 --- a/assets/shaders/2d_texcoord.fsh +++ b/assets/shaders/2d_texcoord.fsh @@ -11,10 +11,9 @@ flat in int g_sampler; void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { - // Always use sampler 0 to avoid dynamic indexing issues - vec4 tex_color = texture2D( g_samplers[0], g_texcoord ); + vec4 tex_color = texture2D( g_samplers[g_sampler], g_texcoord ); color.a = g_color.a * tex_color.a; if (color.a < 0.01) discard; } gl_FragColor = color; -} \ No newline at end of file +} diff --git a/assets/shaders/3d.fsh b/assets/shaders/3d.fsh index 7660204..276f305 100644 --- a/assets/shaders/3d.fsh +++ b/assets/shaders/3d.fsh @@ -11,9 +11,8 @@ flat in uint g_sampler; void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { - // Always use sampler 0 for fonts - color = texture2D( g_samplers[0], g_texcoord ); + color = texture2D( g_samplers[g_sampler], g_texcoord ); color *= g_color; } gl_FragColor = color; -} \ No newline at end of file +} diff --git a/src/render/gl.cpp b/src/render/gl.cpp index 6654dd4..c084db0 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -43,7 +43,7 @@ GL_DATA* gl_create( I32* _canvas ) { GL_DATA* gl = new GL_DATA; gl->window = SDL_CreateWindow( "game", - SDL_WINDOWPOS_CENTERED, // Use centered position + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _canvas[0], _canvas[1], @@ -64,6 +64,7 @@ GL_DATA* gl_create( I32* _canvas ) { return 0; } + SDL_GL_SetSwapInterval(0); SDL_GL_MakeCurrent( gl->window, gl->ctx ); GLenum glewError = glewInit(); @@ -75,17 +76,8 @@ GL_DATA* gl_create( I32* _canvas ) { return 0; } - dlog( "OpenGL Version: %s\n", glGetString(GL_VERSION) ); - dlog( "GLSL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) ); - dlog( "Renderer: %s\n", glGetString(GL_RENDERER) ); - dlog( "Vendor: %s\n", glGetString(GL_VENDOR) ); - - // Set up V-Sync (0 = off, 1 = on, -1 = adaptive) - SDL_GL_SetSwapInterval(1); - - // Clear any OpenGL errors that might have occurred during initialization - while( glGetError() != GL_NO_ERROR ); - + while( glGetError() != GL_NO_ERROR ); // clear errors + // glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, &gl->shader_texture_limit ); if( gl->shader_texture_limit > 255 ) gl->shader_texture_limit = 255; @@ -96,28 +88,22 @@ GL_DATA* gl_create( I32* _canvas ) { memcpy( gl->canvas_size, _canvas, sizeof(I32) * 2 ); gl->clip_start = { 0, 0 }; gl->clip_dim = { (F32)gl->canvas_size[0], (F32)gl->canvas_size[1] }; - - // Set initial viewport glViewport( 0, 0, gl->canvas_size[0], gl->canvas_size[1] ); - - // Set initial clear color (so you can see if clearing is working) - glClearColor( 0.2f, 0.2f, 0.2f, 1.0f ); gl_inst = gl; return gl; } void gl_gen_buffers( GL_DATA* gl ) { - // Generate and bind VAO first glGenVertexArrays( 1, &gl->vao ); glBindVertexArray( gl->vao ); - + glGenBuffers( 1, &gl->vbuffer ); glBindBuffer( GL_ARRAY_BUFFER, gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, 8192, 0, GL_STATIC_DRAW ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); - glBindVertexArray( 0 ); // Unbind VAO + glBindVertexArray( 0 ); } void gl_destroy( GL_DATA *gl ) { diff --git a/src/render/gl_2d_font.cpp b/src/render/gl_2d_font.cpp index a104124..329f0be 100644 --- a/src/render/gl_2d_font.cpp +++ b/src/render/gl_2d_font.cpp @@ -211,31 +211,23 @@ void gl_font_draw( GL_FONT* font, GL_SHADER_PROGRAM* shader, VEC2 origin, const glBindBuffer( GL_ARRAY_BUFFER, shader->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * 6 * len, vertices, GL_STATIC_DRAW ); - + I32 position = glGetAttribLocation( shader->id, "in_pos" ); I32 color = glGetAttribLocation( shader->id, "in_clr" ); I32 texcoord = glGetAttribLocation( shader->id, "in_texcoord" ); I32 sampler = glGetAttribLocation( shader->id, "in_sampler" ); - - if (position >= 0) { - glEnableVertexAttribArray( position ); - glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->pos ); - } - if (color >= 0) { - glEnableVertexAttribArray( color ); - glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); - } + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->pos ); - if (texcoord >= 0) { - glEnableVertexAttribArray( texcoord ); - glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); - } + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); - if (sampler >= 0) { - glEnableVertexAttribArray( sampler ); - glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); - } + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, font->atlas->id ); diff --git a/src/util/allocator.h b/src/util/allocator.h index ee0ddd8..7927b9c 100644 --- a/src/util/allocator.h +++ b/src/util/allocator.h @@ -161,6 +161,18 @@ struct LIST { return &data[size - 1]; } + void resize( U32 size ) { + if( size > capacity ) + reserve( size * 2 ); + + if( size < capacity ) { + for( U32 i = size; i < capacity; ++i ) + data[i] = T(); + } + + this->size = size; + } + // does not call copy constructors, raw memcpy void emplace_list( const LIST& list ) { if( !list.size ) diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp index 6c2d021..a41e455 100644 --- a/src/util/config/config.cpp +++ b/src/util/config/config.cpp @@ -12,21 +12,18 @@ void cfg_seterr( CFG_PARSER* p, const char* fmt, ... ) { } inline U8 is_whitespace( char c ) { - return c == ' ' || c == '\t' || c == '\n' || c == '\r'; // Added \r + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } inline void trim_whitespace( char* buf ) { if (!buf || !*buf) return; - - // Find first non-whitespace character + U32 start = 0; while( buf[start] && is_whitespace( buf[start] ) ) start++; - - // Find last non-whitespace character + U32 end = strlen( buf ); while( end > start && is_whitespace( buf[end - 1] ) ) end--; - - // Move string to beginning and null-terminate + U32 len = end - start; memmove( buf, buf + start, len ); buf[len] = '\0'; @@ -184,20 +181,17 @@ void parse_section( CFG_PARSER* parser, CFG_SECTION* current_section ) { while( fgets( line, sizeof(line), parser->file ) ) { parser->linen++; - - // Remove all whitespace including \r\n + trim_whitespace( line ); - - // Skip empty lines - if( strlen(line) == 0 ) continue; - - // Use a copy for tokenization to preserve original + if( strlen( line ) == 0 ) + continue; + char line_copy[8192]; strcpy( line_copy, line ); - - token = strtok( line_copy, " \t\r\n" ); // Added \r + + token = strtok( line_copy, " \t\r\n" ); if( !token ) continue; - + if( strcmp( token, "{" ) == 0 ) { continue; } else if( strcmp( token, "}" ) == 0 ) { @@ -205,36 +199,33 @@ void parse_section( CFG_PARSER* parser, CFG_SECTION* current_section ) { } else if( strcmp( token, cfg_types[CFGT_SECTION].def ) == 0 ) { next_token = strtok( NULL, " \t\r\n" ); if( !next_token ) { - cfg_seterr( parser, "Missing section name at line %d", parser->linen ); + cfg_seterr( parser, "missing section name at line %d", parser->linen ); return; } - + char sectname[64]; strncpy( sectname, next_token, sizeof(sectname) - 1 ); sectname[sizeof(sectname) - 1] = '\0'; trim_whitespace( sectname ); CFG_SECTION* new_section = cfg_section_new( sectname, (CFG_NODE*)current_section ); - - // Look for opening brace + char* brace = strtok( NULL, " \t\r\n" ); if( !brace || strcmp( brace, "{" ) != 0 ) { - cfg_seterr( parser, "Expected '{' after section name at line %d", parser->linen ); + cfg_seterr( parser, "expected '{' after section name at line %d", parser->linen ); return; } - + parse_section( parser, new_section ); } else { - // Parse variable declaration char name[64]; strncpy( name, token, sizeof(name) - 1 ); name[sizeof(name) - 1] = '\0'; trim_whitespace( name ); - // Find the variable name (between type and =) token = strtok( NULL, "=[" ); if( !token ) { - cfg_seterr( parser, "Invalid variable declaration at line %d", parser->linen ); + cfg_seterr( parser, "invalid variable declaration at line %d", parser->linen ); continue; } @@ -243,24 +234,22 @@ void parse_section( CFG_PARSER* parser, CFG_SECTION* current_section ) { varname[sizeof(varname) - 1] = '\0'; trim_whitespace( varname ); - // Find matching parser - bool found = false; + U8 found = 0; for( I32 i = 0; i < sizeof(cfg_types) / sizeof(CFG_TYPE); ++i ) { const CFG_TYPE* fn = &cfg_types[i]; if( strcmp( name, fn->def ) == 0 ) { - // Reset strtok to work on original line for parser strcpy( line_copy, line ); - strtok( line_copy, " \t\r\n" ); // Skip type - strtok( NULL, "=[" ); // Skip variable name - + strtok( line_copy, " \t\r\n" ); + strtok( NULL, "=[" ); + fn->parser( parser, current_section, varname ); found = true; break; } } - + if( !found ) { - cfg_seterr( parser, "Unknown type '%s' at line %d", name, parser->linen ); + cfg_seterr( parser, "unknown type '%s' at line %d", name, parser->linen ); return; } @@ -273,26 +262,26 @@ void parse_section( CFG_PARSER* parser, CFG_SECTION* current_section ) { } CFG_SECTION* cfg_load( const char* path ) { - FILE* f = fopen( path, "r" ); // Changed from "rb" to "r" for text mode + FILE* f = fopen( path, "r" ); if( !f ) return 0; CFG_PARSER p; - memset( &p, 0, sizeof(p) ); // Initialize all fields + memset( &p, 0, sizeof(p) ); p.iserr = 0; p.file = f; p.linen = 0; p.root = cfg_section_new( "root", 0 ); - + parse_section( &p, p.root ); fclose( f ); - + if( p.iserr ) { cfg_free( (CFG_NODE*)p.root ); return 0; } - + return p.root; } -- cgit v1.2.3 From 496e2bbc68aaaaf99d935233ce3ba0636f1bf0cf Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 10 Sep 2025 12:34:36 +0200 Subject: fix batch render --- src/render/gl_batch.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/render/gl_batch.h b/src/render/gl_batch.h index 944521f..7ca9fe3 100644 --- a/src/render/gl_batch.h +++ b/src/render/gl_batch.h @@ -91,6 +91,7 @@ inline void gl_batch_empty( GL_BATCH* batch ) { template inline void gl_batch_draw( GL_BATCH* batch ) { glUseProgram( batch->shader->id ); + glBindVertexArray( batch->gl->vao ); VEC2 vp_start, vp_dim, clip_start, clip_dim; gl_get_viewport( batch->gl, &vp_start, &vp_dim ); @@ -117,6 +118,7 @@ inline void gl_batch_draw( GL_BATCH* batch ) { gl_set_viewport( batch->gl, vp_start, vp_dim ); gl_set_clip( batch->gl, clip_start, clip_dim ); + glBindVertexArray( 0 ); } template -- cgit v1.2.3 From e2366afb57d69f3952bbb4d1894d82293cd1cb9d Mon Sep 17 00:00:00 2001 From: Kasullian Date: Wed, 10 Sep 2025 07:16:42 -0400 Subject: remove unnecessary code --- src/render/gl.cpp | 2 -- src/render/gl_2d.cpp | 24 ------------------------ src/render/gl_2d_font.cpp | 6 ------ src/render/gl_3d.cpp | 3 --- src/render/gl_batch.h | 2 -- 5 files changed, 37 deletions(-) diff --git a/src/render/gl.cpp b/src/render/gl.cpp index c084db0..382d81e 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -102,8 +102,6 @@ void gl_gen_buffers( GL_DATA* gl ) { glBindBuffer( GL_ARRAY_BUFFER, gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, 8192, 0, GL_STATIC_DRAW ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); - - glBindVertexArray( 0 ); } void gl_destroy( GL_DATA *gl ) { diff --git a/src/render/gl_2d.cpp b/src/render/gl_2d.cpp index ca3a338..1803eb5 100644 --- a/src/render/gl_2d.cpp +++ b/src/render/gl_2d.cpp @@ -30,7 +30,6 @@ void gl_2d_line( GL_SHADER_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { static const U16 order[] = { 0, 1 }; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { .pos = { start.x, start.y }, .clr = col }, @@ -48,15 +47,12 @@ void gl_2d_line( GL_SHADER_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_LINES, 2, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); } void gl_2d_rect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { static const U16 order[] = { 0, 1, 2, 3, 4 }; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { .pos = { origin.x , origin.y }, .clr = col }, @@ -77,15 +73,12 @@ void gl_2d_rect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); } void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* texture, CLR col, VEC2* uv, F32 rotation ) { static const U16 order[] = { 0, 1, 2, 3 }; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { { origin.x, origin.y }, uv? uv[0] : VEC2{ 0.f, 0.f }, col, 0 }, @@ -133,15 +126,12 @@ void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TE glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); glBindTexture( GL_TEXTURE_2D, 0 ); - - glBindVertexArray( 0 ); } void gl_2d_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { static const U16 order[] = { 0, 1, 2, 3 }; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); VERTEX vertices[] = { { .pos = { origin.x, origin.y }, .uv = { 0.f, 0.f }, .clr = col }, @@ -174,8 +164,6 @@ void gl_2d_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); // Unbind VAO } void gl_2d_circle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { @@ -183,7 +171,6 @@ void gl_2d_circle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U3 const F32 step = 360.f / (F32)res; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); if( !order ) { order = (U16*)malloc( sizeof( U16 ) * (res + 1) ); @@ -218,8 +205,6 @@ void gl_2d_circle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U3 glDrawElements( GL_LINE_STRIP, res + 1, GL_UNSIGNED_SHORT, order ); free( vertices ); - - glBindVertexArray( 0 ); } void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { @@ -227,7 +212,6 @@ void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U const F32 step = 360.f / (F32)res; glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); if( !order ) { order = (U16*)malloc( sizeof( U16 ) * (res * 2) ); @@ -274,13 +258,10 @@ void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U glDrawElements( GL_TRIANGLE_STRIP, res + 2, GL_UNSIGNED_SHORT, order ); free( vertices ); - - glBindVertexArray( 0 ); } void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * vertices_count, vertices, GL_STATIC_DRAW ); @@ -302,8 +283,6 @@ void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) order[i] = i; glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); } void gl_textured_polygon( @@ -313,7 +292,6 @@ void gl_textured_polygon( GL_TEX2D *tex ) { glUseProgram( gl2d->id ); - glBindVertexArray( gl2d->gl->vao ); for( U32 i = 0; i < vertices_count; ++i ) vertices[i].sampler = 0; @@ -345,6 +323,4 @@ void gl_textured_polygon( order[i] = i; glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); } diff --git a/src/render/gl_2d_font.cpp b/src/render/gl_2d_font.cpp index 329f0be..10ae71a 100644 --- a/src/render/gl_2d_font.cpp +++ b/src/render/gl_2d_font.cpp @@ -207,7 +207,6 @@ void gl_font_draw( GL_FONT* font, GL_SHADER_PROGRAM* shader, VEC2 origin, const gl_font_calc_vertices_uvs( font, origin, text, _scale, vertices, indices, coords, clr ); glUseProgram( shader->id ); - glBindVertexArray( shader->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, shader->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * 6 * len, vertices, GL_STATIC_DRAW ); @@ -244,8 +243,6 @@ void gl_font_draw( GL_FONT* font, GL_SHADER_PROGRAM* shader, VEC2 origin, const free( vertices ); free( indices ); free( coords ); - - glBindVertexArray( 0 ); } void gl_font_textured( @@ -280,7 +277,6 @@ void gl_font_textured( } glUseProgram( shader->id ); - glBindVertexArray( shader->gl->vao ); glBindBuffer( GL_ARRAY_BUFFER, shader->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(FONT_CUSTOM_VERTEX) * 6 * len, custom_vertices, GL_STATIC_DRAW ); @@ -312,8 +308,6 @@ void gl_font_textured( free( indices ); free( coords ); free( custom_vertices ); - - glBindVertexArray( 0 ); } diff --git a/src/render/gl_3d.cpp b/src/render/gl_3d.cpp index 7209f61..40162e8 100644 --- a/src/render/gl_3d.cpp +++ b/src/render/gl_3d.cpp @@ -69,7 +69,6 @@ void gl_3d_polygon( GL_TEX2D* tex ) { glUseProgram( gl3d->id ); - glBindVertexArray( gl3d->gl->vao ); if( !!tex ) { glActiveTexture( GL_TEXTURE0 ); @@ -100,8 +99,6 @@ void gl_3d_polygon( glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); - - glBindVertexArray( 0 ); } void gl_3d_polygon_fan( diff --git a/src/render/gl_batch.h b/src/render/gl_batch.h index 7ca9fe3..944521f 100644 --- a/src/render/gl_batch.h +++ b/src/render/gl_batch.h @@ -91,7 +91,6 @@ inline void gl_batch_empty( GL_BATCH* batch ) { template inline void gl_batch_draw( GL_BATCH* batch ) { glUseProgram( batch->shader->id ); - glBindVertexArray( batch->gl->vao ); VEC2 vp_start, vp_dim, clip_start, clip_dim; gl_get_viewport( batch->gl, &vp_start, &vp_dim ); @@ -118,7 +117,6 @@ inline void gl_batch_draw( GL_BATCH* batch ) { gl_set_viewport( batch->gl, vp_start, vp_dim ); gl_set_clip( batch->gl, clip_start, clip_dim ); - glBindVertexArray( 0 ); } template -- cgit v1.2.3 From ae694bc0da98e45c5def20ac1d92f9d8aad65fd5 Mon Sep 17 00:00:00 2001 From: Kasullian Date: Wed, 10 Sep 2025 12:08:59 -0400 Subject: 3d view mouse control --- src/editor/view3d.cpp | 21 +++++++++++++++++++++ src/game/player.cpp | 36 +++++++++++++++++++++++++----------- src/util/input.cpp | 9 +++++++++ src/util/input.h | 4 ++++ 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/editor/view3d.cpp b/src/editor/view3d.cpp index f9bd60e..61bcc3e 100644 --- a/src/editor/view3d.cpp +++ b/src/editor/view3d.cpp @@ -31,6 +31,16 @@ void gui_editor_3dview_draw_showpos( GUI_EDITOR_3DVIEW* view ) { objl->pl->rot.y, objl->pl->rot.x ); + + if( input.mouse_captured ) { + gui_draw_str( + x + 2, y + 2, + ALIGN_L, + FNT_JPN12, + ui_clr.txt, + "[capturing mouse]" + ); + } } void gui_editor_3dview_draw_fn( void* ptr ) { @@ -60,9 +70,20 @@ void gui_editor_3dview_draw_fn( void* ptr ) { } void gui_editor_3dview_input_fn( void* ptr ) { + GUI_EDITOR_3DVIEW* view = (GUI_EDITOR_3DVIEW*)ptr; + if( !objl->pl ) return; + if( input.mouse.left && !input.mouse_captured ) { + I32 view_x = gui_relx( view ); + I32 view_y = gui_rely( view ) + EDITORVIEW_TITLE_OFFSET; + if( input.mouse.pos.x >= view_x && input.mouse.pos.x < view_x + view->w && + input.mouse.pos.y >= view_y && input.mouse.pos.y < view_y + view->h ) { + input_capture_mouse( true ); + } + } + game_on_tick( editor->game ); } diff --git a/src/game/player.cpp b/src/game/player.cpp index 87786df..993292c 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -34,18 +34,32 @@ void player_input( GAME_DATA* game, PLAYER* p ) { F32* yaw = &p->rot.y; VEC3* pos = &p->pos; - if( input.keys[(U8)'a'] ) - *yaw -= 360.f * TICK_INTERVAL * 0.5f; - if( input.keys[(U8)'d'] ) - *yaw += 360.f * TICK_INTERVAL * 0.5f; - - if( input.keys[SDL_SCANCODE_UP] ) { - if( p->rot.x < 89.f ) - p->rot.x += 360.f * TICK_INTERVAL * 0.5f; + if( input.keys[SDL_SCANCODE_F1] ) { + input_capture_mouse( false ); } - if( input.keys[SDL_SCANCODE_DOWN] ) { - if( p->rot.x > -89.f ) - p->rot.x -= 360.f * TICK_INTERVAL * 0.5f; + + if( input.mouse_captured ) { + *yaw += input.mouse.pos_delta.x * input.mouse_sensitivity; + p->rot.x -= input.mouse.pos_delta.y * input.mouse_sensitivity; + + if( p->rot.x > 89.f ) p->rot.x = 89.f; + if( p->rot.x < -89.f ) p->rot.x = -89.f; + } + + if( !input.mouse_captured ) { + if( input.keys[(U8)'a'] ) + *yaw -= 360.f * TICK_INTERVAL * 0.5f; + if( input.keys[(U8)'d'] ) + *yaw += 360.f * TICK_INTERVAL * 0.5f; + + if( input.keys[SDL_SCANCODE_UP] ) { + if( p->rot.x < 89.f ) + p->rot.x += 360.f * TICK_INTERVAL * 0.5f; + } + if( input.keys[SDL_SCANCODE_DOWN] ) { + if( p->rot.x > -89.f ) + p->rot.x -= 360.f * TICK_INTERVAL * 0.5f; + } } *yaw = remainderf( *yaw, 360.f ); diff --git a/src/util/input.cpp b/src/util/input.cpp index 4a786aa..7e94c47 100644 --- a/src/util/input.cpp +++ b/src/util/input.cpp @@ -27,6 +27,8 @@ void input_on_event( SDL_Event* e ) { case SDL_MOUSEMOTION: { input.mouse.pos.x = (F32)e->motion.x; input.mouse.pos.y = (F32)e->motion.y; + input.mouse.pos_delta.x = (F32)e->motion.xrel; + input.mouse.pos_delta.y = (F32)e->motion.yrel; } break; case SDL_KEYDOWN: { input.keys[e->key.keysym.sym & 0xff] = 1; @@ -71,4 +73,11 @@ void input_on_mouse( I32 type, I32 x, I32 y ) { void input_frame_end() { input.mouse.wheel = 0; + input.mouse.pos_delta.x = 0; + input.mouse.pos_delta.y = 0; +} + +void input_capture_mouse( bool capture ) { + input.mouse_captured = capture; + SDL_SetRelativeMouseMode( capture ? SDL_TRUE : SDL_FALSE ); } diff --git a/src/util/input.h b/src/util/input.h index e174fe6..4885f0f 100644 --- a/src/util/input.h +++ b/src/util/input.h @@ -16,6 +16,7 @@ const U32 MOUSE_WHEEL = 0x4; struct MOUSE_DATA { VEC2 pos; + VEC2 pos_delta; U8 left; U8 right; U8 middle; @@ -27,6 +28,8 @@ using ON_INPUT_FN = std::function; struct INPUT_DATA { MOUSE_DATA mouse; U8 keys[0xff]; + bool mouse_captured; + F32 mouse_sensitivity = 1.0f; LIST on_input; }; @@ -37,5 +40,6 @@ extern void input_frame_end(); extern void input_on_event( SDL_Event* e ); extern void input_on_mouse( I32 type, I32 x, I32 y ); extern void input_is_key_down( U32 key ); +extern void input_capture_mouse( bool capture ); #define kb_down( key ) input_is_key_down( key ) -- cgit v1.2.3 From 0db9c91742a6ab17c3d8a8b86a34392c1797740b Mon Sep 17 00:00:00 2001 From: navewindre Date: Sun, 28 Sep 2025 02:45:10 +0200 Subject: input bettr --- src/game.cpp | 3 +- src/game/camera.h | 9 ++++ src/game/player.cpp | 126 ++++++++++++++++++++++++++++++++++++++-------------- src/game/player.h | 13 +++++- src/util/input.cpp | 11 +++-- src/util/input.h | 15 ++++++- 6 files changed, 137 insertions(+), 40 deletions(-) create mode 100644 src/game/camera.h diff --git a/src/game.cpp b/src/game.cpp index bd3c4c8..285f288 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -120,6 +120,7 @@ void game_main_loop( GAME_DATA* game ) { gl_beginframe( gl ); gl_2d_frect( gl2d, s_tl(), s_br(), { 0.f, 0.f, 0.f, 1.f } ); + player_input( game, objl->pl ); if( game->state.ingame ) { game_on_tick( game ); @@ -139,7 +140,7 @@ void game_main_loop( GAME_DATA* game ) { void game_on_tick( GAME_DATA* game ) { U64 tick = u_tick(); if( tick - game->state.last_tick > (U64)(TICK_INTERVAL * 10000) ) { - player_input( game, objl->pl ); + player_move( game, objl->pl ); game->state.last_tick = tick; } } diff --git a/src/game/camera.h b/src/game/camera.h new file mode 100644 index 0000000..b9fe402 --- /dev/null +++ b/src/game/camera.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../util/vector.h" + +struct PLAYER_CAMERA { + VEC3 pos; + VEC3 rot; + F32 fov; +}; diff --git a/src/game/player.cpp b/src/game/player.cpp index 993292c..26c03af 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -2,6 +2,7 @@ #include "SDL_scancode.h" #include "objlist.h" #include "world/trace.h" +#include #include "player.h" F32 PLAYER_HULL_HEIGHT = 50.f; @@ -30,64 +31,123 @@ PLAYER* player_create( VEC3 origin, F32 yaw ) { return p; } -void player_input( GAME_DATA* game, PLAYER* p ) { - F32* yaw = &p->rot.y; - VEC3* pos = &p->pos; - +void capture_mouse( PLAYER* p ) { + F32* yaw = &p->input.cam.pos.y; + F32* pitch = &p->input.cam.pos.x; if( input.keys[SDL_SCANCODE_F1] ) { input_capture_mouse( false ); } if( input.mouse_captured ) { *yaw += input.mouse.pos_delta.x * input.mouse_sensitivity; - p->rot.x -= input.mouse.pos_delta.y * input.mouse_sensitivity; - - if( p->rot.x > 89.f ) p->rot.x = 89.f; - if( p->rot.x < -89.f ) p->rot.x = -89.f; - } + *pitch -= input.mouse.pos_delta.y * input.mouse_sensitivity; - if( !input.mouse_captured ) { - if( input.keys[(U8)'a'] ) - *yaw -= 360.f * TICK_INTERVAL * 0.5f; - if( input.keys[(U8)'d'] ) - *yaw += 360.f * TICK_INTERVAL * 0.5f; + if( *pitch > 89.f ) *pitch = 89.f; + if( *pitch < -89.f ) *pitch = -89.f; - if( input.keys[SDL_SCANCODE_UP] ) { - if( p->rot.x < 89.f ) - p->rot.x += 360.f * TICK_INTERVAL * 0.5f; - } - if( input.keys[SDL_SCANCODE_DOWN] ) { - if( p->rot.x > -89.f ) - p->rot.x -= 360.f * TICK_INTERVAL * 0.5f; - } + input_reset_mouse_accumulator(); } *yaw = remainderf( *yaw, 360.f ); + p->rot.x = *pitch; + p->rot.y = *yaw; +} +void capture_move_keys( PLAYER* p ) { + VEC2* move = &p->input.move; + if( input.keys[input.binds.fwd] ) { + if( !p->input.fwd_held ) + move->x = 1.f; + p->input.fwd_held = true; + } else { + if( p->input.fwd_held ) { + if( p->input.bk_held ) + move->x = -1.f; + else + move->x = 0.f; + } + p->input.fwd_held = false; + } + + if( input.keys[input.binds.back] ) { + if( !p->input.bk_held ) + move->x = -1.f; + p->input.bk_held = true; + } else { + if( p->input.bk_held ) { + if( p->input.fwd_held ) + move->x = 1.f; + else + move->x = 0.f; + } + p->input.bk_held = false; + } - VEC3 wishmove; - VEC3 dir = m_radial_offset( *yaw, 70.f ); - if( input.keys[(U8)'w'] ) { - wishmove = dir * TICK_INTERVAL; + if( input.keys[input.binds.left] ) { + if( !p->input.left_held ) + move->y = -1.f; + p->input.left_held = true; + } else { + if( p->input.left_held ) { + if( p->input.right_held ) + move->y = 1.f; + else + move->y = 0.f; + } + p->input.left_held = false; } - if( input.keys[(U8)'s'] ) { - wishmove = dir * -TICK_INTERVAL; + + if( input.keys[input.binds.right] ) { + if( !p->input.right_held ) + move->y = 1.f; + p->input.right_held = true; + } else { + if( p->input.right_held ) { + if( p->input.left_held ) + move->y = -1.f; + else + move->y = 0.f; + } + p->input.right_held = false; } +} + +void player_input( GAME_DATA* game, PLAYER* p ) { + if( !p ) + return; + + capture_mouse( p ); + capture_move_keys( p ); +} + +void player_move( GAME_DATA* game, PLAYER* p ) { + VEC2 move = p->input.move; + F32 yawrad = m_deg2rad( p->rot.y ); + + VEC3 wishdir = { + move.x * cosf( yawrad ) - move.y * sinf( yawrad ), + move.y * cosf( yawrad ) + move.x * sinf( yawrad ), + 0 + }; + VEC3 vel = wishdir * 70.f; + p->velocity = vel; + VEC3 wishmove = vel * TICK_INTERVAL; // todo : should never be false if( vec_len( wishmove ) > BSP_TRACE_EPSILON && game->state.map->bsp ) { BSP_TRACE tr{}; AABB aabb{}; - tr.in_start = *pos; - tr.in_end = *pos + wishmove * 2.f; + tr.in_start = p->pos; + tr.in_end = tr.in_start + wishmove; aabb.min = p->mins; aabb.max = p->maxs; bsp_trace( &tr, game->state.map->bsp, aabb ); if( !tr.hit ) - *pos += wishmove; - else - *pos += wishmove * tr.frac; + p->pos += wishmove; + else { + p->pos += wishmove * tr.frac; + } } } diff --git a/src/game/player.h b/src/game/player.h index 71b1c02..6617f01 100644 --- a/src/game/player.h +++ b/src/game/player.h @@ -1,8 +1,16 @@ #pragma once #include "object.h" +#include "camera.h" + struct PLAYER_INPUT { - + PLAYER_CAMERA cam; + struct PLAYER* pobj; + + // for nulls + U8 fwd_held{}, bk_held{}, left_held{}, right_held{}; + + VEC2 move; }; struct PLAYER : OBJECT { @@ -11,6 +19,8 @@ struct PLAYER : OBJECT { F32 fov{72.f}; F32 eyeoffset{40.f}; + PLAYER_INPUT input; + VEC3 mins; VEC3 maxs; @@ -19,4 +29,5 @@ struct PLAYER : OBJECT { extern PLAYER* player_create( VEC3 origin, F32 yaw ); extern void player_input( struct GAME_DATA* game, PLAYER* player ); +extern void player_move( struct GAME_DATA* game, PLAYER* player ); extern VEC3 player_get_view_pos( PLAYER* player ); diff --git a/src/util/input.cpp b/src/util/input.cpp index 7e94c47..225b696 100644 --- a/src/util/input.cpp +++ b/src/util/input.cpp @@ -27,8 +27,8 @@ void input_on_event( SDL_Event* e ) { case SDL_MOUSEMOTION: { input.mouse.pos.x = (F32)e->motion.x; input.mouse.pos.y = (F32)e->motion.y; - input.mouse.pos_delta.x = (F32)e->motion.xrel; - input.mouse.pos_delta.y = (F32)e->motion.yrel; + input.mouse.pos_delta.x += (F32)e->motion.xrel; + input.mouse.pos_delta.y += (F32)e->motion.yrel; } break; case SDL_KEYDOWN: { input.keys[e->key.keysym.sym & 0xff] = 1; @@ -39,6 +39,10 @@ void input_on_event( SDL_Event* e ) { } } +extern void input_reset_mouse_accumulator() { + input.mouse.pos_delta.x = 0; + input.mouse.pos_delta.y = 0; +} void input_on_mouse( I32 type, I32 x, I32 y ) { if( type == MOUSEEV_MOVE ) { @@ -73,11 +77,10 @@ void input_on_mouse( I32 type, I32 x, I32 y ) { void input_frame_end() { input.mouse.wheel = 0; - input.mouse.pos_delta.x = 0; - input.mouse.pos_delta.y = 0; } void input_capture_mouse( bool capture ) { + input_reset_mouse_accumulator(); input.mouse_captured = capture; SDL_SetRelativeMouseMode( capture ? SDL_TRUE : SDL_FALSE ); } diff --git a/src/util/input.h b/src/util/input.h index 4885f0f..ec901ab 100644 --- a/src/util/input.h +++ b/src/util/input.h @@ -23,15 +23,27 @@ struct MOUSE_DATA { U8 wheel; }; +struct INPUT_KEYBINDS { + U8 fwd = 'w'; + U8 back = 's'; + U8 left = 'a'; + U8 right = 'd'; + + U8 jump = ' '; + U8 crouch = SDL_SCANCODE_LCTRL; +}; + using ON_INPUT_FN = std::function; struct INPUT_DATA { MOUSE_DATA mouse; U8 keys[0xff]; bool mouse_captured; - F32 mouse_sensitivity = 1.0f; + F32 mouse_sensitivity = .3f; + INPUT_KEYBINDS binds; LIST on_input; + }; extern INPUT_DATA input; @@ -41,5 +53,6 @@ extern void input_on_event( SDL_Event* e ); extern void input_on_mouse( I32 type, I32 x, I32 y ); extern void input_is_key_down( U32 key ); extern void input_capture_mouse( bool capture ); +extern void input_reset_mouse_accumulator(); #define kb_down( key ) input_is_key_down( key ) -- cgit v1.2.3 From db702f3197fadf8529789303a472f503100c715c Mon Sep 17 00:00:00 2001 From: navewindre Date: Thu, 2 Oct 2025 06:13:17 +0200 Subject: fix --- src/game/world/trace.cpp | 4 +--- src/util/aabb.h | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp index b3a0041..c8ad3be 100644 --- a/src/game/world/trace.cpp +++ b/src/game/world/trace.cpp @@ -200,9 +200,7 @@ inline U8 point_in_inflated_poly( in = in * -1.0f; F32 dist = vec_dot( point - a, in ); - VEC2 feet = aabb_extend_at_feet( hull, in ); - F32 pos_r = feet.x, neg_r = feet.y; - F32 expand = norm.z >= 0 ? neg_r : pos_r; + F32 expand = aabb_extend_at_feet( hull, in ).x; if( dist < -expand - BSP_TRACE_EPSILON ) return 0; } diff --git a/src/util/aabb.h b/src/util/aabb.h index f2fd251..4d74c88 100644 --- a/src/util/aabb.h +++ b/src/util/aabb.h @@ -14,6 +14,7 @@ inline F32 aabb_support_radius( const AABB& aabb, const VEC3& dir ) { return fabsf(dir.x) * half.x + fabsf(dir.y) * half.y + fabsf(dir.z) * half.z; } +// returns positive radius in X and negative in Y inline VEC2 aabb_extend_at_feet( const AABB& aabb, const VEC3& dir ) { VEC3 half = aabb_half( aabb ); -- cgit v1.2.3 From 8f978c8bc5b9ab17316cdc01caaee9b9d62d683e Mon Sep 17 00:00:00 2001 From: navewindre Date: Thu, 2 Oct 2025 06:26:57 +0200 Subject: fix2 --- src/game/player.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/game/player.cpp b/src/game/player.cpp index 26c03af..c4b9c9a 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -147,6 +147,15 @@ void player_move( GAME_DATA* game, PLAYER* p ) { p->pos += wishmove; else { p->pos += wishmove * tr.frac; + + + // TODO: clipvelocity fixes this, clips velocity to 1 wall (should do 4) + VEC3 left = wishmove * (1.f - tr.frac); + F32 into = vec_dot( left, tr.normal ); + if( into < 0.f ) + left -= tr.normal * into; + + p->pos += left; } } } -- cgit v1.2.3 From 5c8bbc3bc618068af1f7d6f2829c4346570c2ab9 Mon Sep 17 00:00:00 2001 From: Kasullian Date: Thu, 2 Oct 2025 01:21:37 -0400 Subject: fix shader tm --- assets/shaders/2d_texcoord.fsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/shaders/2d_texcoord.fsh b/assets/shaders/2d_texcoord.fsh index cbb9be0..38dc69c 100644 --- a/assets/shaders/2d_texcoord.fsh +++ b/assets/shaders/2d_texcoord.fsh @@ -12,7 +12,7 @@ void main() { vec4 color = g_color; if( g_sampler != SAMPLER_ID_NONE ) { vec4 tex_color = texture2D( g_samplers[g_sampler], g_texcoord ); - color.a = g_color.a * tex_color.a; + color *= tex_color; if (color.a < 0.01) discard; } gl_FragColor = color; -- cgit v1.2.3 From e3de3ba5162f7ddd5005911124d4333e140fd984 Mon Sep 17 00:00:00 2001 From: navewindre Date: Thu, 27 Nov 2025 17:19:02 +0100 Subject: bunch o stuff --- src/editor/editor.h | 6 ++- src/editor/gui.cpp | 39 -------------- src/editor/view2d.cpp | 144 ++++++++++++++++++++++++++++++++++++++++++++++++- src/editor/view3d.cpp | 13 +++-- src/game/assets.cpp | 5 +- src/game/player.cpp | 6 +-- src/game/world/bsp.cpp | 89 ++++++++++++++++++++++++++++-- src/game/world/bsp.h | 5 ++ src/gui/base.h | 1 + src/render/gl.cpp | 17 +++--- src/render/gl_2d.cpp | 16 ++++-- src/util/allocator.h | 18 ++++++- src/util/input.cpp | 10 ++-- src/util/input.h | 8 +-- 14 files changed, 300 insertions(+), 77 deletions(-) diff --git a/src/editor/editor.h b/src/editor/editor.h index 0bf2ab4..a4b1f1a 100644 --- a/src/editor/editor.h +++ b/src/editor/editor.h @@ -70,9 +70,13 @@ extern void editor_load_map_cb( void* ); extern void editor_new_map_cb( void* ); extern void editor_create_map_view( GAME_EDITOR* e ); +extern void editor_update_properties_column( GAME_EDITOR* e ); struct GUI_EDITORWINDOW : GUI_WINDOW {}; -struct GUI_EDITOR_3DVIEW : GUI_VIEW {}; +struct GUI_EDITOR_3DVIEW : GUI_VIEW { + U8 heldoutbounds; +}; + struct GUI_EDITOR_2DVIEW : GUI_VIEW { F32 scale; F32 posx, posy; diff --git a/src/editor/gui.cpp b/src/editor/gui.cpp index 71ce113..94967cc 100644 --- a/src/editor/gui.cpp +++ b/src/editor/gui.cpp @@ -121,48 +121,9 @@ void editor_create_tools_row( GAME_EDITOR* e ) { editor_update_active_tool_label( e ); } -void editor_update_view_settings( GAME_EDITOR* e ) { - GAME_EDITOR::EDITOR_GUI* egui = &e->gui; - - sprintf( egui->gridlabel->name, "grid size: %1.2f", e->grid ); -} - -void editor_grid_increment_cb( void* ) { - if( editor->grid < 16.f ) editor->grid *= 2.f; - editor_update_view_settings( editor ); - - if( editor->propgrid ) - editor_update_properties_column( editor ); -} - -void editor_grid_decrement_cb( void* ) { - if( editor->grid > 0.25f ) editor->grid *= 0.5f; - editor_update_view_settings( editor ); - - if( editor->propgrid ) - editor_update_properties_column( editor ); -} - -void editor_grid_propgrid_cb( void* ) { - editor_update_properties_column( editor ); -} - void editor_create_view_settings_row( GAME_EDITOR* e ) { I32 x = 320, y = 426; - gui_label( x, y, "view settings:" ); x += 95; - editor->gui.gridlabel = gui_label( x, y, "grid size: %1.2f", e->grid ); - x += 95; - gui_button( x, y, 20, 20, "+", editor_grid_increment_cb ); - gui_button( x + 25, y, 20, 20, "-", editor_grid_decrement_cb ); - x += 55; - GUI_CHECKBOX* check = gui_checkbox( x, y, "properties grid", &e->propgrid ); - check->cb = editor_grid_propgrid_cb; - x += 120; - gui_checkbox( x, y, "wireframe", &e->wireframe ); - - x = 320; - y = 440; gui_button( x, y, 100, 20, "compile bsp", pfn( void* b ) { if( editor->map->bsp ) bsp_free( editor->map->bsp ); diff --git a/src/editor/view2d.cpp b/src/editor/view2d.cpp index 35fd208..1445cfc 100644 --- a/src/editor/view2d.cpp +++ b/src/editor/view2d.cpp @@ -1,12 +1,13 @@ #include #include "editor.h" #include "../render/gl_2d.h" - #include "../game/objlist.h" +#include "../game/world/bsp.h" const I32 EDITORVIEW_TITLE_OFFSET = 15; const I32 EDITORVIEW_GUTTERS_OFFSETX = 22; const I32 EDITORVIEW_GUTTERS_OFFSETY = 16; +const I32 EDITORVIEW_TOOLBAR_OFFSET = 20; F32 gui_editor_2dview_calc_scale( GUI_EDITOR_2DVIEW* view ) { WORLD_MAP* m = editor->map; @@ -337,13 +338,23 @@ void gui_editor_2dview_draw_fn( void* ptr ) { U32 offx = EDITORVIEW_GUTTERS_OFFSETX; U32 offy = EDITORVIEW_GUTTERS_OFFSETY; - gui_draw_push_clip( x + offx, y + offy, w - offx, h - offy ); + gui_draw_push_clip( x + offx, y + offy, w - offx, h - offy - EDITORVIEW_TOOLBAR_OFFSET ); gui_editor_2dview_draw_polygons( view, x + offx, y + offy ); gui_editor_2dview_draw_walls( view, x + offx, y + offy ); gui_editor_2dview_draw_sprites( view, x + offx, y + offy ); gui_editor_2dview_draw_player( view, x + offx, y + offy ); gui_editor_2dview_draw_origin( view, x + offx, y + offy ); gui_draw_pop_clip(); + + gui_draw_push_clip( x, y + 16, view->w, view->h ); + view->children.each( fn( GUI_BASE** childptr ) { + GUI_BASE* child = *childptr; + if( !child->enabled ) return; + + if( child->draw_fn ) child->draw_fn( child ); + else dlog( "gui_view_draw_fn(): child %p no draw_fn\n", child ); + } ); + gui_draw_pop_clip(); } U8 gui_editor_2dview_input_drag( GUI_EDITOR_2DVIEW* view, U8 mouse ) { @@ -876,11 +887,91 @@ void gui_editor_2dview_input_tool_draw( GUI_EDITOR_2DVIEW* view ) { } } +void gui_editor_view2d_delete_obj( GUI_EDITOR_2DVIEW* view ) { + void* it; + U8 type; + + if( view->curdrag && view->dragtype ) { + it = view->curdrag; + type = view->dragtype; + view->curdrag = 0; + view->dragtype = EDITOR_SELECT_NONE; + } else if( editor->gui.props->curselect ) { + it = editor->gui.props->curselect; + type = editor->gui.props->seltype; + view->curselect = 0; + view->seltype = EDITOR_SELECT_NONE; + } + else return; + + U8 cleared = 1; + switch( type ) { + case EDITOR_SELECT_POLY: { + I32 idx = editor->map->polygons.idx_of( (MAP_POLYGON*)it ); + if( idx != -1 ) + editor->map->polygons.erase( idx ); + } break; + case EDITOR_SELECT_WALL: { + I32 idx = editor->map->walls.idx_of( (MAP_WALL*)it ); + if( idx != -1 ) + editor->map->walls.erase( idx ); + }; break; + case EDITOR_SELECT_SPRITE: { + I32 idx = editor->map->sprites.idx_of( (MAP_SPRITE*)it ); + if( idx != -1 ) + editor->map->sprites.erase( idx ); + }; break; + case EDITOR_SELECT_PVERTEX: { + I32 vidx = -1, idx = editor->map->polygons.idx_where( fn( MAP_POLYGON* p ) { + vidx = p->vertices.idx_where( fn( MAP_VERTEX* v ) { + return v == it; + } ); + return vidx != -1; + } ); + + if( idx != -1 && vidx != -1 ) { + MAP_POLYGON* p = &editor->map->polygons[idx]; + if( p->vertices.size <= 3 ) { + editor->map->polygons.erase( idx ); + break; + } + editor->map->polygons[idx].vertices.erase( vidx ); + } + }; break; + case EDITOR_SELECT_WVERTEX: { + I32 idx = editor->map->walls.idx_where( fn( MAP_WALL* w ) { + return &w->end == it || &w->start == it; + } ); + + if( idx != -1 ) + editor->map->walls.erase( idx ); + }; break; + default: + cleared = 0; break; + } + + if( cleared && it == editor->gui.props->curselect ) { + gui_editor_propview_select( editor->gui.props, 0, 0 ); + } +} + +void gui_editor_2dview_key_input( GUI_EDITOR_2DVIEW* view ) { + static U8 del_held = 0; + if( kb_down( SDLK_DELETE ) && !input.mouselock ) { + if( !del_held ) + gui_editor_view2d_delete_obj( view ); + + del_held = 1; + } else del_held = 0; +} + void gui_editor_2dview_input_fn( void* ptr ) { GUI_EDITOR_2DVIEW* view = (GUI_EDITOR_2DVIEW*)ptr; if( !editor->map ) return; + gui_editor_2dview_key_input( view ); + I32 x = gui_relx( view ); I32 y = gui_rely( view ) + EDITORVIEW_TITLE_OFFSET; I32 w = view->w; @@ -902,6 +993,10 @@ void gui_editor_2dview_input_fn( void* ptr ) { if( view->heldoutbounds ) return; + gui_base_input_fn( view ); + if( my >= y + h - 18 ) + return; + switch( editor->tool ) { case EDITOR_TOOL_SELECT: return gui_editor_2dview_input_tool_select( view ); case EDITOR_TOOL_WALL: @@ -913,6 +1008,47 @@ void gui_editor_2dview_input_fn( void* ptr ) { } } +void update_view_settings( GAME_EDITOR* e ) { + GAME_EDITOR::EDITOR_GUI* egui = &e->gui; + + sprintf( egui->gridlabel->name, "grid: %1.2f", e->grid ); +} + +void grid_increment_cb( void* ) { + if( editor->grid < 16.f ) editor->grid *= 2.f; + update_view_settings( editor ); + + if( editor->propgrid ) + editor_update_properties_column( editor ); +} + +void grid_decrement_cb( void* ) { + if( editor->grid > 0.25f ) editor->grid *= 0.5f; + update_view_settings( editor ); + + if( editor->propgrid ) + editor_update_properties_column( editor ); +} + +void grid_propgrid_cb( void* ) { + editor_update_properties_column( editor ); +} + +void gui_editor_2dview_create_toolbar( GUI_EDITOR_2DVIEW* view ) { + GAME_EDITOR* e = editor; + I32 x = 150, y = view->h - 4; + + editor->gui.gridlabel = gui_label( x, y + 1, "grid: %1.2f", e->grid ); + x += 70; + gui_button( x, y, 18, 18, "+", grid_increment_cb ); + gui_button( x + 23, y, 18, 18, "-", grid_decrement_cb ); + x += 50; + GUI_CHECKBOX* check = gui_checkbox( x, y, "properties grid", &e->propgrid ); + check->cb = grid_propgrid_cb; + x += 120; + gui_checkbox( x, y, "wireframe", &e->wireframe ); +} + GUI_EDITOR_2DVIEW* gui_editor_2dview( I32 x, I32 y, I32 w, I32 h ) { GUI_EDITOR_2DVIEW* view = new GUI_EDITOR_2DVIEW; view->x = x; @@ -934,5 +1070,9 @@ GUI_EDITOR_2DVIEW* gui_editor_2dview( I32 x, I32 y, I32 w, I32 h ) { parent->children.push( view ); view->parent = parent; + gui_set_view( view ); + gui_editor_2dview_create_toolbar( view ); + gui_set_view( (GUI_VIEW*)parent ); + return view; } diff --git a/src/editor/view3d.cpp b/src/editor/view3d.cpp index 61bcc3e..64cfe85 100644 --- a/src/editor/view3d.cpp +++ b/src/editor/view3d.cpp @@ -32,7 +32,7 @@ void gui_editor_3dview_draw_showpos( GUI_EDITOR_3DVIEW* view ) { objl->pl->rot.x ); - if( input.mouse_captured ) { + if( input.mouselock ) { gui_draw_str( x + 2, y + 2, ALIGN_L, @@ -65,7 +65,7 @@ void gui_editor_3dview_draw_fn( void* ptr ) { bsp_draw( editor->map->bsp, editor->game, wnd, winsize ); else world_draw( editor->game, objl->world, wnd, winsize ); - + gui_editor_3dview_draw_showpos( view ); } @@ -75,14 +75,17 @@ void gui_editor_3dview_input_fn( void* ptr ) { if( !objl->pl ) return; - if( input.mouse.left && !input.mouse_captured ) { + if( input.mouse.left ) { I32 view_x = gui_relx( view ); I32 view_y = gui_rely( view ) + EDITORVIEW_TITLE_OFFSET; if( input.mouse.pos.x >= view_x && input.mouse.pos.x < view_x + view->w && input.mouse.pos.y >= view_y && input.mouse.pos.y < view_y + view->h ) { - input_capture_mouse( true ); + if( !input.mouselock && !view->heldoutbounds ) + input_capture_mouse( true ); + } else { + view->heldoutbounds = 1; } - } + } else view->heldoutbounds = 0; game_on_tick( editor->game ); } diff --git a/src/game/assets.cpp b/src/game/assets.cpp index 7d755c0..62663a9 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -3,8 +3,11 @@ #include "../game.h" #include "../render/gl_2d_font.h" +#include "../util/stb_image.h" +#include "../util/anim.h" + void assets_init( GAME_DATA *game ) { - game->assets.test = gl_texture_create( game->gl, "assets/test.png" ); + game->assets.test = gl_texture_from_file( game->gl, "uvtest.png" ); game->assets.fonts_init = 0; } diff --git a/src/game/player.cpp b/src/game/player.cpp index c4b9c9a..51d1cf8 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -38,9 +38,9 @@ void capture_mouse( PLAYER* p ) { input_capture_mouse( false ); } - if( input.mouse_captured ) { - *yaw += input.mouse.pos_delta.x * input.mouse_sensitivity; - *pitch -= input.mouse.pos_delta.y * input.mouse_sensitivity; + if( input.mouselock ) { + *yaw += input.mouse.pos_delta.x * input.msens; + *pitch -= input.mouse.pos_delta.y * input.msens; if( *pitch > 89.f ) *pitch = 89.f; if( *pitch < -89.f ) *pitch = -89.f; diff --git a/src/game/world/bsp.cpp b/src/game/world/bsp.cpp index 9aa94d7..a95a693 100644 --- a/src/game/world/bsp.cpp +++ b/src/game/world/bsp.cpp @@ -637,7 +637,89 @@ U8 pvs_get( BSP_BITSET* pvs, U32 count, U32 cluster, U32 seen ) { U32 w = seen / 32, b = seen % 32; if( base + w >= pvs->size ) return 0; - return ( pvs->data[base + w] >> b) & 1u; + return (pvs->data[base + w] >> b) & 1u; +} + +void bsp_build_pvs( BSP* bsp ) { + U32 nclusters = bsp->leaves.size; + bsp->pvs_bits.clear(); + bsp->clusters.clear(); + bsp->clusters.reserve( nclusters ); + + LIST> leaf_portals; + leaf_portals.resize( nclusters ); + + for( U32 i = 0; i < bsp->portals.size; ++i ) { + BSP_PORTAL* p = &bsp->portals.data[i]; + I32 lf = bsp_leaf_index( p->front ); + I32 rf = bsp_leaf_index( p->back ); + + leaf_portals.data[lf].push( i ); + leaf_portals.data[rf].push( i ); + } + + for( U32 i = 0; i < nclusters; ++i ) { + BSP_CLUSTER* c = &bsp->clusters.data[i]; + c->first = 0; + c->count = 0; + c->pvs_off = 0; + } + + for( U32 from = 0; from < nclusters; ++from ) { + LIST* plist = &leaf_portals.data[from]; + pvs_set( &bsp->pvs_bits, nclusters, from, from ); + + LIST queue; + for( U32 i = 0; i < plist->size; ++i ) { + I32 pid = plist->data[i]; + BSP_PORTAL* p = &bsp->portals.data[pid]; + + BSP_PORTAL_QUEUE it{ + .front = (I32)from, + .frustum = p->w + }; + + queue.push( it ) ; + } + + while( queue.size ) { + BSP_PORTAL_QUEUE it = queue.pop(); + LIST* plist = &leaf_portals.data[it.front]; + + for( U32 i = 0; plist->size; ++i ) { + BSP_PORTAL* p = &bsp->portals.data[plist->data[i]]; + I32 lf = bsp_leaf_index( p->front ); + I32 lb = bsp_leaf_index( p->back ); + + I32 neighbor = (lf == it.front) ? lb : (lb == it.front) ? lf : -1; + if( neighbor < 0 ) + continue; + + BSP_WINDING next_w; + if( !bsp_winding_intersect_plane( &p->plane, &it.frustum, &p->w, &next_w ) ) + continue; + + if( !pvs_get( &bsp->pvs_bits, nclusters, from, (U32)neighbor ) ) { + pvs_set( &bsp->pvs_bits, nclusters, from, (U32)neighbor ); + + LIST* nbr_plist = &leaf_portals.data[neighbor]; + for( U32 i2 = 0; i2 < nbr_plist->size; ++i2 ) { + BSP_PORTAL* nbr_p = &bsp->portals.data[nbr_plist->data[i2]]; + if( nbr_p == p ) + continue; + + BSP_WINDING clipped = next_w; + if( bsp_winding_intersect_plane( &nbr_p->plane, &clipped, &nbr_p->w, &clipped ) ) { + BSP_PORTAL_QUEUE n{}; + n.front = neighbor; + n.frustum = clipped; + queue.push( n ); + } + } + } + } + } + } } BSP* bsp_build_map( WORLD_MAP* m ) { @@ -647,12 +729,13 @@ BSP* bsp_build_map( WORLD_MAP* m ) { LIST planes = bsp_map_get_planes( m ); bsp->root = bsp_build_nodes( bsp, planes, faces, 0 ); - U32 vertc = 0; - m->polygons.each( fn( MAP_POLYGON* p ) { vertc += p->vertices.size; } ); for( U32 i = 0; i < bsp->faces.size; ++i ) { bsp->faces.data[i].id = i; } bsp_gen_render_vertices( bsp ); + + bsp_build_portals( bsp ); + bsp_build_pvs( bsp ); return bsp; } diff --git a/src/game/world/bsp.h b/src/game/world/bsp.h index 439fce1..457bcb9 100644 --- a/src/game/world/bsp.h +++ b/src/game/world/bsp.h @@ -71,6 +71,11 @@ struct BSP_PORTAL_NODE { BSP_WINDING w; }; +struct BSP_PORTAL_QUEUE { + I32 front; + BSP_WINDING frustum; +}; + struct BSP_BITSET : public LIST {}; struct BSP { diff --git a/src/gui/base.h b/src/gui/base.h index 96e0fa5..7b95d34 100644 --- a/src/gui/base.h +++ b/src/gui/base.h @@ -115,6 +115,7 @@ typedef void( *GUI_DRAW_FN )( void* el ); typedef void( *GUI_INPUT_FN )( void* el ); extern void gui_base_input_fn( void* ); +extern void gui_view_draw_fn( void* ); struct GUI_BASE { I32 x{}, y{}; diff --git a/src/render/gl.cpp b/src/render/gl.cpp index 382d81e..e44a165 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -276,7 +276,7 @@ GL_TEX2D* gl_texture_from_file( GL_DATA* gl, const char* name ) { return tex; } -GL_TEX2D* gl_texture_from_bitmap( GL_DATA* gl, const char* name, U8* bitmap, U32 width, U32 height ) { +GL_TEX2D* gl_texture_from_bitmap( GL_DATA* gl, const char* name, U8* bitmap, U32 w, U32 h ) { GL_TEX2D* tex = gl_texture_create( gl, name ); glBindTexture( GL_TEXTURE_2D, tex->id ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); @@ -284,18 +284,13 @@ GL_TEX2D* gl_texture_from_bitmap( GL_DATA* gl, const char* name, U8* bitmap, U32 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - tex->width = width; - tex->height = height; - - glTexImage2D( - GL_TEXTURE_2D, - 0, GL_RGBA, - (I32)width, (I32)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, bitmap - ); - + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap ); + glGenerateMipmap( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, 0 ); + tex->width = w; + tex->height = h; + return tex; } diff --git a/src/render/gl_2d.cpp b/src/render/gl_2d.cpp index 1803eb5..78af1da 100644 --- a/src/render/gl_2d.cpp +++ b/src/render/gl_2d.cpp @@ -104,25 +104,33 @@ void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TE glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_DYNAMIC_DRAW ); + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); + glEnableVertexAttribArray( position ); glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); - I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); - I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); - I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); + glEnableVertexAttribArray( sampler ); glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, texture->id ); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, texture->id ); - glUniform1f( glGetUniformLocation( gl2d->id, "in_time" ), u_time() ); + // glUniform1f( glGetUniformLocation( gl2d->id, "in_time" ), u_time() ); glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); glBindTexture( GL_TEXTURE_2D, 0 ); diff --git a/src/util/allocator.h b/src/util/allocator.h index 7927b9c..27b21c0 100644 --- a/src/util/allocator.h +++ b/src/util/allocator.h @@ -165,8 +165,12 @@ struct LIST { if( size > capacity ) reserve( size * 2 ); - if( size < capacity ) { - for( U32 i = size; i < capacity; ++i ) + if( size < capacity / 4 ) + shrink(); + + if( this->size < size ) { + memset( &data[this->size], 0, sizeof(T) * (size - this->size) ); + for( U32 i = this->size; i < size; ++i ) data[i] = T(); } @@ -262,6 +266,16 @@ struct LIST { return -1; } + I32 idx_of( const T* what ) { + for( U32 i = 0; i < size; ++i ) { + if( &data[i] == what ) { + return i; + } + } + + return -1; + } + I32 idx_where( ON_SEARCH_FN what ) { for( U32 i = 0; i < size; ++i ) { if( what( &data[i] ) ) { diff --git a/src/util/input.cpp b/src/util/input.cpp index 225b696..284ebfe 100644 --- a/src/util/input.cpp +++ b/src/util/input.cpp @@ -27,8 +27,8 @@ void input_on_event( SDL_Event* e ) { case SDL_MOUSEMOTION: { input.mouse.pos.x = (F32)e->motion.x; input.mouse.pos.y = (F32)e->motion.y; - input.mouse.pos_delta.x += (F32)e->motion.xrel; - input.mouse.pos_delta.y += (F32)e->motion.yrel; + input.mouse.pos_delta.x += (F32)e->motion.xrel * input.mpitch; + input.mouse.pos_delta.y += (F32)e->motion.yrel * input.myaw; } break; case SDL_KEYDOWN: { input.keys[e->key.keysym.sym & 0xff] = 1; @@ -79,8 +79,12 @@ void input_frame_end() { input.mouse.wheel = 0; } +U8 input_is_key_down( U32 key ) { + return input.keys[key]; +} + void input_capture_mouse( bool capture ) { input_reset_mouse_accumulator(); - input.mouse_captured = capture; + input.mouselock = capture; SDL_SetRelativeMouseMode( capture ? SDL_TRUE : SDL_FALSE ); } diff --git a/src/util/input.h b/src/util/input.h index ec901ab..86d715c 100644 --- a/src/util/input.h +++ b/src/util/input.h @@ -38,8 +38,10 @@ using ON_INPUT_FN = std::function; struct INPUT_DATA { MOUSE_DATA mouse; U8 keys[0xff]; - bool mouse_captured; - F32 mouse_sensitivity = .3f; + bool mouselock; + F32 msens = .3f; + F32 myaw = 1.f; + F32 mpitch = 1.f; INPUT_KEYBINDS binds; LIST on_input; @@ -51,7 +53,7 @@ extern INPUT_DATA input; extern void input_frame_end(); extern void input_on_event( SDL_Event* e ); extern void input_on_mouse( I32 type, I32 x, I32 y ); -extern void input_is_key_down( U32 key ); +extern U8 input_is_key_down( U32 key ); extern void input_capture_mouse( bool capture ); extern void input_reset_mouse_accumulator(); -- cgit v1.2.3 From 3e094f20d4dda90e0356aba3f0abc4b7c7015844 Mon Sep 17 00:00:00 2001 From: navewindre Date: Thu, 27 Nov 2025 21:39:59 +0100 Subject: move bsp button --- src/editor/gui.cpp | 13 ------------- src/editor/view3d.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/editor/gui.cpp b/src/editor/gui.cpp index 94967cc..1060c00 100644 --- a/src/editor/gui.cpp +++ b/src/editor/gui.cpp @@ -121,18 +121,6 @@ void editor_create_tools_row( GAME_EDITOR* e ) { editor_update_active_tool_label( e ); } -void editor_create_view_settings_row( GAME_EDITOR* e ) { - I32 x = 320, y = 426; - - gui_button( x, y, 100, 20, "compile bsp", pfn( void* b ) { - if( editor->map->bsp ) - bsp_free( editor->map->bsp ); - editor->map->bsp = bsp_build_map( editor->map ); - } ); x += 110; - - gui_checkbox( x, y, "draw bsp", &e->drawbsp ); -} - void editor_create_map_view( GAME_EDITOR* e ) { if( !e->map ) { dlog( "editor_create_map_views() : no map loaded\n" ); @@ -153,7 +141,6 @@ void editor_create_map_view( GAME_EDITOR* e ) { editor_create_properties_column( e ); editor_create_game_view_column( e ); editor_create_tools_row( e ); - editor_create_view_settings_row( e ); } void close_new_map_popup( void* ) { diff --git a/src/editor/view3d.cpp b/src/editor/view3d.cpp index 64cfe85..f8d1def 100644 --- a/src/editor/view3d.cpp +++ b/src/editor/view3d.cpp @@ -6,6 +6,7 @@ #include "../game.h" const I32 EDITORVIEW_TITLE_OFFSET = 15; +const I32 EDITORVIEW_TOOLBAR_OFFSET = 20; void gui_editor_3dview_draw_showpos( GUI_EDITOR_3DVIEW* view ) { I32 x = gui_relx( view ); @@ -66,11 +67,22 @@ void gui_editor_3dview_draw_fn( void* ptr ) { else world_draw( editor->game, objl->world, wnd, winsize ); + gui_draw_push_clip( x, y, view->w, view->h ); + view->children.each( fn( GUI_BASE** childptr ) { + GUI_BASE* child = *childptr; + if( !child->enabled ) return; + + if( child->draw_fn ) child->draw_fn( child ); + else dlog( "gui_view_draw_fn(): child %p no draw_fn\n", child ); + } ); + gui_draw_pop_clip(); gui_editor_3dview_draw_showpos( view ); } void gui_editor_3dview_input_fn( void* ptr ) { GUI_EDITOR_3DVIEW* view = (GUI_EDITOR_3DVIEW*)ptr; + if( !input.mouselock ) + gui_base_input_fn( view ); if( !objl->pl ) return; @@ -79,7 +91,7 @@ void gui_editor_3dview_input_fn( void* ptr ) { I32 view_x = gui_relx( view ); I32 view_y = gui_rely( view ) + EDITORVIEW_TITLE_OFFSET; if( input.mouse.pos.x >= view_x && input.mouse.pos.x < view_x + view->w && - input.mouse.pos.y >= view_y && input.mouse.pos.y < view_y + view->h ) { + input.mouse.pos.y >= view_y && input.mouse.pos.y < view_y + view->h - EDITORVIEW_TOOLBAR_OFFSET ) { if( !input.mouselock && !view->heldoutbounds ) input_capture_mouse( true ); } else { @@ -90,6 +102,19 @@ void gui_editor_3dview_input_fn( void* ptr ) { game_on_tick( editor->game ); } +void gui_editor_3dview_create_toolbar( GUI_EDITOR_3DVIEW* view ) { + GAME_EDITOR* e = editor; + I32 x = 1, y = view->h - 4; + + gui_button( x, y, 90, 18, "compile bsp", pfn( void* b ) { + if( editor->map->bsp ) + bsp_free( editor->map->bsp ); + editor->map->bsp = bsp_build_map( editor->map ); + } ); x += 100; + + gui_checkbox( x, y, "draw bsp", &e->drawbsp ); +} + GUI_EDITOR_3DVIEW* gui_editor_3dview( I32 x, I32 y, I32 w, I32 h ) { GUI_EDITOR_3DVIEW* view = new GUI_EDITOR_3DVIEW; view->x = x; @@ -108,5 +133,10 @@ GUI_EDITOR_3DVIEW* gui_editor_3dview( I32 x, I32 y, I32 w, I32 h ) { parent->children.push( view ); view->parent = parent; + + gui_set_view( view ); + gui_editor_3dview_create_toolbar( view ); + gui_set_view( (GUI_VIEW*)parent ); + return view; } -- cgit v1.2.3