From 734401c321c04700fdc50f23e82dbb7d3e64f740 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Tue, 19 Apr 2022 13:04:42 -0600 Subject: [PATCH] Implement player wall collision detection --- src/physics/collision_scene.c | 18 ++++++++++++++ src/physics/collision_scene.h | 4 +++ src/physics/collision_sphere.c | 4 +-- src/player/player.c | 45 ++++++++++++++++++++++++++++------ src/player/player.h | 4 ++- src/scene/scene.c | 4 +-- 6 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/physics/collision_scene.c b/src/physics/collision_scene.c index 6160abd..148a2bd 100644 --- a/src/physics/collision_scene.c +++ b/src/physics/collision_scene.c @@ -11,4 +11,22 @@ void collisionObjectCollideWithScene(struct CollisionObject* object, struct Coll for (int i = 0; i < scene->quadCount; ++i) { collisionObjectCollideWithQuad(object, &scene->quads[i], contactSolver); } +} + +void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback) { + CollideWithQuad quadCollider = object->collider->callbacks->collideWithQuad; + + if (!quadCollider) { + return; + } + + struct ContactConstraintState localContact; + + for (int i = 0; i < scene->quadCount; ++i) { + localContact.contactCount = 0; + + if (quadCollider(object->collider->data, &object->body->transform, scene->quads[i].collider->data, &localContact)) { + callback(data, &localContact); + } + } } \ No newline at end of file diff --git a/src/physics/collision_scene.h b/src/physics/collision_scene.h index fbafb23..69223d2 100644 --- a/src/physics/collision_scene.h +++ b/src/physics/collision_scene.h @@ -8,9 +8,13 @@ struct CollisionScene { int quadCount; }; +typedef void (*ManifoldCallback)(void* data, struct ContactConstraintState* contact); + extern struct CollisionScene gCollisionScene; void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount); void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver); +void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback); + #endif \ No newline at end of file diff --git a/src/physics/collision_sphere.c b/src/physics/collision_sphere.c index c278c09..0798f54 100644 --- a/src/physics/collision_sphere.c +++ b/src/physics/collision_sphere.c @@ -24,13 +24,13 @@ int collisionSphereCollideQuad(void* data, struct Transform* boxTransform, struc vector3AddScaled(&quad->corner, &quad->edgeA, aLerp, &contact->ra); vector3AddScaled(&contact->ra, &quad->edgeB, bLerp, &contact->ra); - vector3Sub(&boxTransform->position, &contact->rb, &output->normal); + vector3Sub(&boxTransform->position, &contact->ra, &output->normal); float outputLength = vector3MagSqrd(&output->normal); float extraRadius = sphere->radius + NEGATIVE_PENETRATION_BIAS; - if (outputLength * outputLength > extraRadius * extraRadius || vector3Dot(&output->normal, &quad->plane.normal) < 0.0f) { + if (outputLength * outputLength > extraRadius * extraRadius || vector3Dot(&output->normal, &quad->plane.normal) <= 0.0f) { return 0; } diff --git a/src/player/player.c b/src/player/player.c index 48ff35e..6048803 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -5,12 +5,26 @@ #include "../defs.h" #include "../physics/point_constraint.h" #include "../math/mathf.h" +#include "physics/collision_sphere.h" +#include "physics/collision_scene.h" struct Vector3 gGrabDistance = {0.0f, 0.0f, -2.5f}; struct Vector3 gCameraOffset = {0.0f, 1.2f, 0.0f}; +struct CollisionSphere gPlayerCollider = { + 0.25f, +}; + +struct ColliderTypeData gPlayerColliderData = { + CollisionShapeTypeSphere, + &gPlayerCollider, + 0.1f, + 0.5f, + &gCollisionSphereCallbacks, +}; + void playerInit(struct Player* player) { - transformInitIdentity(&player->transform); + collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f); player->grabbing = NULL; player->yaw = 0.0f; player->pitch = 0.0f; @@ -24,12 +38,27 @@ void playerInit(struct Player* player) { #define ROTATE_RATE_DELTA (M_PI * 0.25f) #define ROTATE_RATE_STOP_DELTA (M_PI * 0.25f) +void playerHandleCollision(void* data, struct ContactConstraintState* contact) { + struct Player* player = (struct Player*)data; + + if (contact->contactCount == 1 && contact->contacts[0].penetration < 0.0f) { + vector3AddScaled( + &player->body.transform.position, + &contact->normal, + -contact->contacts[0].penetration, + &player->body.transform.position + ); + } +} + void playerUpdate(struct Player* player, struct Transform* cameraTransform) { struct Vector3 forward; struct Vector3 right; - quatMultVector(&player->transform.rotation, &gForward, &forward); - quatMultVector(&player->transform.rotation, &gRight, &right); + struct Transform* transform = &player->body.transform; + + quatMultVector(&transform->rotation, &gForward, &forward); + quatMultVector(&transform->rotation, &gRight, &right); forward.y = 0.0f; right.y = 0.0f; @@ -50,7 +79,9 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { vector3Dot(&player->velocity, &targetVelocity) > 0.0f ? PLAYER_ACCEL * FIXED_DELTA_TIME : PLAYER_STOP_ACCEL * FIXED_DELTA_TIME, &player->velocity ); - vector3AddScaled(&player->transform.position, &player->velocity, FIXED_DELTA_TIME, &player->transform.position); + vector3AddScaled(&transform->position, &player->velocity, FIXED_DELTA_TIME, &transform->position); + + collisionObjectQueryScene(&player->collisionObject, &gCollisionScene, player, playerHandleCollision); float targetYaw = 0.0f; float targetPitch = 0.0f; @@ -81,13 +112,13 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { player->yaw += player->yawVelocity * FIXED_DELTA_TIME; player->pitch = clampf(player->pitch + player->pitchVelocity * FIXED_DELTA_TIME, -M_PI * 0.5f, M_PI * 0.5f); - quatAxisAngle(&gUp, player->yaw, &player->transform.rotation); + quatAxisAngle(&gUp, player->yaw, &transform->rotation); struct Quaternion pitch; quatAxisAngle(&gRight, player->pitch, &pitch); - quatMultiply(&player->transform.rotation, &pitch, &cameraTransform->rotation); + quatMultiply(&transform->rotation, &pitch, &cameraTransform->rotation); - transformPoint(&player->transform, &gCameraOffset, &cameraTransform->position); + transformPoint(transform, &gCameraOffset, &cameraTransform->position); if (player->grabbing) { struct Vector3 grabPoint; diff --git a/src/player/player.h b/src/player/player.h index 26c759c..5ed3adf 100644 --- a/src/player/player.h +++ b/src/player/player.h @@ -4,9 +4,11 @@ #include "../math/transform.h" #include "../graphics/renderstate.h" #include "../physics/rigid_body.h" +#include "../physics/collision_object.h" struct Player { - struct Transform transform; + struct CollisionObject collisionObject; + struct RigidBody body; struct RigidBody* grabbing; struct Vector3 velocity; float pitch; diff --git a/src/scene/scene.c b/src/scene/scene.c index f8cc7c2..f7b39f8 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -21,10 +21,10 @@ struct Vector3 gStartPosition = {5.0f, 0.0f, -5.0f}; void sceneInit(struct Scene* scene) { - cameraInit(&scene->camera, 45.0f, 0.25f * SCENE_SCALE, 80.0f * SCENE_SCALE); + cameraInit(&scene->camera, 45.0f, 0.125f * SCENE_SCALE, 80.0f * SCENE_SCALE); playerInit(&scene->player); - scene->player.transform.position = gStartPosition; + scene->player.body.transform.position = gStartPosition; scene->player.yaw = M_PI; portalInit(&scene->portals[0], 0);