Rework player collider

This commit is contained in:
James Lambert 2022-06-07 08:32:16 -06:00
parent a6aba230c5
commit bbe5c38eff
15 changed files with 204 additions and 63 deletions

View file

@ -57,10 +57,10 @@ where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where blender
## Current TODO list ## Current TODO list
Cylinder touching bug
Create elevator geometry Create elevator geometry
Allow player to press button
Collide player with objects in scene Collide player with objects in scene
Cylinder touching bug
Allow player to press button
Radio Radio
Create radio model Create radio model
Create radio texture Create radio texture

View file

@ -21,6 +21,7 @@ enum CollisionShapeType {
struct ColliderTypeData; struct ColliderTypeData;
struct CollisionObject; struct CollisionObject;
struct RaycastHit; struct RaycastHit;
struct CollisionSphere;
typedef float (*MomentOfInertiaCalculator)(struct ColliderTypeData* typeData, float mass); typedef float (*MomentOfInertiaCalculator)(struct ColliderTypeData* typeData, float mass);
typedef void (*BoundingBoxCalculator)(struct ColliderTypeData* typeData, struct Transform* transform, struct Box3D* box); typedef void (*BoundingBoxCalculator)(struct ColliderTypeData* typeData, struct Transform* transform, struct Box3D* box);
@ -31,12 +32,15 @@ typedef int (*RaycastCollider)(struct CollisionObject* object, struct Ray* ray,
typedef int (*MinkowsiSumWithBasis)(void* data, struct Basis* basis, struct Vector3* direction, struct Vector3* output); typedef int (*MinkowsiSumWithBasis)(void* data, struct Basis* basis, struct Vector3* direction, struct Vector3* output);
typedef int (*CollideWithSphere)(void* data, struct Transform* transform, struct CollisionSphere* sphere, struct Vector3* spherePos, struct ContactManifold* contact);
struct ColliderCallbacks { struct ColliderCallbacks {
CollideWithQuad collideWithQuad; CollideWithQuad collideWithQuad;
RaycastCollider raycast; RaycastCollider raycast;
MomentOfInertiaCalculator mofICalculator; MomentOfInertiaCalculator mofICalculator;
BoundingBoxCalculator boundingBoxCalculator; BoundingBoxCalculator boundingBoxCalculator;
MinkowsiSumWithBasis minkowsiSum; MinkowsiSumWithBasis minkowsiSum;
CollideWithSphere collideWithSphere;
}; };
struct ColliderTypeData { struct ColliderTypeData {

View file

@ -17,6 +17,10 @@ int collisionObjectIsActive(struct CollisionObject* object) {
return object->body && (object->body->flags & (RigidBodyIsKinematic | RigidBodyIsSleeping)) == 0; return object->body && (object->body->flags & (RigidBodyIsKinematic | RigidBodyIsSleeping)) == 0;
} }
int collisionObjectShouldGenerateConctacts(struct CollisionObject* object) {
return collisionObjectIsActive(object) || (object->body->flags & RigidBodyGenerateContacts) != 0;
}
void collisionObjectCollideWithQuad(struct CollisionObject* object, struct CollisionObject* quadObject, struct ContactSolver* contactSolver) { void collisionObjectCollideWithQuad(struct CollisionObject* object, struct CollisionObject* quadObject, struct ContactSolver* contactSolver) {
if ((object->collisionLayers | quadObject->collisionLayers) == 0) { if ((object->collisionLayers | quadObject->collisionLayers) == 0) {
return; return;

View file

@ -18,6 +18,7 @@ struct CollisionObject {
}; };
int collisionObjectIsActive(struct CollisionObject* object); int collisionObjectIsActive(struct CollisionObject* object);
int collisionObjectShouldGenerateConctacts(struct CollisionObject* object);
void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData *collider, struct RigidBody* body, float mass, int collisionLayers); void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData *collider, struct RigidBody* body, float mass, int collisionLayers);

View file

@ -515,7 +515,7 @@ void collisionSceneWalkBroadphase(struct CollisionScene* collisionScene, struct
continue; continue;
} }
if (!collisionObjectIsActive(existing) && !collisionObjectIsActive(subject)) { if (!collisionObjectShouldGenerateConctacts(existing) && !collisionObjectShouldGenerateConctacts(subject)) {
continue; continue;
} }
@ -571,7 +571,7 @@ void collisionSceneUpdateDynamics() {
contactSolverRemoveUnusedContacts(&gContactSolver); contactSolverRemoveUnusedContacts(&gContactSolver);
for (unsigned i = 0; i < gCollisionScene.dynamicObjectCount; ++i) { for (unsigned i = 0; i < gCollisionScene.dynamicObjectCount; ++i) {
if (!collisionObjectIsActive(gCollisionScene.dynamicObjects[i])) { if (!collisionObjectShouldGenerateConctacts(gCollisionScene.dynamicObjects[i])) {
continue; continue;
} }
@ -585,9 +585,14 @@ void collisionSceneUpdateDynamics() {
for (unsigned i = 0; i < gCollisionScene.dynamicObjectCount; ++i) { for (unsigned i = 0; i < gCollisionScene.dynamicObjectCount; ++i) {
struct CollisionObject* collisionObject = gCollisionScene.dynamicObjects[i]; struct CollisionObject* collisionObject = gCollisionScene.dynamicObjects[i];
if (!collisionObjectIsActive(collisionObject)) { if (!collisionObjectIsActive(collisionObject)) {
// kind of a hack, but the player is the only kinematic body that
// also generates contacts and the player velocty should not be
// cleared
if (!collisionObjectShouldGenerateConctacts(collisionObject)) {
// clear out any velocities // clear out any velocities
collisionObject->body->velocity = gZeroVec; collisionObject->body->velocity = gZeroVec;
collisionObject->body->angularVelocity = gZeroVec; collisionObject->body->angularVelocity = gZeroVec;
}
continue; continue;
} }

View file

@ -84,4 +84,82 @@ struct ColliderCallbacks gCollisionSphereCallbacks = {
NULL, // TODO NULL, // TODO
collisionSphereSolidMofI, collisionSphereSolidMofI,
collisionSphereBoundingBox, collisionSphereBoundingBox,
NULL,
collisionSphereCollideWithSphere,
}; };
int collisionSphereCheckWithNearestPoint(struct Vector3* nearestPoint, struct CollisionSphere* otherSphere, struct Vector3* spherePos, struct ContactManifold* contact) {
vector3Sub(spherePos, nearestPoint, &contact->normal);
float distanceSqrd = vector3MagSqrd(&contact->normal);
if (distanceSqrd > otherSphere->radius * otherSphere->radius) {
return 0;
}
float distance = 0.0f;
if (distanceSqrd < 0.00001f) {
contact->normal = gRight;
} else {
distance = sqrtf(distanceSqrd);
vector3Scale(&contact->normal, &contact->normal, 1.0f / distance);
}
struct ContactPoint* contactPoint = &contact->contacts[0];
vector3Scale(&contact->normal, &contactPoint->contactAWorld, otherSphere->radius);
vector3Scale(&contact->normal, &contactPoint->contactBWorld, -otherSphere->radius);
contactPoint->bias = 0.0f;
contactPoint->id = 0;
contactPoint->normalImpulse = 0.0f;
contactPoint->normalMass = 0.0f;
contactPoint->penetration = distance - otherSphere->radius;
contactPoint->tangentImpulse[0] = 0.0f;
contactPoint->tangentImpulse[1] = 0.0f;
contactPoint->tangentMass[0] = 0.0f;
contactPoint->tangentMass[0] = 0.0f;
return 1;
}
int collisionSphereCollideWithSphere(void* data, struct Transform* transform, struct CollisionSphere* otherSphere, struct Vector3* spherePos, struct ContactManifold* contact) {
struct CollisionSphere* sphere = (struct CollisionSphere*)data;
vector3Sub(spherePos, &transform->position, &contact->normal);
float radiusSum = sphere->radius + otherSphere->radius;
float distanceSqrd = vector3MagSqrd(&contact->normal);
if (distanceSqrd > radiusSum * radiusSum) {
return 0;
}
float distance = 0.0f;
if (distanceSqrd < 0.00001f) {
contact->normal = gRight;
} else {
distance = sqrtf(distanceSqrd);
vector3Scale(&contact->normal, &contact->normal, 1.0f / distance);
}
struct ContactPoint* contactPoint = &contact->contacts[0];
vector3Scale(&contact->normal, &contactPoint->contactAWorld, sphere->radius);
vector3Scale(&contact->normal, &contactPoint->contactBWorld, -otherSphere->radius);
contactPoint->bias = 0.0f;
contactPoint->id = 0;
contactPoint->normalImpulse = 0.0f;
contactPoint->normalMass = 0.0f;
contactPoint->penetration = distance - radiusSum;
contactPoint->tangentImpulse[0] = 0.0f;
contactPoint->tangentImpulse[1] = 0.0f;
contactPoint->tangentMass[0] = 0.0f;
contactPoint->tangentMass[0] = 0.0f;
return 1;
}

View file

@ -11,6 +11,7 @@ struct CollisionSphere {
int collisionSphereCollideQuad(void* data, struct Transform* boxTransform, struct CollisionQuad* quad, struct ContactManifold* output); int collisionSphereCollideQuad(void* data, struct Transform* boxTransform, struct CollisionQuad* quad, struct ContactManifold* output);
float collisionSphereSolidMofI(struct ColliderTypeData* typeData, float mass); float collisionSphereSolidMofI(struct ColliderTypeData* typeData, float mass);
int collisionSphereCheckWithNearestPoint(struct Vector3* nearestPoint, struct CollisionSphere* otherSphere, struct Vector3* spherePos, struct ContactManifold* contact);
int collisionSphereCollideWithSphere(void* data, struct Transform* transform, struct CollisionSphere* otherSphere, struct Vector3* spherePos, struct ContactManifold* contact);
#endif #endif

View file

@ -475,6 +475,8 @@ struct ContactManifold* contactSolverGetContactManifold(struct ContactSolver* so
struct ContactManifold* contactSolverNextManifold(struct ContactSolver* solver, struct CollisionObject* forObject, struct ContactManifold* current) { struct ContactManifold* contactSolverNextManifold(struct ContactSolver* solver, struct CollisionObject* forObject, struct ContactManifold* current) {
if (!current) { if (!current) {
current = solver->activeContacts; current = solver->activeContacts;
} else {
current = current->next;
} }
while (current) { while (current) {

View file

@ -24,7 +24,7 @@ void rigidBodyInit(struct RigidBody* rigidBody, float mass, float momentOfIniter
basisFromQuat(&rigidBody->rotationBasis, &rigidBody->transform.rotation); basisFromQuat(&rigidBody->rotationBasis, &rigidBody->transform.rotation);
} }
void rigitBodyMarkKinematic(struct RigidBody* rigidBody) { void rigidBodyMarkKinematic(struct RigidBody* rigidBody) {
rigidBody->flags |= RigidBodyIsKinematic; rigidBody->flags |= RigidBodyIsKinematic;
rigidBody->mass = 1000000000000000.0f; rigidBody->mass = 1000000000000000.0f;
rigidBody->massInv = 0.0f; rigidBody->massInv = 0.0f;

View file

@ -17,6 +17,9 @@ enum RigidBodyFlags {
RigidBodyIsKinematic = (1 << 8), RigidBodyIsKinematic = (1 << 8),
RigidBodyIsSleeping = (1 << 9), RigidBodyIsSleeping = (1 << 9),
// for kinematic bodies that should generate
// contacts with other kinematic bodies
RigidBodyGenerateContacts = (1 << 10),
}; };
struct RigidBody { struct RigidBody {
@ -41,7 +44,7 @@ struct RigidBody {
}; };
void rigidBodyInit(struct RigidBody* rigidBody, float mass, float momentOfIniteria); void rigidBodyInit(struct RigidBody* rigidBody, float mass, float momentOfIniteria);
void rigitBodyMarkKinematic(struct RigidBody* rigidBody); void rigidBodyMarkKinematic(struct RigidBody* rigidBody);
void rigidBodyAppyImpulse(struct RigidBody* rigidBody, struct Vector3* worldPoint, struct Vector3* impulse); void rigidBodyAppyImpulse(struct RigidBody* rigidBody, struct Vector3* worldPoint, struct Vector3* impulse);
void rigidBodyUpdate(struct RigidBody* rigidBody); void rigidBodyUpdate(struct RigidBody* rigidBody);
void rigidBodyVelocityAtLocalPoint(struct RigidBody* rigidBody, struct Vector3* localPoint, struct Vector3* worldVelocity); void rigidBodyVelocityAtLocalPoint(struct RigidBody* rigidBody, struct Vector3* localPoint, struct Vector3* worldVelocity);

View file

@ -1,36 +1,51 @@
#include "player.h" #include "player.h"
#include "../controls/controller.h"
#include "../util/time.h"
#include "../defs.h"
#include "../physics/point_constraint.h"
#include "../math/mathf.h"
#include "physics/collision_sphere.h"
#include "physics/collision_scene.h"
#include "physics/config.h"
#include "../levels/levels.h"
#include "../audio/soundplayer.h"
#include "../audio/clips.h" #include "../audio/clips.h"
#include "../audio/soundplayer.h"
#include "../controls/controller.h"
#include "../defs.h"
#include "../levels/levels.h"
#include "../math/mathf.h"
#include "../physics/collision_cylinder.h"
#include "../physics/collision_scene.h"
#include "../physics/collision.h"
#include "../physics/config.h"
#include "../physics/point_constraint.h"
#include "../util/time.h"
#define GRAB_RAYCAST_DISTANCE 2.5f #define GRAB_RAYCAST_DISTANCE 2.5f
struct Vector3 gGrabDistance = {0.0f, 0.0f, -1.5f}; struct Vector3 gGrabDistance = {0.0f, 0.0f, -1.5f};
struct Vector3 gCameraOffset = {0.0f, 0.0f, 0.0f}; struct Vector3 gCameraOffset = {0.0f, 0.0f, 0.0f};
struct CollisionSphere gPlayerCollider = { struct Vector2 gPlayerColliderEdgeVectors[] = {
{0.0f, 1.0f},
{0.707f, 0.707f},
{1.0f, 0.0f},
{0.707f, -0.707f},
};
struct CollisionCylinder gPlayerCollider = {
0.25f, 0.25f,
0.7f,
gPlayerColliderEdgeVectors,
sizeof(gPlayerColliderEdgeVectors) / sizeof(*gPlayerColliderEdgeVectors),
}; };
struct ColliderTypeData gPlayerColliderData = { struct ColliderTypeData gPlayerColliderData = {
CollisionShapeTypeSphere, CollisionShapeTypeCylinder,
&gPlayerCollider, &gPlayerCollider,
0.1f, 0.0f,
0.5f, 0.6f,
&gCollisionSphereCallbacks, &gCollisionCylinderCallbacks,
}; };
void playerInit(struct Player* player, struct Location* startLocation) { void playerInit(struct Player* player, struct Location* startLocation) {
collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f, COLLISION_LAYERS_TANGIBLE); collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f, COLLISION_LAYERS_TANGIBLE);
rigidBodyMarkKinematic(&player->body);
player->body.flags |= RigidBodyGenerateContacts;
collisionSceneAddDynamicObject(&player->collisionObject);
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING; player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
player->grabbing = NULL; player->grabbing = NULL;
player->pitchVelocity = 0.0f; player->pitchVelocity = 0.0f;
@ -38,13 +53,16 @@ void playerInit(struct Player* player, struct Location* startLocation) {
player->flags = 0; player->flags = 0;
if (startLocation) { if (startLocation) {
player->body.transform = startLocation->transform; player->lookTransform = startLocation->transform;
player->body.currentRoom = startLocation->roomIndex; player->body.currentRoom = startLocation->roomIndex;
} else { } else {
transformInitIdentity(&player->body.transform); transformInitIdentity(&player->lookTransform);
player->body.currentRoom = 0; player->body.currentRoom = 0;
} }
player->body.transform.position.y += PLAYER_HEAD_HEIGHT; player->lookTransform.position.y += PLAYER_HEAD_HEIGHT;
player->body.transform = player->lookTransform;
collisionObjectUpdateBB(&player->collisionObject);
} }
#define PLAYER_SPEED (3.0f) #define PLAYER_SPEED (3.0f)
@ -57,16 +75,33 @@ void playerInit(struct Player* player, struct Location* startLocation) {
#define JUMP_IMPULSE 3.2f #define JUMP_IMPULSE 3.2f
void playerHandleCollision(void* data, struct ContactManifold* contact) { void playerHandleCollision(struct Player* player) {
struct Player* player = (struct Player*)data; struct ContactManifold* contact = contactSolverNextManifold(&gContactSolver, &player->collisionObject, NULL);
if (contact->contactCount == 1 && contact->contacts[0].penetration < 0.0f) { while (contact) {
float offset = 0.0f;
for (int i = 0; i < contact->contactCount; ++i) {
struct ContactPoint* contactPoint = &contact->contacts[i];
offset = MIN(offset, contactPoint->penetration);
}
if (offset != 0.0f) {
vector3AddScaled( vector3AddScaled(
&player->body.transform.position, &player->body.transform.position,
&contact->normal, &contact->normal,
-contact->contacts[0].penetration, (contact->shapeA == &player->collisionObject ? offset : -offset) * 0.9f,
&player->body.transform.position &player->body.transform.position
); );
float relativeVelocity = vector3Dot(&contact->normal, &player->body.velocity);
if ((contact->shapeA == &player->collisionObject) == (relativeVelocity > 0.0f)) {
vector3ProjectPlane(&player->body.velocity, &contact->normal, &player->body.velocity);
}
}
contact = contactSolverNextManifold(&gContactSolver, &player->collisionObject, contact);
} }
} }
@ -85,8 +120,8 @@ void playerUpdateGrabbedObject(struct Player* player) {
} else { } else {
struct Ray ray; struct Ray ray;
ray.origin = player->body.transform.position; ray.origin = player->lookTransform.position;
quatMultVector(&player->body.transform.rotation, &gForward, &ray.dir); quatMultVector(&player->lookTransform.rotation, &gForward, &ray.dir);
vector3Negate(&ray.dir, &ray.dir); vector3Negate(&ray.dir, &ray.dir);
struct RaycastHit hit; struct RaycastHit hit;
@ -121,9 +156,9 @@ void playerUpdateGrabbedObject(struct Player* player) {
} }
struct Vector3 grabPoint; struct Vector3 grabPoint;
struct Quaternion grabRotation = player->body.transform.rotation; struct Quaternion grabRotation = player->lookTransform.rotation;
transformPoint(&player->body.transform, &gGrabDistance, &grabPoint); transformPoint(&player->lookTransform, &gGrabDistance, &grabPoint);
if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) { if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) {
if (!collisionSceneIsPortalOpen()) { if (!collisionSceneIsPortalOpen()) {
@ -169,9 +204,9 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
struct Vector3 forward; struct Vector3 forward;
struct Vector3 right; struct Vector3 right;
int doorwayMask = worldCheckDoorwaySides(&gCurrentLevel->world, &player->body.transform.position, player->body.currentRoom); int doorwayMask = worldCheckDoorwaySides(&gCurrentLevel->world, &player->lookTransform.position, player->body.currentRoom);
struct Transform* transform = &player->body.transform; struct Transform* transform = &player->lookTransform;
quatMultVector(&transform->rotation, &gForward, &forward); quatMultVector(&transform->rotation, &gForward, &forward);
quatMultVector(&transform->rotation, &gRight, &right); quatMultVector(&transform->rotation, &gRight, &right);
@ -218,12 +253,13 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
vector3Dot(&player->body.velocity, &targetVelocity) > 0.0f ? PLAYER_ACCEL * FIXED_DELTA_TIME : PLAYER_STOP_ACCEL * FIXED_DELTA_TIME, vector3Dot(&player->body.velocity, &targetVelocity) > 0.0f ? PLAYER_ACCEL * FIXED_DELTA_TIME : PLAYER_STOP_ACCEL * FIXED_DELTA_TIME,
&player->body.velocity &player->body.velocity
); );
player->body.angularVelocity = gZeroVec;
player->body.velocity.y += GRAVITY_CONSTANT * FIXED_DELTA_TIME; player->body.velocity.y += GRAVITY_CONSTANT * FIXED_DELTA_TIME;
vector3AddScaled(&transform->position, &player->body.velocity, FIXED_DELTA_TIME, &transform->position); vector3AddScaled(&player->body.transform.position, &player->body.velocity, FIXED_DELTA_TIME, &player->body.transform.position);
collisionObjectQueryScene(&player->collisionObject, &gCollisionScene, player, playerHandleCollision); playerHandleCollision(player);
struct RaycastHit hit; struct RaycastHit hit;
struct Ray ray; struct Ray ray;
@ -238,8 +274,14 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
player->flags &= ~PlayerFlagsGrounded; player->flags &= ~PlayerFlagsGrounded;
} }
player->body.transform.rotation = player->lookTransform.rotation;
int didPassThroughPortal = rigidBodyCheckPortals(&player->body); int didPassThroughPortal = rigidBodyCheckPortals(&player->body);
player->lookTransform.position = player->body.transform.position;
player->lookTransform.rotation = player->body.transform.rotation;
quatIdent(&player->body.transform.rotation);
if (didPassThroughPortal) { if (didPassThroughPortal) {
soundPlayerPlay(soundsPortalEnter[didPassThroughPortal - 1], 0.75f, 1.0f); soundPlayerPlay(soundsPortalEnter[didPassThroughPortal - 1], 0.75f, 1.0f);
soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f); soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f);
@ -263,13 +305,13 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
struct Vector3 lookingForward; struct Vector3 lookingForward;
vector3Negate(&gForward, &lookingForward); vector3Negate(&gForward, &lookingForward);
quatMultVector(&player->body.transform.rotation, &lookingForward, &lookingForward); quatMultVector(&player->lookTransform.rotation, &lookingForward, &lookingForward);
// if player is looking close to directly up or down, don't correct the rotation // if player is looking close to directly up or down, don't correct the rotation
if (fabsf(lookingForward.y) < 0.99f) { if (fabsf(lookingForward.y) < 0.99f) {
struct Quaternion upRotation; struct Quaternion upRotation;
quatLook(&lookingForward, &gUp, &upRotation); quatLook(&lookingForward, &gUp, &upRotation);
quatLerp(&upRotation, &player->body.transform.rotation, 0.9f, &player->body.transform.rotation); quatLerp(&upRotation, &player->lookTransform.rotation, 0.9f, &player->lookTransform.rotation);
} }
@ -277,18 +319,18 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
struct Quaternion deltaRotate; struct Quaternion deltaRotate;
quatAxisAngle(&gUp, player->yawVelocity * FIXED_DELTA_TIME, &deltaRotate); quatAxisAngle(&gUp, player->yawVelocity * FIXED_DELTA_TIME, &deltaRotate);
struct Quaternion tempRotation; struct Quaternion tempRotation;
quatMultiply(&deltaRotate, &player->body.transform.rotation, &tempRotation); quatMultiply(&deltaRotate, &player->lookTransform.rotation, &tempRotation);
// pitch // pitch
quatAxisAngle(&gRight, player->pitchVelocity * FIXED_DELTA_TIME, &deltaRotate); quatAxisAngle(&gRight, player->pitchVelocity * FIXED_DELTA_TIME, &deltaRotate);
quatMultiply(&tempRotation, &deltaRotate, &player->body.transform.rotation); quatMultiply(&tempRotation, &deltaRotate, &player->lookTransform.rotation);
// prevent player from looking too far up or down // prevent player from looking too far up or down
vector3Negate(&gForward, &lookingForward); vector3Negate(&gForward, &lookingForward);
quatMultVector(&tempRotation, &lookingForward, &lookingForward); quatMultVector(&tempRotation, &lookingForward, &lookingForward);
struct Vector3 newLookingForward; struct Vector3 newLookingForward;
vector3Negate(&gForward, &newLookingForward); vector3Negate(&gForward, &newLookingForward);
quatMultVector(&player->body.transform.rotation, &newLookingForward, &newLookingForward); quatMultVector(&player->lookTransform.rotation, &newLookingForward, &newLookingForward);
float pitchSign = signf(player->pitchVelocity); float pitchSign = signf(player->pitchVelocity);
@ -297,15 +339,15 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
newForward.y = pitchSign; newForward.y = pitchSign;
struct Vector3 newUp; struct Vector3 newUp;
quatMultVector(&tempRotation, &gUp, &newUp); quatMultVector(&tempRotation, &gUp, &newUp);
quatLook(&newForward, &newUp, &player->body.transform.rotation); quatLook(&newForward, &newUp, &player->lookTransform.rotation);
player->pitchVelocity = 0.0f; player->pitchVelocity = 0.0f;
} }
cameraTransform->rotation = player->body.transform.rotation; cameraTransform->rotation = player->lookTransform.rotation;
transformPoint(transform, &gCameraOffset, &cameraTransform->position); cameraTransform->position = player->lookTransform.position;
playerUpdateGrabbedObject(player); playerUpdateGrabbedObject(player);
collisionObjectUpdateBB(&player->collisionObject); collisionObjectUpdateBB(&player->collisionObject);
player->body.currentRoom = worldCheckDoorwayCrossings(&gCurrentLevel->world, &player->body.transform.position, player->body.currentRoom, doorwayMask); player->body.currentRoom = worldCheckDoorwayCrossings(&gCurrentLevel->world, &player->lookTransform.position, player->body.currentRoom, doorwayMask);
} }

View file

@ -18,6 +18,7 @@ enum PlayerFlags {
struct Player { struct Player {
struct CollisionObject collisionObject; struct CollisionObject collisionObject;
struct RigidBody body; struct RigidBody body;
struct Transform lookTransform;
short grabbingThroughPortal; short grabbingThroughPortal;
struct RigidBody* grabbing; struct RigidBody* grabbing;
float pitchVelocity; float pitchVelocity;

View file

@ -55,7 +55,7 @@ void buttonRender(void* data, struct RenderScene* renderScene) {
void buttonInit(struct Button* button, struct ButtonDefinition* definition) { void buttonInit(struct Button* button, struct ButtonDefinition* definition) {
collisionObjectInit(&button->collisionObject, &gButtonCollider, &button->rigidBody, 1.0f, COLLISION_LAYERS_TANGIBLE); collisionObjectInit(&button->collisionObject, &gButtonCollider, &button->rigidBody, 1.0f, COLLISION_LAYERS_TANGIBLE);
rigitBodyMarkKinematic(&button->rigidBody); rigidBodyMarkKinematic(&button->rigidBody);
collisionSceneAddDynamicObject(&button->collisionObject); collisionSceneAddDynamicObject(&button->collisionObject);
button->rigidBody.transform.position = definition->location; button->rigidBody.transform.position = definition->location;

View file

@ -51,7 +51,7 @@ void doorRender(void* data, struct RenderScene* renderScene) {
void doorInit(struct Door* door, struct DoorDefinition* doorDefinition, struct World* world) { void doorInit(struct Door* door, struct DoorDefinition* doorDefinition, struct World* world) {
collisionObjectInit(&door->collisionObject, &gDoorCollider, &door->rigidBody, 1.0f, COLLISION_LAYERS_TANGIBLE); collisionObjectInit(&door->collisionObject, &gDoorCollider, &door->rigidBody, 1.0f, COLLISION_LAYERS_TANGIBLE);
rigitBodyMarkKinematic(&door->rigidBody); rigidBodyMarkKinematic(&door->rigidBody);
collisionSceneAddDynamicObject(&door->collisionObject); collisionSceneAddDynamicObject(&door->collisionObject);
door->rigidBody.transform.position = doorDefinition->location; door->rigidBody.transform.position = doorDefinition->location;

View file

@ -134,10 +134,10 @@ void sceneRenderPerformanceMetrics(struct Scene* scene, struct RenderState* rend
void sceneRenderPortalGun(struct Scene* scene, struct RenderState* renderState) { void sceneRenderPortalGun(struct Scene* scene, struct RenderState* renderState) {
struct Transform gunTransform; struct Transform gunTransform;
transformPoint(&scene->player.body.transform, &gPortalGunOffset, &gunTransform.position); transformPoint(&scene->player.lookTransform, &gPortalGunOffset, &gunTransform.position);
struct Quaternion relativeRotation; struct Quaternion relativeRotation;
quatLook(&gPortalGunForward, &gPortalGunUp, &relativeRotation); quatLook(&gPortalGunForward, &gPortalGunUp, &relativeRotation);
quatMultiply(&scene->player.body.transform.rotation, &relativeRotation, &gunTransform.rotation); quatMultiply(&scene->player.lookTransform.rotation, &relativeRotation, &gunTransform.rotation);
gunTransform.scale = gOneVec; gunTransform.scale = gOneVec;
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderState, 1);
transformToMatrixL(&gunTransform, matrix, SCENE_SCALE); transformToMatrixL(&gunTransform, matrix, SCENE_SCALE);
@ -178,10 +178,10 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
void sceneCheckPortals(struct Scene* scene) { void sceneCheckPortals(struct Scene* scene) {
struct Ray raycastRay; struct Ray raycastRay;
struct Vector3 playerUp; struct Vector3 playerUp;
raycastRay.origin = scene->player.body.transform.position; raycastRay.origin = scene->player.lookTransform.position;
vector3Negate(&gForward, &raycastRay.dir); vector3Negate(&gForward, &raycastRay.dir);
quatMultVector(&scene->player.body.transform.rotation, &raycastRay.dir, &raycastRay.dir); quatMultVector(&scene->player.lookTransform.rotation, &raycastRay.dir, &raycastRay.dir);
quatMultVector(&scene->player.body.transform.rotation, &gUp, &playerUp); quatMultVector(&scene->player.lookTransform.rotation, &gUp, &playerUp);
if (controllerGetButtonDown(0, Z_TRIG)) { if (controllerGetButtonDown(0, Z_TRIG)) {
sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom); sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom);
@ -217,7 +217,7 @@ void sceneUpdate(struct Scene* scene) {
collisionSceneUpdateDynamics(); collisionSceneUpdateDynamics();
levelCheckTriggers(&scene->player.body.transform.position); levelCheckTriggers(&scene->player.lookTransform.position);
cutsceneRunnerUpdate(&gCutsceneRunner); cutsceneRunnerUpdate(&gCutsceneRunner);
scene->cpuTime = osGetTime() - frameStart; scene->cpuTime = osGetTime() - frameStart;