diff --git a/src/physics/collision_scene.c b/src/physics/collision_scene.c index bdfa52d..8d78657 100644 --- a/src/physics/collision_scene.c +++ b/src/physics/collision_scene.c @@ -80,4 +80,24 @@ int collisionSceneIsTouchingPortal(struct Vector3* contactPoint) { int collisionSceneIsPortalOpen() { return gCollisionScene.portalTransforms[0] != NULL && gCollisionScene.portalTransforms[1] != NULL; +} + +#define NO_RAY_HIT_DISTANCE 1000000000000.0f + +int collisionSceneRayTrace(struct CollisionScene* scene, struct Vector3* at, struct Vector3* dir, int passThroughPortals, struct RayTraceHit* hit) { + hit->distance = NO_RAY_HIT_DISTANCE; + + 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) { + + hit->at = hitTest.at; + hit->normal = hitTest.normal; + hit->distance = hitTest.distance; + hit->object = &scene->quads[i]; + } + } + + return hit->distance != NO_RAY_HIT_DISTANCE; } \ No newline at end of file diff --git a/src/physics/collision_scene.h b/src/physics/collision_scene.h index ed15246..99fa838 100644 --- a/src/physics/collision_scene.h +++ b/src/physics/collision_scene.h @@ -2,6 +2,7 @@ #define __COLLISION_SCENE_H__ #include "collision_object.h" +#include "ray_tracing.h" #define PORTAL_THICKNESS 0.11f #define PORTAL_X_RADIUS 0.5f @@ -24,4 +25,6 @@ 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); + #endif \ No newline at end of file diff --git a/src/physics/ray_tracing.c b/src/physics/ray_tracing.c new file mode 100644 index 0000000..253094a --- /dev/null +++ b/src/physics/ray_tracing.c @@ -0,0 +1,24 @@ +#include "ray_tracing.h" + +#include "math/mathf.h" + +#define NEAR_DOT_ZERO 0.00001f + +int rayTraceQuad(struct Vector3* from, struct Vector3* dir, struct CollisionQuad* quad, struct RayTraceHit* contact) { + float normalDot = vector3Dot(dir, &quad->plane.normal); + + if (fabsf(normalDot) < NEAR_DOT_ZERO) { + return 0; + } + + contact->distance = -(vector3Dot(from, &quad->plane.normal) + quad->plane.d) / normalDot; + vector3AddScaled(from, dir, contact->distance, &contact->at); + + if (collisionQuadDetermineEdges(&contact->at, quad)) { + return 0; + } + + contact->normal = quad->plane.normal; + + return 1; +} \ No newline at end of file diff --git a/src/physics/ray_tracing.h b/src/physics/ray_tracing.h new file mode 100644 index 0000000..3c29c07 --- /dev/null +++ b/src/physics/ray_tracing.h @@ -0,0 +1,16 @@ +#ifndef __RAY_TRACING_H__ +#define __RAY_TRACING_H__ + +#include "collision_quad.h" +#include "collision_object.h" + +struct RayTraceHit { + struct Vector3 at; + struct Vector3 normal; + float distance; + struct CollisionObject* object; +}; + +int rayTraceQuad(struct Vector3* from, struct Vector3* dir, struct CollisionQuad* quad, struct RayTraceHit* contact); + +#endif \ No newline at end of file