|
|
@ -2979,53 +2979,32 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius) |
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Detect collision between ray and sphere |
|
|
|
kt">bool CheckCollisionRaySphere(Ray ray, Vector3 center, float radius) |
|
|
|
// Get collision info between ray and sphere |
|
|
|
n">RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius) |
|
|
|
{ |
|
|
|
bool collision = false; |
|
|
|
|
|
|
|
Vector3 raySpherePos = Vector3Subtract(center, ray.position); |
|
|
|
float distance = Vector3Length(raySpherePos); |
|
|
|
float vector = Vector3DotProduct(raySpherePos, ray.direction); |
|
|
|
float d = radius*radius - (distance*distance - vector*vector); |
|
|
|
|
|
|
|
if (d >= 0.0f) collision = true; |
|
|
|
|
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Detect collision between ray and sphere with extended parameters and collision point detection |
|
|
|
bool CheckCollisionRaySphereEx(Ray ray, Vector3 center, float radius, Vector3 *collisionPoint) |
|
|
|
{ |
|
|
|
bool collision = false; |
|
|
|
RayCollision collision = { 0 }; |
|
|
|
|
|
|
|
Vector3 raySpherePos = Vector3Subtract(center, ray.position); |
|
|
|
float distance = Vector3Length(raySpherePos); |
|
|
|
float vector = Vector3DotProduct(raySpherePos, ray.direction); |
|
|
|
float d = radius*radius - (distance*distance - vector*vector); |
|
|
|
|
|
|
|
if (d >= 0.0f) collision = true; |
|
|
|
if (d >= 0.0f) collision.hit = true; |
|
|
|
|
|
|
|
// Check if ray origin is inside the sphere to calculate the correct collision point |
|
|
|
float collisionDistance = 0; |
|
|
|
|
|
|
|
if (distance < radius) collisionDistance = vector + sqrtf(d); |
|
|
|
else collisionDistance = vector - sqrtf(d); |
|
|
|
if (distance < radius) collision.distance = vector + sqrtf(d); |
|
|
|
else collision.distance = vector - sqrtf(d); |
|
|
|
|
|
|
|
// Calculate collision point |
|
|
|
Vector3 cPoint = Vector3Add(ray.position, Vector3Scale(ray.direction, collisionDistance)); |
|
|
|
|
|
|
|
collisionPoint->x = cPoint.x; |
|
|
|
collisionPoint->y = cPoint.y; |
|
|
|
collisionPoint->z = cPoint.z; |
|
|
|
collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance)); |
|
|
|
|
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Detect collision between ray and bounding box |
|
|
|
kt">bool CheckCollisionRayBox(Ray ray, BoundingBox box) |
|
|
|
// Get collision info between ray and box |
|
|
|
n">RayCollision GetRayCollisionBox(Ray ray, BoundingBox box) |
|
|
|
{ |
|
|
|
kt">bool collision = false; |
|
|
|
n">RayCollision collision = { 0 }; |
|
|
|
|
|
|
|
float t[8] = { 0 }; |
|
|
|
t[0] = (box.min.x - ray.position.x)/ray.direction.x; |
|
|
@ -3037,14 +3016,17 @@ bool CheckCollisionRayBox(Ray ray, BoundingBox box) |
|
|
|
t[6] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); |
|
|
|
t[7] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); |
|
|
|
|
|
|
|
collision = !(t[7] < 0 || t[6] > t[7]); |
|
|
|
collision.hit = !(t[7] < 0 || t[6] > t[7]); |
|
|
|
|
|
|
|
// TODO: Calculate other RayCollision data |
|
|
|
|
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Get collision info between ray and mesh |
|
|
|
RayHitInfo GetCollisionRayMesh(Ray ray, Mesh mesh, Matrix transform) |
|
|
|
RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform) |
|
|
|
{ |
|
|
|
RayHitInfo result = { 0 }; |
|
|
|
RayCollision collision = { 0 }; |
|
|
|
|
|
|
|
// Check if mesh vertex data on CPU for testing |
|
|
|
if (mesh.vertices != NULL) |
|
|
@ -3074,47 +3056,49 @@ RayHitInfo GetCollisionRayMesh(Ray ray, Mesh mesh, Matrix transform) |
|
|
|
b = Vector3Transform(b, transform); |
|
|
|
c = Vector3Transform(c, transform); |
|
|
|
|
|
|
|
RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, a, b, c); |
|
|
|
RayCollision triHitInfo = GetRayCollisionTriangle(ray, a, b, c); |
|
|
|
|
|
|
|
if (triHitInfo.hit) |
|
|
|
{ |
|
|
|
// Save the closest hit triangle |
|
|
|
if ((!result.hit) || (result.distance > triHitInfo.distance)) result = triHitInfo; |
|
|
|
if ((!collision.hit) || (collision.distance > triHitInfo.distance)) collision = triHitInfo; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return result; |
|
|
|
|
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Get collision info between ray and model |
|
|
|
RayHitInfo GetCollisionRayModel(Ray ray, Model model) |
|
|
|
RayCollision GetRayCollisionModel(Ray ray, Model model) |
|
|
|
{ |
|
|
|
RayHitInfo result = { 0 }; |
|
|
|
RayCollision collision = { 0 }; |
|
|
|
|
|
|
|
for (int m = 0; m < model.meshCount; m++) |
|
|
|
{ |
|
|
|
RayHitInfo meshHitInfo = GetCollisionRayMesh(ray, model.meshes[m], model.transform); |
|
|
|
RayCollision meshHitInfo = GetRayCollisionMesh(ray, model.meshes[m], model.transform); |
|
|
|
|
|
|
|
if (meshHitInfo.hit) |
|
|
|
{ |
|
|
|
// Save the closest hit mesh |
|
|
|
if ((!result.hit) || (result.distance > meshHitInfo.distance)) result = meshHitInfo; |
|
|
|
if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Get collision info between ray and triangle |
|
|
|
// NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm |
|
|
|
RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) |
|
|
|
RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) |
|
|
|
{ |
|
|
|
#define EPSILON 0.000001 // A small number |
|
|
|
|
|
|
|
Vector3 edge1, edge2; |
|
|
|
RayCollision collision = { 0 }; |
|
|
|
Vector3 edge1 = { 0 }; |
|
|
|
Vector3 edge2 = { 0 }; |
|
|
|
Vector3 p, q, tv; |
|
|
|
float det, invDet, u, v, t; |
|
|
|
RayHitInfo result = {0}; |
|
|
|
|
|
|
|
// Find vectors for two edges sharing V1 |
|
|
|
edge1 = Vector3Subtract(p2, p1); |
|
|
@ -3127,7 +3111,7 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) |
|
|
|
det = Vector3DotProduct(edge1, p); |
|
|
|
|
|
|
|
// Avoid culling! |
|
|
|
if ((det > -EPSILON) && (det < EPSILON)) return result; |
|
|
|
if ((det > -EPSILON) && (det < EPSILON)) return collision; |
|
|
|
|
|
|
|
invDet = 1.0f/det; |
|
|
|
|
|
|
@ -3138,7 +3122,7 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) |
|
|
|
u = Vector3DotProduct(tv, p)*invDet; |
|
|
|
|
|
|
|
// The intersection lies outside of the triangle |
|
|
|
if ((u < 0.0f) || (u > 1.0f)) return result; |
|
|
|
if ((u < 0.0f) || (u > 1.0f)) return collision; |
|
|
|
|
|
|
|
// Prepare to test v parameter |
|
|
|
q = Vector3CrossProduct(tv, edge1); |
|
|
@ -3147,29 +3131,28 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) |
|
|
|
v = Vector3DotProduct(ray.direction, q)*invDet; |
|
|
|
|
|
|
|
// The intersection lies outside of the triangle |
|
|
|
if ((v < 0.0f) || ((u + v) > 1.0f)) return result; |
|
|
|
if ((v < 0.0f) || ((u + v) > 1.0f)) return collision; |
|
|
|
|
|
|
|
t = Vector3DotProduct(edge2, q)*invDet; |
|
|
|
|
|
|
|
if (t > EPSILON) |
|
|
|
{ |
|
|
|
// Ray hit, get hit point and normal |
|
|
|
result.hit = true; |
|
|
|
result.distance = t; |
|
|
|
result.hit = true; |
|
|
|
result.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2)); |
|
|
|
result.position = Vector3Add(ray.position, Vector3Scale(ray.direction, t)); |
|
|
|
collision.hit = true; |
|
|
|
collision.distance = t; |
|
|
|
collision.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2)); |
|
|
|
collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, t)); |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
// Get collision info between ray and ground plane (Y-normal plane) |
|
|
|
RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) |
|
|
|
RayCollision GetRayCollisionGround(Ray ray, float groundHeight) |
|
|
|
{ |
|
|
|
#define EPSILON 0.000001 // A small number |
|
|
|
|
|
|
|
RayHitInfo result = { 0 }; |
|
|
|
RayCollision collision = { 0 }; |
|
|
|
|
|
|
|
if (fabsf(ray.direction.y) > EPSILON) |
|
|
|
{ |
|
|
@ -3177,15 +3160,15 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) |
|
|
|
|
|
|
|
if (distance >= 0.0) |
|
|
|
{ |
|
|
|
result.hit = true; |
|
|
|
result.distance = distance; |
|
|
|
result.normal = (Vector3){ 0.0, 1.0, 0.0 }; |
|
|
|
result.position = Vector3Add(ray.position, Vector3Scale(ray.direction, distance)); |
|
|
|
result.position.y = groundHeight; |
|
|
|
collision.hit = true; |
|
|
|
collision.distance = distance; |
|
|
|
collision.normal = (Vector3){ 0.0, 1.0, 0.0 }; |
|
|
|
collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, distance)); |
|
|
|
collision.point.y = groundHeight; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
return collision; |
|
|
|
} |
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|