Add collision to portal border

This commit is contained in:
James Lambert 2023-08-20 21:57:49 -06:00
parent e4d12713ec
commit 60485246d1
10 changed files with 55 additions and 32 deletions

View file

@ -181,6 +181,7 @@ MODEL_LIST = assets/models/player/chell.blend \
assets/models/portal/portal_blue.blend \ assets/models/portal/portal_blue.blend \
assets/models/portal/portal_blue_filled.blend \ assets/models/portal/portal_blue_filled.blend \
assets/models/portal/portal_blue_face.blend \ assets/models/portal/portal_blue_face.blend \
assets/models/portal/portal_collider.blend \
assets/models/portal/portal_orange.blend \ assets/models/portal/portal_orange.blend \
assets/models/portal/portal_orange_filled.blend \ assets/models/portal/portal_orange_filled.blend \
assets/models/portal/portal_orange_face.blend \ assets/models/portal/portal_orange_face.blend \

Binary file not shown.

View file

@ -0,0 +1 @@
-r 0,0,0 --mesh-collider

View file

@ -38,9 +38,9 @@ void sceneSerializePortals(struct Serializer* serializer, SerializeAction action
char flags = portal->flags; char flags = portal->flags;
action(serializer, &flags, sizeof(flags)); action(serializer, &flags, sizeof(flags));
action(serializer, &portal->transform, sizeof(struct PartialTransform)); action(serializer, &portal->rigidBody.transform, sizeof(struct PartialTransform));
action(serializer, &portal->portalSurfaceIndex, sizeof(portal->portalSurfaceIndex)); action(serializer, &portal->portalSurfaceIndex, sizeof(portal->portalSurfaceIndex));
action(serializer, &portal->roomIndex, sizeof(portal->roomIndex)); action(serializer, &portal->rigidBody.currentRoom, sizeof(portal->rigidBody.currentRoom));
action(serializer, &portal->colliderIndex, sizeof(portal->colliderIndex)); action(serializer, &portal->colliderIndex, sizeof(portal->colliderIndex));
action(serializer, &portal->transformIndex, sizeof(portal->transformIndex)); action(serializer, &portal->transformIndex, sizeof(portal->transformIndex));
@ -87,12 +87,13 @@ void sceneDeserializePortals(struct Serializer* serializer, struct Scene* scene)
serializeRead(serializer, &portal->relativePos, sizeof(portal->relativePos)); serializeRead(serializer, &portal->relativePos, sizeof(portal->relativePos));
} }
portal->transform = transform; portal->rigidBody.transform = transform;
gCollisionScene.portalVelocity[portalIndex] = gZeroVec; gCollisionScene.portalVelocity[portalIndex] = gZeroVec;
portal->roomIndex = roomIndex; portal->rigidBody.currentRoom = roomIndex;
portal->colliderIndex = colliderIndex; portal->colliderIndex = colliderIndex;
portal->scale = 1.0f; portal->scale = 1.0f;
collisionSceneSetPortal(portalIndex, &portal->transform, roomIndex, colliderIndex); collisionSceneSetPortal(portalIndex, &portal->rigidBody.transform, roomIndex, colliderIndex);
collisionObjectUpdateBB(&portal->collisionObject);
if (flags & PortalFlagsPlayerPortal) { if (flags & PortalFlagsPlayerPortal) {
portal->flags |= PortalFlagsPlayerPortal; portal->flags |= PortalFlagsPlayerPortal;

View file

@ -10,14 +10,22 @@
#include "../util/time.h" #include "../util/time.h"
#include "../levels/levels.h" #include "../levels/levels.h"
#include "./portal_surface_generator.h" #include "./portal_surface_generator.h"
#include "../scene/dynamic_scene.h"
#include "../build/assets/models/portal/portal_blue.h" #include "../build/assets/models/portal/portal_blue.h"
#include "../build/assets/models/portal/portal_blue_filled.h" #include "../build/assets/models/portal/portal_blue_filled.h"
#include "../build/assets/models/portal/portal_blue_face.h" #include "../build/assets/models/portal/portal_blue_face.h"
#include "../build/assets/models/portal/portal_collider.h"
#include "../build/assets/models/portal/portal_orange.h" #include "../build/assets/models/portal/portal_orange.h"
#include "../build/assets/models/portal/portal_orange_face.h" #include "../build/assets/models/portal/portal_orange_face.h"
#include "../build/assets/models/portal/portal_orange_filled.h" #include "../build/assets/models/portal/portal_orange_filled.h"
struct ColliderTypeData gPortalColliderType = {
CollisionShapeTypeMesh,
&portal_portal_collider_collider,
0.0f, 0.6f,
&gMeshColliderCallbacks
};
#define CALC_SCREEN_SPACE(clip_space, screen_size) ((clip_space + 1.0f) * ((screen_size) / 2)) #define CALC_SCREEN_SPACE(clip_space, screen_size) ((clip_space + 1.0f) * ((screen_size) / 2))
@ -38,7 +46,8 @@ struct Vector3 gPortalOutline[PORTAL_LOOP_SIZE] = {
#define PORTAL_GROW_TIME 0.3f #define PORTAL_GROW_TIME 0.3f
void portalInit(struct Portal* portal, enum PortalFlags flags) { void portalInit(struct Portal* portal, enum PortalFlags flags) {
transformInitIdentity(&portal->transform); collisionObjectInit(&portal->collisionObject, &gPortalColliderType, &portal->rigidBody, 1.0f, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_TANGIBLE);
rigidBodyMarkKinematic(&portal->rigidBody);
portal->flags = flags; portal->flags = flags;
portal->opacity = 1.0f; portal->opacity = 1.0f;
portal->scale = 0.0f; portal->scale = 0.0f;
@ -70,12 +79,12 @@ void portalUpdate(struct Portal* portal, int isOpen) {
void portalCalculateBB(struct Portal* portal, struct Box3D* bb) { void portalCalculateBB(struct Portal* portal, struct Box3D* bb) {
struct Vector3 portalUp; struct Vector3 portalUp;
quatMultVector(&portal->transform.rotation, &gUp, &portalUp); quatMultVector(&portal->rigidBody.transform.rotation, &gUp, &portalUp);
struct Vector3 portalRight; struct Vector3 portalRight;
quatMultVector(&portal->transform.rotation, &gRight, &portalRight); quatMultVector(&portal->rigidBody.transform.rotation, &gRight, &portalRight);
vector3AddScaled( vector3AddScaled(
&portal->transform.position, &portal->rigidBody.transform.position,
&portalUp, PORTAL_COVER_HEIGHT * 0.5f, &portalUp, PORTAL_COVER_HEIGHT * 0.5f,
&bb->min &bb->min
); );
@ -84,7 +93,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) {
struct Vector3 nextPoint; struct Vector3 nextPoint;
vector3AddScaled( vector3AddScaled(
&portal->transform.position, &portal->rigidBody.transform.position,
&portalUp, -PORTAL_COVER_HEIGHT * 0.5f, &portalUp, -PORTAL_COVER_HEIGHT * 0.5f,
&nextPoint &nextPoint
); );
@ -92,7 +101,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) {
box3DUnionPoint(bb, &nextPoint, bb); box3DUnionPoint(bb, &nextPoint, bb);
vector3AddScaled( vector3AddScaled(
&portal->transform.position, &portal->rigidBody.transform.position,
&portalRight, PORTAL_COVER_WIDTH * 0.25f, &portalRight, PORTAL_COVER_WIDTH * 0.25f,
&nextPoint &nextPoint
); );
@ -100,7 +109,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) {
box3DUnionPoint(bb, &nextPoint, bb); box3DUnionPoint(bb, &nextPoint, bb);
vector3AddScaled( vector3AddScaled(
&portal->transform.position, &portal->rigidBody.transform.position,
&portalRight, -PORTAL_COVER_WIDTH * 0.25f, &portalRight, -PORTAL_COVER_WIDTH * 0.25f,
&nextPoint &nextPoint
); );
@ -130,6 +139,11 @@ int portalAttachToSurface(struct Portal* portal, struct PortalSurface* surface,
portal->flags |= PortalFlagsNeedsNewHole; portal->flags |= PortalFlagsNeedsNewHole;
portal->fullSizeLoopCenter = correctPosition; portal->fullSizeLoopCenter = correctPosition;
if (portal->portalSurfaceIndex == -1) {
collisionSceneAddDynamicObject(&portal->collisionObject);
}
portal->portalSurfaceIndex = surfaceIndex; portal->portalSurfaceIndex = surfaceIndex;
portalSurfaceInverse(surface, &correctPosition, &portalAt->position); portalSurfaceInverse(surface, &correctPosition, &portalAt->position);
@ -161,7 +175,7 @@ int portalSurfaceCutNewHole(struct Portal* portal, int portalIndex) {
return 0; return 0;
} }
portalSurfaceReplace(portal->portalSurfaceIndex, portal->roomIndex, portalIndex, &newSurface); portalSurfaceReplace(portal->portalSurfaceIndex, portal->rigidBody.currentRoom, portalIndex, &newSurface);
return 1; return 1;
} }

View file

@ -9,6 +9,7 @@
#include "camera.h" #include "camera.h"
#include "static_scene.h" #include "static_scene.h"
#include "./portal_surface.h" #include "./portal_surface.h"
#include "../physics/collision_object.h"
#define STARTING_RENDER_DEPTH 2 #define STARTING_RENDER_DEPTH 2
#define PORTAL_LOOP_SIZE 8 #define PORTAL_LOOP_SIZE 8
@ -20,14 +21,15 @@ enum PortalFlags {
}; };
struct Portal { struct Portal {
struct Transform transform; struct CollisionObject collisionObject;
struct RigidBody rigidBody;
short dynamicId;
enum PortalFlags flags; enum PortalFlags flags;
float opacity; float opacity;
float scale; float scale;
struct Vector2s16 originCentertedLoop[PORTAL_LOOP_SIZE]; struct Vector2s16 originCentertedLoop[PORTAL_LOOP_SIZE];
struct Vector2s16 fullSizeLoopCenter; struct Vector2s16 fullSizeLoopCenter;
short portalSurfaceIndex; short portalSurfaceIndex;
short roomIndex;
short colliderIndex; short colliderIndex;
// used to attach portals to moving surfaces // used to attach portals to moving surfaces
short transformIndex; short transformIndex;

View file

@ -82,10 +82,10 @@ void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct R
void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]) { void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]) {
struct Transform finalTransform; struct Transform finalTransform;
finalTransform = portal->transform; finalTransform = portal->rigidBody.transform;
if (portal->flags & PortalFlagsOddParity) { if (portal->flags & PortalFlagsOddParity) {
quatMultiply(&portal->transform.rotation, &gVerticalFlip, &finalTransform.rotation); quatMultiply(&portal->rigidBody.transform.rotation, &gVerticalFlip, &finalTransform.rotation);
} }
vector3Scale(&gOneVec, &finalTransform.scale, portal->scale); vector3Scale(&gOneVec, &finalTransform.scale, portal->scale);

View file

@ -122,10 +122,10 @@ int renderPlanPortal(struct RenderPlan* renderPlan, struct Scene* scene, struct
} }
struct Vector3 worldForward; struct Vector3 worldForward;
quatMultVector(&portal->transform.rotation, &forward, &worldForward); quatMultVector(&portal->rigidBody.transform.rotation, &forward, &worldForward);
struct Vector3 offsetFromCamera; struct Vector3 offsetFromCamera;
vector3Sub(&current->camera.transform.position, &portal->transform.position, &offsetFromCamera); vector3Sub(&current->camera.transform.position, &portal->rigidBody.transform.position, &offsetFromCamera);
// don't render the portal if it is facing the wrong way // don't render the portal if it is facing the wrong way
if (vector3Dot(&worldForward, &offsetFromCamera) < 0.0f) { if (vector3Dot(&worldForward, &offsetFromCamera) < 0.0f) {
@ -239,8 +239,8 @@ int renderPlanPortal(struct RenderPlan* renderPlan, struct Scene* scene, struct
return 0; return 0;
} }
struct Transform* fromPortal = &scene->portals[portalIndex].transform; struct Transform* fromPortal = &scene->portals[portalIndex].rigidBody.transform;
struct Transform* exitPortal = &scene->portals[exitPortalIndex].transform; struct Transform* exitPortal = &scene->portals[exitPortalIndex].rigidBody.transform;
struct Transform otherInverse; struct Transform otherInverse;
transformInvert(fromPortal, &otherInverse); transformInvert(fromPortal, &otherInverse);
@ -338,7 +338,7 @@ void renderPlanFinishView(struct RenderPlan* renderPlan, struct Scene* scene, st
cameraSetupMatrices(&properties->camera, renderState, properties->aspectRatio, properties->viewport, 0, &properties->cameraMatrixInfo); cameraSetupMatrices(&properties->camera, renderState, properties->aspectRatio, properties->viewport, 0, &properties->cameraMatrixInfo);
int closerPortal = vector3DistSqrd(&properties->camera.transform.position, &scene->portals[0].transform.position) < vector3DistSqrd(&properties->camera.transform.position, &scene->portals[1].transform.position) ? 0 : 1; int closerPortal = vector3DistSqrd(&properties->camera.transform.position, &scene->portals[0].rigidBody.transform.position) < vector3DistSqrd(&properties->camera.transform.position, &scene->portals[1].rigidBody.transform.position) ? 0 : 1;
int otherPortal = 1 - closerPortal; int otherPortal = 1 - closerPortal;
if (closerPortal) { if (closerPortal) {

View file

@ -407,14 +407,14 @@ void sceneCheckPortals(struct Scene* scene) {
#define MAX_LISTEN_THROUGH_PORTAL_DISTANCE 3.0f #define MAX_LISTEN_THROUGH_PORTAL_DISTANCE 3.0f
int sceneUpdatePortalListener(struct Scene* scene, int portalIndex, int listenerIndex) { int sceneUpdatePortalListener(struct Scene* scene, int portalIndex, int listenerIndex) {
if (vector3DistSqrd(&scene->player.lookTransform.position, &scene->portals[portalIndex].transform.position) > MAX_LISTEN_THROUGH_PORTAL_DISTANCE * MAX_LISTEN_THROUGH_PORTAL_DISTANCE) { if (vector3DistSqrd(&scene->player.lookTransform.position, &scene->portals[portalIndex].rigidBody.transform.position) > MAX_LISTEN_THROUGH_PORTAL_DISTANCE * MAX_LISTEN_THROUGH_PORTAL_DISTANCE) {
return 0; return 0;
} }
struct Transform otherInverse; struct Transform otherInverse;
transformInvert(&scene->portals[1 - portalIndex].transform, &otherInverse); transformInvert(&scene->portals[1 - portalIndex].rigidBody.transform, &otherInverse);
struct Transform portalCombined; struct Transform portalCombined;
transformConcat(&scene->portals[portalIndex].transform, &otherInverse, &portalCombined); transformConcat(&scene->portals[portalIndex].rigidBody.transform, &otherInverse, &portalCombined);
struct Transform relativeTransform; struct Transform relativeTransform;
transformConcat(&portalCombined, &scene->player.lookTransform, &relativeTransform); transformConcat(&portalCombined, &scene->player.lookTransform, &relativeTransform);
@ -473,6 +473,7 @@ void sceneUpdatePortalVelocity(struct Scene* scene) {
// update portal position // update portal position
gCollisionScene.portalTransforms[i]->position = newPos; gCollisionScene.portalTransforms[i]->position = newPos;
collisionObjectUpdateBB(&portal->collisionObject);
} }
} }
@ -754,19 +755,20 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
// the portal position may have been adjusted // the portal position may have been adjusted
if (transformIndex != NO_TRANSFORM_INDEX) { if (transformIndex != NO_TRANSFORM_INDEX) {
portal->relativePos = finalAt.position; portal->relativePos = finalAt.position;
transformConcat(&relativeToTransform, &finalAt, &portal->transform); transformConcat(&relativeToTransform, &finalAt, &portal->rigidBody.transform);
} else { } else {
portal->transform = finalAt; portal->rigidBody.transform = finalAt;
} }
gCollisionScene.portalVelocity[portalIndex] = gZeroVec; gCollisionScene.portalVelocity[portalIndex] = gZeroVec;
portal->transformIndex = transformIndex; portal->transformIndex = transformIndex;
portal->roomIndex = roomIndex; portal->rigidBody.currentRoom = roomIndex;
portal->colliderIndex = levelQuadIndex(collisionObject); portal->colliderIndex = levelQuadIndex(collisionObject);
portal->scale = 0.0f; portal->scale = 0.0f;
collisionSceneSetPortal(portalIndex, &portal->transform, roomIndex, portal->colliderIndex); collisionSceneSetPortal(portalIndex, &portal->rigidBody.transform, roomIndex, portal->colliderIndex);
collisionObjectUpdateBB(&portal->collisionObject);
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &portal->transform.position, &gZeroVec); soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &portal->rigidBody.transform.position, &gZeroVec);
if (fromPlayer) { if (fromPlayer) {
portal->flags |= PortalFlagsPlayerPortal; portal->flags |= PortalFlagsPlayerPortal;
@ -783,7 +785,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
// something changed and play sound near other portal // something changed and play sound near other portal
struct Portal* otherPortal = &scene->portals[1 - portalIndex]; struct Portal* otherPortal = &scene->portals[1 - portalIndex];
otherPortal->opacity = 1.0f; otherPortal->opacity = 1.0f;
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &otherPortal->transform.position, &gZeroVec); soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &otherPortal->rigidBody.transform.position, &gZeroVec);
} }
sceneCheckSecurityCamera(scene, portal); sceneCheckSecurityCamera(scene, portal);
@ -794,7 +796,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
} }
contactSolverCheckPortalContacts(&gContactSolver, collisionObject); contactSolverCheckPortalContacts(&gContactSolver, collisionObject);
ballBurnFilterOnPortal(&portal->transform, portalIndex); ballBurnFilterOnPortal(&portal->rigidBody.transform, portalIndex);
playerSignalPortalChanged(&scene->player); playerSignalPortalChanged(&scene->player);
return 1; return 1;
} }
@ -895,6 +897,8 @@ void sceneClosePortal(struct Scene* scene, int portalIndex) {
scene->portals[portalIndex].flags |= PortalFlagsNeedsNewHole; scene->portals[portalIndex].flags |= PortalFlagsNeedsNewHole;
scene->portals[portalIndex].portalSurfaceIndex = -1; scene->portals[portalIndex].portalSurfaceIndex = -1;
scene->portals[portalIndex].transformIndex = NO_TRANSFORM_INDEX; scene->portals[portalIndex].transformIndex = NO_TRANSFORM_INDEX;
collisionSceneRemoveDynamicObject(&scene->portals[portalIndex].collisionObject);
} }
return; return;
} }