Implement special case logic when standing close to a portal
This commit is contained in:
parent
9c478b6585
commit
abf2c858db
|
@ -89,7 +89,7 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
|
||||||
- Implement loading levels from the cartridge
|
- Implement loading levels from the cartridge
|
||||||
- [x] Implement "Emancipation grid"
|
- [x] Implement "Emancipation grid"
|
||||||
- [ ] Change the way player standing logic works
|
- [ ] Change the way player standing logic works
|
||||||
- [ ] Cut holes in portal walls
|
- [x] Cut holes in portal walls
|
||||||
- [ ] Cube dispenser
|
- [ ] Cube dispenser
|
||||||
- [ ] NAN in overlap
|
- [ ] NAN in overlap
|
||||||
- [ ] Get an optimized build working
|
- [ ] Get an optimized build working
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern struct CollisionScene gCollisionScene;
|
||||||
void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount, struct World* world);
|
void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount, struct World* world);
|
||||||
void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver);
|
void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver);
|
||||||
|
|
||||||
|
int collisionSceneIsTouchingSinglePortal(struct Vector3* contactPoint, struct Vector3* contactNormal, struct Transform* portalTransform, int portalIndex);
|
||||||
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint, struct Vector3* contactNormal);
|
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint, struct Vector3* contactNormal);
|
||||||
int collisionSceneIsPortalOpen();
|
int collisionSceneIsPortalOpen();
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "../graphics/graphics.h"
|
#include "../graphics/graphics.h"
|
||||||
|
|
||||||
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingBoxs16* boundingBox) {
|
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingBoxs16* boundingBox) {
|
||||||
for (int i = 0; i < CLIPPING_PLANE_COUNT; ++i) {
|
for (int i = 0; i < frustrum->usedClippingPlaneCount; ++i) {
|
||||||
struct Vector3 closestPoint;
|
struct Vector3 closestPoint;
|
||||||
|
|
||||||
struct Vector3* normal = &frustrum->clippingPlanes[i].normal;
|
struct Vector3* normal = &frustrum->clippingPlanes[i].normal;
|
||||||
|
@ -24,7 +24,7 @@ int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct Boundi
|
||||||
}
|
}
|
||||||
|
|
||||||
int isSphereOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct Vector3* scaledCenter, float scaledRadius) {
|
int isSphereOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct Vector3* scaledCenter, float scaledRadius) {
|
||||||
for (int i = 0; i < CLIPPING_PLANE_COUNT; ++i) {
|
for (int i = 0; i < frustrum->usedClippingPlaneCount; ++i) {
|
||||||
if (planePointDistance(&frustrum->clippingPlanes[i], scaledCenter) < -scaledRadius) {
|
if (planePointDistance(&frustrum->clippingPlanes[i], scaledCenter) < -scaledRadius) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ int isSphereOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct
|
||||||
}
|
}
|
||||||
|
|
||||||
int isQuadOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct CollisionQuad* quad) {
|
int isQuadOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct CollisionQuad* quad) {
|
||||||
for (int i = 0; i < CLIPPING_PLANE_COUNT; ++i) {
|
for (int i = 0; i < frustrum->usedClippingPlaneCount; ++i) {
|
||||||
struct Vector3* normal = &frustrum->clippingPlanes[i].normal;
|
struct Vector3* normal = &frustrum->clippingPlanes[i].normal;
|
||||||
float aLerp = vector3Dot(normal, &quad->edgeA) < 0.0f ? 0.0f : quad->edgeALength;
|
float aLerp = vector3Dot(normal, &quad->edgeA) < 0.0f ? 0.0f : quad->edgeALength;
|
||||||
float bLerp = vector3Dot(normal, &quad->edgeB) < 0.0f ? 0.0f : quad->edgeBLength;
|
float bLerp = vector3Dot(normal, &quad->edgeB) < 0.0f ? 0.0f : quad->edgeBLength;
|
||||||
|
@ -126,6 +126,7 @@ Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState,
|
||||||
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[3], 1, -1.0f);
|
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[3], 1, -1.0f);
|
||||||
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[4], 2, 1.0f);
|
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[4], 2, 1.0f);
|
||||||
clippingInfo->cameraPos = camera->transform.position;
|
clippingInfo->cameraPos = camera->transform.position;
|
||||||
|
clippingInfo->usedClippingPlaneCount = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
gSPMatrix(renderState->dl++, osVirtualToPhysical(&viewProjMatrix[1]), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
|
gSPMatrix(renderState->dl++, osVirtualToPhysical(&viewProjMatrix[1]), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "../physics/collision_quad.h"
|
#include "../physics/collision_quad.h"
|
||||||
#include "../math/boxs16.h"
|
#include "../math/boxs16.h"
|
||||||
|
|
||||||
#define CLIPPING_PLANE_COUNT 5
|
#define MAX_CLIPPING_PLANE_COUNT 6
|
||||||
|
|
||||||
struct Camera {
|
struct Camera {
|
||||||
struct Transform transform;
|
struct Transform transform;
|
||||||
|
@ -21,7 +21,8 @@ struct Camera {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FrustrumCullingInformation {
|
struct FrustrumCullingInformation {
|
||||||
struct Plane clippingPlanes[CLIPPING_PLANE_COUNT];
|
struct Plane clippingPlanes[MAX_CLIPPING_PLANE_COUNT];
|
||||||
|
short usedClippingPlaneCount;
|
||||||
|
|
||||||
struct Vector3 cameraPos;
|
struct Vector3 cameraPos;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../defs.h"
|
#include "../defs.h"
|
||||||
#include "dynamic_scene.h"
|
#include "dynamic_scene.h"
|
||||||
#include "../physics/collision_scene.h"
|
#include "../physics/collision_scene.h"
|
||||||
|
#include "../math/mathf.h"
|
||||||
|
|
||||||
#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))
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ struct Quaternion gVerticalFlip = {0.0f, 1.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
#define PORTAL_CLIPPING_PLANE_BIAS (SCENE_SCALE * 0.25f)
|
#define PORTAL_CLIPPING_PLANE_BIAS (SCENE_SCALE * 0.25f)
|
||||||
|
|
||||||
|
#define CAMERA_CLIPPING_RADIUS 0.2f
|
||||||
|
|
||||||
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState, u16 roomIndex) {
|
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState, u16 roomIndex) {
|
||||||
props->camera = *camera;
|
props->camera = *camera;
|
||||||
props->aspectRatio = aspectRatio;
|
props->aspectRatio = aspectRatio;
|
||||||
|
@ -66,6 +69,40 @@ void renderPropsInit(struct RenderProps* props, struct Camera* camera, float asp
|
||||||
props->perspectiveMatrix = cameraSetupMatrices(&externalCamera, renderState, aspectRatio, &props->perspectiveCorrect, &fullscreenViewport, NULL, 0.0f);
|
props->perspectiveMatrix = cameraSetupMatrices(&externalCamera, renderState, aspectRatio, &props->perspectiveCorrect, &fullscreenViewport, NULL, 0.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
props->clippingPortalIndex = -1;
|
||||||
|
|
||||||
|
if (collisionSceneIsPortalOpen()) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
struct Vector3 portalOffset;
|
||||||
|
|
||||||
|
vector3Sub(&camera->transform.position, &gCollisionScene.portalTransforms[i]->position, &portalOffset);
|
||||||
|
|
||||||
|
struct Vector3 portalNormal;
|
||||||
|
quatMultVector(&gCollisionScene.portalTransforms[i]->rotation, &gForward, &portalNormal);
|
||||||
|
struct Vector3 projectedPoint;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
vector3Negate(&portalNormal, &portalNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
float clippingDistnace = vector3Dot(&portalNormal, &portalOffset);
|
||||||
|
|
||||||
|
if (fabsf(clippingDistnace) > CAMERA_CLIPPING_RADIUS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector3AddScaled(&camera->transform.position, &portalNormal, -clippingDistnace, &projectedPoint);
|
||||||
|
|
||||||
|
if (collisionSceneIsTouchingSinglePortal(&projectedPoint, &portalNormal, gCollisionScene.portalTransforms[i], i)) {
|
||||||
|
vector3Negate(&portalNormal, &portalNormal);
|
||||||
|
planeInitWithNormalAndPoint(&props->cullingInfo.clippingPlanes[5], &portalNormal, &gCollisionScene.portalTransforms[i]->position);
|
||||||
|
++props->cullingInfo.usedClippingPlaneCount;
|
||||||
|
props->clippingPortalIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
props->minX = 0;
|
props->minX = 0;
|
||||||
props->minY = 0;
|
props->minY = 0;
|
||||||
props->maxX = SCREEN_WD;
|
props->maxX = SCREEN_WD;
|
||||||
|
@ -149,12 +186,15 @@ void renderPropsNext(struct RenderProps* current, struct RenderProps* next, stru
|
||||||
next->perspectiveMatrix = cameraSetupMatrices(&externalCamera, renderState, (float)SCREEN_WD / (float)SCREEN_HT, &next->perspectiveCorrect, &fullscreenViewport, NULL, zBias);
|
next->perspectiveMatrix = cameraSetupMatrices(&externalCamera, renderState, (float)SCREEN_WD / (float)SCREEN_HT, &next->perspectiveCorrect, &fullscreenViewport, NULL, zBias);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// set the near clipping plane to be the exit portal surface
|
if (current->clippingPortalIndex != -1) {
|
||||||
quatMultVector(&toPortal->rotation, &gForward, &next->cullingInfo.clippingPlanes[4].normal);
|
// set the near clipping plane to be the exit portal surface
|
||||||
if (toPortal < fromPortal) {
|
quatMultVector(&toPortal->rotation, &gForward, &next->cullingInfo.clippingPlanes[4].normal);
|
||||||
vector3Negate(&next->cullingInfo.clippingPlanes[4].normal, &next->cullingInfo.clippingPlanes[4].normal);
|
if (toPortal < fromPortal) {
|
||||||
|
vector3Negate(&next->cullingInfo.clippingPlanes[4].normal, &next->cullingInfo.clippingPlanes[4].normal);
|
||||||
|
}
|
||||||
|
next->cullingInfo.clippingPlanes[4].d = -vector3Dot(&next->cullingInfo.clippingPlanes[4].normal, &toPortal->position) * SCENE_SCALE - PORTAL_CLIPPING_PLANE_BIAS;
|
||||||
}
|
}
|
||||||
next->cullingInfo.clippingPlanes[4].d = -vector3Dot(&next->cullingInfo.clippingPlanes[4].normal, &toPortal->position) * SCENE_SCALE - PORTAL_CLIPPING_PLANE_BIAS;
|
next->clippingPortalIndex = -1;
|
||||||
|
|
||||||
next->currentDepth = current->currentDepth - 1;
|
next->currentDepth = current->currentDepth - 1;
|
||||||
next->fromPortalIndex = toPortal < fromPortal ? 0 : 1;
|
next->fromPortalIndex = toPortal < fromPortal ? 0 : 1;
|
||||||
|
@ -219,26 +259,35 @@ void portalRender(struct Portal* portal, struct Portal* otherPortal, struct Rend
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
screenClipperInitWithCamera(&clipper, &props->camera, (float)SCREEN_WD / (float)SCREEN_HT, portalTransform);
|
|
||||||
|
|
||||||
struct Box2D clippingBounds;
|
|
||||||
|
|
||||||
screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds);
|
|
||||||
|
|
||||||
struct RenderProps nextProps;
|
struct RenderProps nextProps;
|
||||||
|
|
||||||
nextProps.minX = CALC_SCREEN_SPACE(clippingBounds.min.x, SCREEN_WD);
|
int portalIndex = portal < otherPortal ? 0 : 1;
|
||||||
nextProps.maxX = CALC_SCREEN_SPACE(clippingBounds.max.x, SCREEN_WD);
|
|
||||||
nextProps.minY = CALC_SCREEN_SPACE(-clippingBounds.max.y, SCREEN_HT);
|
|
||||||
nextProps.maxY = CALC_SCREEN_SPACE(-clippingBounds.min.y, SCREEN_HT);
|
|
||||||
|
|
||||||
nextProps.minX = MAX(nextProps.minX, props->minX);
|
if (props->clippingPortalIndex == portalIndex) {
|
||||||
nextProps.maxX = MIN(nextProps.maxX, props->maxX);
|
nextProps.minX = props->minX;
|
||||||
nextProps.minY = MAX(nextProps.minY, props->minY);
|
nextProps.maxX = props->maxX;
|
||||||
nextProps.maxY = MIN(nextProps.maxY, props->maxY);
|
nextProps.minY = props->minY;
|
||||||
|
nextProps.maxY = props->maxY;
|
||||||
|
} else {
|
||||||
|
screenClipperInitWithCamera(&clipper, &props->camera, (float)SCREEN_WD / (float)SCREEN_HT, portalTransform);
|
||||||
|
|
||||||
|
struct Box2D clippingBounds;
|
||||||
|
|
||||||
|
screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds);
|
||||||
|
|
||||||
|
|
||||||
|
nextProps.minX = CALC_SCREEN_SPACE(clippingBounds.min.x, SCREEN_WD);
|
||||||
|
nextProps.maxX = CALC_SCREEN_SPACE(clippingBounds.max.x, SCREEN_WD);
|
||||||
|
nextProps.minY = CALC_SCREEN_SPACE(-clippingBounds.max.y, SCREEN_HT);
|
||||||
|
nextProps.maxY = CALC_SCREEN_SPACE(-clippingBounds.min.y, SCREEN_HT);
|
||||||
|
|
||||||
|
nextProps.minX = MAX(nextProps.minX, props->minX);
|
||||||
|
nextProps.maxX = MIN(nextProps.maxX, props->maxX);
|
||||||
|
nextProps.minY = MAX(nextProps.minY, props->minY);
|
||||||
|
nextProps.maxY = MIN(nextProps.maxY, props->maxY);
|
||||||
|
}
|
||||||
|
|
||||||
if (nextProps.minX < nextProps.maxX && nextProps.minY < nextProps.maxY) {
|
if (nextProps.minX < nextProps.maxX && nextProps.minY < nextProps.maxY) {
|
||||||
|
|
||||||
renderPropsNext(props, &nextProps, &portal->transform, &otherPortal->transform, renderState);
|
renderPropsNext(props, &nextProps, &portal->transform, &otherPortal->transform, renderState);
|
||||||
sceneRenderer(data, &nextProps, renderState);
|
sceneRenderer(data, &nextProps, renderState);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct RenderProps {
|
||||||
short minY;
|
short minY;
|
||||||
short maxX;
|
short maxX;
|
||||||
short maxY;
|
short maxY;
|
||||||
|
|
||||||
|
s8 clippingPortalIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState, u16 roomIndex);
|
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState, u16 roomIndex);
|
||||||
|
|
Loading…
Reference in a new issue