Fixup some bugs

This commit is contained in:
James Lambert 2022-08-15 08:22:44 -06:00
parent 333b17f9ad
commit d56aac8c1d
21 changed files with 64 additions and 37 deletions

View file

@ -84,6 +84,8 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
## Current TODO list
- [ ] level transition jump
- [ ] Z buffer allocation
- [ ] Release grabbed objects when line of sight is cut
- [ ] Correct elevator timing
- [ ] Elevator and door sounds
@ -91,6 +93,9 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
- [ ] Cube dispenser
- [ ] Signage should not always be on
- [ ] Camera shake
- [x] collide player with dynamic objects
- [x] Render objects intersecting portals differently
- [x] Sliding against walls
- [x] It is too easy to fall through portals
- [x] Change the way player standing logic works
- [x] crash on level transition

Binary file not shown.

View file

@ -82,12 +82,6 @@ void decorObjectUpdate(struct DecorObject* decorObject) {
soundPlayerUpdatePosition(decorObject->playingSound, &decorObject->rigidBody.transform.position);
}
if (decorObject->rigidBody.flags & (RigidBodyIsTouchingPortalA | RigidBodyWasTouchingPortalA | RigidBodyIsTouchingPortalB | RigidBodyWasTouchingPortalB)) {
dynamicSceneSetFlags(decorObject->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
} else {
dynamicSceneClearFlags(decorObject->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
}
if (decorObject->rigidBody.flags & RigidBodyFizzled) {
if (decorObject->fizzleTime == 0.0f) {
vector3Scale(&decorObject->rigidBody.velocity, &decorObject->rigidBody.velocity, 0.25f);

View file

@ -148,9 +148,11 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
struct Transform exitInverse;
transformInvert(&gCurrentLevel->locations[step->loadLevel.fromLocation].transform, &exitInverse);
struct Transform relativeExit;
struct Vector3 relativeVelocity;
transformConcat(&exitInverse, &gScene.player.lookTransform, &relativeExit);
levelQueueLoad(step->loadLevel.levelIndex, &relativeExit);
quatMultVector(&exitInverse.rotation, &gScene.player.body.velocity, &relativeVelocity);
levelQueueLoad(step->loadLevel.levelIndex, &relativeExit, &relativeVelocity);
break;
}
case CutsceneStepTypeGoto:

View file

@ -7,6 +7,7 @@
#include "static_render.h"
#include "cutscene_runner.h"
#include "../graphics/graphics.h"
#include "../player/player.h"
#include "../util/rom.h"
#include "../util/memory.h"
@ -17,11 +18,13 @@ u64 gTriggeredCutscenes;
int gQueuedLevel = NO_QUEUED_LEVEL;
struct Transform gRelativeTransform = {
{0.0f, 0.0f, 0.0f},
{0.0f, PLAYER_HEAD_HEIGHT, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 1.0f},
};
struct Vector3 gRelativeVelocity;
int levelCount() {
return LEVEL_COUNT;
}
@ -102,13 +105,14 @@ void levelLoad(int index) {
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);
}
void levelQueueLoad(int index, struct Transform* relativeExitTransform) {
void levelQueueLoad(int index, struct Transform* relativeExitTransform, struct Vector3* relativeVelocity) {
if (index == NEXT_LEVEL) {
gQueuedLevel = gCurrentLevelIndex + 1;
} else {
gQueuedLevel = index;
}
gRelativeTransform = *relativeExitTransform;
gRelativeVelocity = *relativeVelocity;
}
int levelGetQueued() {
@ -119,6 +123,10 @@ struct Transform* levelRelativeTransform() {
return &gRelativeTransform;
}
struct Vector3* levelRelativeVelocity() {
return &gRelativeVelocity;
}
int levelMaterialCount() {
return STATIC_MATERIAL_COUNT;
}

View file

@ -10,9 +10,10 @@
int levelCount();
void levelLoad(int index);
void levelQueueLoad(int index, struct Transform* relativeExitTransform);
void levelQueueLoad(int index, struct Transform* relativeExitTransform, struct Vector3* relativeVelocity);
int levelGetQueued();
struct Transform* levelRelativeTransform();
struct Vector3* levelRelativeVelocity();
extern struct LevelDefinition* gCurrentLevel;

View file

@ -14,6 +14,7 @@ void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData
object->collisionLayers = collisionLayers;
object->data = 0;
object->trigger = 0;
object->manifoldIds = 0;
}
int collisionObjectIsActive(struct CollisionObject* object) {

View file

@ -25,6 +25,7 @@ struct CollisionObject {
short flags;
void* data;
TriggerCallback trigger;
u32 manifoldIds;
};
struct SweptCollisionObject {

View file

@ -120,6 +120,21 @@ void collisionObjectCollideWithSceneSwept(struct CollisionObject* object, struct
}
}
void collisionObjectCollideMixed(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, struct CollisionScene* scene, struct ContactSolver* contactSolver) {
short colliderIndices[MAX_COLLIDERS];
int quadCount = collisionObjectRoomColliders(&scene->world->rooms[object->body->currentRoom], sweptBB, colliderIndices);
for (int i = 0; i < quadCount; ++i) {
struct CollisionObject* quad = &scene->quads[colliderIndices[i]];
if (quad->manifoldIds & object->manifoldIds) {
collisionObjectCollideWithQuad(object, quad, contactSolver);
} else {
collisionObjectCollideWithQuadSwept(object, objectPrevPos, sweptBB, quad, contactSolver);
}
}
}
int collisionSceneFilterPortalContacts(struct ContactManifold* contact) {
int writeIndex = 0;

View file

@ -27,6 +27,7 @@ extern struct CollisionScene gCollisionScene;
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 collisionObjectCollideWithSceneSwept(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, struct CollisionScene* scene, struct ContactSolver* contactSolver);
void collisionObjectCollideMixed(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, 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);

View file

@ -7,6 +7,7 @@
void contactInsert(struct ContactManifold* contactState, struct EpaResult* epaResult) {
int shouldReplace = 1;
int replacementIndex = 0;
int idMask = 1 << (contactState - gContactSolver.contacts);
float smallestOverlap = -10000.0f;
int insertIndex;
@ -41,6 +42,9 @@ void contactInsert(struct ContactManifold* contactState, struct EpaResult* epaRe
vector3Normalize(&contactState->tangentVectors[0], &contactState->tangentVectors[0]);
vector3Cross(&contactState->normal, &contactState->tangentVectors[0], &contactState->tangentVectors[1]);
contactState->shapeA->manifoldIds |= idMask;
contactState->shapeB->manifoldIds |= idMask;
if (insertIndex == MAX_CONTACTS_PER_MANIFOLD) {
if (!shouldReplace) {
return;

View file

@ -78,6 +78,12 @@ void contactSolverCleanupManifold(struct ContactManifold* manifold) {
manifold->contactCount = writeIndex;
}
void contactSolverManifoldCleanup(struct ContactSolver* contactSolver, struct ContactManifold* contact) {
int idMask = ~(1 << (contact - contactSolver->contacts));
contact->shapeA->manifoldIds &= idMask;
contact->shapeB->manifoldIds &= idMask;
}
void contactSolverRemoveUnusedContacts(struct ContactSolver* contactSolver) {
struct ContactManifold* curr = contactSolver->activeContacts;
struct ContactManifold* prev = NULL;
@ -86,6 +92,8 @@ void contactSolverRemoveUnusedContacts(struct ContactSolver* contactSolver) {
contactSolverCleanupManifold(curr);
if (curr->contactCount == 0) {
contactSolverManifoldCleanup(contactSolver, curr);
if (prev) {
prev->next = curr->next;
} else {
@ -136,6 +144,7 @@ void contactSolverCheckPortalContacts(struct ContactSolver* contactSolver, struc
}
if (curr->contactCount == 0) {
contactSolverManifoldCleanup(contactSolver, curr);
if (prev) {
prev->next = curr->next;
} else {

View file

@ -42,7 +42,7 @@ struct ContactManifold {
struct ContactManifold* next;
};
#define MAX_CONTACT_COUNT 16
#define MAX_CONTACT_COUNT 20
struct ContactSolver {
struct ContactManifold contacts[MAX_CONTACT_COUNT];

View file

@ -81,7 +81,8 @@ void meshColliderCollideObject(struct CollisionObject* meshColliderObject, struc
continue;
}
// contactA is already in the local space for the mesh object
// contactA should be in world coordinates
transformPoint(&meshColliderObject->body->transform, &result.contactA, &result.contactA);
// transform contactB to be in the localspace of the other object
transformPoint(&meshColliderObject->body->transform, &result.contactB, &result.contactB);

View file

@ -23,8 +23,7 @@ enum RigidBodyFlags {
RigidBodyIsKinematic = (1 << 10),
RigidBodyIsSleeping = (1 << 11),
// for kinematic bodies that should generate
// contacts with other kinematic bodies
// tells the collision system to generate contacts with the player
RigidBodyIsPlayer = (1 << 12),
RigidBodyFizzled = (1 << 13),

View file

@ -46,12 +46,13 @@ struct ColliderTypeData gPlayerColliderData = {
&gCollisionCylinderCallbacks,
};
void playerInit(struct Player* player, struct Location* startLocation) {
void playerInit(struct Player* player, struct Location* startLocation, struct Vector3* velocity) {
collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f, PLAYER_COLLISION_LAYERS);
// rigidBodyMarkKinematic(&player->body);
player->body.flags |= RigidBodyIsKinematic | RigidBodyIsPlayer;
collisionSceneAddDynamicObject(&player->collisionObject);
player->body.velocity = *velocity;
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
player->grabbing = NULL;
player->pitchVelocity = 0.0f;
@ -65,7 +66,6 @@ void playerInit(struct Player* player, struct Location* startLocation) {
transformInitIdentity(&player->lookTransform);
player->body.currentRoom = 0;
}
player->lookTransform.position.y += PLAYER_HEAD_HEIGHT;
player->body.transform = player->lookTransform;
collisionObjectUpdateBB(&player->collisionObject);
@ -283,7 +283,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
collisionObjectUpdateBB(&player->collisionObject);
box3DUnion(&sweptBB, &player->collisionObject.boundingBox, &sweptBB);
collisionObjectCollideWithSceneSwept(&player->collisionObject, &prevPos, &sweptBB, &gCollisionScene, &gContactSolver);
collisionObjectCollideMixed(&player->collisionObject, &prevPos, &sweptBB, &gCollisionScene, &gContactSolver);
struct RaycastHit hit;
struct Ray ray;

View file

@ -26,7 +26,7 @@ struct Player {
enum PlayerFlags flags;
};
void playerInit(struct Player* player, struct Location* startLocation);
void playerInit(struct Player* player, struct Location* startLocation, struct Vector3* velocity);
void playerUpdate(struct Player* player, struct Transform* cameraTransform);
void playerRender(struct Player* player, struct RenderState* renderState);

View file

@ -5,10 +5,9 @@
struct DynamicScene gDynamicScene;
#define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
#define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE)
#define FLAG_VALUE_NOT_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE)
#define FLAG_VALUE_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
void dynamicSceneInit() {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
@ -16,7 +15,6 @@ void dynamicSceneInit() {
}
}
void dynamicScenePopulateWithFlags(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene, int flags) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
@ -33,13 +31,6 @@ void dynamicScenePopulateWithFlags(struct FrustrumCullingInformation* cullingInf
}
}
void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState) {
struct RenderScene* tmpScene = renderSceneNew(cameraTransform, renderState, MAX_DYNAMIC_SCENE_OBJECTS, ~0);
dynamicScenePopulateWithFlags(cullingInfo, tmpScene, FLAG_VALUE_TOUCHING_PORTAL);
renderSceneGenerate(tmpScene, renderState);
renderSceneFree(tmpScene);
}
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
struct DynamicSceneObject* object = &gDynamicScene.objects[i];

View file

@ -12,7 +12,6 @@ typedef void (*DynamicRender)(void* data, struct RenderScene* renderScene);
#define DYNAMIC_SCENE_OBJECT_FLAGS_USED (1 << 0)
#define DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE (1 << 1)
#define DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL (1 << 2)
#define INVALID_DYNAMIC_OBJECT -1
@ -30,8 +29,6 @@ struct DynamicScene {
void dynamicSceneInit();
void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState);
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius);
void dynamicSceneRemove(int id);
void dynamicSceneSetFlags(int id, int flags);

View file

@ -204,8 +204,6 @@ int renderPropsNext(struct RenderProps* current, struct RenderProps* next, struc
return 0;
}
dynamicSceneRenderTouchingPortal(&next->camera.transform, &current->cullingInfo, renderState);
next->currentDepth = current->currentDepth - 1;
Vp* viewport = renderPropsBuildViewport(next, renderState);

View file

@ -40,14 +40,16 @@ void sceneUpdateListeners(struct Scene* scene);
void sceneInit(struct Scene* scene) {
signalsInit(1);
cameraInit(&scene->camera, 70.0f, 0.125f * SCENE_SCALE, 40.0f * SCENE_SCALE);
cameraInit(&scene->camera, 70.0f, 0.125f * SCENE_SCALE, 30.0f * SCENE_SCALE);
struct Location* startLocation = levelGetLocation(gCurrentLevel->startLocation);
struct Location combinedLocation;
struct Vector3 startVelocity;
combinedLocation.roomIndex = startLocation->roomIndex;
transformConcat(&startLocation->transform, levelRelativeTransform(), &combinedLocation.transform);
quatMultVector(&startLocation->transform.rotation, levelRelativeVelocity(), &startVelocity);
playerInit(&scene->player, &combinedLocation);
playerInit(&scene->player, &combinedLocation, &startVelocity);
sceneUpdateListeners(scene);
portalInit(&scene->portals[0], 0);
@ -192,8 +194,6 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
dynamicSceneRenderTouchingPortal(&scene->camera.transform, &renderProperties.cullingInfo, renderState);
sceneRenderWithProperties(scene, &renderProperties, renderState);
sceneRenderPortalGun(scene, renderState);