Implement player wall collision detection

This commit is contained in:
James Lambert 2022-04-19 13:04:42 -06:00
parent 7ca5660e11
commit 734401c321
6 changed files with 67 additions and 12 deletions

View file

@ -12,3 +12,21 @@ void collisionObjectCollideWithScene(struct CollisionObject* object, struct Coll
collisionObjectCollideWithQuad(object, &scene->quads[i], contactSolver); 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);
}
}
}

View file

@ -8,9 +8,13 @@ struct CollisionScene {
int quadCount; int quadCount;
}; };
typedef void (*ManifoldCallback)(void* data, struct ContactConstraintState* contact);
extern struct CollisionScene gCollisionScene; extern struct CollisionScene gCollisionScene;
void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount); void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount);
void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver); void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver);
void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback);
#endif #endif

View file

@ -24,13 +24,13 @@ int collisionSphereCollideQuad(void* data, struct Transform* boxTransform, struc
vector3AddScaled(&quad->corner, &quad->edgeA, aLerp, &contact->ra); vector3AddScaled(&quad->corner, &quad->edgeA, aLerp, &contact->ra);
vector3AddScaled(&contact->ra, &quad->edgeB, bLerp, &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 outputLength = vector3MagSqrd(&output->normal);
float extraRadius = sphere->radius + NEGATIVE_PENETRATION_BIAS; 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; return 0;
} }

View file

@ -5,12 +5,26 @@
#include "../defs.h" #include "../defs.h"
#include "../physics/point_constraint.h" #include "../physics/point_constraint.h"
#include "../math/mathf.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 gGrabDistance = {0.0f, 0.0f, -2.5f};
struct Vector3 gCameraOffset = {0.0f, 1.2f, 0.0f}; 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) { void playerInit(struct Player* player) {
transformInitIdentity(&player->transform); collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f);
player->grabbing = NULL; player->grabbing = NULL;
player->yaw = 0.0f; player->yaw = 0.0f;
player->pitch = 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_DELTA (M_PI * 0.25f)
#define ROTATE_RATE_STOP_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) { void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
struct Vector3 forward; struct Vector3 forward;
struct Vector3 right; struct Vector3 right;
quatMultVector(&player->transform.rotation, &gForward, &forward); struct Transform* transform = &player->body.transform;
quatMultVector(&player->transform.rotation, &gRight, &right);
quatMultVector(&transform->rotation, &gForward, &forward);
quatMultVector(&transform->rotation, &gRight, &right);
forward.y = 0.0f; forward.y = 0.0f;
right.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, vector3Dot(&player->velocity, &targetVelocity) > 0.0f ? PLAYER_ACCEL * FIXED_DELTA_TIME : PLAYER_STOP_ACCEL * FIXED_DELTA_TIME,
&player->velocity &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 targetYaw = 0.0f;
float targetPitch = 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->yaw += player->yawVelocity * FIXED_DELTA_TIME;
player->pitch = clampf(player->pitch + player->pitchVelocity * FIXED_DELTA_TIME, -M_PI * 0.5f, M_PI * 0.5f); 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; struct Quaternion pitch;
quatAxisAngle(&gRight, player->pitch, &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) { if (player->grabbing) {
struct Vector3 grabPoint; struct Vector3 grabPoint;

View file

@ -4,9 +4,11 @@
#include "../math/transform.h" #include "../math/transform.h"
#include "../graphics/renderstate.h" #include "../graphics/renderstate.h"
#include "../physics/rigid_body.h" #include "../physics/rigid_body.h"
#include "../physics/collision_object.h"
struct Player { struct Player {
struct Transform transform; struct CollisionObject collisionObject;
struct RigidBody body;
struct RigidBody* grabbing; struct RigidBody* grabbing;
struct Vector3 velocity; struct Vector3 velocity;
float pitch; float pitch;

View file

@ -21,10 +21,10 @@
struct Vector3 gStartPosition = {5.0f, 0.0f, -5.0f}; struct Vector3 gStartPosition = {5.0f, 0.0f, -5.0f};
void sceneInit(struct Scene* scene) { 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); playerInit(&scene->player);
scene->player.transform.position = gStartPosition; scene->player.body.transform.position = gStartPosition;
scene->player.yaw = M_PI; scene->player.yaw = M_PI;
portalInit(&scene->portals[0], 0); portalInit(&scene->portals[0], 0);