diff --git a/src/game.c b/src/game.c index 8dd7d49..c381a58 100644 --- a/src/game.c +++ b/src/game.c @@ -97,6 +97,15 @@ static void tick_pairs() { } } +static void vec3_project_to_plane(vec3 v, vec3 n, vec3 ret) { + float scale = glm_vec3_dot(v, n) / glm_vec3_dot(n, n); + + vec3 n2; + glm_vec3_scale(n, scale, n2); + + glm_vec3_sub(v, n2, ret); +} + static void contact_callback(void *data, dGeomID g1, dGeomID g2) { uint16_t e1 = (uintptr_t) dGeomGetData(g1); uint16_t e2 = (uintptr_t) dGeomGetData(g2); @@ -197,19 +206,17 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) { vec3 n = {0, 1, 0}; glm_quat_rotatev(q, n, n); - if(!ghost) for(int i = 0; i < numc; i++) { + /*if(!ghost) for(int i = 0; i < numc; i++) { if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) { struct CMovement *m = game_getcomponent(e1, movement); if(m) { if(m->holding != ENT_ID_INVALID && m->holding == e2) { ghost = 1; } - - m->canJump = 1; break; } } - } + }*/ if(c->trigger != TRIGGER_INVALID) { Game.triggers[c->trigger - 1](c->trigger, e1, e2, triggerType); @@ -238,19 +245,16 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) { vec3 n = {0, -1, 0}; glm_quat_rotatev(q, n, n); - if(!ghost) for(int i = 0; i < numc; i++) { + /*if(!ghost) for(int i = 0; i < numc; i++) { if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) { struct CMovement *m = game_getcomponent(e2, movement); if(m) { if(m->holding != ENT_ID_INVALID && m->holding == e1) { ghost = 1; } - - m->canJump = 1; - break; } } - } + }*/ if(c->trigger != TRIGGER_INVALID) { Game.triggers[c->trigger - 1](c->trigger, e2, e1, triggerType); @@ -349,7 +353,82 @@ void game_raycast(struct LocalRay *rays, size_t count) { } } +static void game_character_controller_raycast_handler(void *data, dGeomID g1, dGeomID g2) { + if(dGeomGetClass(g1) != dRayClass && dGeomGetClass(g2) != dRayClass) { + return; + } + + dContact contact[1]; + memset(contact, 0, sizeof(contact)); + + int numc = dCollide(g1, g2, 1, &contact[0].geom, sizeof(dContact)); + + uint16_t e1 = (uintptr_t) dGeomGetData(g1); + uint16_t e2 = (uintptr_t) dGeomGetData(g2); + + if(numc) { + + vec3 n = {0, -1, 0}; + + if(dGeomGetClass(g1) == dRayClass) { + struct CMovement *cm = &Game.entities.movement[(uintptr_t) dGeomGetData(g1)]; + + if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) { + cm->canJump = 1; + glm_vec3_scale(contact[0].geom.normal, 1, cm->groundNormal); + } + + return; + } else if(dGeomGetClass(g2) == dRayClass) { + struct CMovement *cm = &Game.entities.movement[(uintptr_t) dGeomGetData(g2)]; + + if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) { + cm->canJump = 1; + glm_vec3_scale(contact[0].geom.normal, -1, cm->groundNormal); + } + + return; + } + + } +} +void game_character_controller_raycast() { + dGeomID rayGeoms[Game.entities.movementCount]; + + for(int i = 0; i < Game.entities.movementCount; i++) { + struct CPhysics *cp = game_getcomponent(Game.entities.movement[i].entity, physics); + + if(!cp || !cp->geom || cp->type != CPHYSICS_CAPSULE) { + rayGeoms[i] = NULL; + continue; + } + + rayGeoms[i] = dCreateRay(Game.space, 1); + + dGeomSetData(rayGeoms[i], (void*) (uintptr_t) i); + + dGeomSetCategoryBits(rayGeoms[i], CATEGORY_RAY); + dGeomSetCollideBits(rayGeoms[i], CATEGORY_STATIC | CATEGORY_ENTITY); + + dBodyID bid = dGeomGetBody(cp->geom); + + const float *position = dBodyGetPosition(bid); + + dGeomRaySet(rayGeoms[i], position[0], position[1] - cp->capsule.length / 2 + 0.5, position[2], 0, -1, 0); + } + + dSpaceCollide(Game.space, NULL, game_character_controller_raycast_handler); + + for(int i = 0; i < Game.entities.movementCount; i++) { + if(rayGeoms[i]) { + dGeomDestroy(rayGeoms[i]); + } + } +} + void game_update() { + game_character_controller_raycast(); + for(size_t i = 0; i < Game.entities.playerctrlCount; i++) { struct CPlayerCtrl *cc = &Game.entities.playerctrl[i]; @@ -528,6 +607,8 @@ void game_update() { if(glm_vec3_norm(wishvel) > 3) { glm_vec3_scale_as(wishvel, 3, wishvel); } + } else { + vec3_project_to_plane(wishvel, Game.entities.movement[mi].groundNormal, wishvel); } float currentspeed = glm_vec3_dot(wishvel, dBodyGetLinearVel(bid)); diff --git a/src/game.h b/src/game.h index 4a66259..592a23d 100644 --- a/src/game.h +++ b/src/game.h @@ -88,6 +88,7 @@ struct CMovement { vec3 dir; float pointing; char jump, canJump; + vec3 groundNormal; uint16_t holding; }; diff --git a/src/main.c b/src/main.c index b887ee9..7457231 100644 --- a/src/main.c +++ b/src/main.c @@ -227,6 +227,7 @@ static int eng_init() { GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL); } + // Attempt compatibility if(!GameWnd) { glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); @@ -299,7 +300,7 @@ static void fix_resol() { } static void eng_ui_init() { - set_ui_mode(1); + set_ui_mode(!!UiActive); } static void fps_counter_step(double newDT) { @@ -338,6 +339,7 @@ static int gr_shadowmap_init() { "!!ARBfp1.0\n" "TEMP col;\n" "TEX col, fragment.texcoord, texture[0], 2D;\n" + "MOV result.color, col;\n" "MAD col.xyz, -col, 29.9, 30.1;\n" "RCP col.x, col.x;\n" "RCP col.y, col.y;\n" @@ -393,7 +395,6 @@ int main(int argc_, char **argv_) { argv = argv_; eng_init(); - eng_ui_init(); gr_shadowmap_init(); gr_bloom_init(); @@ -413,6 +414,8 @@ int main(int argc_, char **argv_) { luaapi_load(k4_get_arg("script") ? k4_get_arg("script") : "init"); // + eng_ui_init(); + LuaapiStartTime = glfwGetTime(); LastTime = glfwGetTime();