Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teste de intersecção raio-AABBs #37

Merged
merged 3 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
build/*
bin/
bin/
.vscode/*
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(SOURCES
src/stackMatrix.cpp
src/textrendering.cpp
src/window.cpp
src/collisions.cpp
)

cmake_minimum_required(VERSION 3.5.0)
Expand Down
11 changes: 11 additions & 0 deletions include/collisions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef _COLLISIONS_H
#define _COLLISIONS_H

#include "globals.h"

bool CubeIntersectsCube(AABB a, AABB b);
bool RayIntersectsCube(glm::vec4 rayOrigin, glm::vec3 rayDirection, AABB cube);
AABB GetWorldAABB(SceneObject obj, glm::mat4 model);
glm::vec3 MouseRayCasting(glm::mat4 projectionMatrix, glm::mat4 viewMatrix);

#endif // _COLLISIONS_H
15 changes: 15 additions & 0 deletions include/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ struct SceneObject
glm::vec3 bbox_max;
};

/**
* @brief Struct que representa uma axis-aligned bounding box (AABB).
*
* Uma AABB (Axis-Aligned Bounding Box) é utilizada para representar uma caixa delimitadora
* que possui seus lados paralelos aos eixos do sistema de coordenadas. Ela é definida pelos pontos
* mínimo e máximo que a delimitam.
*/
struct AABB {
glm::vec3 min;
glm::vec3 max;
};

// Abaixo definimos variáveis globais utilizadas em várias funções do código.

Expand All @@ -101,6 +112,10 @@ extern std::map<std::string, SceneObject> g_VirtualScene;
// Pilha que guardará as matrizes de modelagem.
extern std::stack<glm::mat4> g_MatrixStack;

// Largura e altura da janela de renderização.
extern float g_ScreenWidth;
extern float g_ScreenHeight;

// Razão de proporção da janela (largura/altura). Veja função FramebufferSizeCallback().
extern float g_ScreenRatio;

Expand Down
7 changes: 4 additions & 3 deletions src/callback.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "callback.h"
#include <iostream>

bool isInput1Digit0 = true;
bool isInput2Digit0 = true;
Expand Down Expand Up @@ -287,8 +288,8 @@ void CursorPosCallback(GLFWwindow* window, double xpos, double ypos)
g_LastCursorPosY = ypos;
}

if (g_RightMouseButtonPressed)
{
// if (g_RightMouseButtonPressed)
// {
// Deslocamento do cursor do mouse em x e y de coordenadas de tela!
float dx = xpos - g_LastCursorPosX;
float dy = ypos - g_LastCursorPosY;
Expand All @@ -301,7 +302,7 @@ void CursorPosCallback(GLFWwindow* window, double xpos, double ypos)
// cursor como sendo a última posição conhecida do cursor.
g_LastCursorPosX = xpos;
g_LastCursorPosY = ypos;
}
// }

