Added basic triangle raycasting.

This commit is contained in:
2023-02-20 15:50:26 -08:00
parent 9606b4dc9b
commit 2495362438
7 changed files with 64 additions and 27 deletions

View File

@ -23,6 +23,9 @@ bool_t Dawn::raytestSphere(
glm::vec3 *hit,
glm::vec3 *normal
) {
assertNotNull(hit);
assertNotNull(normal);
glm::vec3 h, n;
auto result = glm::intersectRaySphere(
ray.origin, ray.direction,
@ -30,8 +33,8 @@ bool_t Dawn::raytestSphere(
h, n
);
if(hit != nullptr) *hit = h;
if(normal != nullptr) *normal = n;
*hit = h;
*normal = n;
return result;
}
@ -39,19 +42,54 @@ bool_t Dawn::raytestSphere(
bool_t Dawn::raytestTriangle(
struct Ray3D ray,
struct PhysicsTriangle triangle,
glm::vec2 *hit,
float_t *distance
glm::vec3 *hitPoint,
glm::vec3 *hitNormal,
float_t *hitDistance
) {
glm::vec2 h;
float_t d;
auto result = glm::intersectRayTriangle(
ray.origin, ray.direction,
triangle.v0, triangle.v1, triangle.v2,
h, d
);
if(hit != nullptr) *hit = h;
if(distance != nullptr) *distance = d;
return result;
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(

View File

@ -26,8 +26,9 @@ namespace Dawn {
bool_t raytestTriangle(
struct Ray3D ray,
struct PhysicsTriangle triangle,
glm::vec2 *hit,
float_t *distance
glm::vec3 *hitPoint,
glm::vec3 *hitNormal,
float_t *hitDistance
);
bool_t raytestAABB(

View File

@ -18,8 +18,10 @@ void RayTester3D::onStart() {
void RayTester3D::onUpdate() {
prefab->transform.setLocalPosition(glm::vec3(0, 0, 0));
box.max = glm::vec3( 0.5f, 0.5f, 0.5f);
box.min = glm::vec3(-0.5f, -0.5f, -0.5f);
triangle.v0 = glm::vec3(-0.5f, -0.5f, 0);
triangle.v1 = glm::vec3(0.5f, -0.5f, 0);
triangle.v2 = glm::vec3(0, 0.5f, 0);
auto mouse = this->getGame()->inputManager.getAxis2D(INPUT_BIND_MOUSE_X, INPUT_BIND_MOUSE_Y);
mouse *= 2.0f;
@ -32,7 +34,7 @@ void RayTester3D::onUpdate() {
// prefab->transform.setLocalPosition(pos);
// ray.origin = glm::vec3(0, 0, 5);
bool_t x = raytestAABB(ray, box, &hit, &normal, &distance);
bool_t x = raytestTriangle(ray, triangle, &hit, &normal, &distance);
if(x) {
prefab->material->color = COLOR_RED;

View File

@ -14,7 +14,7 @@ namespace Dawn {
public:
SimpleSpinningCubePrefab *prefab;
Camera *camera;
struct AABB3D box;
struct PhysicsTriangle triangle;
struct Ray3D ray;
glm::vec3 hit;
glm::vec3 normal;

View File

@ -9,8 +9,4 @@ using namespace Dawn;
CubeCollider::CubeCollider(SceneItem *item) : Collider3D(item) {
}
bool_t CubeCollider::raycast(struct Ray3D ray, struct Collider3DRayResult *out){
return false;
}

View File

@ -5,6 +5,7 @@
#pragma once
#include "Collider3D.hpp"
#include "physics/3d/Ray3D.hpp"
namespace Dawn {
class CubeCollider : public Collider3D {
@ -13,7 +14,5 @@ namespace Dawn {
glm::vec3 size = glm::vec3(1, 1, 1);
CubeCollider(SceneItem *item);
bool_t raycast(struct Ray3D ray, struct Collider3DRayResult *out)override;
};
}

View File

@ -7,7 +7,7 @@
#include "scene/Scene.hpp"
#include "prefabs/SimpleSpinningCubePrefab.hpp"
#include "prefabs/TicTacToeTilePrefab.hpp"
#include "display/mesh/SphereMesh.hpp"
#include "display/mesh/TriangleMesh.hpp"
#include "scene/components/physics/3d/RayTester3D.hpp"
@ -31,6 +31,7 @@ namespace Dawn {
camera->orthoRight = s * ratio;
auto cube = SimpleSpinningCubePrefab::create(this);
TriangleMesh::createTriangleMesh(&cube->meshHost->mesh);
// SphereMesh::createSphere(&cube->meshHost->mesh, 1.0f, 16, 16);
auto tester = cube->addComponent<RayTester3D>();
tester->prefab = cube;