Skip to content

Commit

Permalink
Merge pull request #50 from Deconimus/grab_rotation_snap_cubenormals
Browse files Browse the repository at this point in the history
Snap grab rotations to cube normals
  • Loading branch information
mwpenny authored Apr 6, 2024
2 parents 618f147 + 62c49dd commit d5fea9a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 21 deletions.
89 changes: 70 additions & 19 deletions src/player/player.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ struct ColliderTypeData gPlayerColliderData = {
&gCollisionCapsuleCallbacks,
};

struct Vector3 gCubeNormals[6] = {
{ 1.0f, 0.0f, 0.0f },
{ -1.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, -1.0f }
};

void playerRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState) {
struct Player* player = (struct Player*)data;

Expand All @@ -90,7 +99,7 @@ void playerRender(void* data, struct DynamicRenderDataList* renderList, struct R
struct Vector3 forwardVector;
struct Vector3 unusedRight;

playerGetMoveBasis(&player->lookTransform, &forwardVector, &unusedRight);
playerGetMoveBasis(&player->lookTransform.rotation, &forwardVector, &unusedRight);

finalPlayerTransform.position = player->body.transform.position;
quatLook(&forwardVector, &gUp, &finalPlayerTransform.rotation);
Expand Down Expand Up @@ -263,6 +272,45 @@ void playerSetGrabbing(struct Player* player, struct CollisionObject* grabbing)
} else if (grabbing != player->grabConstraint.object) {
pointConstraintInit(&player->grabConstraint, grabbing, 8.0f, 5.0f, 1.0f);
}

playerInitGrabRotationBase(player);
}

void playerInitGrabRotationBase(struct Player* player) {
if (!player->grabConstraint.object) {
return;
}
struct Quaternion forwardRotation = player->lookTransform.rotation;
struct Vector3 forward, tmpVec, up;
playerGetMoveBasis(&forwardRotation, &forward, &tmpVec);
vector3Negate(&forward, &tmpVec);
quatLook(&tmpVec, &gUp, &forwardRotation);
playerPortalGrabTransform(player, NULL, &forwardRotation);
quatMultVector(&forwardRotation, &gForward, &forward);
quatMultVector(&forwardRotation, &gUp, &up);

struct Quaternion objectRotation = player->grabConstraint.object->body->transform.rotation;

// snap target rotation to nearest cube normals
int closestNormalUp = 0, closestNormalTowards = 0;
float closestNormalTowardsDot = 1.0f, closestNormalUpDot = -1.0f;
for (int i = 0; i < 6; ++i) {
struct Vector3 surfaceNormal;
quatMultVector(&objectRotation, &gCubeNormals[i], &surfaceNormal);

float dot = vector3Dot(&surfaceNormal, &forward);
if (dot < closestNormalTowardsDot) {
closestNormalTowardsDot = dot;
closestNormalTowards = i;
}
dot = vector3Dot(&surfaceNormal, &up);
if (dot > closestNormalUpDot) {
closestNormalUpDot = dot;
closestNormalUp = i;
}
}
quatLook(&gCubeNormals[closestNormalTowards], &gCubeNormals[closestNormalUp], &objectRotation);
quatConjugate(&objectRotation, &player->grabRotationBase);
}

