Fix ray origin

This commit is contained in:
mid 2025-06-12 12:00:16 +03:00
parent 9478bca2ad
commit ce465ef449

View File

@ -161,7 +161,7 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
if(e1 != ENT_ID_INVALID) { if(e1 != ENT_ID_INVALID) {
struct CPhysics *cp = game_getcomponent(e1, physics); struct CPhysics *cp = game_getcomponent(e1, physics);
if(!cp) { if(!cp) {
// Entity being killed // Entity being killed maybe
return; return;
} }
@ -173,7 +173,7 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
if(e2 != ENT_ID_INVALID) { if(e2 != ENT_ID_INVALID) {
struct CPhysics *cp = game_getcomponent(e2, physics); struct CPhysics *cp = game_getcomponent(e2, physics);
if(!cp) { if(!cp) {
// Entity being killed // Entity being killed maybe
return; return;
} }
@ -189,35 +189,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
friction *= c->friction; friction *= c->friction;
vec4 q;
if(b1) {
memcpy(q, dBodyGetQuaternion(b1), sizeof(q));
} else {
dGeomGetQuaternion(c->geom, q);
}
{
float temp = q[0];
q[0] = q[1];
q[1] = q[2];
q[2] = q[3];
q[3] = temp;
}
vec3 n = {0, 1, 0};
glm_quat_rotatev(q, n, n);
/*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;
}
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);
} }
@ -228,34 +199,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
friction *= c->friction; friction *= c->friction;
vec4 q;
if(b2) {
memcpy(q, dBodyGetQuaternion(b2), sizeof(q));
} else {
dGeomGetQuaternion(c->geom, q);
}
{
float temp = q[0];
q[0] = q[1];
q[1] = q[2];
q[2] = q[3];
q[3] = temp;
}
vec3 n = {0, -1, 0};
glm_quat_rotatev(q, n, n);
/*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;
}
}
}
}*/
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);
} }
@ -358,36 +301,47 @@ static void game_character_controller_raycast_handler(void *data, dGeomID g1, dG
return; return;
} }
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
if(e1 == e2) {
// This means the ray is hitting the entity casting it.
return;
}
dContact contact[1]; dContact contact[1];
memset(contact, 0, sizeof(contact)); memset(contact, 0, sizeof(contact));
int numc = dCollide(g1, g2, 1, &contact[0].geom, sizeof(dContact)); 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) { if(numc) {
vec3 n = {0, -1, 0}; vec3 n = {0, -1, 0};
if(dGeomGetClass(g1) == dRayClass) { if(dGeomGetClass(g1) == dRayClass) {
struct CMovement *cm = &Game.entities.movement[(uintptr_t) dGeomGetData(g1)]; struct CMovement *cm = game_getcomponent(e1, movement);
struct CPhysics *cp2 = game_getcomponent(e2, physics);
if(cp2 && (cp2->dynamics & CPHYSICS_GHOST)) {
return;
}
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) { if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) {
cm->canJump = 1; cm->canJump = 1;
glm_vec3_scale(contact[0].geom.normal, 1, cm->groundNormal); glm_vec3_scale(contact[0].geom.normal, 1, cm->groundNormal);
} }
return;
} else if(dGeomGetClass(g2) == dRayClass) { } else if(dGeomGetClass(g2) == dRayClass) {
struct CMovement *cm = &Game.entities.movement[(uintptr_t) dGeomGetData(g2)]; struct CMovement *cm = game_getcomponent(e2, movement);
struct CPhysics *cp1 = game_getcomponent(e1, physics);
if(cp1 && (cp1->dynamics & CPHYSICS_GHOST)) {
return;
}
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) { if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) {
cm->canJump = 1; cm->canJump = 1;
glm_vec3_scale(contact[0].geom.normal, -1, cm->groundNormal); glm_vec3_scale(contact[0].geom.normal, -1, cm->groundNormal);
} }
return;
} }
} }
@ -403,9 +357,11 @@ void game_character_controller_raycast() {
continue; continue;
} }
rayGeoms[i] = dCreateRay(Game.space, 1); const float raylen = 0.5;
dGeomSetData(rayGeoms[i], (void*) (uintptr_t) i); rayGeoms[i] = dCreateRay(Game.space, raylen);
dGeomSetData(rayGeoms[i], (void*) (uintptr_t) Game.entities.movement[i].entity);
dGeomSetCategoryBits(rayGeoms[i], CATEGORY_RAY); dGeomSetCategoryBits(rayGeoms[i], CATEGORY_RAY);
dGeomSetCollideBits(rayGeoms[i], CATEGORY_STATIC | CATEGORY_ENTITY); dGeomSetCollideBits(rayGeoms[i], CATEGORY_STATIC | CATEGORY_ENTITY);
@ -414,7 +370,7 @@ void game_character_controller_raycast() {
const float *position = dBodyGetPosition(bid); const float *position = dBodyGetPosition(bid);
dGeomRaySet(rayGeoms[i], position[0], position[1] - cp->capsule.length / 2 + 0.5, position[2], 0, -1, 0); dGeomRaySet(rayGeoms[i], position[0], position[1] - cp->capsule.length / 2 - cp->capsule.radius + raylen / 2, position[2], 0, -1, 0);
} }
dSpaceCollide(Game.space, NULL, game_character_controller_raycast_handler); dSpaceCollide(Game.space, NULL, game_character_controller_raycast_handler);
@ -608,6 +564,8 @@ void game_update() {
glm_vec3_scale_as(wishvel, 3, wishvel); glm_vec3_scale_as(wishvel, 3, wishvel);
} }
} else { } else {
// We project the movement vector onto the ground plane (set by game_character_controller_raycast_handler)
// to "slide" along the ground with minimal bouncing
vec3_project_to_plane(wishvel, Game.entities.movement[mi].groundNormal, wishvel); vec3_project_to_plane(wishvel, Game.entities.movement[mi].groundNormal, wishvel);
} }