if (g_MiddleMouseButtonPressed)
{
Expand Down
120 changes: 120 additions & 0 deletions src/collisions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "collisions.h"
#include <iostream>

/**
* @brief Verifica se dois cubos representados por AABBs se intersectam nos eixos x, y e z.
* Adaptado de https://gamedev.stackexchange.com/questions/96060/collision-detection-in-opengl
*
* @param a O primeiro cubo AABB.
* @param b O segundo cubo AABB.
* @return True se os cubos AABB se intersectam, false caso contrário.
*/
bool CubeIntersectsCube(AABB a, AABB b){
int intersectedAxes = 0;

if (a.min.x <= b.max.x && a.max.x >= b.min.x) intersectedAxes++;
if (a.min.y <= b.max.y && a.max.y >= b.min.y) intersectedAxes++;
if (a.min.z <= b.max.z && a.max.z >= b.min.z) intersectedAxes++;

std::cout << "Eixos com intersecção: em " << intersectedAxes << std::endl;

return intersectedAxes == 3;
}

/**
* Shirley, P., Wald, I., Marrs, A. (2021). Ray Axis-Aligned Bounding Box Intersection.
* In: Marrs, A., Shirley, P., Wald, I. (eds) Ray Tracing Gems II. Apress, Berkeley, CA.
* https://doi.org/10.1007/978-1-4842-7185-8_2
*/

// Adaptado de: https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection.html
bool RayIntersectsCube(glm::vec4 rayOrigin, glm::vec3 rayDirection, AABB cube){
float tmin_x = (cube.min.x - rayOrigin.x) / rayDirection.x;
float tmax_x = (cube.max.x - rayOrigin.x) / rayDirection.x;

if (tmin_x > tmax_x) std::swap(tmin_x, tmax_x);

float tmin = tmin_x;
float tmax = tmax_x;

float tmin_y = (cube.min.y - rayOrigin.y) / rayDirection.y;
float tmax_y = (cube.max.y - rayOrigin.y) / rayDirection.y;

if (tmin_y > tmax_y) std::swap(tmin_y, tmax_y);

// Verifica se o raio não intersecta o cubo
if (tmin > tmax_y || tmin_y > tmax) return false;

// Seleciona os valores de t, onde tmin é o maior valor e tmax é o menor valor
if (tmin_y > tmin) tmin = tmin_y;
if (tmax_y < tmax) tmax = tmax_y;

float tmin_z = (cube.min.z - rayOrigin.z) / rayDirection.z;
float tmax_z = (cube.max.z - rayOrigin.z) / rayDirection.z;

if (tmin_z > tmax_z) std::swap(tmin_z, tmax_z);

// Verifica se o raio não intersecta o cubo
if (tmin > tmax_z || tmin_z > tmax) return false;

if (tmin_z > tmin) tmin = tmin_z;
if (tmax_z < tmax) tmax = tmax_z;

return true;
}

/**
* @brief Calcula o axis-aligned bounding box (AABB) para um objeto da cena em coordenadas de mundo.
*
* @param obj O objeto da cena, que contém em sua struct uma AABB em coordenadas de modelo.
* @param model A matriz modelo que representa as transformações geométricas necessárias para o objeto estar em coordenadas de mundo.
* @return A AABB do objeto em coordenadas de mundo.
*/
AABB GetWorldAABB(SceneObject obj, glm::mat4 model){
// Dada uma matriz model, transforma as coordenadas locais da AABB do objeto para coordenadas de mundo.
glm::vec4 min = model * glm::vec4(obj.bbox_min.x, obj.bbox_min.y, obj.bbox_min.z, 1.0f);
glm::vec4 max = model * glm::vec4(obj.bbox_max.x, obj.bbox_max.y, obj.bbox_max.z, 1.0f);

// @DEBUG
// std::cout << "BBox Local Min: " << obj.bbox_min.x << " " << obj.bbox_min.y << " " << obj.bbox_min.z << std::endl;
// std::cout << "BBox Local Max: " << obj.bbox_max.x << " " << obj.bbox_max.y << " " << obj.bbox_max.z << std::endl;
std::cout << "BBox World Min: " << min.x << " " << min.y << " " << min.z << std::endl;
std::cout << "BBox World Max: " << max.x << " " << max.y << " " << max.z << std::endl;

// Retorna a bounding box em coordenadas de mundo
return AABB{min, max};
}

/**
* @brief Projeta um ray casting a partir das coordenadas do mouse.
* Adaptado de: https://antongerdelan.net/opengl/raycasting.html
*
* As coordenadas do mouse são convertidas para o sistema de coordenadas normalizado (NDC),
* em seguida para o sistema de coordenadas do clip, para o sistema de coordenadas
* da câmera e, por fim, para o sistema de coordenadas do mundo.. O vetor resultante é
* normalizado.
*/
glm::vec3 MouseRayCasting(glm::mat4 projectionMatrix, glm::mat4 viewMatrix){
// Coordenadas do mouse em NDC
float x = (2.0f * g_LastCursorPosX) / g_ScreenWidth - 1.0f;
float y = 1.0f - (2.0f * g_LastCursorPosY) / g_ScreenHeight;
float z = 1.0f;
glm::vec3 ray_nds = glm::vec3(x, y, z);

// Coordenadas do mouse em clip
glm::vec4 ray_clip = glm::vec4(ray_nds.x, ray_nds.y, -1.0, 1.0);

// Coordenadas do mouse no sistema da câmera
glm::vec4 ray_camera = glm::inverse(projectionMatrix) * ray_clip;
ray_camera = glm::vec4(ray_camera.x, ray_camera.y, -1.0, 0.0); // Desconsidera os componentes z,w

// Normaliza o vetor de coordenadas do mouse
glm::vec3 ray_world = glm::vec3(glm::inverse(viewMatrix) * ray_camera);
ray_world = glm::normalize(ray_world);

// @DEBUG
// std::cout << "Ray World: " << ray_world.x << " " << ray_world.y << " " << ray_world.z << std::endl;

return ray_world;

}
2 changes: 2 additions & 0 deletions src/globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ std::map<std::string, SceneObject> g_VirtualScene;
// Pilha que guardará as matrizes de modelagem.
std::stack<glm::mat4> g_MatrixStack;

float g_ScreenWidth = 800.0f;
float g_ScreenHeight = 600.0f;
float g_ScreenRatio = 1.0f;

float g_AngleX = 0.0f;
Expand Down
Loading