rework API
This commit is contained in:
@@ -37,7 +37,7 @@ SortIncludes: Never
|
||||
SortUsingDeclarations: Never
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
|
||||
@@ -19,11 +19,15 @@
|
||||
#include "Scene/MorphableCameraController.hpp"
|
||||
#include "Scene/PlaneCameraController.hpp"
|
||||
#include "Scene/UI/PerformanceInfo.hpp"
|
||||
#include "Scene/SceneIntersectionTestController.hpp"
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "Host/GraphicsAppManager.hpp"
|
||||
#include "Base/EngineConfiguration.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Controller/FreeCamCameraController.hpp"
|
||||
#include "Scene/Prefabs/LabelDrawable.hpp"
|
||||
#include "Scene/SimpleDrawable.hpp"
|
||||
#include "Scene/Ray.hpp"
|
||||
|
||||
#define USE_PLANE_CAM_CONTROL 0
|
||||
|
||||
@@ -54,6 +58,7 @@ namespace OpenVulkano
|
||||
|
||||
Scene::SimpleAnimationController m_simpleAnimationController;
|
||||
Scene::SequenceAnimationController m_sequenceAnimationController;
|
||||
Scene::SceneIntersectionTestController intersectionTestController;
|
||||
|
||||
Scene::UI::SimpleUi m_ui;
|
||||
std::shared_ptr<Scene::UI::PerformanceInfo> m_perfInfo;
|
||||
@@ -154,6 +159,10 @@ namespace OpenVulkano
|
||||
m_shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic");
|
||||
m_shader.AddVertexInputDescription(Vertex::GetVertexInputDescription());
|
||||
|
||||
intersectionTestController.OnHit += EventHandler(this, &MovingCubeAppImpl::OnRayHit);
|
||||
intersectionTestController.SetCamera(&m_camera);
|
||||
intersectionTestController.SetDefaultKeybindings();
|
||||
|
||||
GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene);
|
||||
#if USE_PLANE_CAM_CONTROL
|
||||
m_cameraControl.Init(&m_camera, PLANE_NORMAL);
|
||||
@@ -219,12 +228,23 @@ namespace OpenVulkano
|
||||
anim->Reset();
|
||||
}
|
||||
|
||||
void OnRayHit(const Scene::DrawableRayHit &hit)
|
||||
{
|
||||
using namespace Scene;
|
||||
Drawable *d = hit.drawable;
|
||||
if (SimpleDrawable *sd = dynamic_cast<SimpleDrawable *>(d))
|
||||
{
|
||||
Logger::APP->info("Ray intersects object {}", sd->GetMesh()->name);
|
||||
}
|
||||
}
|
||||
|
||||
void Tick() override
|
||||
{
|
||||
m_cameraControl.Tick();
|
||||
m_morphableCameraControl.Tick();
|
||||
m_simpleAnimationController.Tick();
|
||||
m_sequenceAnimationController.Tick();
|
||||
intersectionTestController.Tick();
|
||||
}
|
||||
|
||||
void Close() override {}
|
||||
|
||||
@@ -19,8 +19,6 @@ using namespace OpenVulkano;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GraphicsAppManager manager;
|
||||
|
||||
std::vector<std::string> examples;
|
||||
for (const auto& e : EXAMPLE_APPS)
|
||||
{
|
||||
@@ -38,7 +36,8 @@ int main(int argc, char** argv)
|
||||
if (selectedExample >= examples.size()) throw std::runtime_error("Invalid menu selection!");
|
||||
|
||||
std::unique_ptr<IGraphicsApp> app( EXAMPLE_APPS[selectedExample].second() );
|
||||
manager.SetApp(app.get());
|
||||
|
||||
GraphicsAppManager manager(app.get());
|
||||
manager.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#include "CameraController.hpp"
|
||||
#include "Scene/Camera.hpp"
|
||||
#include "Input/InputDeviceMouse.hpp"
|
||||
#include "Input/InputDeviceController.hpp"
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "Input/Touch/InputDeviceTouch.hpp"
|
||||
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
CameraController::CameraController(Scene::Camera* camera)
|
||||
{
|
||||
m_inputManager = Input::InputManager::GetInstance();
|
||||
m_camera = camera;
|
||||
m_actionCastRay = m_inputManager->GetAction("cast ray");
|
||||
m_actionCastRay->BindKey(Input::InputKey::Mouse::BUTTON_1);
|
||||
m_actionCastRay->BindKey(Input::InputKey::Touch::AXIS_TAP_X);
|
||||
m_actionCastRay->BindKey(Input::InputKey::Touch::AXIS_TAP_Y);
|
||||
}
|
||||
|
||||
void CameraController::Tick()
|
||||
{
|
||||
Input::InputDeviceMouse* mouse = static_cast<Input::InputDeviceMouse*>(m_inputManager->GetDevice(Input::InputDeviceType::MOUSE));
|
||||
Input::InputDeviceTouch* touch = static_cast<Input::InputDeviceTouch*>(m_inputManager->GetDevice(Input::InputDeviceType::TOUCH));
|
||||
if (m_camera->CanCastRay() && m_inputManager->GetButton(m_actionCastRay))
|
||||
{
|
||||
if (mouse && mouse->GetButtonDown(Input::InputKey::Mouse::BUTTON_1))
|
||||
{
|
||||
Math::Vector2i pos = mouse->GetMousePosition();
|
||||
mouse->onLeftButtonClick.NotifyAll(pos);
|
||||
}
|
||||
// not sure about second condition here, but here should be something
|
||||
else if (touch && (touch->GetAxis(Input::InputKey::Touch::AXIS_TAP_X) != 0
|
||||
|| touch->GetAxis(Input::InputKey::Touch::AXIS_TAP_Y) != 0))
|
||||
{
|
||||
Math::Vector2i pos = touch->GetTapPosition();
|
||||
touch->OnTap.NotifyAll(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,6 @@
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
class InputAction;
|
||||
class InputManager;
|
||||
}
|
||||
|
||||
namespace Scene
|
||||
{
|
||||
class Camera;
|
||||
@@ -24,26 +18,22 @@ namespace OpenVulkano
|
||||
|
||||
class CameraController : public ITickable, ICloseable
|
||||
{
|
||||
protected:
|
||||
Scene::Camera* m_camera;
|
||||
Input::InputAction* m_actionCastRay;
|
||||
Input::InputManager* m_inputManager;
|
||||
|
||||
CameraController(Scene::Camera* camera = nullptr);
|
||||
protected:
|
||||
CameraController(Scene::Camera* camera = nullptr)
|
||||
: m_camera(camera)
|
||||
{}
|
||||
|
||||
public:
|
||||
~CameraController() override = default;
|
||||
|
||||
void Tick() override;
|
||||
|
||||
virtual void Init(Scene::Camera* camera) { m_camera = camera; }
|
||||
|
||||
void Close() override { m_camera = nullptr; }
|
||||
|
||||
void SetCamera(Scene::Camera* camera) { m_camera = camera; }
|
||||
|
||||
Input::InputAction* GetActionCastRay() { return m_actionCastRay; }
|
||||
|
||||
Scene::Camera* GetCamera() { return m_camera; }
|
||||
|
||||
virtual void SetActive() {}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "Base/FrameMetadata.hpp"
|
||||
#include "Scene/Camera.hpp"
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "Input/InputDeviceMouse.hpp"
|
||||
#include "Input/InputKey.hpp"
|
||||
|
||||
namespace OpenVulkano
|
||||
@@ -40,8 +39,6 @@ namespace OpenVulkano
|
||||
vec *= m_boostFactor;
|
||||
}
|
||||
|
||||
CameraController::Tick();
|
||||
|
||||
m_yaw -= input->GetAxis(m_actionLookSide) * timeScale / 2.0f;
|
||||
m_pitch -= input->GetAxis(m_actionLookUp) * timeScale / 2.0f;
|
||||
m_pitch = std::min(1.4f, std::max(-1.4f, m_pitch));
|
||||
@@ -51,7 +48,6 @@ namespace OpenVulkano
|
||||
Math::Matrix4f camTransformation = Math::Utils::toMat4(rot);
|
||||
camTransformation[3] = Math::Vector4f(m_position, 1);
|
||||
GetCamera()->SetMatrix(camTransformation);
|
||||
//CameraController::Tick();
|
||||
CURRENT_FRAME.needsRedraw = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,64 +24,65 @@ namespace OpenVulkano
|
||||
{
|
||||
using clock = std::chrono::steady_clock;
|
||||
|
||||
GraphicsAppManager::GraphicsAppManager(RenderAPI::RenderApi renderApi) { Init(nullptr, nullptr, renderApi); }
|
||||
|
||||
GraphicsAppManager::GraphicsAppManager(OpenVulkano::IGraphicsApp* app, RenderAPI::RenderApi renderApi)
|
||||
: app(app), renderApi(renderApi)
|
||||
{
|
||||
Init(app, nullptr, renderApi);
|
||||
}
|
||||
|
||||
GraphicsAppManager::GraphicsAppManager(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi)
|
||||
: app(app), renderApi(renderApi)
|
||||
{
|
||||
Init(app, window, renderApi);
|
||||
}
|
||||
|
||||
void GraphicsAppManager::SetApp(IGraphicsApp* app)
|
||||
{
|
||||
this->app = app;
|
||||
app->SetGraphicsAppManager(this);
|
||||
}
|
||||
|
||||
void GraphicsAppManager::Init(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi)
|
||||
{
|
||||
Utils::SetThreadName("Main");
|
||||
#ifdef HAS_TRACY
|
||||
ZoneScoped;
|
||||
#endif
|
||||
|
||||
|
||||
Logger::SetupLogger();
|
||||
Logger::MANAGER->info("Initializing graphics app manager ...");
|
||||
this->renderApi = renderApi;
|
||||
if (!app)
|
||||
{
|
||||
constexpr auto msg = "The app must not be null!";
|
||||
Logger::MANAGER->error(msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
platform = std::unique_ptr<IPlatform>(PlatformProducer::CreatePlatform(renderApi));
|
||||
window = platform->MakeWindow();
|
||||
renderer = std::unique_ptr<IRenderer>(PlatformProducer::CreateRenderManager(renderApi));
|
||||
app->SetGraphicsAppManager(this);
|
||||
window->SetWindowHandler(this);
|
||||
inputManager = Input::InputManager::GetInstance();
|
||||
engineConfig = EngineConfiguration::GetEngineConfiguration();
|
||||
engineConfig->OnFpsCapChanged += EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo);
|
||||
if (window)
|
||||
{
|
||||
this->window = window;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->window = platform->MakeWindow();
|
||||
}
|
||||
if (app)
|
||||
{
|
||||
app->SetGraphicsAppManager(this);
|
||||
}
|
||||
this->window->SetWindowHandler(this);
|
||||
|
||||
// set initial values
|
||||
if (engineConfig->GetFpsCap() > 0)
|
||||
{
|
||||
UpdateCappedFpsInfo(engineConfig->GetFpsCap());
|
||||
}
|
||||
if (platform)
|
||||
}
|
||||
|
||||
GraphicsAppManager::GraphicsAppManager(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi)
|
||||
: app(app), renderApi(renderApi)
|
||||
{
|
||||
Utils::SetThreadName("Main");
|
||||
#ifdef HAS_TRACY
|
||||
ZoneScoped;
|
||||
#endif
|
||||
|
||||
Logger::SetupLogger();
|
||||
if (!app)
|
||||
{
|
||||
platform->Init();
|
||||
constexpr auto msg = "The app must not be null!";
|
||||
Logger::MANAGER->error(msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
//platform = std::unique_ptr<IPlatform>(PlatformProducer::CreatePlatform(renderApi));
|
||||
this->window = window;
|
||||
renderer = std::unique_ptr<IRenderer>(PlatformProducer::CreateRenderManager(renderApi));
|
||||
app->SetGraphicsAppManager(this);
|
||||
window->SetWindowHandler(this);
|
||||
inputManager = OpenVulkano::Input::InputManager::GetInstance();
|
||||
engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration();
|
||||
engineConfig->OnFpsCapChanged += EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo);
|
||||
// set initial values
|
||||
if (engineConfig->GetFpsCap() > 0)
|
||||
{
|
||||
UpdateCappedFpsInfo(engineConfig->GetFpsCap());
|
||||
}
|
||||
Logger::MANAGER->info("Initialized...");
|
||||
}
|
||||
|
||||
void GraphicsAppManager::UpdateCappedFpsInfo(int32_t newFpsCap)
|
||||
@@ -143,12 +144,6 @@ namespace OpenVulkano
|
||||
|
||||
void GraphicsAppManager::StartUp()
|
||||
{
|
||||
if (!app)
|
||||
{
|
||||
constexpr auto msg = "The app must not be null!";
|
||||
Logger::MANAGER->error(msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
#ifdef HAS_TRACY
|
||||
ZoneScoped;
|
||||
#endif
|
||||
@@ -156,9 +151,7 @@ namespace OpenVulkano
|
||||
{
|
||||
Logger::MANAGER->info("Initializing ...");
|
||||
app->Init();
|
||||
|
||||
//if (platform) platform->Init();
|
||||
|
||||
if (platform) platform->Init();
|
||||
window->Init(renderApi);
|
||||
//TODO restore window settings if there are any set
|
||||
renderer->Init(static_cast<IGraphicsAppManager*>(this), window);
|
||||
|
||||
@@ -48,17 +48,10 @@ namespace OpenVulkano
|
||||
void OnCappedFPS(const auto& frameStartTime);
|
||||
void UpdateCappedFpsInfo(int32_t newFpsCap);
|
||||
public:
|
||||
|
||||
GraphicsAppManager(RenderAPI::RenderApi renderApi = RenderAPI::Vulkan);
|
||||
|
||||
explicit GraphicsAppManager(IGraphicsApp* app, RenderAPI::RenderApi renderApi = RenderAPI::Vulkan);
|
||||
|
||||
explicit GraphicsAppManager(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi = RenderAPI::Vulkan);
|
||||
|
||||
void SetApp(IGraphicsApp* app);
|
||||
|
||||
void Init(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi);
|
||||
|
||||
~GraphicsAppManager() noexcept override;
|
||||
|
||||
public: // Getter
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace OpenVulkano::Input
|
||||
{
|
||||
axes[InputKey::Mouse::AXIS_X] = static_cast<float>(posX - mousePosX);
|
||||
axes[InputKey::Mouse::AXIS_Y] = static_cast<float>(posY - mousePosY);
|
||||
axes[InputKey::Mouse::AXIS_X_ABS] = posX;
|
||||
axes[InputKey::Mouse::AXIS_Y_ABS] = posY;
|
||||
mousePosX = posX;
|
||||
mousePosY = posY;
|
||||
Logger::INPUT->trace("Mouse moved posX: {0} posY: {1}, relativeX: {2}, relativeY: {3}", posX, posY, axes[InputKey::Mouse::AXIS_X], axes[InputKey::Mouse::AXIS_Y]);
|
||||
@@ -53,9 +55,9 @@ namespace OpenVulkano::Input
|
||||
|
||||
void InputDeviceMouse::ClearAxes()
|
||||
{
|
||||
for (float& axis : axes)
|
||||
for (int i = 2; i < AXES_SIZE; i++)
|
||||
{
|
||||
axis = 0;
|
||||
axes[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "InputDevice.hpp"
|
||||
#include "Math/Math.hpp"
|
||||
#include "Base/Event.hpp"
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
@@ -18,7 +17,8 @@ namespace OpenVulkano
|
||||
{
|
||||
class InputDeviceMouse : public InputDevice
|
||||
{
|
||||
float axes[InputKey::Mouse::Axis::AXIS_LAST + 2] = { 0 };
|
||||
static constexpr int AXES_SIZE = InputKey::Mouse::Axis::AXIS_LAST + 2;
|
||||
float axes[AXES_SIZE] = { 0 };
|
||||
uint8_t pressedButtons = 0, lastPressedButtons = 0;
|
||||
double mousePosX = 0, mousePosY = 0;
|
||||
IWindow* lastWindow = nullptr;
|
||||
@@ -144,9 +144,6 @@ namespace OpenVulkano
|
||||
{
|
||||
return window == lastWindow;
|
||||
}
|
||||
|
||||
Event<Math::Vector2i> onLeftButtonClick;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,9 @@ namespace OpenVulkano::Input
|
||||
|
||||
enum Axis : int16_t
|
||||
{
|
||||
AXIS_X = 0,
|
||||
AXIS_X_ABS = 0,
|
||||
AXIS_Y_ABS,
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
AXIS_WHEEL_X,
|
||||
AXIS_WHEEL_Y,
|
||||
|
||||
@@ -75,6 +75,23 @@ namespace OpenVulkano::Input
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputManager::GetButtonDown(InputAction* action) const
|
||||
{
|
||||
const std::vector<InputDevice*>& testDevices = action->GetDevices().empty() ? devices : action->GetDevices();
|
||||
for (const InputDevice* device : testDevices)
|
||||
{
|
||||
for (const KeyBinding binding : action->GetKeys())
|
||||
{
|
||||
if (binding.key.GetInputDeviceType() != device->GetType())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return device->GetButtonDown(binding.key);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputManager::GetButton(InputKey key) const
|
||||
{
|
||||
for(const InputDevice* device : devices)
|
||||
@@ -87,9 +104,13 @@ namespace OpenVulkano::Input
|
||||
|
||||
InputDevice* InputManager::GetDevice(InputDeviceType type) const
|
||||
{
|
||||
for (InputDevice* device: devices)
|
||||
if (type == InputDeviceType::UNKNOWN)
|
||||
{
|
||||
if (device->GetType() == type && type != InputDeviceType::UNKNOWN)
|
||||
return nullptr;
|
||||
}
|
||||
for (InputDevice* device : devices)
|
||||
{
|
||||
if (device->GetType() == type)
|
||||
{
|
||||
return device;
|
||||
}
|
||||
@@ -97,6 +118,24 @@ namespace OpenVulkano::Input
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<InputDevice*> InputManager::GetDevices(InputDeviceType type) const
|
||||
{
|
||||
if (type == InputDeviceType::UNKNOWN)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
std::vector<InputDevice*> devices;
|
||||
devices.reserve(this->devices.size());
|
||||
for (InputDevice* device : this->devices)
|
||||
{
|
||||
if (device->GetType() == type)
|
||||
{
|
||||
devices.push_back(device);
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
void InputManager::Tick()
|
||||
{
|
||||
for(InputDevice* device : devices)
|
||||
|
||||
@@ -40,10 +40,14 @@ namespace OpenVulkano::Input
|
||||
|
||||
[[nodiscard]] bool GetButton(InputAction* action) const;
|
||||
|
||||
[[nodiscard]] bool GetButtonDown(InputAction* action) const;
|
||||
|
||||
[[nodiscard]] bool GetButton(InputKey key) const;
|
||||
|
||||
[[nodiscard]] InputDevice* GetDevice(InputDeviceType type) const;
|
||||
|
||||
[[nodiscard]] std::vector<InputDevice*> GetDevices(InputDeviceType type) const;
|
||||
|
||||
[[nodiscard]] InputDevice* GetLastActiveDevice() const
|
||||
{
|
||||
return lastActiveDevice;
|
||||
|
||||
@@ -84,6 +84,5 @@ namespace OpenVulkano::Input
|
||||
[[nodiscard]] bool IsMultiTouch() const { return m_multiTouch; }
|
||||
|
||||
Event<Touch&> OnTouchAdded, OnTouchDown, OnTouchUp, OnTouchMoved, OnTouchRemoved;
|
||||
Event<Math::Vector2i> OnTap;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,24 +5,14 @@
|
||||
*/
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "Scene/Scene.hpp"
|
||||
#include "Scene/SimpleDrawable.hpp"
|
||||
#include "Scene/Geometry.hpp"
|
||||
#include "Scene/Shader/Shader.hpp"
|
||||
#include "Scene/TextDrawable.hpp"
|
||||
#include "Scene/Prefabs/LabelDrawable.hpp"
|
||||
#include "Scene/Ray.hpp"
|
||||
#include "Scene/TextDrawable.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
|
||||
std::optional<DrawableRayHit> PerspectiveCamera::CastRay(const Math::Vector2i& xy) const
|
||||
Ray Camera::CastRay(const Math::Vector2i& xy) const
|
||||
{
|
||||
using namespace Math::Utils;
|
||||
|
||||
auto scene = GetScene();
|
||||
|
||||
// nds
|
||||
float ndsX = (2.f * xy.x) / m_width - 1.0f;
|
||||
float ndsY = (2.f * xy.y) / m_height - 1.0f;
|
||||
@@ -35,34 +25,7 @@ namespace OpenVulkano::Scene
|
||||
|
||||
Math::Vector3f rayWorld = normalize(inverse(m_view) * rayEye);
|
||||
|
||||
std::optional<DrawableRayHit> res;
|
||||
for (Drawable* d: scene->rayHittableDrawables)
|
||||
{
|
||||
const auto& m = d->GetNodes()[0]->GetWorldMatrix();
|
||||
const Math::Vector3f rayLocalDir = normalize(inverse(m) * Math::Vector4f(rayWorld, 0));
|
||||
const Math::Vector4f rayLocalPos = inverse(m) * m_camPosition;
|
||||
const Ray ray(rayLocalPos, rayLocalDir);
|
||||
if (auto hit = d->Intersect(ray))
|
||||
{
|
||||
// choose the closest one
|
||||
if (!res || (hit->distance < res->distance))
|
||||
{
|
||||
res = hit;
|
||||
res->drawable = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (res)
|
||||
//{
|
||||
// if (SimpleDrawable* sd = dynamic_cast<SimpleDrawable*>(res->drawable))
|
||||
// {
|
||||
// Logger::APP->info("Ray intersects object {}", sd->GetMesh()->name);
|
||||
// }
|
||||
// else if (LabelDrawable* sd = dynamic_cast<LabelDrawable*>(res->drawable))
|
||||
// {
|
||||
// Logger::APP->info("Ray intersects label {}", sd->GetTexts().front().GetText());
|
||||
// }
|
||||
//}
|
||||
return res;
|
||||
Ray r(GetPosition(), rayWorld);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
#include "Node.hpp"
|
||||
#include "Math/Math.hpp"
|
||||
#include "Math/Frustum.hpp"
|
||||
#include "Input/InputDeviceMouse.hpp"
|
||||
#include "Input/Touch/InputDeviceTouch.hpp"
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Scene/Ray.hpp"
|
||||
#include <array>
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
@@ -31,7 +28,6 @@ namespace OpenVulkano::Scene
|
||||
float m_contentScaleFactor = 1, m_zoom = 1; // For use with ortho camera
|
||||
float m_interfaceOrientation = 0;
|
||||
float m_padding = 0; //Unused
|
||||
bool m_canCastRay = true;
|
||||
|
||||
Camera() : m_nearPlane(0), m_farPlane(0), m_width(0), m_height(0) {}
|
||||
|
||||
@@ -50,20 +46,6 @@ namespace OpenVulkano::Scene
|
||||
m_farPlane = farPlane;
|
||||
Node::Init();
|
||||
UpdateProjectionMatrix();
|
||||
if (m_canCastRay)
|
||||
{
|
||||
Input::InputDeviceMouse* mouse = static_cast<Input::InputDeviceMouse*>(Input::InputManager::GetInstance()->GetDevice(Input::InputDeviceType::MOUSE));
|
||||
Input::InputDeviceTouch* touch = static_cast<Input::InputDeviceTouch*>(Input::InputManager::GetInstance()->GetDevice(Input::InputDeviceType::TOUCH));
|
||||
if (mouse)
|
||||
{
|
||||
mouse->onLeftButtonClick += EventHandler(this, &Camera::CastRay);
|
||||
}
|
||||
else if (touch)
|
||||
{
|
||||
touch->OnTap += EventHandler(this, &Camera::CastRay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -85,8 +67,6 @@ namespace OpenVulkano::Scene
|
||||
|
||||
[[nodiscard]] float FarPlane() const { return m_farPlane; }
|
||||
|
||||
[[nodiscard]] bool CanCastRay() const { return m_canCastRay; }
|
||||
|
||||
void SetContentScaleFactor(float contentScale = 1)
|
||||
{
|
||||
m_contentScaleFactor = 1.0f / contentScale;
|
||||
@@ -104,7 +84,7 @@ namespace OpenVulkano::Scene
|
||||
|
||||
virtual void UpdateProjectionMatrix() = 0;
|
||||
|
||||
virtual std::optional<DrawableRayHit> CastRay(const Math::Vector2i& xy) const = 0;
|
||||
Ray CastRay(const Math::Vector2i& xy) const;
|
||||
|
||||
void UpdateViewProjectionMatrix()
|
||||
{
|
||||
@@ -264,8 +244,6 @@ namespace OpenVulkano::Scene
|
||||
SetProjectionMatrix(Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane));
|
||||
}
|
||||
|
||||
std::optional<DrawableRayHit> CastRay(const Math::Vector2i& xy) const override;
|
||||
|
||||
[[nodiscard]] bool IsPerspective() const override { return true; }
|
||||
};
|
||||
|
||||
@@ -279,11 +257,6 @@ namespace OpenVulkano::Scene
|
||||
SetProjectionMatrix(Math::Utils::orthoRH_ZO(-widthHalf, widthHalf, -heightHalf, heightHalf, m_nearPlane, m_farPlane));
|
||||
}
|
||||
|
||||
std::optional<DrawableRayHit> CastRay(const Math::Vector2i& xy) const override
|
||||
{
|
||||
throw std::runtime_error("Not implemented yet");
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsOrtho() const override { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace OpenVulkano::Scene
|
||||
RayHit hitRes;
|
||||
if (intersectRaySphere(m_origin, m_dir, center, radius, hitRes.point, hitRes.normal))
|
||||
{
|
||||
hitRes.distance = distance(m_origin, hitRes.point);
|
||||
hitRes.distance2 = distance2(m_origin, hitRes.point);
|
||||
return hitRes;
|
||||
}
|
||||
return {};
|
||||
@@ -57,6 +57,7 @@ namespace OpenVulkano::Scene
|
||||
Math::Vector3f e = v1 - v0;
|
||||
Math::Vector3f e2 = v2 - v0;
|
||||
// triangle normal. won't work if triangle is smoothly shaded. use other overloaded method instead.
|
||||
hitRes.distance2 = distance2(m_origin, hitRes.point);
|
||||
hitRes.normal = normalize(cross(e, e2));
|
||||
return hitRes;
|
||||
}
|
||||
@@ -99,7 +100,7 @@ namespace OpenVulkano::Scene
|
||||
case 1:
|
||||
return h1;
|
||||
case 2:
|
||||
return (h1.distance < h2.distance) ? h1 : h2;
|
||||
return (h1.distance2 < h2.distance2) ? h1 : h2;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -169,8 +170,8 @@ namespace OpenVulkano::Scene
|
||||
|
||||
p1.point = m_origin + txmin * m_dir;
|
||||
p2.point = m_origin + txmax * m_dir;
|
||||
p1.distance = distance(m_origin, p1.point);
|
||||
p2.distance = distance(m_origin, p2.point);
|
||||
p1.distance2 = distance2(m_origin, p1.point);
|
||||
p2.distance2 = distance2(m_origin, p2.point);
|
||||
p1.normal = p2.normal = Math::Vector3f(0);
|
||||
return intersections;
|
||||
}
|
||||
@@ -182,6 +183,7 @@ namespace OpenVulkano::Scene
|
||||
if (intersectRayPlane(m_origin, m_dir, pOrigin, pNorm, hit.distance))
|
||||
{
|
||||
hit.point = m_origin + m_dir * hit.distance;
|
||||
hit.distance2 = distance2(m_origin, hit.point);
|
||||
hit.normal = norm;
|
||||
return hit;
|
||||
}
|
||||
@@ -214,7 +216,7 @@ namespace OpenVulkano::Scene
|
||||
return 0;
|
||||
}
|
||||
p1.point = m_origin + x1 * m_dir;
|
||||
p1.distance = distance(m_origin, p1.point);
|
||||
p1.distance2 = distance2(m_origin, p1.point);
|
||||
p1.normal = normalize(p1.point - center);
|
||||
p2 = p1;
|
||||
}
|
||||
@@ -228,10 +230,10 @@ namespace OpenVulkano::Scene
|
||||
if (x1 >= 0 && x2 >= 0)
|
||||
{
|
||||
p1.point = m_origin + x1 * m_dir;
|
||||
p1.distance = distance(m_origin, p1.point);
|
||||
p1.distance2 = distance2(m_origin, p1.point);
|
||||
p1.normal = normalize(p1.point - center);
|
||||
p2.point = m_origin + x2 * m_dir;
|
||||
p2.distance = distance(m_origin, p2.point);
|
||||
p2.distance2 = distance2(m_origin, p2.point);
|
||||
p2.normal = normalize(p2.point - center);
|
||||
}
|
||||
else
|
||||
@@ -242,11 +244,18 @@ namespace OpenVulkano::Scene
|
||||
x1 = x2;
|
||||
}
|
||||
p1.point = m_origin + x1 * m_dir;
|
||||
p1.distance = distance(m_origin, p1.point);
|
||||
p1.distance2 = distance2(m_origin, p1.point);
|
||||
p1.normal = normalize(p1.point - center);
|
||||
p2 = p1;
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
bool RayHit::operator==(const RayHit& other) const
|
||||
{
|
||||
return distance2 == other.distance2 && point == other.point && normal == other.normal;
|
||||
}
|
||||
|
||||
bool RayHit::operator!=(const RayHit& other) const { return !(*this == other); }
|
||||
}
|
||||
|
||||
@@ -13,14 +13,26 @@
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
class Drawable;
|
||||
class Node;
|
||||
|
||||
struct RayHit
|
||||
{
|
||||
Math::Vector3f point;
|
||||
Math::Vector3f normal;
|
||||
float distance;
|
||||
bool operator==(const RayHit& other) const = default;
|
||||
bool operator!=(const RayHit& other) const = default;
|
||||
float distance2;
|
||||
[[nodiscard]] float GetDistance() const
|
||||
{
|
||||
if (distance == -1)
|
||||
{
|
||||
distance = std::sqrt(distance2);
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
bool operator==(const RayHit& other) const;
|
||||
bool operator!=(const RayHit& other) const;
|
||||
friend class Ray;
|
||||
private:
|
||||
mutable float distance = -1;
|
||||
};
|
||||
|
||||
struct DrawableRayHit : RayHit
|
||||
@@ -28,6 +40,7 @@ namespace OpenVulkano::Scene
|
||||
DrawableRayHit() = default;
|
||||
DrawableRayHit(const RayHit& hit) : RayHit(hit) {};
|
||||
Drawable* drawable = nullptr;
|
||||
Node* node = nullptr;
|
||||
};
|
||||
|
||||
class Ray
|
||||
|
||||
68
openVulkanoCpp/Scene/SceneIntersectionTestController.cpp
Normal file
68
openVulkanoCpp/Scene/SceneIntersectionTestController.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "SceneIntersectionTestController.hpp"
|
||||
#include "Scene.hpp"
|
||||
#include "SimpleDrawable.hpp"
|
||||
#include "Prefabs/LabelDrawable.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
void SceneIntersectionTestController::Tick()
|
||||
{
|
||||
Input::InputManager* input = Input::InputManager::GetInstance();
|
||||
if (input->GetButtonDown(m_actionClick))
|
||||
{
|
||||
const float x = input->GetAxis(m_actionClickX);
|
||||
const float y = input->GetAxis(m_actionClickY);
|
||||
const Ray ray = m_camera->CastRay(Math::Vector2i(x, y));
|
||||
const auto& camPos = m_camera->GetPosition();
|
||||
const auto scene = m_camera->GetScene();
|
||||
std::optional<DrawableRayHit> res;
|
||||
for (Drawable* d : scene->rayHittableDrawables)
|
||||
{
|
||||
for (Node* n : d->GetNodes())
|
||||
{
|
||||
const auto& m = n->GetWorldMatrix();
|
||||
const Math::Vector3f rayLocalDir = normalize(inverse(m) * Math::Vector4f(ray.GetDir(), 0));
|
||||
const Math::Vector4f rayLocalPos = inverse(m) * camPos;
|
||||
const Ray ray(rayLocalPos, rayLocalDir);
|
||||
if (auto hit = d->Intersect(ray))
|
||||
{
|
||||
// choose the closest one
|
||||
if (!res || (hit->distance2 < res->distance2))
|
||||
{
|
||||
res = hit;
|
||||
res->drawable = d;
|
||||
res->node = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
OnHit.NotifyAll(*res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneIntersectionTestController::SetDefaultKeybindings()
|
||||
{
|
||||
auto input = Input::InputManager::GetInstance();
|
||||
m_actionClick = input->GetAction("ClickIntersection");
|
||||
m_actionClick->BindKey(Input::InputKey::Mouse::BUTTON_1);
|
||||
m_actionClick->BindKey(Input::InputKey::Touch::BUTTON_TAP);
|
||||
|
||||
m_actionClickX = input->GetAction("ClickIntersectionPosX");
|
||||
m_actionClickX->BindKey(Input::InputKey::Touch::Axis::AXIS_TAP_X);
|
||||
m_actionClickX->BindKey(Input::InputKey::Mouse::Axis::AXIS_X_ABS);
|
||||
m_actionClickY = input->GetAction("ClickIntersectionPosY");
|
||||
m_actionClickY->BindKey(Input::InputKey::Touch::Axis::AXIS_TAP_Y);
|
||||
m_actionClickY->BindKey(Input::InputKey::Mouse::Axis::AXIS_Y_ABS);
|
||||
}
|
||||
}
|
||||
33
openVulkanoCpp/Scene/SceneIntersectionTestController.hpp
Normal file
33
openVulkanoCpp/Scene/SceneIntersectionTestController.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Base/ITickable.hpp"
|
||||
#include "Base/Event.hpp"
|
||||
#include "Scene/Ray.hpp"
|
||||
#include "Input/InputAction.hpp"
|
||||
#include "Camera.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
class SceneIntersectionTestController : public ITickable
|
||||
{
|
||||
public:
|
||||
SceneIntersectionTestController() = default;
|
||||
SceneIntersectionTestController(Camera* camera) : m_camera(camera) {}
|
||||
void SetCamera(Camera* camera) { m_camera = camera; }
|
||||
[[nodiscard]] Camera* GetCamera() const { return m_camera; }
|
||||
void Tick() override;
|
||||
void SetDefaultKeybindings();
|
||||
Event<DrawableRayHit> OnHit;
|
||||
|
||||
private:
|
||||
Input::InputAction* m_actionClick = nullptr;
|
||||
Input::InputAction* m_actionClickX = nullptr;
|
||||
Input::InputAction* m_actionClickY = nullptr;
|
||||
Camera* m_camera;
|
||||
};
|
||||
}
|
||||
@@ -28,48 +28,56 @@ namespace
|
||||
TEST_CASE("RaySphereIntersection")
|
||||
{
|
||||
auto sphere = GeometryFactory::MakeSphere(1, 32, 16);
|
||||
RayHit h1, h2;
|
||||
// 2 intersections
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, -5), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1, h1, h2) == 2);
|
||||
REQUIRE((h1.point == Vector3f(0, 0, -1) && h2.point == Vector3f(0, 0, 1)));
|
||||
REQUIRE((h1.normal == Vector3f(0, 0, -1) && h2.normal == Vector3f(0, 0, 1)));
|
||||
REQUIRE(h1.distance < h2.distance);
|
||||
REQUIRE((h1.distance == distance(ray.GetOrigin(), h1.point) && h2.distance == distance(ray.GetOrigin(), h2.point)));
|
||||
REQUIRE(h1.distance2 < h2.distance2);
|
||||
REQUIRE((h1.GetDistance() == distance(ray.GetOrigin(), h1.point)
|
||||
&& h2.GetDistance() == distance(ray.GetOrigin(), h2.point)));
|
||||
REQUIRE_THAT(h1.GetDistance(), Catch::Matchers::WithinRel(std::sqrt(h1.distance2)));
|
||||
// this returns just closest point
|
||||
if (auto opt = ray.IntersectSphere(Vector3f(0), 1))
|
||||
{
|
||||
opt->GetDistance();
|
||||
REQUIRE(opt.value() == h1);
|
||||
}
|
||||
}
|
||||
// 1 intersection
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(1, 0, -1), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1, h1, h2) == 1);
|
||||
REQUIRE(h1 == h2);
|
||||
REQUIRE(h1.point == Vector3f(1, 0, 0));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1).value() == h1);
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1) == h1);
|
||||
}
|
||||
// 0 intersections
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(2, 0, -1), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1, h1, h2) == 0);
|
||||
REQUIRE(!ray.IntersectSphere(Vector3f(0), 1).has_value());
|
||||
}
|
||||
// ray is inside sphere
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, 0), Vector3f(0.5, 0.5, 1));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1, h1, h2) == 1);
|
||||
REQUIRE(h1 == h2);
|
||||
::CompareVec3Approx(h1.normal, h1.point);
|
||||
auto value = ray.IntersectSphere(Vector3f(0), 1);
|
||||
REQUIRE(value->distance == h1.distance);
|
||||
REQUIRE(value->GetDistance() == h1.GetDistance());
|
||||
REQUIRE_THAT(value->distance2, Catch::Matchers::WithinRel(h1.distance2));
|
||||
::CompareVec3Approx(value->normal, h1.normal);
|
||||
::CompareVec3Approx(value->point, h1.point);
|
||||
}
|
||||
// ray intersects sphere behind the origin
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, 3), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectSphere(Vector3f(0), 1, h1, h2) == 0);
|
||||
REQUIRE(!ray.IntersectSphere(Vector3f(0), 1).has_value());
|
||||
@@ -79,31 +87,30 @@ TEST_CASE("RaySphereIntersection")
|
||||
TEST_CASE("RayTriangleIntersection")
|
||||
{
|
||||
auto tri = GeometryFactory::MakeTriangle(Vector3f(0), Vector3f(3, 0, 0), Vector3f(1.5, 2, 0));
|
||||
std::optional<RayHit> hit;
|
||||
// intersects
|
||||
{
|
||||
Ray ray(Vector3f(1.5, 2, -5), Vector3f(0, 0, 1));
|
||||
hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
std::optional<RayHit> hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
REQUIRE(hit.has_value());
|
||||
REQUIRE(hit->distance == distance(ray.GetOrigin(), hit->point));
|
||||
REQUIRE(hit->GetDistance() == distance(ray.GetOrigin(), hit->point));
|
||||
REQUIRE(hit->point == Vector3f(1.5, 2, 0));
|
||||
}
|
||||
{
|
||||
Ray ray(Vector3f(1.5, 1, -1), Vector3f(0, 0, 1));
|
||||
hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
std::optional<RayHit> hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
REQUIRE(hit.has_value());
|
||||
REQUIRE(hit->distance == distance(ray.GetOrigin(), hit->point));
|
||||
REQUIRE(hit->GetDistance() == distance(ray.GetOrigin(), hit->point));
|
||||
REQUIRE(hit->point == Vector3f(1.5, 1, 0));
|
||||
}
|
||||
// no intersections
|
||||
{
|
||||
Ray ray(Vector3f(5, 0, 0), Vector3f(0, 0, 1));
|
||||
hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
std::optional<RayHit> hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
REQUIRE(!hit.has_value());
|
||||
}
|
||||
{
|
||||
Ray ray(Vector3f(1.5, 1, 0.5), Vector3f(0, 0, 1));
|
||||
hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
std::optional<RayHit> hit = ray.IntersectTriangle(tri.vertices[0].position, tri.vertices[1].position, tri.vertices[2].position);
|
||||
REQUIRE(!hit.has_value());
|
||||
}
|
||||
}
|
||||
@@ -141,52 +148,59 @@ TEST_CASE("RayAABBIntersection")
|
||||
auto sphere = GeometryFactory::MakeSphere(1, 32, 16);
|
||||
sphere.CalculateAABB();
|
||||
std::optional<RayHit> hit;
|
||||
RayHit h1, h2;
|
||||
// intersects
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, -2), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 2);
|
||||
REQUIRE(h1.distance < h2.distance);
|
||||
REQUIRE(h1.distance2 < h2.distance2);
|
||||
REQUIRE(h1.point == Vector3f(0, 0, -1));
|
||||
REQUIRE(h2.point == Vector3f(0, 0, 1));
|
||||
auto p = ray.IntersectAABB(sphere.aabb);
|
||||
REQUIRE(p->point == h1.point);
|
||||
REQUIRE(p->distance == h1.distance);
|
||||
REQUIRE(p->distance2 == h1.distance2);
|
||||
REQUIRE(p->GetDistance() == h1.GetDistance());
|
||||
}
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, 1), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 1);
|
||||
REQUIRE(h1.distance == h2.distance);
|
||||
REQUIRE(h1.distance2 == h2.distance2);
|
||||
CompareVec3Approx(h1.point, h2.point);
|
||||
REQUIRE(h1.point == Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb)->distance == h1.distance);
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb)->distance2 == h1.distance2);
|
||||
}
|
||||
{
|
||||
RayHit h1, h2;
|
||||
// inside sphere
|
||||
Ray ray(Vector3f(0), Vector3f(0.3));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 1);
|
||||
REQUIRE(h1 == h2);
|
||||
auto val = ray.IntersectAABB(sphere.aabb);
|
||||
REQUIRE(val.has_value());
|
||||
REQUIRE_THAT(val->distance, Catch::Matchers::WithinRel(h1.distance));
|
||||
REQUIRE_THAT(val->distance2, Catch::Matchers::WithinRel(h1.distance2));
|
||||
CompareVec3Approx(val->point, h1.point);
|
||||
}
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(2, -0.5, 1.5), Vector3f(-2, 0.5, -1.5));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 2);
|
||||
REQUIRE(h1.distance < h2.distance);
|
||||
REQUIRE(h1.distance2 < h2.distance2);
|
||||
auto val = ray.IntersectAABB(sphere.aabb);
|
||||
REQUIRE(val.has_value());
|
||||
REQUIRE(val->distance == h1.distance);
|
||||
REQUIRE(val->distance2 == h1.distance2);
|
||||
REQUIRE_THAT(val->GetDistance(), Catch::Matchers::WithinRel(h1.GetDistance()));
|
||||
CompareVec3Approx(val->point, h1.point);
|
||||
}
|
||||
// no intersections
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(3, 0, 1), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 0);
|
||||
REQUIRE(!ray.IntersectAABB(sphere.aabb).has_value());
|
||||
}
|
||||
{
|
||||
RayHit h1, h2;
|
||||
Ray ray(Vector3f(0, 0, 1.1), Vector3f(0, 0, 1));
|
||||
REQUIRE(ray.IntersectAABB(sphere.aabb, h1, h2) == 0);
|
||||
REQUIRE(!ray.IntersectAABB(sphere.aabb).has_value());
|
||||
@@ -202,7 +216,7 @@ TEST_CASE("RayPlaneIntersection")
|
||||
auto hit = ray.IntersectPlane(pOrigin, pNorm);
|
||||
REQUIRE(hit.has_value());
|
||||
REQUIRE(hit->normal == pNorm);
|
||||
REQUIRE(hit->distance == 2.f);
|
||||
REQUIRE(hit->GetDistance() == 2.f);
|
||||
REQUIRE(hit->point == Vector3f(2, 0, 2));
|
||||
}
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user