diff --git a/CMakeLists.txt b/CMakeLists.txt index 5511b9b..1c58f2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.25) -set(BLT_GRAPHICS_VERSION 0.12.1) +set(BLT_GRAPHICS_VERSION 0.12.2) set(BLT_GRAPHICS_TEST_VERSION 0.0.1) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) diff --git a/include/blt/gfx/raycast.h b/include/blt/gfx/raycast.h new file mode 100644 index 0000000..bcf093d --- /dev/null +++ b/include/blt/gfx/raycast.h @@ -0,0 +1,49 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_GRAPHICS_RAYCAST_H +#define BLT_GRAPHICS_RAYCAST_H + +#include +#include + +namespace blt::gfx +{ + + blt::vec3 calculateRay3D(float mx, float my, float width, float height, const blt::mat4x4& view, const blt::mat4x4& proj); + blt::vec3 calculateRay2D(float mx, float my, float width, float height, const blt::vec2 scale, const blt::mat4x4& view, const blt::mat4x4& proj); + blt::vec3 calculateRay3D(float width, float height, const blt::mat4x4& view, const blt::mat4x4& proj); + blt::vec3 calculateRay2D(float width, float height, const blt::vec2 scale, const blt::mat4x4& view, const blt::mat4x4& proj); + + namespace detail + { + blt::vec3 toWorldCoords(const blt::vec4& eyeCoords, const blt::mat4x4& view); + + blt::vec4 toEyeCoords(const blt::vec4& clipCoords, const blt::mat4x4& proj); + + inline blt::vec2 getNormalisedDeviceCoordinates(float mx, float my, float width, float height) + { + float x = (2.0f * mx) / width - 1.0f; + float y = (2.0f * my) / height - 1.0f; + return blt::vec2(x, y); + } + } + +} + +#endif //BLT_GRAPHICS_RAYCAST_H diff --git a/include/blt/gfx/state.h b/include/blt/gfx/state.h index c4b012c..1ff8f77 100644 --- a/include/blt/gfx/state.h +++ b/include/blt/gfx/state.h @@ -97,6 +97,20 @@ namespace blt::gfx float ortho_near = 0, float ortho_far = 1.1); void update(); + + const mat4x4& getView() const; + + const mat4x4& getOrtho() const; + + const mat4x4& getPerspective() const; + + const mat4x4& getPvm() const; + + const mat4x4& getOvm() const; + + const mat4x4& getView2D() const; + + const vec3& getScale2D() const; }; } diff --git a/libraries/BLT b/libraries/BLT index 133728b..0a04408 160000 --- a/libraries/BLT +++ b/libraries/BLT @@ -1 +1 @@ -Subproject commit 133728b64100292779df64436c51c61317f608f5 +Subproject commit 0a04408e70f9aa20704b8d7db9ee248dd53d57e8 diff --git a/src/blt/gfx/raycast.cpp b/src/blt/gfx/raycast.cpp new file mode 100644 index 0000000..ab93c51 --- /dev/null +++ b/src/blt/gfx/raycast.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include + +namespace blt::gfx +{ + + blt::vec3 calculateRay3D(float mx, float my, float width, float height, const mat4x4& view, const mat4x4& proj) + { + auto normalized_coords = detail::getNormalisedDeviceCoordinates(mx, my, width, height); + blt::vec4 clip_coords(normalized_coords.x(), normalized_coords.y(), -1.0f, 1.0f); + auto eye_coords = detail::toEyeCoords(clip_coords, proj); + return detail::toWorldCoords(eye_coords, view); + } + + blt::vec3 calculateRay3D(float width, float height, const blt::mat4x4& view, const blt::mat4x4& proj) + { + return calculateRay3D(static_cast(getMouseX()), static_cast(getMouseY()), width, height, view, proj); + } + + blt::vec3 calculateRay2D(float mx, float my, float width, float height, const blt::vec2 scale, const mat4x4& view, const mat4x4& proj) + { + auto inv_p = proj.inverse(); + blt::mat4x4 inv_v = view.inverse(); + + BLT_DEBUG_STREAM << inv_v << '\n'; + BLT_TRACE_STREAM << view << '\n'; + BLT_INFO_STREAM << (inv_v * view) << '\n'; + BLT_INFO_STREAM << (view * inv_v) << '\n'; + + mat4x4 scale_mat; + //scale_mat.scale(blt::vec3(scale.x(), scale.y(), 0)); + auto inv_s = scale_mat.inverse(); + + //auto normalized_coords = detail::getNormalisedDeviceCoordinates(mx, my, width, height); + blt::vec2 normalized_coords(mx * 2.0 / width, my * 2.0 / height); + blt::vec4 clip_coords(normalized_coords.x(), normalized_coords.y(), 0.0, 1.0f); + auto scaled_coords = inv_s * clip_coords; + auto eye_coords = inv_p * scaled_coords; + auto world_coords = inv_v * eye_coords; + + //auto world_coords = view * blt::vec4(-mx, my, 0, 1.0); + + return blt::vec3(world_coords.x(), world_coords.y(), world_coords.z()); + } + + blt::vec3 calculateRay2D(float width, float height, const blt::vec2 scale, const blt::mat4x4& view, const blt::mat4x4& proj) + { + return calculateRay2D(static_cast(getMouseX()), static_cast(getMouseY()), width, height, scale, view, proj); + } + + blt::vec3 detail::toWorldCoords(const vec4& eyeCoords, const mat4x4& view) + { + mat4x4 inverted_view = view.inverse(); + auto ray_world = inverted_view * eyeCoords; + return blt::vec3(ray_world.x(), ray_world.y(), ray_world.z()).normalize(); + } + + blt::vec4 detail::toEyeCoords(const vec4& clipCoords, const mat4x4& proj) + { + mat4x4 inverted_projection = proj.inverse(); + auto eye_coords = inverted_projection * clipCoords; + return blt::vec4(eye_coords.x(), eye_coords.y(), -1.0f, 0.0f); + } +} \ No newline at end of file diff --git a/src/blt/gfx/state.cpp b/src/blt/gfx/state.cpp index 0f03a26..3f5e6cf 100644 --- a/src/blt/gfx/state.cpp +++ b/src/blt/gfx/state.cpp @@ -45,3 +45,38 @@ void blt::gfx::matrix_state_manager::update_perspectives(std::int32_t width, std ortho = blt::ortho(0, (float)width, (float)height, 0, ortho_near, ortho_far); } } + +const blt::mat4x4& blt::gfx::matrix_state_manager::getView() const +{ + return view; +} + +const blt::mat4x4& blt::gfx::matrix_state_manager::getOrtho() const +{ + return ortho; +} + +const blt::mat4x4& blt::gfx::matrix_state_manager::getPerspective() const +{ + return perspective; +} + +const blt::mat4x4& blt::gfx::matrix_state_manager::getPvm() const +{ + return pvm; +} + +const blt::mat4x4& blt::gfx::matrix_state_manager::getOvm() const +{ + return ovm; +} + +const blt::mat4x4& blt::gfx::matrix_state_manager::getView2D() const +{ + return view_2d; +} + +const blt::vec3& blt::gfx::matrix_state_manager::getScale2D() const +{ + return scale_2d; +}