Removed physics for now.
This commit is contained in:
97
archive/physics/2d/Box.cpp
Normal file
97
archive/physics/2d/Box.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Box.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
bool_t boxIsPointInside(glm::vec2 point, glm::vec2 min, glm::vec2 max) {
|
||||
return (
|
||||
point.x >= min.x && point.x <= max.x &&
|
||||
point.y >= min.y && point.y <= max.y
|
||||
);
|
||||
}
|
||||
|
||||
bool_t Dawn::boxCheckCollision(
|
||||
glm::vec2 posA, glm::vec2 minA, glm::vec2 maxA,
|
||||
glm::vec2 posB, glm::vec2 minB, glm::vec2 maxB,
|
||||
glm::vec2 velocity,
|
||||
glm::vec2 &normal,
|
||||
float_t &entryTime,
|
||||
float_t &exitTime,
|
||||
glm::vec2 &entryPoint,
|
||||
glm::vec2 &exitPoint
|
||||
) {
|
||||
// Calculate the time intervals of overlap in the x and y axes
|
||||
glm::vec2 invEntry = glm::vec2(0.0f);
|
||||
glm::vec2 invExit = glm::vec2(0.0f);
|
||||
|
||||
if (velocity.x >= 0.0f) {
|
||||
invEntry.x = ((minB.x + posB.x) - (maxA.x + posA.x)) / velocity.x;
|
||||
invExit.x = ((maxB.x + posB.x) - (minA.x + posA.x)) / velocity.x;
|
||||
} else {
|
||||
invEntry.x = ((maxB.x + posB.x) - (minA.x + posA.x)) / velocity.x;
|
||||
invExit.x = ((minB.x + posB.x) - (maxA.x + posA.x)) / velocity.x;
|
||||
}
|
||||
|
||||
|
||||
if (velocity.y >= 0.0f) {
|
||||
invEntry.y = ((minB.y + posB.y) - (maxA.y + posA.y)) / velocity.y;
|
||||
invExit.y = ((maxB.y + posB.y) - (minA.y + posA.y)) / velocity.y;
|
||||
} else {
|
||||
invEntry.y = ((maxB.y + posB.y) - (minA.y + posA.y)) / velocity.y;
|
||||
invExit.y = ((minB.y + posB.y) - (maxA.y + posA.y)) / velocity.y;
|
||||
}
|
||||
|
||||
// Calculate the time of entry and exit for each axis
|
||||
glm::vec2 entry = glm::max(invEntry, glm::vec2(0.0f));
|
||||
glm::vec2 exit = glm::min(invExit, glm::vec2(1.0f));
|
||||
|
||||
// Find the time of entry and exit
|
||||
entryTime = glm::max(entry.x, entry.y);
|
||||
exitTime = glm::min(exit.x, exit.y);
|
||||
|
||||
// If there is no overlap in either axis, there is no collision
|
||||
if (entryTime > exitTime || entry.x < 0.0f && entry.y < 0.0f || entry.x > 1.0f || entry.y > 1.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate the normal of the collision
|
||||
if (entry.x > entry.y) {
|
||||
if (invEntry.x < 0.0f) {
|
||||
normal = glm::vec2(1.0f, 0.0f);
|
||||
} else {
|
||||
normal = glm::vec2(-1.0f, 0.0f);
|
||||
}
|
||||
} else {
|
||||
if (invEntry.y < 0.0f) {
|
||||
normal = glm::vec2(0.0f, 1.0f);
|
||||
} else {
|
||||
normal = glm::vec2(0.0f, -1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the entry and exit points
|
||||
entryPoint = posA + velocity * entryTime;
|
||||
exitPoint = posA + velocity * exitTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t Dawn::boxIsBoxColliding(
|
||||
glm::vec2 posA, glm::vec2 minA, glm::vec2 maxA,
|
||||
glm::vec2 posB, glm::vec2 minB, glm::vec2 maxB
|
||||
) {
|
||||
// Check for no overlap in X axis
|
||||
if (posA.x + maxA.x < posB.x + minB.x || posB.x + maxB.x < posA.x + minA.x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for no overlap in Y axis
|
||||
if (posA.y + maxA.y < posB.y + minB.y || posB.y + maxB.y < posA.y + minA.y) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
48
archive/physics/2d/Box.hpp
Normal file
48
archive/physics/2d/Box.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "util/mathutils.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
bool_t boxCheckCollision(
|
||||
glm::vec2 posA, glm::vec2 minA, glm::vec2 maxA,
|
||||
glm::vec2 posB, glm::vec2 minB, glm::vec2 maxB,
|
||||
glm::vec2 velocity,
|
||||
glm::vec2 &normal,
|
||||
float_t &entryTime,
|
||||
float_t &exitTime,
|
||||
glm::vec2 &entryPoint,
|
||||
glm::vec2 &exitPoint
|
||||
);
|
||||
|
||||
/**
|
||||
* Checks if two boxes are colliding.
|
||||
*
|
||||
* @param posA Position of the first box.
|
||||
* @param minA Minimum point on the first box.
|
||||
* @param maxA Maximum point on the first box.
|
||||
* @param posB Position of the second box.
|
||||
* @param minB Minimum point on the second box.
|
||||
* @param maxB Maximum point on the second box.
|
||||
* @return True if the boxes are colliding with each other, false otherwise.
|
||||
*/
|
||||
bool_t boxIsBoxColliding(
|
||||
glm::vec2 posA, glm::vec2 minA, glm::vec2 maxA,
|
||||
glm::vec2 posB, glm::vec2 minB, glm::vec2 maxB
|
||||
);
|
||||
|
||||
/**
|
||||
* Checks if a given point is within the 2D Boundaries of an object.
|
||||
*
|
||||
* @param point Point to test.
|
||||
* @param min Minimum point on the box.
|
||||
* @param max Maximum point on the box.
|
||||
* @return True if the point is within the box.
|
||||
*/
|
||||
static bool_t boxIsPointInside(glm::vec2 point, glm::vec2 min, glm::vec2 max);
|
||||
}
|
11
archive/physics/2d/CMakeLists.txt
Normal file
11
archive/physics/2d/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2023 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
Box.cpp
|
||||
Ray2D.cpp
|
||||
)
|
12
archive/physics/2d/Circle.hpp
Normal file
12
archive/physics/2d/Circle.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
#include "assert/assert.hpp
|
||||
|
||||
namespace Dawn {
|
||||
|
||||
}
|
13
archive/physics/2d/Physics2D.hpp
Normal file
13
archive/physics/2d/Physics2D.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
static inline glm::vec2 physics3Dto2D(glm::vec3 v) {
|
||||
return glm::vec2(v.x, v.z);
|
||||
}
|
||||
}
|
0
archive/physics/2d/PhysicsGrid.hpp
Normal file
0
archive/physics/2d/PhysicsGrid.hpp
Normal file
27
archive/physics/2d/Ray2D.cpp
Normal file
27
archive/physics/2d/Ray2D.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Ray2D.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
Ray2D::Ray2D(glm::vec2 pos, glm::vec2 dir) :
|
||||
position(pos),
|
||||
direction(dir)
|
||||
{
|
||||
}
|
||||
|
||||
bool_t Ray2D::intersects(struct Ray2D ray, glm::vec2 *out) {
|
||||
glm::vec2 j = this->position - ray.position;
|
||||
float_t f = -ray.direction.x * direction.y + direction.x * ray.direction.y;
|
||||
float_t s = (-direction.y * j.x + direction.x * j.y) / f;
|
||||
float_t t = (ray.direction.x * j.y - ray.direction.y * j.x) / f;
|
||||
if(s >= 0 && s <= 1 && t >= 0 && t <= 1) {
|
||||
*out = position + (t * direction);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
31
archive/physics/2d/Ray2D.hpp
Normal file
31
archive/physics/2d/Ray2D.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct Ray2D {
|
||||
const glm::vec2 position;
|
||||
const glm::vec2 direction;
|
||||
|
||||
/**
|
||||
* Constructs a new Ray 2D.
|
||||
*
|
||||
* @param position Position of this ray in 2D space.
|
||||
* @param direction Direction from the origin in 2D space of this ray.
|
||||
*/
|
||||
Ray2D(glm::vec2 position, glm::vec2 direction);
|
||||
|
||||
/**
|
||||
* Checks whether one ray is intersecting with another ray.
|
||||
*
|
||||
* @param ray The ray to check if this ray is intersecting.
|
||||
* @param out The point in space where the two rays intersect.
|
||||
* @return True if they intersect, otherwise false.
|
||||
*/
|
||||
bool_t intersects(struct Ray2D ray, glm::vec2 *out);
|
||||
};
|
||||
}
|
71
archive/physics/3d/AABB3D.cpp
Normal file
71
archive/physics/3d/AABB3D.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "AABB3D.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
bool_t Dawn::aabb3dIntersect(struct AABB3D cube1, struct AABB3D cube2) {
|
||||
return (
|
||||
(cube1.min.x <= cube2.max.x && cube1.max.x >= cube2.min.x) &&
|
||||
(cube1.min.y <= cube2.max.y && cube1.max.y >= cube2.min.y) &&
|
||||
(cube1.min.z <= cube2.max.z && cube1.max.z >= cube2.min.z)
|
||||
);
|
||||
}
|
||||
|
||||
bool_t aabb3dSweep(
|
||||
struct AABB3D cube1, glm::vec3 velocity1,
|
||||
struct AABB3D cube2, glm::vec3 velocity2,
|
||||
glm::vec3 *normal
|
||||
) {
|
||||
glm::vec3 relVel = vel1 - vel2;
|
||||
glm::vec3 relPos = pos1 - pos2;
|
||||
|
||||
// If the relative velocity is zero, the cubes are already intersecting
|
||||
if(glm::length2(relVel) == 0.0f) {
|
||||
fraction = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Expand the size of the cubes by the magnitude of the relative velocity
|
||||
glm::vec3 size1exp = size1 + glm::abs(relVel);
|
||||
glm::vec3 size2exp = size2 + glm::abs(relVel);
|
||||
|
||||
// Compute the times at which the cubes first and last overlap on each axis
|
||||
float_t tminx = (size1exp.x + size2exp.x - glm::abs(relPos.x)) / glm::abs(relVel.x);
|
||||
float_t tmaxx = (size1.x + size2.x - glm::abs(relPos.x)) / glm::abs(relVel.x);
|
||||
float_t tminy = (size1exp.y + size2exp.y - glm::abs(relPos.y)) / glm::abs(relVel.y);
|
||||
float_t tmaxy = (size1.y + size2.y - glm::abs(relPos.y)) / glm::abs(relVel.y);
|
||||
float_t tminz = (size1exp.z + size2exp.z - glm::abs(relPos.z)) / glm::abs(relVel.z);
|
||||
float_t tmaxz = (size1.z + size2.z - glm::abs(relPos.z)) / glm::abs(relVel.z);
|
||||
|
||||
// Find the earliest and latest times of overlap
|
||||
float_t tmin = glm::max(glm::max(glm::min(tminx, tmaxx), glm::min(tminy, tmaxy)), glm::min(tminz, tmaxz));
|
||||
float_t tmax = glm::min(glm::min(glm::max(tminx, tmaxx), glm::max(tminy, tmaxy)), glm::max(tminz, tmaxz));
|
||||
|
||||
// If the earliest time of overlap is greater than the length of the timestep, the cubes
|
||||
// will not collide during the timestep
|
||||
if(tmin > 1.0f) {
|
||||
fraction = 1.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the latest time of overlap is less than or equal to zero, the cubes are already
|
||||
// colliding and will collide throughout the timestep
|
||||
if(tmax <= 0.0f) {
|
||||
fraction = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute the fraction of the timestep at which the collision occurs
|
||||
fraction = glm::clamp(tmin, 0.0f, 1.0f);
|
||||
|
||||
// Check if the two AABB cubes are intersecting at the time of collision
|
||||
glm::vec3 min1 = pos1 + vel1 * fraction - size1 / 2.0f;
|
||||
glm::vec3 max1 = pos1 + vel1 * fraction + size1 / 2.0f;
|
||||
glm::vec3 min2 = pos2 + vel2 * fraction - size2 / 2.0f;
|
||||
glm::vec3 max2 = pos2 + vel2 * fraction + size2 / 2.0f;
|
||||
return aabbIntersect(min1, max1, min2, max2);
|
||||
}
|
30
archive/physics/3d/AABB3D.hpp
Normal file
30
archive/physics/3d/AABB3D.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct AABB3D {
|
||||
glm::vec3 min;
|
||||
glm::vec3 max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether two 3D AABB are intersecting or not.
|
||||
*
|
||||
* @param cube1 First cube.
|
||||
* @param cube2 Second cube.
|
||||
* @return True if the two cubes are intersecting, otherwise false.
|
||||
*/
|
||||
bool_t aabb3dIntersect(struct AABB3D cube1, struct AABB3D cube2);
|
||||
|
||||
|
||||
bool_t aabb3dSweep(
|
||||
glm::vec3 pos1, glm::vec3 size1, glm::vec3 vel1,
|
||||
glm::vec3 pos2, glm::vec3 size2, glm::vec3 vel2,
|
||||
float_t& fraction
|
||||
);
|
||||
}
|
10
archive/physics/3d/CMakeLists.txt
Normal file
10
archive/physics/3d/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2023 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
Ray3D.cpp
|
||||
)
|
15
archive/physics/3d/PhysicsCapsule.hpp
Normal file
15
archive/physics/3d/PhysicsCapsule.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct PhysicsCapsule {
|
||||
float_t height;
|
||||
float_t radius;
|
||||
glm::vec3 origin;
|
||||
};
|
||||
}
|
14
archive/physics/3d/PhysicsSphere.hpp
Normal file
14
archive/physics/3d/PhysicsSphere.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct PhysicsSphere {
|
||||
glm::vec3 center;
|
||||
float_t radius;
|
||||
};
|
||||
}
|
15
archive/physics/3d/PhysicsTriangle.hpp
Normal file
15
archive/physics/3d/PhysicsTriangle.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct PhysicsTriangle {
|
||||
glm::vec3 v0;
|
||||
glm::vec3 v1;
|
||||
glm::vec3 v2;
|
||||
};
|
||||
}
|
257
archive/physics/3d/Ray3D.cpp
Normal file
257
archive/physics/3d/Ray3D.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Ray3D.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
bool_t Dawn::raytestSphere(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsSphere sphere,
|
||||
glm::vec3 *hit,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
) {
|
||||
float_t a = glm::dot(ray.direction, ray.direction);
|
||||
float_t b = 2.0f * glm::dot(ray.direction, ray.origin - sphere.center);
|
||||
float_t c = glm::dot(ray.origin - sphere.center, ray.origin - sphere.center);
|
||||
c -= sphere.radius * sphere.radius;
|
||||
|
||||
float_t dt = b * b - 4.0f * a * c;
|
||||
if(dt < 0.0f) return false;
|
||||
|
||||
float_t t0 = (-b - sqrtf(dt)) / (a * 2.0f);
|
||||
if(t0 < 0.0f) return false;
|
||||
|
||||
*hit = ray.origin + t0 * ray.direction;
|
||||
*normal = glm::normalize(*hit - sphere.center);
|
||||
*distance = t0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestTriangle(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsTriangle triangle,
|
||||
glm::vec3 *hitPoint,
|
||||
glm::vec3 *hitNormal,
|
||||
float_t *hitDistance
|
||||
) {
|
||||
assertNotNull(hitPoint, "Ray3D::raytestTriangle: hitPoint cannot be null");
|
||||
assertNotNull(hitNormal, "Ray3D::raytestTriangle: hitNormal cannot be null");
|
||||
assertNotNull(hitDistance, "Ray3D::raytestTriangle: hitDistance cannot be null");
|
||||
|
||||
// Calculate the normal of the triangle
|
||||
glm::vec3 e0 = triangle.v1 - triangle.v0;
|
||||
glm::vec3 e1 = triangle.v2 - triangle.v0;
|
||||
glm::vec3 normal = glm::normalize(glm::cross(e0, e1));
|
||||
|
||||
// Calculate the denominator of the ray-triangle intersection formula
|
||||
float_t denominator = glm::dot(normal, ray.direction);
|
||||
|
||||
// If the denominator is zero, the ray and triangle are parallel and there is no intersection
|
||||
if(denominator == 0) return -1;
|
||||
|
||||
// Calculate the distance from the ray origin to the plane of the triangle
|
||||
float_t d = glm::dot(triangle.v0 - ray.origin, normal) / denominator;
|
||||
|
||||
// If the distance is negative, the intersection point is behind the ray origin and there is no intersection
|
||||
if(d < 0) return -1;
|
||||
|
||||
// Calculate the intersection point
|
||||
glm::vec3 intersectionPoint = ray.origin + d * ray.direction;
|
||||
|
||||
// Check if the intersection point is inside the triangle
|
||||
glm::vec3 edge0 = triangle.v1 - triangle.v0;
|
||||
glm::vec3 edge1 = triangle.v2 - triangle.v1;
|
||||
glm::vec3 edge2 = triangle.v0 - triangle.v2;
|
||||
glm::vec3 c0 = intersectionPoint - triangle.v0;
|
||||
glm::vec3 c1 = intersectionPoint - triangle.v1;
|
||||
glm::vec3 c2 = intersectionPoint - triangle.v2;
|
||||
glm::vec3 n0 = glm::cross(edge0, c0);
|
||||
glm::vec3 n1 = glm::cross(edge1, c1);
|
||||
glm::vec3 n2 = glm::cross(edge2, c2);
|
||||
if(glm::dot(n0, normal) >= 0 && glm::dot(n1, normal) >= 0 && glm::dot(n2, normal) >= 0) {
|
||||
// If the intersection point is inside the triangle, set the hit point, normal and distance
|
||||
*hitPoint = intersectionPoint;
|
||||
*hitNormal = normal;
|
||||
*hitDistance = d;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the intersection point is outside the triangle, there is no intersection
|
||||
return false;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestAABB(
|
||||
struct Ray3D ray,
|
||||
struct AABB3D box,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
) {
|
||||
assertNotNull(point, "Ray3D::raytestAABB: point cannot be null");
|
||||
assertNotNull(normal, "Ray3D::raytestAABB: normal cannot be null");
|
||||
assertNotNull(distance, "Ray3D::raytestAABB: distance cannot be null");
|
||||
|
||||
// Compute the inverse direction of the ray, for numerical stability
|
||||
glm::vec3 invDir(1.0f / ray.direction.x, 1.0f / ray.direction.y, 1.0f / ray.direction.z);
|
||||
|
||||
// Compute the t-values for the two intersection candidates
|
||||
glm::vec3 tMin = (box.min - ray.origin) * invDir;
|
||||
glm::vec3 tMax = (box.max - ray.origin) * invDir;
|
||||
|
||||
// Make sure tMin is less than or equal to tMax for all components
|
||||
glm::vec3 t1 = glm::min(tMin, tMax);
|
||||
glm::vec3 t2 = glm::max(tMin, tMax);
|
||||
float tNear = glm::compMax(t1);
|
||||
float tFar = glm::compMin(t2);
|
||||
|
||||
// If tNear is greater than or equal to tFar, there is no intersection
|
||||
if(tNear >= tFar) return false;
|
||||
|
||||
// If tFar is negative, the ray is pointing away from the box
|
||||
if(tFar < 0.0f) return false;
|
||||
|
||||
// Compute the hit point and normal
|
||||
glm::vec3 hitPoint = ray.origin + tNear * ray.direction;
|
||||
|
||||
*point = hitPoint;
|
||||
*distance = tNear;
|
||||
|
||||
// Small value to account for floating point imprecision
|
||||
const float epsilon = 0.001f;
|
||||
if(std::abs(hitPoint.x - box.min.x) < epsilon) {
|
||||
*normal = glm::vec3(-1, 0, 0);
|
||||
} else if(std::abs(hitPoint.x - box.max.x) < epsilon) {
|
||||
*normal = glm::vec3(1, 0, 0);
|
||||
} else if(std::abs(hitPoint.y - box.min.y) < epsilon) {
|
||||
*normal = glm::vec3(0, -1, 0);
|
||||
} else if(std::abs(hitPoint.y - box.max.y) < epsilon) {
|
||||
*normal = glm::vec3(0, 1, 0);
|
||||
} else if(std::abs(hitPoint.z - box.min.z) < epsilon) {
|
||||
*normal = glm::vec3(0, 0, -1);
|
||||
} else if(std::abs(hitPoint.z - box.max.z) < epsilon) {
|
||||
*normal = glm::vec3(0, 0, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestCube(
|
||||
struct Ray3D ray,
|
||||
struct AABB3D box,
|
||||
glm::mat4 transform,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
) {
|
||||
// Compute the inverse transformation matrix
|
||||
glm::mat4 inverseTransform = glm::inverse(transform);
|
||||
|
||||
// Transform the ray into model space
|
||||
struct Ray3D localRay;
|
||||
localRay.origin = glm::vec3(inverseTransform * glm::vec4(ray.origin, 1.0f));
|
||||
localRay.direction = glm::normalize(glm::vec3(inverseTransform * glm::vec4(ray.direction, 0.0f)));
|
||||
|
||||
// Call raytestAABB with the transformed ray and cube
|
||||
bool_t hit = raytestAABB(localRay, box, point, normal, distance);
|
||||
if(!hit) return false;
|
||||
|
||||
// Transform the hit point and normal back into world space
|
||||
*point = glm::vec3(transform * glm::vec4(*point, 1.0f));
|
||||
*normal = glm::normalize(glm::vec3(glm::transpose(inverseTransform) * glm::vec4(*normal, 0.0f)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestQuad(
|
||||
struct Ray3D ray,
|
||||
glm::vec2 min,
|
||||
glm::vec2 max,
|
||||
glm::mat4 transform,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
) {
|
||||
assertNotNull(point, "Ray3D::raytestQuad: point cannot be null");
|
||||
assertNotNull(normal, "Ray3D::raytestQuad: normal cannot be null");
|
||||
assertNotNull(distance, "Ray3D::raytestQuad: distance cannot be null");
|
||||
|
||||
// transform ray into local space of the quad
|
||||
glm::mat4 inverseTransform = glm::inverse(transform);
|
||||
glm::vec3 localRayOrigin = glm::vec3(inverseTransform * glm::vec4(ray.origin, 1.0f));
|
||||
glm::vec3 localRayDirection = glm::vec3(inverseTransform * glm::vec4(ray.direction, 0.0f));
|
||||
|
||||
// perform ray-quad intersection test
|
||||
float_t t = -localRayOrigin.z / localRayDirection.z; // intersection distance along ray
|
||||
if(t < 0) return false; // intersection is behind the ray origin
|
||||
glm::vec2 intersectionPoint = glm::vec2(localRayOrigin) + t * glm::vec2(localRayDirection);
|
||||
if(
|
||||
glm::any(glm::lessThan(intersectionPoint, min)) ||
|
||||
glm::any(glm::greaterThan(intersectionPoint, max))
|
||||
) {
|
||||
return false; // intersection is outside the quad
|
||||
}
|
||||
*distance = t;
|
||||
|
||||
// compute point and normal of intersection in world space
|
||||
glm::vec3 localIntersectionPoint = glm::vec3(intersectionPoint, 0.0f);
|
||||
*point = glm::vec3(transform * glm::vec4(localIntersectionPoint, 1.0f));
|
||||
*normal = glm::normalize(glm::vec3(transform * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f)));
|
||||
|
||||
return true; // intersection found
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestCapsule(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsCapsule capsule,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
) {
|
||||
// Calculate the axis of the capsule
|
||||
glm::vec3 capsuleAxis = glm::normalize(ray.direction);
|
||||
glm::vec3 capsuleP0 = capsule.origin;
|
||||
glm::vec3 capsuleP1 = capsule.origin + capsule.height * capsuleAxis;
|
||||
|
||||
// Calculate the sphere centers and radii of the capsule end-caps
|
||||
glm::vec3 sphereP0 = capsule.origin;
|
||||
glm::vec3 sphereP1 = capsule.origin + capsule.height * capsuleAxis;
|
||||
float_t sphereR = capsule.radius;
|
||||
|
||||
// Calculate the closest points on the capsule axis and the ray
|
||||
glm::vec3 closestPointRay, closestPointAxis;
|
||||
if(glm::distance(ray.origin, capsuleP0) < glm::distance(ray.origin, capsuleP1)) {
|
||||
closestPointAxis = glm::clamp(glm::dot(ray.origin - capsuleP0, capsuleAxis), 0.0f, capsule.height) * capsuleAxis + capsuleP0;
|
||||
} else {
|
||||
closestPointAxis = glm::clamp(glm::dot(ray.origin - capsuleP1, -capsuleAxis), 0.0f, capsule.height) * -capsuleAxis + capsuleP1;
|
||||
}
|
||||
|
||||
closestPointRay = glm::clamp(
|
||||
glm::dot(closestPointAxis - ray.origin, ray.direction),
|
||||
0.0f, glm::length(ray.direction)
|
||||
) * ray.direction + ray.origin;
|
||||
|
||||
// Calculate the distance between the closest points on the ray and the axis
|
||||
glm::vec3 temp = (closestPointRay - closestPointAxis);
|
||||
float_t distanceSquared = glm::dot(temp, temp);
|
||||
|
||||
// Check if the ray intersects the end-caps of the capsule
|
||||
if(
|
||||
raytestSphere(ray, { .center = sphereP0, .radius = sphereR }, point, normal, distance) ||
|
||||
raytestSphere(ray, { .center = sphereP1, .radius = sphereR }, point, normal, distance)
|
||||
) {
|
||||
*normal = glm::normalize(*point - sphereP0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the ray intersects the cylinder part of the capsule
|
||||
if(distanceSquared > sphereR * sphereR) return false;
|
||||
*distance = glm::distance(ray.origin, closestPointRay);
|
||||
*point = closestPointRay;
|
||||
*normal = glm::normalize(*point - closestPointAxis);
|
||||
return true;
|
||||
}
|
70
archive/physics/3d/Ray3D.hpp
Normal file
70
archive/physics/3d/Ray3D.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "PhysicsTriangle.hpp"
|
||||
#include "PhysicsSphere.hpp"
|
||||
#include "PhysicsCapsule.hpp"
|
||||
#include "AABB3D.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct Ray3D {
|
||||
glm::vec3 origin;
|
||||
glm::vec3 direction;
|
||||
};
|
||||
|
||||
bool_t raytestSphere(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsSphere sphere,
|
||||
glm::vec3 *hit,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
);
|
||||
|
||||
bool_t raytestTriangle(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsTriangle triangle,
|
||||
glm::vec3 *hitPoint,
|
||||
glm::vec3 *hitNormal,
|
||||
float_t *hitDistance
|
||||
);
|
||||
|
||||
bool_t raytestAABB(
|
||||
struct Ray3D ray,
|
||||
struct AABB3D box,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
);
|
||||
|
||||
bool_t raytestCube(
|
||||
struct Ray3D ray,
|
||||
struct AABB3D box,
|
||||
glm::mat4 transform,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
);
|
||||
|
||||
bool_t raytestQuad(
|
||||
struct Ray3D ray,
|
||||
glm::vec2 min,
|
||||
glm::vec2 max,
|
||||
glm::mat4 transform,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
);
|
||||
|
||||
bool_t raytestCapsule(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsCapsule capsule,
|
||||
glm::vec3 *point,
|
||||
glm::vec3 *normal,
|
||||
float_t *distance
|
||||
);
|
||||
}
|
14
archive/physics/CMakeLists.txt
Normal file
14
archive/physics/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
ScenePhysicsManager.cpp
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(2d)
|
||||
add_subdirectory(3d)
|
36
archive/physics/ScenePhysicsManager.cpp
Normal file
36
archive/physics/ScenePhysicsManager.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "ScenePhysicsManager.hpp"
|
||||
#include "scene/Scene.hpp"
|
||||
#include "scene/components/physics/3d/Collider3D.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
ScenePhysicsManager::ScenePhysicsManager(Scene *scene) {
|
||||
this->scene = scene;
|
||||
}
|
||||
|
||||
void ScenePhysicsManager::update() {
|
||||
|
||||
}
|
||||
|
||||
std::vector<struct Collider3DRayResult> ScenePhysicsManager::raycast3DAll(
|
||||
struct Ray3D ray
|
||||
) {
|
||||
// TODO: Optimize the crap out of this.
|
||||
struct Collider3DRayResult result;
|
||||
auto colliders = scene->findComponents<Collider3D>();
|
||||
std::vector<struct Collider3DRayResult> results;
|
||||
auto itCollider = colliders.begin();
|
||||
while(itCollider != colliders.end()) {
|
||||
if((*itCollider)->raycast(&result, ray)) {
|
||||
results.push_back(result);
|
||||
}
|
||||
++itCollider;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
34
archive/physics/ScenePhysicsManager.hpp
Normal file
34
archive/physics/ScenePhysicsManager.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
#include "physics/3d/Ray3D.hpp"
|
||||
|
||||
typedef int64_t scenechunk_t;
|
||||
|
||||
#define SCENE_CHUNK_SIZE_2D 512
|
||||
|
||||
namespace Dawn {
|
||||
class Scene;
|
||||
class Collider3D;
|
||||
struct Collider3DRayResult;
|
||||
|
||||
class ScenePhysicsManager {
|
||||
protected:
|
||||
Scene *scene;
|
||||
// std::map<scenechunk_t, std::vector<SceneItem*>> chunkItems;
|
||||
// std::map<SceneItem*, std::vector<scenechunk_t>> itemChunks;
|
||||
|
||||
public:
|
||||
ScenePhysicsManager(Scene *scene);
|
||||
|
||||
void update();
|
||||
|
||||
std::vector<struct Collider3DRayResult> raycast3DAll(struct Ray3D ray);
|
||||
|
||||
friend class Scene;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user