Working portal gun
This commit is contained in:
parent
9e6903f11b
commit
ea0f4ce45c
Binary file not shown.
|
@ -165,28 +165,49 @@ void quatRandom(struct Quaternion* q) {
|
|||
}
|
||||
|
||||
void quatLook(struct Vector3* lookDir, struct Vector3* up, struct Quaternion* out) {
|
||||
struct Vector3 horizontal;
|
||||
horizontal = *lookDir;
|
||||
horizontal.y = 0.0f;
|
||||
vector3Normalize(&horizontal, &horizontal);
|
||||
// calculate orthonormal basis
|
||||
struct Vector3 zDir;
|
||||
vector3Normalize(lookDir, &zDir);
|
||||
vector3Negate(&zDir, &zDir);
|
||||
|
||||
struct Vector2 complex;
|
||||
complex.x = -horizontal.z;
|
||||
complex.y = -horizontal.x;
|
||||
struct Vector3 yDir;
|
||||
vector3AddScaled(up, &zDir, -vector3Dot(&zDir, up), &yDir);
|
||||
vector3Normalize(&yDir, &yDir);
|
||||
|
||||
struct Quaternion yaw;
|
||||
quatAxisComplex(&gUp, &complex, &yaw);
|
||||
struct Vector3 xDir;
|
||||
vector3Cross(&yDir, &zDir, &xDir);
|
||||
|
||||
struct Vector3 lookNormalized;
|
||||
vector3Normalize(lookDir, &lookNormalized);
|
||||
|
||||
complex.y = lookNormalized.y;
|
||||
complex.x = sqrtf(1.0f - complex.y * complex.y);
|
||||
|
||||
struct Quaternion pitch;
|
||||
quatAxisComplex(&gRight, &complex, &pitch);
|
||||
|
||||
quatMultiply(&yaw, &pitch, out);
|
||||
// convert orthonormal basis to a quaternion
|
||||
float trace = xDir.x + yDir.y + zDir.z;
|
||||
if (trace > 0) {
|
||||
float sqrtResult = sqrtf(trace+1.0f) * 2.0f;
|
||||
float invSqrtResult = 1.0f / sqrtResult;
|
||||
out->w = 0.25 * sqrtResult;
|
||||
out->x = (yDir.z - zDir.y) * invSqrtResult;
|
||||
out->y = (zDir.x - xDir.z) * invSqrtResult;
|
||||
out->z = (xDir.y - yDir.x) * invSqrtResult;
|
||||
} else if ((xDir.x > yDir.y) && (xDir.x > zDir.z)) {
|
||||
float sqrtResult = sqrtf(1.0 + xDir.x - yDir.y - zDir.z) * 2.0f;
|
||||
float invSqrtResult = 1.0f / sqrtResult;
|
||||
out->w = (yDir.z - zDir.y) * invSqrtResult;
|
||||
out->x = 0.25 * sqrtResult;
|
||||
out->y = (yDir.x + xDir.y) * invSqrtResult;
|
||||
out->z = (zDir.x + xDir.z) * invSqrtResult;
|
||||
} else if (yDir.y > zDir.z) {
|
||||
float sqrtResult = sqrtf(1.0 + yDir.y - xDir.x - zDir.z) * 2.0f;
|
||||
float invSqrtResult = 1.0f / sqrtResult;
|
||||
out->w = (zDir.x - xDir.z) * invSqrtResult;
|
||||
out->x = (yDir.x + xDir.y) * invSqrtResult;
|
||||
out->y = 0.25 * sqrtResult;
|
||||
out->z = (zDir.y + yDir.z) * invSqrtResult;
|
||||
} else {
|
||||
float sqrtResult = sqrtf(1.0 + zDir.z - xDir.x - yDir.y) * 2.0f;
|
||||
float invSqrtResult = 1.0f / sqrtResult;
|
||||
out->w = (xDir.y - yDir.x) * invSqrtResult;
|
||||
out->x = (zDir.x + xDir.z) * invSqrtResult;
|
||||
out->y = (zDir.y + yDir.z) * invSqrtResult;
|
||||
out->z = 0.25 * sqrtResult;
|
||||
}
|
||||
}
|
||||
|
||||
void quatLerp(struct Quaternion* a, struct Quaternion* b, float t, struct Quaternion* out) {
|
||||
|
|
|
@ -124,7 +124,7 @@ void rigidBodyCheckPortals(struct RigidBody* rigidBody) {
|
|||
quatConjugate(&gCollisionScene.portalTransforms[i]->rotation, &inverseARotation);
|
||||
|
||||
struct Quaternion rotationTransfer;
|
||||
quatMultiply(&inverseARotation, &otherPortal->rotation, &rotationTransfer);
|
||||
quatMultiply(&otherPortal->rotation, &inverseARotation, &rotationTransfer);
|
||||
|
||||
quatMultVector(&rotationTransfer, &rigidBody->velocity, &rigidBody->velocity);
|
||||
quatMultVector(&rotationTransfer, &rigidBody->angularVelocity, &rigidBody->angularVelocity);
|
||||
|
|
|
@ -217,6 +217,14 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
|
|||
player->pitchVelocity * targetPitch > 0.0f ? ROTATE_RATE_DELTA : ROTATE_RATE_STOP_DELTA
|
||||
);
|
||||
|
||||
struct Vector3 lookingForward;
|
||||
vector3Negate(&gForward, &lookingForward);
|
||||
quatMultVector(&player->body.transform.rotation, &lookingForward, &lookingForward);
|
||||
struct Quaternion upRotation;
|
||||
quatLook(&lookingForward, &gUp, &upRotation);
|
||||
quatLerp(&upRotation, &player->body.transform.rotation, 0.9f, &player->body.transform.rotation);
|
||||
|
||||
|
||||
struct Quaternion deltaRotate;
|
||||
quatAxisAngle(&gUp, player->yawVelocity * FIXED_DELTA_TIME, &deltaRotate);
|
||||
|
||||
|
|
|
@ -48,11 +48,11 @@ int portalSurfaceIsInside(struct PortalSurface* surface, struct Transform* porta
|
|||
continue;
|
||||
}
|
||||
|
||||
int yIntersection = (int)(a.y - b.y) * (portalPosition.x - b.x) / (a.x - b.x);
|
||||
int yIntersection = (int)(a.y - b.y) * (portalPosition.x - b.x) / (a.x - b.x) + b.y;
|
||||
|
||||
if (yIntersection > 0) {
|
||||
if (yIntersection > portalPosition.y) {
|
||||
++intersectionCount;
|
||||
} else if (yIntersection == 0) {
|
||||
} else if (yIntersection == portalPosition.y) {
|
||||
// portal is on an edge exit early
|
||||
return 0;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform
|
|||
halfSize.x = (maxPortal.x - minPortal.x) >> 1;
|
||||
halfSize.y = (maxPortal.y - minPortal.y) >> 1;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (int interation = 0; interation < 2; ++interation) {
|
||||
int minOverlap = NO_OVERLAP;
|
||||
struct Vector2s16 minOverlapOffset;
|
||||
|
||||
|
@ -136,11 +136,11 @@ void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform
|
|||
if (abs(offset.x) > abs(offset.y)) {
|
||||
lineAxis = 0;
|
||||
crossAxis = 1;
|
||||
crossDirection = sign(offset.x);
|
||||
crossDirection = -sign(offset.x);
|
||||
} else {
|
||||
lineAxis = 1;
|
||||
crossAxis = 0;
|
||||
crossDirection = -sign(offset.y);
|
||||
crossDirection = sign(offset.y);
|
||||
}
|
||||
|
||||
int portalPosLineAxis = VECTOR2s16_AS_ARRAY(output)[lineAxis];
|
||||
|
@ -153,14 +153,14 @@ void portalSurfaceAdjustPosition(struct PortalSurface* surface, struct Transform
|
|||
int boxPosition = VECTOR2s16_AS_ARRAY(output)[crossAxis] + crossDirection * VECTOR2s16_AS_ARRAY(&halfSize)[crossAxis];
|
||||
int distance = (boxPosition - VECTOR2s16_AS_ARRAY(&a)[crossAxis]) * crossDirection;
|
||||
|
||||
if (distance <= 0) {
|
||||
if (distance <= 0 && distance < VECTOR2s16_AS_ARRAY(&halfSize)[crossAxis]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distance < minOverlap) {
|
||||
minOverlap = distance;
|
||||
VECTOR2s16_AS_ARRAY(&minOverlapOffset)[lineAxis] = 0;
|
||||
VECTOR2s16_AS_ARRAY(&minOverlapOffset)[crossAxis] = distance * crossDirection;
|
||||
VECTOR2s16_AS_ARRAY(&minOverlapOffset)[crossAxis] = -distance * crossDirection;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,13 +103,29 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
|
|||
// contactSolverDebugDraw(&gContactSolver, renderState);
|
||||
}
|
||||
|
||||
unsigned ignoreInputFrames = 10;
|
||||
void sceneCheckPortals(struct Scene* scene) {
|
||||
struct Ray raycastRay;
|
||||
struct Vector3 playerUp;
|
||||
raycastRay.origin = scene->player.body.transform.position;
|
||||
vector3Negate(&gForward, &raycastRay.dir);
|
||||
quatMultVector(&scene->player.body.transform.rotation, &raycastRay.dir, &raycastRay.dir);
|
||||
quatMultVector(&scene->player.body.transform.rotation, &gUp, &playerUp);
|
||||
|
||||
if (controllerGetButtonDown(0, Z_TRIG)) {
|
||||
sceneFirePortal(scene, &raycastRay, &playerUp, 0);
|
||||
}
|
||||
|
||||
if (controllerGetButtonDown(0, R_TRIG)) {
|
||||
sceneFirePortal(scene, &raycastRay, &playerUp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void sceneUpdate(struct Scene* scene) {
|
||||
OSTime frameStart = osGetTime();
|
||||
scene->lastFrameTime = frameStart - scene->lastFrameStart;
|
||||
|
||||
playerUpdate(&scene->player, &scene->camera.transform);
|
||||
sceneCheckPortals(scene);
|
||||
|
||||
collisionSceneUpdateDynamics();
|
||||
|
||||
|
@ -146,9 +162,6 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
|
|||
quatLook(&hitDirection, playerUp, &portalLocation.rotation);
|
||||
}
|
||||
|
||||
// TODO remove once there is a hole in the wall
|
||||
vector3AddScaled(&portalLocation.position, &hit.normal, 0.1f, &portalLocation.position);
|
||||
|
||||
return sceneOpenPortal(scene, &portalLocation, portalIndex, quadIndex);
|
||||
}
|
||||
|
||||
|
@ -157,6 +170,11 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex,
|
|||
|
||||
for (int i = surfaceMapping.minPortalIndex; i < surfaceMapping.maxPortalIndex; ++i) {
|
||||
if (portalSurfaceGenerate(&gCurrentLevel->portalSurfaces[i], at, NULL, NULL)) {
|
||||
struct Vector3 portalForward;
|
||||
quatMultVector(&at->rotation, &gForward, &portalForward);
|
||||
// TODO remove once there is a hole in the wall
|
||||
vector3AddScaled(&at->position, &portalForward, (portalIndex == 0) ? -0.1f : 0.1f, &at->position);
|
||||
|
||||
scene->portals[portalIndex].transform = *at;
|
||||
gCollisionScene.portalTransforms[portalIndex] = &scene->portals[portalIndex].transform;
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue