mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-23 04:19:50 +00:00
Start work on raycasting
This commit is contained in:
parent
9fd69ebefd
commit
fd9e361506
@ -54,23 +54,27 @@ void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionS
|
||||
}
|
||||
}
|
||||
|
||||
int collisionSceneIsTouchingSinglePortal(struct Vector3* contactPoint, struct Transform* portalTransform) {
|
||||
struct Vector3 localPoint;
|
||||
transformPointInverse(portalTransform, contactPoint, &localPoint);
|
||||
|
||||
if (fabsf(localPoint.z) > PORTAL_THICKNESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
localPoint.x *= (1.0f / PORTAL_X_RADIUS);
|
||||
localPoint.z = 0.0f;
|
||||
|
||||
return vector3MagSqrd(&localPoint) < 1.0f;
|
||||
}
|
||||
|
||||
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint) {
|
||||
if (!collisionSceneIsPortalOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
struct Vector3 localPoint;
|
||||
transformPointInverse(gCollisionScene.portalTransforms[i], contactPoint, &localPoint);
|
||||
|
||||
if (fabsf(localPoint.z) > PORTAL_THICKNESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
localPoint.x *= (1.0f / PORTAL_X_RADIUS);
|
||||
localPoint.z = 0.0f;
|
||||
|
||||
if (vector3MagSqrd(&localPoint) < 1.0f) {
|
||||
if (collisionSceneIsTouchingSinglePortal(contactPoint, gCollisionScene.portalTransforms[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -84,14 +88,14 @@ int collisionSceneIsPortalOpen() {
|
||||
|
||||
#define NO_RAY_HIT_DISTANCE 1000000000000.0f
|
||||
|
||||
int collisionSceneRayTrace(struct CollisionScene* scene, struct Vector3* at, struct Vector3* dir, int passThroughPortals, struct RayTraceHit* hit) {
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, struct Vector3* at, struct Vector3* dir, float maxDistance, int passThroughPortals, struct RaycastHit* hit) {
|
||||
hit->distance = NO_RAY_HIT_DISTANCE;
|
||||
hit->throughPortal = NULL;
|
||||
|
||||
for (int i = 0; i < scene->quadCount; ++i) {
|
||||
struct RayTraceHit hitTest;
|
||||
|
||||
if (rayTraceQuad(at, dir, scene->quads[i].collider->data, &hitTest) && hitTest.distance < hit->distance) {
|
||||
struct RaycastHit hitTest;
|
||||
|
||||
if (raycastQuad(at, dir, maxDistance, scene->quads[i].collider->data, &hitTest) && hitTest.distance < hit->distance) {
|
||||
hit->at = hitTest.at;
|
||||
hit->normal = hitTest.normal;
|
||||
hit->distance = hitTest.distance;
|
||||
@ -99,5 +103,39 @@ int collisionSceneRayTrace(struct CollisionScene* scene, struct Vector3* at, str
|
||||
}
|
||||
}
|
||||
|
||||
if (passThroughPortals &&
|
||||
hit->distance != NO_RAY_HIT_DISTANCE &&
|
||||
collisionSceneIsPortalOpen()) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (collisionSceneIsTouchingSinglePortal(&hit->at, gCollisionScene.portalTransforms[i])) {
|
||||
struct Transform portalTransform;
|
||||
collisionSceneGetPortalTransform(i, &portalTransform);
|
||||
|
||||
struct Vector3 newStart;
|
||||
struct Vector3 newDir;
|
||||
|
||||
transformPoint(&portalTransform, &hit->at, &newStart);
|
||||
quatMultVector(&portalTransform.rotation, dir, &newDir);
|
||||
|
||||
struct RaycastHit newHit;
|
||||
|
||||
int result = collisionSceneRaycast(scene, &newStart, &newDir, maxDistance - hit->distance, 0, &newHit);
|
||||
|
||||
if (result) {
|
||||
newHit.distance += hit->distance;
|
||||
newHit.throughPortal = gCollisionScene.portalTransforms[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit->distance != NO_RAY_HIT_DISTANCE;
|
||||
}
|
||||
|
||||
void collisionSceneGetPortalTransform(int fromPortal, struct Transform* out) {
|
||||
struct Transform inverseA;
|
||||
transformInvert(gCollisionScene.portalTransforms[fromPortal], &inverseA);
|
||||
transformConcat(gCollisionScene.portalTransforms[1 - fromPortal], &inverseA, out);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#define __COLLISION_SCENE_H__
|
||||
|
||||
#include "collision_object.h"
|
||||
#include "ray_tracing.h"
|
||||
#include "raycasting.h"
|
||||
|
||||
#define PORTAL_THICKNESS 0.11f
|
||||
#define PORTAL_X_RADIUS 0.5f
|
||||
@ -25,6 +25,8 @@ int collisionSceneIsPortalOpen();
|
||||
|
||||
void collisionObjectQueryScene(struct CollisionObject* object, struct CollisionScene* scene, void* data, ManifoldCallback callback);
|
||||
|
||||
int collisionSceneRayTrace(struct CollisionScene* scene, struct Vector3* at, struct Vector3* dir, int passThroughPortals, struct RayTraceHit* hit);
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, struct Vector3* at, struct Vector3* dir, float maxDistance, int passThroughPortals, struct RaycastHit* hit);
|
||||
|
||||
void collisionSceneGetPortalTransform(int fromPortal, struct Transform* out);
|
||||
|
||||
#endif
|
@ -1,10 +1,11 @@
|
||||
#include "ray_tracing.h"
|
||||
#include "raycasting.h"
|
||||
|
||||
#include "math/mathf.h"
|
||||
|
||||
#define NEAR_DOT_ZERO 0.00001f
|
||||
#define MIN_RAY_LENGTH 0.05f
|
||||
|
||||
int rayTraceQuad(struct Vector3* from, struct Vector3* dir, struct CollisionQuad* quad, struct RayTraceHit* contact) {
|
||||
int raycastQuad(struct Vector3* from, struct Vector3* dir, float maxDistance, struct CollisionQuad* quad, struct RaycastHit* contact) {
|
||||
float normalDot = vector3Dot(dir, &quad->plane.normal);
|
||||
|
||||
if (fabsf(normalDot) < NEAR_DOT_ZERO) {
|
||||
@ -12,6 +13,11 @@ int rayTraceQuad(struct Vector3* from, struct Vector3* dir, struct CollisionQuad
|
||||
}
|
||||
|
||||
contact->distance = -(vector3Dot(from, &quad->plane.normal) + quad->plane.d) / normalDot;
|
||||
|
||||
if (contact->distance < MIN_RAY_LENGTH || contact->distance > maxDistance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector3AddScaled(from, dir, contact->distance, &contact->at);
|
||||
|
||||
if (collisionQuadDetermineEdges(&contact->at, quad)) {
|
@ -4,13 +4,14 @@
|
||||
#include "collision_quad.h"
|
||||
#include "collision_object.h"
|
||||
|
||||
struct RayTraceHit {
|
||||
struct RaycastHit {
|
||||
struct Vector3 at;
|
||||
struct Vector3 normal;
|
||||
float distance;
|
||||
struct CollisionObject* object;
|
||||
struct Transform* throughPortal;
|
||||
};
|
||||
|
||||
int rayTraceQuad(struct Vector3* from, struct Vector3* dir, struct CollisionQuad* quad, struct RayTraceHit* contact);
|
||||
int raycastQuad(struct Vector3* from, struct Vector3* dir, float maxDistance, struct CollisionQuad* quad, struct RaycastHit* contact);
|
||||
|
||||
#endif
|
@ -91,10 +91,8 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct Transform inverseA;
|
||||
transformInvert(gCollisionScene.portalTransforms[player->grabbingThroughPortal], &inverseA);
|
||||
struct Transform pointTransform;
|
||||
transformConcat(gCollisionScene.portalTransforms[1 - player->grabbingThroughPortal], &inverseA, &pointTransform);
|
||||
collisionSceneGetPortalTransform(player->grabbingThroughPortal, &pointTransform);
|
||||
|
||||
transformPoint(&pointTransform, &grabPoint, &grabPoint);
|
||||
struct Quaternion finalRotation;
|
||||
@ -139,6 +137,15 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
|
||||
|
||||
collisionObjectQueryScene(&player->collisionObject, &gCollisionScene, player, playerHandleCollision);
|
||||
|
||||
struct RaycastHit hit;
|
||||
struct Vector3 down;
|
||||
vector3Scale(&gUp, &down, -1.0f);
|
||||
if (collisionSceneRaycast(&gCollisionScene, &player->body.transform.position, &down, PLAYER_HEAD_HEIGHT, 1, &hit)) {
|
||||
vector3AddScaled(&hit.at, &gUp, PLAYER_HEAD_HEIGHT, &player->body.transform.position);
|
||||
|
||||
player->body.velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
rigidBodyCheckPortals(&player->body);
|
||||
|
||||
float targetYaw = 0.0f;
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#define PLAYER_GRABBING_THROUGH_NOTHING -1
|
||||
|
||||
#define PLAYER_HEAD_HEIGHT 1.2f
|
||||
|
||||
struct Player {
|
||||
struct CollisionObject collisionObject;
|
||||
struct RigidBody body;
|
||||
|
Loading…
Reference in New Issue
Block a user