Start work on raycasting

This commit is contained in:
James Lambert 2022-04-20 22:12:07 -06:00
parent 9fd69ebefd
commit fd9e361506
6 changed files with 80 additions and 24 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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)) {

View file

@ -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

View file

@ -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;

View file

@ -8,6 +8,8 @@
#define PLAYER_GRABBING_THROUGH_NOTHING -1
#define PLAYER_HEAD_HEIGHT 1.2f
struct Player {
struct CollisionObject collisionObject;
struct RigidBody body;