UI menu now accepts mouse input from absolutes.
This commit is contained in:
@ -1,165 +1,203 @@
|
||||
// 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
|
||||
) {
|
||||
assertNotNull(hit);
|
||||
assertNotNull(normal);
|
||||
|
||||
glm::vec3 h, n;
|
||||
auto result = glm::intersectRaySphere(
|
||||
ray.origin, ray.direction,
|
||||
sphere.center, sphere.radius,
|
||||
h, n
|
||||
);
|
||||
|
||||
*hit = h;
|
||||
*normal = n;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestTriangle(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsTriangle triangle,
|
||||
glm::vec3 *hitPoint,
|
||||
glm::vec3 *hitNormal,
|
||||
float_t *hitDistance
|
||||
) {
|
||||
assertNotNull(hitPoint);
|
||||
assertNotNull(hitNormal);
|
||||
assertNotNull(hitDistance);
|
||||
|
||||
// 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);
|
||||
assertNotNull(normal);
|
||||
assertNotNull(distance);
|
||||
|
||||
// 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;
|
||||
// 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
|
||||
) {
|
||||
assertNotNull(hit);
|
||||
assertNotNull(normal);
|
||||
|
||||
glm::vec3 h, n;
|
||||
auto result = glm::intersectRaySphere(
|
||||
ray.origin, ray.direction,
|
||||
sphere.center, sphere.radius,
|
||||
h, n
|
||||
);
|
||||
|
||||
*hit = h;
|
||||
*normal = n;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool_t Dawn::raytestTriangle(
|
||||
struct Ray3D ray,
|
||||
struct PhysicsTriangle triangle,
|
||||
glm::vec3 *hitPoint,
|
||||
glm::vec3 *hitNormal,
|
||||
float_t *hitDistance
|
||||
) {
|
||||
assertNotNull(hitPoint);
|
||||
assertNotNull(hitNormal);
|
||||
assertNotNull(hitDistance);
|
||||
|
||||
// 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);
|
||||
assertNotNull(normal);
|
||||
assertNotNull(distance);
|
||||
|
||||
// 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);
|
||||
assertNotNull(normal);
|
||||
assertNotNull(distance);
|
||||
|
||||
// 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
|
||||
}
|
@ -1,50 +1,60 @@
|
||||
// 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 "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
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
// 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 "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
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
@ -1,34 +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;
|
||||
};
|
||||
// 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