Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grab rotation flags #58

Merged
merged 8 commits into from
Apr 22, 2024
101 changes: 101 additions & 0 deletions src/player/grab_rotation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "grab_rotation.h"
#include "../player/player.h"


struct Vector3 gCubeSurfaceNormals[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 }
};


enum GrabRotationFlags grabRotationFlagsForDecorId(const int decorId) {
enum GrabRotationFlags flags = 0;
// object specific flags
if (decorId == DECOR_TYPE_RADIO) {
flags |= GrabRotationTurnTowardsPlayer | GrabRotationUseZLookDirection;
}
else // default flags
{
flags |= GrabRotationSnapToCubeNormals;
}
return flags;
}

enum GrabRotationFlags grabRotationFlagsForDecorObjectDef(struct DecorObjectDefinition* decorObjectDef) {
return grabRotationFlagsForDecorId(decorIdForObjectDefinition(decorObjectDef));
}

enum GrabRotationFlags grabRotationFlagsForCollisionObject(struct CollisionObject* collisionObject) {
return grabRotationFlagsForDecorId(decorIdForCollisionObject(collisionObject)); // this will probably need to be replaced in the future
}


void grabRotationApplyTurnTowardsPlayer(struct Quaternion* grabRotationBaseOut) {
quatIdent(grabRotationBaseOut);
}

