mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Grab rotation flags (#58)
* introduced "enum GrabRotationFlags" for type-based grab behavior and added grab_rotation.c/.h to offload grabRotation code from player.c * grab_rotation snap cube normals fix * grab_rotation: some cleanup * grab_rotation.c: simplify grabRotationInitBase + some cleanup
This commit is contained in:
parent
86915350b8
commit
247e66fb62
101
src/player/grab_rotation.c
Normal file
101
src/player/grab_rotation.c
Normal file
|
@ -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
src/player/grab_rotation.h
Normal file
21
src/player/grab_rotation.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
if (player->grabbingThroughPortal != PLAYER_GRABBING_THROUGH_NOTHING) {
|
||||
if (!collisionSceneIsPortalOpen()) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue