Raycasting character controller
This commit is contained in:
parent
da59158fd1
commit
9478bca2ad
99
src/game.c
99
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) {
|
static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||||
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
||||||
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
|
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};
|
vec3 n = {0, 1, 0};
|
||||||
glm_quat_rotatev(q, n, n);
|
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) {
|
if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) {
|
||||||
struct CMovement *m = game_getcomponent(e1, movement);
|
struct CMovement *m = game_getcomponent(e1, movement);
|
||||||
if(m) {
|
if(m) {
|
||||||
if(m->holding != ENT_ID_INVALID && m->holding == e2) {
|
if(m->holding != ENT_ID_INVALID && m->holding == e2) {
|
||||||
ghost = 1;
|
ghost = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->canJump = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(c->trigger != TRIGGER_INVALID) {
|
if(c->trigger != TRIGGER_INVALID) {
|
||||||
Game.triggers[c->trigger - 1](c->trigger, e1, e2, triggerType);
|
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};
|
vec3 n = {0, -1, 0};
|
||||||
glm_quat_rotatev(q, n, n);
|
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) {
|
if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) {
|
||||||
struct CMovement *m = game_getcomponent(e2, movement);
|
struct CMovement *m = game_getcomponent(e2, movement);
|
||||||
if(m) {
|
if(m) {
|
||||||
if(m->holding != ENT_ID_INVALID && m->holding == e1) {
|
if(m->holding != ENT_ID_INVALID && m->holding == e1) {
|
||||||
ghost = 1;
|
ghost = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->canJump = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(c->trigger != TRIGGER_INVALID) {
|
if(c->trigger != TRIGGER_INVALID) {
|
||||||
Game.triggers[c->trigger - 1](c->trigger, e2, e1, triggerType);
|
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() {
|
void game_update() {
|
||||||
|
game_character_controller_raycast();
|
||||||
|
|
||||||
for(size_t i = 0; i < Game.entities.playerctrlCount; i++) {
|
for(size_t i = 0; i < Game.entities.playerctrlCount; i++) {
|
||||||
struct CPlayerCtrl *cc = &Game.entities.playerctrl[i];
|
struct CPlayerCtrl *cc = &Game.entities.playerctrl[i];
|
||||||
|
|
||||||
@ -528,6 +607,8 @@ void game_update() {
|
|||||||
if(glm_vec3_norm(wishvel) > 3) {
|
if(glm_vec3_norm(wishvel) > 3) {
|
||||||
glm_vec3_scale_as(wishvel, 3, wishvel);
|
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));
|
float currentspeed = glm_vec3_dot(wishvel, dBodyGetLinearVel(bid));
|
||||||
|
@ -88,6 +88,7 @@ struct CMovement {
|
|||||||
vec3 dir;
|
vec3 dir;
|
||||||
float pointing;
|
float pointing;
|
||||||
char jump, canJump;
|
char jump, canJump;
|
||||||
|
vec3 groundNormal;
|
||||||
uint16_t holding;
|
uint16_t holding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,6 +227,7 @@ static int eng_init() {
|
|||||||
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
|
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt compatibility
|
||||||
if(!GameWnd) {
|
if(!GameWnd) {
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
|
||||||
@ -299,7 +300,7 @@ static void fix_resol() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void eng_ui_init() {
|
static void eng_ui_init() {
|
||||||
set_ui_mode(1);
|
set_ui_mode(!!UiActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fps_counter_step(double newDT) {
|
static void fps_counter_step(double newDT) {
|
||||||
@ -338,6 +339,7 @@ static int gr_shadowmap_init() {
|
|||||||
"!!ARBfp1.0\n"
|
"!!ARBfp1.0\n"
|
||||||
"TEMP col;\n"
|
"TEMP col;\n"
|
||||||
"TEX col, fragment.texcoord, texture[0], 2D;\n"
|
"TEX col, fragment.texcoord, texture[0], 2D;\n"
|
||||||
|
"MOV result.color, col;\n"
|
||||||
"MAD col.xyz, -col, 29.9, 30.1;\n"
|
"MAD col.xyz, -col, 29.9, 30.1;\n"
|
||||||
"RCP col.x, col.x;\n"
|
"RCP col.x, col.x;\n"
|
||||||
"RCP col.y, col.y;\n"
|
"RCP col.y, col.y;\n"
|
||||||
@ -393,7 +395,6 @@ int main(int argc_, char **argv_) {
|
|||||||
argv = argv_;
|
argv = argv_;
|
||||||
|
|
||||||
eng_init();
|
eng_init();
|
||||||
eng_ui_init();
|
|
||||||
|
|
||||||
gr_shadowmap_init();
|
gr_shadowmap_init();
|
||||||
gr_bloom_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");
|
luaapi_load(k4_get_arg("script") ? k4_get_arg("script") : "init");
|
||||||
//
|
//
|
||||||
|
|
||||||
|
eng_ui_init();
|
||||||
|
|
||||||
LuaapiStartTime = glfwGetTime();
|
LuaapiStartTime = glfwGetTime();
|
||||||
|
|
||||||
LastTime = glfwGetTime();
|
LastTime = glfwGetTime();
|
||||||
|
Loading…
Reference in New Issue
Block a user