Player can walk through portals

This commit is contained in:
James Lambert 2022-04-19 20:36:48 -06:00
parent 734401c321
commit b64ba2b9b7
7 changed files with 72 additions and 10 deletions

View file

@ -25,7 +25,7 @@ void collisionObjectCollideWithPlane(struct CollisionObject* object, struct Coll
return; return;
} }
contactSolverAssign(contact, &localContact); contactSolverAssign(contact, &localContact, 1);
} else if (contact) { } else if (contact) {
contactSolverRemoveContact(contactSolver, contact); contactSolverRemoveContact(contactSolver, contact);
} }
@ -44,12 +44,11 @@ void collisionObjectCollideWithQuad(struct CollisionObject* object, struct Colli
struct ContactConstraintState* contact = contactSolverPeekContact(contactSolver, quad, object); struct ContactConstraintState* contact = contactSolverPeekContact(contactSolver, quad, object);
if (quadCollider(object->collider->data, &object->body->transform, quad->collider->data, &localContact)) { if (quadCollider(object->collider->data, &object->body->transform, quad->collider->data, &localContact)) {
if (!contact) { if (!contact) {
return; return;
} }
contactSolverAssign(contact, &localContact); contactSolverAssign(contact, &localContact, 1);
} else if (contact) { } else if (contact) {
contactSolverRemoveContact(contactSolver, contact); contactSolverRemoveContact(contactSolver, contact);
} }

View file

@ -1,5 +1,7 @@
#include "collision_scene.h" #include "collision_scene.h"
#include "math/mathf.h"
struct CollisionScene gCollisionScene; struct CollisionScene gCollisionScene;
void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount) { void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount) {
@ -13,6 +15,26 @@ void collisionObjectCollideWithScene(struct CollisionObject* object, struct Coll
} }
} }
int collisionSceneFilterPortalContacts(struct ContactConstraintState* contact) {
int writeIndex = 0;
for (int readIndex = 0; readIndex < contact->contactCount; ++readIndex) {
if (collisionSceneIsTouchingPortal(&contact->contacts[readIndex].ra)) {
continue;;
}
if (readIndex != writeIndex) {
contact->contacts[writeIndex] = contact->contacts[readIndex];
}
++writeIndex;
}
contact->contactCount = writeIndex;
return writeIndex;
}
void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback) { void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback) {
CollideWithQuad quadCollider = object->collider->callbacks->collideWithQuad; CollideWithQuad quadCollider = object->collider->callbacks->collideWithQuad;
@ -25,8 +47,32 @@ void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionS
for (int i = 0; i < scene->quadCount; ++i) { for (int i = 0; i < scene->quadCount; ++i) {
localContact.contactCount = 0; localContact.contactCount = 0;
if (quadCollider(object->collider->data, &object->body->transform, scene->quads[i].collider->data, &localContact)) { if (quadCollider(object->collider->data, &object->body->transform, scene->quads[i].collider->data, &localContact) &&
collisionSceneFilterPortalContacts(&localContact)) {
callback(data, &localContact); callback(data, &localContact);
} }
} }
} }
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint) {
if (!gCollisionScene.portalTransforms[0] || !gCollisionScene.portalTransforms[1]) {
return 0;
}
for (int i = 0; i < 2; ++i) {
struct Vector3 localPoint;
transformPointInverse(gCollisionScene.portalTransforms[i], contactPoint, &localPoint);
if (fabsf(localPoint.z) > PORTAL_THICKNESS) {
continue;
}
localPoint.x *= 2.0f;
if (vector3MagSqrd(&localPoint) < 1.0f) {
return 1;
}
}
return 0;
}

View file