void grabRotationApplySnapToCubeNormals(struct Quaternion* forwardRotationIn, struct Quaternion* objectRotationIn, struct Quaternion* grabRotationBaseOut) {
struct Vector3 forward, up;
quatMultVector(forwardRotationIn, &gForward, &forward);
quatMultVector(forwardRotationIn, &gUp, &up);

int closestNormalTowards = 0, closestNormalUp = 0;
float closestNormalTowardsDot = 1.0f, closestNormalUpDot = -1.0f;
for (int i = 0; i < 6; ++i) {
struct Vector3 surfaceNormal;
quatMultVector(objectRotationIn, &gCubeSurfaceNormals[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;
}
}
struct Quaternion normalRotation;
quatLook(&gCubeSurfaceNormals[closestNormalTowards], &gCubeSurfaceNormals[closestNormalUp], &normalRotation);
quatConjugate(&normalRotation, grabRotationBaseOut);
}

void grabRotationApplyNoRotation(struct Quaternion* forwardRotationIn, struct Quaternion* objectRotationIn, struct Quaternion* grabRotationBaseOut) {
struct Quaternion forwardRotationInverted;
quatConjugate(forwardRotationIn, &forwardRotationInverted);
quatMultiply(&forwardRotationInverted, objectRotationIn, grabRotationBaseOut);
}

void grabRotationInitBase(const enum GrabRotationFlags flags, struct Quaternion* forwardRotationIn, struct Quaternion* objectRotationIn, struct Quaternion* grabRotationBaseOut) {
// modify object rotation according to flags
if (flags & GrabRotationTurnTowardsPlayer) {
grabRotationApplyTurnTowardsPlayer(grabRotationBaseOut);
} else if (flags & GrabRotationSnapToCubeNormals) {
grabRotationApplySnapToCubeNormals(forwardRotationIn, objectRotationIn, grabRotationBaseOut);
} else { // with no rotation modifier, object is not rotated on grab
grabRotationApplyNoRotation(forwardRotationIn, objectRotationIn, grabRotationBaseOut);
}
}


void grabRotationApplyUseZLookDirection(struct Quaternion* lookRotationDeltaIn, struct Quaternion* grabRotationBaseInOut) {
struct Quaternion tmp;
quatMultiply(lookRotationDeltaIn, grabRotationBaseInOut, &tmp);
*grabRotationBaseInOut = tmp;
}

void grabRotationUpdate(const enum GrabRotationFlags flags, struct Quaternion* lookRotationDeltaIn, struct Quaternion* forwardRotationIn, struct Quaternion* grabRotationBaseIn, struct Quaternion* grabRotationOut) {
// modify target object rotation in object-space
struct Quaternion grabRotationBase = *grabRotationBaseIn;
if (flags & GrabRotationUseZLookDirection) {
grabRotationApplyUseZLookDirection(lookRotationDeltaIn, &grabRotationBase);
}

// maintain object's relative rotation
quatMultiply(forwardRotationIn, &grabRotationBase, grabRotationOut);
}
21 changes: 21 additions & 0 deletions src/player/grab_rotation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef __GRAB_ROTATION_H__
#define __GRAB_ROTATION_H__

#include "../decor/decor_object_list.h"
#include "../physics/collision_object.h"
#include "../math/transform.h"

enum GrabRotationFlags {
GrabRotationSnapToCubeNormals = (1 << 0),
GrabRotationTurnTowardsPlayer = (1 << 1),
GrabRotationUseZLookDirection = (1 << 2),
};

enum GrabRotationFlags grabRotationFlagsForDecorId(const int decorId);
enum GrabRotationFlags grabRotationFlagsForDecorObjectDef(struct DecorObjectDefinition* decorObjectDef);
enum GrabRotationFlags grabRotationFlagsForCollisionObject(struct CollisionObject* collisionObject);

void grabRotationInitBase(const enum GrabRotationFlags flags, struct Quaternion* forwardRotationIn, struct Quaternion* objectRotationIn, struct Quaternion* grabRotationBaseOut);
void grabRotationUpdate(const enum GrabRotationFlags flags, struct Quaternion* lookRotationDeltaIn, struct Quaternion* forwardRotationIn, struct Quaternion* grabRotationBaseIn, struct Quaternion* grabRotationOut);

#endif
58 changes: 16 additions & 42 deletions src/player/player.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
#include "../physics/contact_insertion.h"
#include "../scene/ball.h"
#include "../savefile/savefile.h"
#include "../player/grab_rotation.h"

#include "../build/assets/models/player/chell.h"
#include "../build/assets/materials/static.h"
#include "../build/assets/models/portal_gun/w_portalgun.h"

#define GRAB_RAYCAST_DISTANCE 2.5f
#define GRAB_MIN_OFFSET_Y -1.1f
#define GRAB_MAX_OFFSET_Y 1.25f
#define GRAB_MIN_OFFSET_Y -1.1f
#define GRAB_MAX_OFFSET_Y 1.25f

#define DROWN_TIME 2.0f
#define STEP_TIME 0.35f
Expand Down Expand Up @@ -79,15 +80,6 @@ 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 Down Expand Up @@ -284,36 +276,14 @@ void playerInitGrabRotationBase(struct Player* player) {
return;
}
struct Quaternion forwardRotation = player->lookTransform.rotation;
struct Vector3 forward, tmpVec, up;
struct Vector3 forward, tmpVec;
playerGetMoveBasis(&forwardRotation, &forward, &tmpVec);
vector3Negate(&forward, &tmpVec);
quatLook(&tmpVec, &gUp, &forwardRotation);
vector3Negate(&forward, &forward);
quatLook(&forward, &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);
enum GrabRotationFlags grabRotationFlags = grabRotationFlagsForCollisionObject(player->grabConstraint.object);
grabRotationInitBase(grabRotationFlags, &forwardRotation, &player->grabConstraint.object->body->transform.rotation, &player->grabRotationBase);
}

void playerShakeUpdate(struct Player* player) {
Expand Down Expand Up @@ -488,7 +458,10 @@ void playerUpdateGrabbedObject(struct Player* player) {
vector3Add(&player->lookTransform.position, &grabPoint, &grabPoint);
grabPoint.y += grabY;

struct Quaternion grabRotation;
// remember delta between forwardRotation and lookTransform.rotation
struct Quaternion lookRotationDelta, forwardRotationInv;
quatConjugate(&forwardRotation, &forwardRotationInv);
quatMultiply(&forwardRotationInv, &player->lookTransform.rotation, &lookRotationDelta);
mwpenny marked this conversation as resolved.
Show resolved Hide resolved

if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) {
if (!collisionSceneIsPortalOpen()) {
Expand All @@ -500,9 +473,10 @@ void playerUpdateGrabbedObject(struct Player* player) {
playerPortalGrabTransform(player, &grabPoint, &forwardRotation);
}

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

struct Quaternion grabRotation;
enum GrabRotationFlags grabRotationFlags = grabRotationFlagsForCollisionObject(player->grabConstraint.object);
grabRotationUpdate(grabRotationFlags, &lookRotationDelta, &forwardRotation, &player->grabRotationBase, &grabRotation);

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