void playerShakeUpdate(struct Player* player) {
Expand Down Expand Up @@ -301,12 +349,11 @@ void playerThrowObject(struct Player* player) {
if (!playerIsGrabbing(player)) {
return;
}

struct Transform throwTransform = player->lookTransform;
playerPortalGrabTransform(player, &throwTransform.position, &throwTransform.rotation);
struct Quaternion throwRotation = player->lookTransform.rotation;
playerPortalGrabTransform(player, NULL, &throwRotation);

struct Vector3 forward, right;
playerGetMoveBasis(&throwTransform, &forward, &right);
playerGetMoveBasis(&throwRotation, &forward, &right);

struct CollisionObject* object = player->grabConstraint.object;
playerSetGrabbing(player, NULL);
Expand Down Expand Up @@ -356,9 +403,9 @@ void playerUpdateGrabbedObject(struct Player* player) {
hit.object->flags |= COLLISION_OBJECT_INTERACTED;

if (hit.object->body && (hit.object->body->flags & RigidBodyFlagsGrabbable) && !(hit.object->flags & COLLISION_OBJECT_PLAYER_STANDING)) {
playerSetGrabbing(player, hit.object);
player->flags |= PlayerJustSelect;
player->grabbingThroughPortal = hit.numPortalsPassed;
playerSetGrabbing(player, hit.object);
}
else if ((hit.object->body)){
player->flags |= PlayerJustSelect;
Expand Down Expand Up @@ -427,18 +474,18 @@ void playerUpdateGrabbedObject(struct Player* player) {
// determine object target height
quatMultVector(&player->lookTransform.rotation, &temp_grab_dist, &grabPoint);
float grabY = grabPoint.y;
//
// keep object at steady XZ-planar distance in front of player
struct Quaternion forwardRotation;
struct Vector3 forward, forwardNegate, right;
playerGetMoveBasis(&player->lookTransform, &forward, &right);
playerGetMoveBasis(&player->lookTransform.rotation, &forward, &right);
vector3Negate(&forward, &forwardNegate);
quatLook(&forwardNegate, &gUp, &forwardRotation);
quatMultVector(&forwardRotation, &temp_grab_dist, &grabPoint);
vector3Add(&player->lookTransform.position, &grabPoint, &grabPoint);
grabPoint.y += grabY;

struct Quaternion grabRotation = forwardRotation;
struct Quaternion grabRotation;

if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) {
if (!collisionSceneIsPortalOpen()) {
Expand All @@ -447,22 +494,25 @@ void playerUpdateGrabbedObject(struct Player* player) {
return;
}

playerPortalGrabTransform(player, &grabPoint, &grabRotation);
playerPortalGrabTransform(player, &grabPoint, &forwardRotation);
}

// maintain object's relative rotation
quatMultiply(&forwardRotation, &player->grabRotationBase, &grabRotation);

pointConstraintUpdateTarget(&player->grabConstraint, &grabPoint, &grabRotation);
}
}

void playerGetMoveBasis(struct Transform* transform, struct Vector3* forward, struct Vector3* right) {
quatMultVector(&transform->rotation, &gForward, forward);
quatMultVector(&transform->rotation, &gRight, right);
void playerGetMoveBasis(struct Quaternion* rotation, struct Vector3* forward, struct Vector3* right) {
quatMultVector(rotation, &gForward, forward);
quatMultVector(rotation, &gRight, right);

if (forward->y > 0.7f) {
quatMultVector(&transform->rotation, &gUp, forward);
quatMultVector(rotation, &gUp, forward);
vector3Negate(forward, forward);
} else if (forward->y < -0.7f) {
quatMultVector(&transform->rotation, &gUp, forward);
quatMultVector(rotation, &gUp, forward);
}

forward->y = 0.0f;
Expand All @@ -476,12 +526,13 @@ void playerPortalGrabTransform(struct Player* player, struct Vector3* grabPoint,
if (player->grabbingThroughPortal == PLAYER_GRABBING_THROUGH_NOTHING) {
return;
}

struct Transform pointTransform;
collisionSceneGetPortalTransform(player->grabbingThroughPortal > 0 ? 0 : 1, &pointTransform);

for (int i = 0; i < abs(player->grabbingThroughPortal); ++i) {
transformPoint(&pointTransform, grabPoint, grabPoint);
if (grabPoint) {
transformPoint(&pointTransform, grabPoint, grabPoint);
}
struct Quaternion finalRotation;
quatMultiply(&pointTransform.rotation, grabRotation, &finalRotation);
*grabRotation = finalRotation;
Expand Down Expand Up @@ -731,7 +782,7 @@ void playerUpdate(struct Player* player) {
skBlenderUpdate(&player->animator, player->armature.pose, FIXED_DELTA_TIME);

int doorwayMask = worldCheckDoorwaySides(&gCurrentLevel->world, &player->lookTransform.position, player->body.currentRoom);
playerGetMoveBasis(&player->lookTransform, &forward, &right);
playerGetMoveBasis(&player->lookTransform.rotation, &forward, &right);

int isDead = playerIsDead(player);

Expand Down
4 changes: 3 additions & 1 deletion src/player/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct Player {
short grabbingThroughPortal;
short dynamicId;
struct PointConstraint grabConstraint;
struct Quaternion grabRotationBase;
float pitchVelocity;
float yawVelocity;
enum PlayerFlags flags;
Expand All @@ -63,8 +64,9 @@ void playerUpdate(struct Player* player);
void playerUpdateFooting(struct Player* player, float maxStandDistance);
void playerApplyCameraTransform(struct Player* player, struct Transform* cameraTransform);

void playerGetMoveBasis(struct Transform* transform, struct Vector3* forward, struct Vector3* right);
void playerGetMoveBasis(struct Quaternion* rotation, struct Vector3* forward, struct Vector3* right);
void playerPortalGrabTransform(struct Player* player, struct Vector3* point, struct Quaternion* rotation);
void playerInitGrabRotationBase(struct Player* player);

void playerGivePortalGun(struct Player* player, int flags);

Expand Down
2 changes: 1 addition & 1 deletion src/scene/scene.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ void sceneUpdate(struct Scene* scene) {
struct Vector3 lookDir;
struct Vector3 rightDir;

playerGetMoveBasis(&scene->camera.transform, &lookDir, &rightDir);
playerGetMoveBasis(&scene->camera.transform.rotation, &lookDir, &rightDir);

if (freecam->stick_y) {
if (controllerGetButton(2, Z_TRIG)) {
Expand Down

0 comments on commit d5fea9a

Please sign in to comment.