From 6f1454768975cc8f9a22b380337652e3c8291ed7 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Wed, 20 Apr 2022 18:53:18 -0600 Subject: [PATCH] Portals work now --- src/physics/collision_scene.c | 6 ++- src/physics/collision_scene.h | 1 + src/physics/rigid_body.c | 28 ++++++++------ src/physics/rigid_body.h | 4 +- src/player/player.c | 73 +++++++++++++++++++++++++++-------- src/player/player.h | 3 ++ src/scene/cube.c | 2 + src/scene/scene.c | 1 + 8 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/physics/collision_scene.c b/src/physics/collision_scene.c index 011ab52..bdfa52d 100644 --- a/src/physics/collision_scene.c +++ b/src/physics/collision_scene.c @@ -55,7 +55,7 @@ void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionS } int collisionSceneIsTouchingPortal(struct Vector3* contactPoint) { - if (!gCollisionScene.portalTransforms[0] || !gCollisionScene.portalTransforms[1]) { + if (!collisionSceneIsPortalOpen()) { return 0; } @@ -76,4 +76,8 @@ int collisionSceneIsTouchingPortal(struct Vector3* contactPoint) { } return 0; +} + +int collisionSceneIsPortalOpen() { + return gCollisionScene.portalTransforms[0] != NULL && gCollisionScene.portalTransforms[1] != NULL; } \ No newline at end of file diff --git a/src/physics/collision_scene.h b/src/physics/collision_scene.h index 73d85bd..ed15246 100644 --- a/src/physics/collision_scene.h +++ b/src/physics/collision_scene.h @@ -20,6 +20,7 @@ void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* qu void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver); int collisionSceneIsTouchingPortal(struct Vector3* contactPoint); +int collisionSceneIsPortalOpen(); void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback); diff --git a/src/physics/rigid_body.c b/src/physics/rigid_body.c index 88c6ffa..c71dc09 100644 --- a/src/physics/rigid_body.c +++ b/src/physics/rigid_body.c @@ -62,19 +62,17 @@ float rigidBodyMassInverseAtLocalPoint(struct RigidBody* rigidBody, struct Vecto } -int rigidBodyCheckPortals(struct RigidBody* rigidBody) { +void rigidBodyCheckPortals(struct RigidBody* rigidBody) { if (!gCollisionScene.portalTransforms[0] || !gCollisionScene.portalTransforms[1]) { rigidBody->flags &= ~(RigidBodyFlagsInFrontPortal0 | RigidBodyFlagsInFrontPortal1); rigidBody->flags |= RigidBodyFlagsPortalsInactive; - return 0; + return; } struct Vector3 localPoint; enum RigidBodyFlags newFlags = 0; - int didTeleport = 0; - for (int i = 0; i < 2; ++i) { transformPointInverse(gCollisionScene.portalTransforms[i], &rigidBody->transform.position, &localPoint); @@ -85,8 +83,13 @@ int rigidBodyCheckPortals(struct RigidBody* rigidBody) { } // skip checking if portal was crossed if this is the - // first frame portals were active - if (rigidBody->flags & RigidBodyFlagsPortalsInactive || didTeleport) { + // first frame portals were active or the object was + // just teleported + if (rigidBody->flags & ( + RigidBodyFlagsPortalsInactive | + (RigidBodyFlagsCrossedPortal0 << (1 - i))) || + (newFlags & RigidBodyFlagsCrossedPortal0) + ) { continue; } @@ -132,12 +135,15 @@ int rigidBodyCheckPortals(struct RigidBody* rigidBody) { rigidBody->transform.rotation = newRotation; - didTeleport = 1; - newFlags |= RigidBodyFlagsPortalsInactive; + newFlags |= RigidBodyFlagsCrossedPortal0 << i; } - rigidBody->flags &= ~(RigidBodyFlagsInFrontPortal0 | RigidBodyFlagsInFrontPortal1 | RigidBodyFlagsPortalsInactive); + rigidBody->flags &= ~( + RigidBodyFlagsInFrontPortal0 | + RigidBodyFlagsInFrontPortal1 | + RigidBodyFlagsPortalsInactive | + RigidBodyFlagsCrossedPortal0 | + RigidBodyFlagsCrossedPortal1 + ); rigidBody->flags |= newFlags; - - return didTeleport; } \ No newline at end of file diff --git a/src/physics/rigid_body.h b/src/physics/rigid_body.h index 011c5de..7f3ce33 100644 --- a/src/physics/rigid_body.h +++ b/src/physics/rigid_body.h @@ -8,6 +8,8 @@ enum RigidBodyFlags { RigidBodyFlagsInFrontPortal0 = (1 << 0), RigidBodyFlagsInFrontPortal1 = (1 << 1), RigidBodyFlagsPortalsInactive = (1 << 2), + RigidBodyFlagsCrossedPortal0 = (1 << 3), + RigidBodyFlagsCrossedPortal1 = (1 << 4), }; struct RigidBody { @@ -34,7 +36,7 @@ void rigidBodyUpdate(struct RigidBody* rigidBody); void rigidBodyVelocityAtLocalPoint(struct RigidBody* rigidBody, struct Vector3* localPoint, struct Vector3* worldVelocity); void rigidBodyVelocityAtWorldPoint(struct RigidBody* rigidBody, struct Vector3* worldPoint, struct Vector3* worldVelocity); -int rigidBodyCheckPortals(struct RigidBody* rigidBody); +void rigidBodyCheckPortals(struct RigidBody* rigidBody); #endif \ No newline at end of file diff --git a/src/player/player.c b/src/player/player.c index 405f6a5..194d429 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -28,6 +28,8 @@ void playerInit(struct Player* player) { player->grabbing = NULL; player->yaw = 0.0f; player->pitch = 0.0f; + + player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING; } #define PLAYER_SPEED (5.0f) @@ -51,6 +53,60 @@ void playerHandleCollision(void* data, struct ContactConstraintState* contact) { } } +void playerApplyPortalGrab(struct Player* player, int portalIndex) { + if (player->grabbingThroughPortal == PLAYER_GRABBING_THROUGH_NOTHING) { + player->grabbingThroughPortal = portalIndex; + } else if (player->grabbingThroughPortal != portalIndex) { + player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING; + } +} + +void playerUpdateGrabbedObject(struct Player* player) { + if (player->grabbing) { + if (player->body.flags & RigidBodyFlagsCrossedPortal0) { + playerApplyPortalGrab(player, 1); + } + + if (player->body.flags & RigidBodyFlagsCrossedPortal1) { + playerApplyPortalGrab(player, 0); + } + + if (player->grabbing->flags & RigidBodyFlagsCrossedPortal0) { + playerApplyPortalGrab(player, 0); + } + + if (player->grabbing->flags & RigidBodyFlagsCrossedPortal1) { + playerApplyPortalGrab(player, 1); + } + + struct Vector3 grabPoint; + struct Quaternion grabRotation = player->body.transform.rotation; + + transformPoint(&player->body.transform, &gGrabDistance, &grabPoint); + + if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) { + if (!collisionSceneIsPortalOpen()) { + // portal was closed while holding object through it + player->grabbing = NULL; + return; + } + + struct Transform inverseA; + transformInvert(gCollisionScene.portalTransforms[player->grabbingThroughPortal], &inverseA); + struct Transform pointTransform; + transformConcat(gCollisionScene.portalTransforms[1 - player->grabbingThroughPortal], &inverseA, &pointTransform); + + transformPoint(&pointTransform, &grabPoint, &grabPoint); + struct Quaternion finalRotation; + quatMultiply(&pointTransform.rotation, &grabRotation, &finalRotation); + grabRotation = finalRotation; + } + + pointConstraintMoveToPoint(player->grabbing, &grabPoint, 20.0f); + pointConstraintRotateTo(player->grabbing, &grabRotation, 5.0f); + } +} + void playerUpdate(struct Player* player, struct Transform* cameraTransform) { struct Vector3 forward; struct Vector3 right; @@ -121,24 +177,9 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { quatMultiply(&tempRotation, &deltaRotate, &player->body.transform.rotation); - - // 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, &transform->rotation); - - // struct Quaternion pitch; - // quatAxisAngle(&gRight, player->pitch, &pitch); - // quatMultiply(&transform->rotation, &pitch, &cameraTransform->rotation); - cameraTransform->rotation = player->body.transform.rotation; transformPoint(transform, &gCameraOffset, &cameraTransform->position); - if (player->grabbing) { - struct Vector3 grabPoint; - transformPoint(cameraTransform, &gGrabDistance, &grabPoint); - pointConstraintMoveToPoint(player->grabbing, &grabPoint, 20.0f); - pointConstraintRotateTo(player->grabbing, &cameraTransform->rotation, 5.0f); - } + playerUpdateGrabbedObject(player); } diff --git a/src/player/player.h b/src/player/player.h index 9f24280..13140f7 100644 --- a/src/player/player.h +++ b/src/player/player.h @@ -6,9 +6,12 @@ #include "../physics/rigid_body.h" #include "../physics/collision_object.h" +#define PLAYER_GRABBING_THROUGH_NOTHING -1 + struct Player { struct CollisionObject collisionObject; struct RigidBody body; + short grabbingThroughPortal; struct RigidBody* grabbing; float pitch; float pitchVelocity; diff --git a/src/scene/cube.c b/src/scene/cube.c index 4ae0601..960c372 100644 --- a/src/scene/cube.c +++ b/src/scene/cube.c @@ -69,6 +69,8 @@ void cubeUpdate(struct Cube* cube) { contactSolverSolve(&gContactSolver); rigidBodyUpdate(&cube->rigidBody); + + rigidBodyCheckPortals(&cube->rigidBody); } void cubeRender(struct Cube* cube, struct RenderState* renderState) { diff --git a/src/scene/scene.c b/src/scene/scene.c index 98e5266..b8eb365 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -110,6 +110,7 @@ void sceneUpdate(struct Scene* scene) { scene->player.grabbing = NULL; } else { scene->player.grabbing = &scene->cube.rigidBody; + scene->player.grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING; } }