diff --git a/Makefile b/Makefile index 5d64b56..a1e0574 100644 --- a/Makefile +++ b/Makefile @@ -181,6 +181,7 @@ MODEL_LIST = assets/models/player/chell.blend \ assets/models/portal/portal_blue.blend \ assets/models/portal/portal_blue_filled.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_filled.blend \ assets/models/portal/portal_orange_face.blend \ diff --git a/assets/models/portal/portal_blue.blend b/assets/models/portal/portal_blue.blend index 5c74a4a..dbc7012 100644 Binary files a/assets/models/portal/portal_blue.blend and b/assets/models/portal/portal_blue.blend differ diff --git a/assets/models/portal/portal_collider.blend b/assets/models/portal/portal_collider.blend new file mode 100644 index 0000000..b9e3e78 Binary files /dev/null and b/assets/models/portal/portal_collider.blend differ diff --git a/assets/models/portal/portal_collider.flags b/assets/models/portal/portal_collider.flags new file mode 100644 index 0000000..6047ab9 --- /dev/null +++ b/assets/models/portal/portal_collider.flags @@ -0,0 +1 @@ +-r 0,0,0 --mesh-collider \ No newline at end of file diff --git a/src/savefile/scene_serialize.c b/src/savefile/scene_serialize.c index 6ac064a..9b0de21 100644 --- a/src/savefile/scene_serialize.c +++ b/src/savefile/scene_serialize.c @@ -38,9 +38,9 @@ void sceneSerializePortals(struct Serializer* serializer, SerializeAction action char flags = portal->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->roomIndex, sizeof(portal->roomIndex)); + action(serializer, &portal->rigidBody.currentRoom, sizeof(portal->rigidBody.currentRoom)); action(serializer, &portal->colliderIndex, sizeof(portal->colliderIndex)); 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)); } - portal->transform = transform; + portal->rigidBody.transform = transform; gCollisionScene.portalVelocity[portalIndex] = gZeroVec; - portal->roomIndex = roomIndex; + portal->rigidBody.currentRoom = roomIndex; portal->colliderIndex = colliderIndex; portal->scale = 1.0f; - collisionSceneSetPortal(portalIndex, &portal->transform, roomIndex, colliderIndex); + collisionSceneSetPortal(portalIndex, &portal->rigidBody.transform, roomIndex, colliderIndex); + collisionObjectUpdateBB(&portal->collisionObject); if (flags & PortalFlagsPlayerPortal) { portal->flags |= PortalFlagsPlayerPortal; diff --git a/src/scene/portal.c b/src/scene/portal.c index 6fac09c..799a86f 100644 --- a/src/scene/portal.c +++ b/src/scene/portal.c @@ -10,14 +10,22 @@ #include "../util/time.h" #include "../levels/levels.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_filled.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_face.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)) @@ -38,7 +46,8 @@ struct Vector3 gPortalOutline[PORTAL_LOOP_SIZE] = { #define PORTAL_GROW_TIME 0.3f 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->opacity = 1.0f; portal->scale = 0.0f; @@ -70,12 +79,12 @@ void portalUpdate(struct Portal* portal, int isOpen) { void portalCalculateBB(struct Portal* portal, struct Box3D* bb) { struct Vector3 portalUp; - quatMultVector(&portal->transform.rotation, &gUp, &portalUp); + quatMultVector(&portal->rigidBody.transform.rotation, &gUp, &portalUp); struct Vector3 portalRight; - quatMultVector(&portal->transform.rotation, &gRight, &portalRight); + quatMultVector(&portal->rigidBody.transform.rotation, &gRight, &portalRight); vector3AddScaled( - &portal->transform.position, + &portal->rigidBody.transform.position, &portalUp, PORTAL_COVER_HEIGHT * 0.5f, &bb->min ); @@ -84,7 +93,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) { struct Vector3 nextPoint; vector3AddScaled( - &portal->transform.position, + &portal->rigidBody.transform.position, &portalUp, -PORTAL_COVER_HEIGHT * 0.5f, &nextPoint ); @@ -92,7 +101,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) { box3DUnionPoint(bb, &nextPoint, bb); vector3AddScaled( - &portal->transform.position, + &portal->rigidBody.transform.position, &portalRight, PORTAL_COVER_WIDTH * 0.25f, &nextPoint ); @@ -100,7 +109,7 @@ void portalCalculateBB(struct Portal* portal, struct Box3D* bb) { box3DUnionPoint(bb, &nextPoint, bb); vector3AddScaled( - &portal->transform.position, + &portal->rigidBody.transform.position, &portalRight, -PORTAL_COVER_WIDTH * 0.25f, &nextPoint ); @@ -130,6 +139,11 @@ int portalAttachToSurface(struct Portal* portal, struct PortalSurface* surface, portal->flags |= PortalFlagsNeedsNewHole; portal->fullSizeLoopCenter = correctPosition; + + if (portal->portalSurfaceIndex == -1) { + collisionSceneAddDynamicObject(&portal->collisionObject); + } + portal->portalSurfaceIndex = surfaceIndex; portalSurfaceInverse(surface, &correctPosition, &portalAt->position); @@ -161,7 +175,7 @@ int portalSurfaceCutNewHole(struct Portal* portal, int portalIndex) { return 0; } - portalSurfaceReplace(portal->portalSurfaceIndex, portal->roomIndex, portalIndex, &newSurface); + portalSurfaceReplace(portal->portalSurfaceIndex, portal->rigidBody.currentRoom, portalIndex, &newSurface); return 1; } diff --git a/src/scene/portal.h b/src/scene/portal.h index 7cd4dbb..6872fb0 100644 --- a/src/scene/portal.h +++ b/src/scene/portal.h @@ -9,6 +9,7 @@ #include "camera.h" #include "static_scene.h" #include "./portal_surface.h" +#include "../physics/collision_object.h" #define STARTING_RENDER_DEPTH 2 #define PORTAL_LOOP_SIZE 8 @@ -20,14 +21,15 @@ enum PortalFlags { }; struct Portal { - struct Transform transform; + struct CollisionObject collisionObject; + struct RigidBody rigidBody; + short dynamicId; enum PortalFlags flags; float opacity; float scale; struct Vector2s16 originCentertedLoop[PORTAL_LOOP_SIZE]; struct Vector2s16 fullSizeLoopCenter; short portalSurfaceIndex; - short roomIndex; short colliderIndex; // used to attach portals to moving surfaces short transformIndex; diff --git a/src/scene/portal_render.c b/src/scene/portal_render.c index 95a009d..d1b4fa5 100644 --- a/src/scene/portal_render.c +++ b/src/scene/portal_render.c @@ -82,10 +82,10 @@ void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct R void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]) { struct Transform finalTransform; - finalTransform = portal->transform; + finalTransform = portal->rigidBody.transform; 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); diff --git a/src/scene/render_plan.c b/src/scene/render_plan.c index 48a3bbc..d8594c5 100644 --- a/src/scene/render_plan.c +++ b/src/scene/render_plan.c @@ -122,10 +122,10 @@ int renderPlanPortal(struct RenderPlan* renderPlan, struct Scene* scene, struct } struct Vector3 worldForward; - quatMultVector(&portal->transform.rotation, &forward, &worldForward); + quatMultVector(&portal->rigidBody.transform.rotation, &forward, &worldForward); struct Vector3 offsetFromCamera; - vector3Sub(¤t->camera.transform.position, &portal->transform.position, &offsetFromCamera); + vector3Sub(¤t->camera.transform.position, &portal->rigidBody.transform.position, &offsetFromCamera); // don't render the portal if it is facing the wrong way if (vector3Dot(&worldForward, &offsetFromCamera) < 0.0f) { @@ -239,8 +239,8 @@ int renderPlanPortal(struct RenderPlan* renderPlan, struct Scene* scene, struct return 0; } - struct Transform* fromPortal = &scene->portals[portalIndex].transform; - struct Transform* exitPortal = &scene->portals[exitPortalIndex].transform; + struct Transform* fromPortal = &scene->portals[portalIndex].rigidBody.transform; + struct Transform* exitPortal = &scene->portals[exitPortalIndex].rigidBody.transform; struct Transform 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); - 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; if (closerPortal) { diff --git a/src/scene/scene.c b/src/scene/scene.c index 877c266..8393c41 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -407,14 +407,14 @@ void sceneCheckPortals(struct Scene* scene) { #define MAX_LISTEN_THROUGH_PORTAL_DISTANCE 3.0f 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; } struct Transform otherInverse; - transformInvert(&scene->portals[1 - portalIndex].transform, &otherInverse); + transformInvert(&scene->portals[1 - portalIndex].rigidBody.transform, &otherInverse); struct Transform portalCombined; - transformConcat(&scene->portals[portalIndex].transform, &otherInverse, &portalCombined); + transformConcat(&scene->portals[portalIndex].rigidBody.transform, &otherInverse, &portalCombined); struct Transform relativeTransform; transformConcat(&portalCombined, &scene->player.lookTransform, &relativeTransform); @@ -473,6 +473,7 @@ void sceneUpdatePortalVelocity(struct Scene* scene) { // update portal position 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 if (transformIndex != NO_TRANSFORM_INDEX) { portal->relativePos = finalAt.position; - transformConcat(&relativeToTransform, &finalAt, &portal->transform); + transformConcat(&relativeToTransform, &finalAt, &portal->rigidBody.transform); } else { - portal->transform = finalAt; + portal->rigidBody.transform = finalAt; } gCollisionScene.portalVelocity[portalIndex] = gZeroVec; portal->transformIndex = transformIndex; - portal->roomIndex = roomIndex; + portal->rigidBody.currentRoom = roomIndex; portal->colliderIndex = levelQuadIndex(collisionObject); 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) { 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 struct Portal* otherPortal = &scene->portals[1 - portalIndex]; 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); @@ -794,7 +796,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde } contactSolverCheckPortalContacts(&gContactSolver, collisionObject); - ballBurnFilterOnPortal(&portal->transform, portalIndex); + ballBurnFilterOnPortal(&portal->rigidBody.transform, portalIndex); playerSignalPortalChanged(&scene->player); return 1; } @@ -895,6 +897,8 @@ void sceneClosePortal(struct Scene* scene, int portalIndex) { scene->portals[portalIndex].flags |= PortalFlagsNeedsNewHole; scene->portals[portalIndex].portalSurfaceIndex = -1; scene->portals[portalIndex].transformIndex = NO_TRANSFORM_INDEX; + + collisionSceneRemoveDynamicObject(&scene->portals[portalIndex].collisionObject); } return; } \ No newline at end of file