@ -3,9 +3,12 @@
#include "collision_object.h" #include "collision_object.h"
#define PORTAL_THICKNESS 0.11f
struct CollisionScene { struct CollisionScene {
struct CollisionObject* quads; struct CollisionObject* quads;
int quadCount; int quadCount;
struct Transform* portalTransforms[0];
}; };
typedef void (*ManifoldCallback)(void* data, struct ContactConstraintState* contact); typedef void (*ManifoldCallback)(void* data, struct ContactConstraintState* contact);
@ -15,6 +18,8 @@ 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);
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint);
void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback); void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback);
#endif #endif

View file

@ -4,6 +4,7 @@
#include "../math/mathf.h" #include "../math/mathf.h"
#include "rigid_body.h" #include "rigid_body.h"
#include "collision_object.h" #include "collision_object.h"
#include "collision_scene.h"
#include <string.h> #include <string.h>
@ -378,7 +379,7 @@ struct ContactState* contactSolverGetContact(struct ContactConstraintState* cont
return result; return result;
} }
void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from) { void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts) {
for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) { for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) {
int targetIndex; int targetIndex;
@ -397,11 +398,18 @@ void contactSolverAssign(struct ContactConstraintState* into, struct ContactCons
} }
} }
int copiedCount = 0;
for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) { for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) {
into->contacts[sourceIndex] = from->contacts[sourceIndex]; if (filterPortalContacts && collisionSceneIsTouchingPortal(&from->contacts[sourceIndex].ra)) {
continue;
} }
into->contactCount = from->contactCount; into->contacts[copiedCount] = from->contacts[sourceIndex];
++copiedCount;
}
into->contactCount = copiedCount;
into->tangentVectors[0] = from->tangentVectors[0]; into->tangentVectors[0] = from->tangentVectors[0];
into->tangentVectors[1] = from->tangentVectors[1]; into->tangentVectors[1] = from->tangentVectors[1];
into->normal = from->normal; into->normal = from->normal;

View file

@ -62,7 +62,7 @@ void contactSolverRemoveContact(struct ContactSolver* solver, struct ContactCons
struct ContactState* contactSolverGetContact(struct ContactConstraintState* contact, int id); struct ContactState* contactSolverGetContact(struct ContactConstraintState* contact, int id);
void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from); void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts);
#endif #endif

View file

@ -9,7 +9,7 @@
#include "physics/collision_scene.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, 0.0f, 0.0f};
struct CollisionSphere gPlayerCollider = { struct CollisionSphere gPlayerCollider = {
0.25f, 0.25f,

View file

@ -15,10 +15,11 @@
#include "../physics/point_constraint.h" #include "../physics/point_constraint.h"
#include "../physics/debug_renderer.h" #include "../physics/debug_renderer.h"
#include "../controls/controller.h" #include "../controls/controller.h"
#include "../physics/collision_scene.h"
#include "../levels/test_chamber_00_0/header.h" #include "../levels/test_chamber_00_0/header.h"
struct Vector3 gStartPosition = {5.0f, 0.0f, -5.0f}; struct Vector3 gStartPosition = {5.0f, 1.2f, -5.0f};
void sceneInit(struct Scene* scene) { void sceneInit(struct Scene* scene) {
cameraInit(&scene->camera, 45.0f, 0.125f * SCENE_SCALE, 80.0f * SCENE_SCALE); cameraInit(&scene->camera, 45.0f, 0.125f * SCENE_SCALE, 80.0f * SCENE_SCALE);
@ -38,6 +39,9 @@ void sceneInit(struct Scene* scene) {
scene->portals[1].transform.position.y = 1.0f; scene->portals[1].transform.position.y = 1.0f;
scene->portals[1].transform.position.z = -6.0f; scene->portals[1].transform.position.z = -6.0f;
gCollisionScene.portalTransforms[0] = &scene->portals[0].transform;
gCollisionScene.portalTransforms[1] = &scene->portals[1].transform;
quatAxisAngle(&gUp, M_PI * 0.5f, &scene->portals[1].transform.rotation); quatAxisAngle(&gUp, M_PI * 0.5f, &scene->portals[1].transform.rotation);
cubeInit(&scene->cube); cubeInit(&scene->cube);