update math and misc functions

This commit is contained in:
T1ti
2024-09-26 03:12:06 +02:00
parent 162145a233
commit 94b879ab8d
19 changed files with 251 additions and 68 deletions

View File

@@ -42,21 +42,22 @@ namespace math
{
}
aabb::aabb(std::vector<glm::vec3> points)
aabb::aabb(std::vector<glm::vec3> const& points)
: aabb(min_per_dimension(points), max_per_dimension(points))
{
assert(!points.empty());
}
//! \todo Optimize: iterate lazily.
std::vector<glm::vec3> aabb::all_corners() const
std::array<glm::vec3, 8> aabb::all_corners() const
{
return box_points(min, max);
}
std::vector<glm::vec3> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max)
std::array<glm::vec3, 8> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max)
{
return std::vector<glm::vec3> {
return std::array<glm::vec3, 8> {
glm::vec3(box_max.x, box_max.y, box_max.z),
glm::vec3(box_max.x, box_max.y, box_min.z),
glm::vec3(box_max.x, box_min.y, box_max.z),
@@ -67,4 +68,25 @@ namespace math
glm::vec3(box_min.x, box_min.y, box_min.z)
};
}
aabb_2d::aabb_2d(std::vector<glm::vec2> const& points)
{
assert(!points.empty());
min = glm::vec2(
std::numeric_limits<float>::max(),
std::numeric_limits<float>::max()
);
max = glm::vec2(
std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::lowest()
);
for (auto const& point : points)
{
min = glm::min(min, point);
max = glm::max(max, point);
}
}
}

View File

@@ -3,20 +3,33 @@
#pragma once
#include <vector>
#include <array>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
namespace math
{
struct aabb
{
aabb(glm::vec3 const& min_, glm::vec3 const& max_);
aabb(std::vector<glm::vec3> points);
aabb(std::vector<glm::vec3> const& points);
std::vector<glm::vec3> all_corners() const;
std::array<glm::vec3, 8> all_corners() const;
glm::vec3 min;
glm::vec3 max;
};
std::vector<glm::vec3> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max);
std::array<glm::vec3, 8> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max);
// 2d bounding box, aka square
struct aabb_2d
{
aabb_2d(std::vector<glm::vec2> const& points);
// std::array<glm::vec2, 4> all_corners() const;
glm::vec2 min;
glm::vec2 max;
};
}

View File

@@ -1,39 +0,0 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "coordinates.hpp"
#include <noggit/MapHeaders.h>
namespace math
{
void to_client(glm::vec3& vector)
{
float x = vector.x;
vector.x = -vector.y + ZEROPOINT;
vector.y = vector.z;
vector.z = -x + ZEROPOINT;
}
void to_client(float vector[3])
{
float x = vector[0];
vector[0] = -vector[1] + ZEROPOINT;
vector[1] = vector[2];
vector[2] = -x + ZEROPOINT;
}
void to_server(glm::vec3& vector)
{
float x = vector.x;
vector.x = ZEROPOINT - vector.z;
vector.z = vector.y;
vector.y = ZEROPOINT - x;
}
void to_server(float vector[3])
{
float x = vector[0];
vector[0] = ZEROPOINT - vector[2];
vector[2] = vector[1];
vector[1] = ZEROPOINT - x;
}
}

View File

@@ -2,12 +2,39 @@
#pragma once
#include <glm/vec3.hpp>
#include <noggit/MapHeaders.h>
namespace math
{
void to_client(glm::vec3& vector);
void to_client(float vector[3]);
void to_server(glm::vec3& vector);
void to_server(float vector[3]);
inline void to_client(glm::vec3& vector)
{
float x = vector.x;
vector.x = -vector.y + ZEROPOINT;
vector.y = vector.z;
vector.z = -x + ZEROPOINT;
}
inline void to_client(float vector[3])
{
float x = vector[0];
vector[0] = -vector[1] + ZEROPOINT;
vector[1] = vector[2];
vector[2] = -x + ZEROPOINT;
}
inline void to_server(glm::vec3& vector)
{
float x = vector.x;
vector.x = ZEROPOINT - vector.z;
vector.z = vector.y;
vector.y = ZEROPOINT - x;
}
inline void to_server(float vector[3])
{
float x = vector[0];
vector[0] = ZEROPOINT - vector[2];
vector[2] = vector[1];
vector[1] = ZEROPOINT - x;
}
}

View File

@@ -3,10 +3,12 @@
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <cmath>
#include <glm/common.hpp>
#include <glm/trigonometric.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <glm/ext/scalar_constants.hpp>
namespace math
@@ -82,10 +84,60 @@ namespace math
*y = xa * glm::sin(angle._) + ya * glm::cos(angle._) + y0;
}
inline bool is_inside_of(const glm::vec3& pos, const glm::vec3& a, const glm::vec3& b)
// inside of axis aligned box
inline bool is_inside_of_aabb(const glm::vec3& pos, const glm::vec3& a, const glm::vec3& b)
{
return a.x < pos.x&& b.x > pos.x
&& a.y < pos.y&& b.y > pos.y
&& a.z < pos.z&& b.z > pos.z;
}
// if a point is in a rectangle in 2D space
inline bool is_inside_of_aabb_2d(const glm::vec2& pos, const glm::vec2& a, const glm::vec2& b)
{
return a.x < pos.x && b.x > pos.x
&& a.y < pos.y && b.y > pos.y;
}
// check if a rectangle intersects with another in 2D space
inline bool boxIntersects(const glm::vec2& minA, const glm::vec2& maxA, const glm::vec2& minB, const glm::vec2& maxB)
{
// Check if one box is to the left or right of the other
if (minA.x > maxB.x || minB.x > maxA.x)
return false;
// Check if one box is above or below the other
if (minA.y > maxB.y || minB.y > maxA.y)
return false;
// The boxes intersect
return true;
}
bool is_inside_of_polygon(const glm::vec2& pos, const std::vector<glm::vec2>& polygon);
// bool is_inside_of_polygon(const glm::vec2& pos, const std::vector<glm::vec2>& polygon) {
// int n = polygon.size();
// bool inside = false;
//
// // Iterate through each edge of the polygon
// for (int i = 0; i < n; ++i) {
// // Get the current vertex and the next vertex (looping back to the start)
// glm::vec2 v1 = polygon[i];
// glm::vec2 v2 = polygon[(i + 1) % n];
//
// // Check if the point is within the y-bounds of the edge
// if ((v1.y > pos.y) != (v2.y > pos.y)) {
// // Compute the x-coordinate of the intersection point
// float intersectX = (pos.y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y) + v1.x;
//
// // Check if the intersection point is to the right of the point
// if (pos.x < intersectX) {
// inside = !inside;
// }
// }
// }
//
// return inside;
// }
}

View File

@@ -13,7 +13,7 @@ namespace Noggit
, _roll (0.0f)
, _yaw (0.f)
, _pitch (0.f)
, _fov (math::degrees (54.f))
, _fov (math::degrees (54.f)) // this seems to be vertical FOV. 60 degrees vertical FOV equals 91.49 horizontal FOV in 16:9
{
//! \note ensure ranges
yaw (yaw_);

View File

@@ -398,12 +398,12 @@ bool MapTile::isTile(int pX, int pZ)
float MapTile::getMaxHeight()
{
return _extents[1].y;
return getExtents()[1].y;
}
float MapTile::getMinHeight()
{
return _extents[0].y;
return getExtents()[0].y;
}
void MapTile::forceRecalcExtents()

View File

@@ -160,8 +160,8 @@ public:
void recalcExtents();
void recalcObjectInstanceExtents();
void recalcCombinedExtents();
std::array<glm::vec3, 2>& getExtents() { return _extents; };
std::array<glm::vec3, 2>& getCombinedExtents() { return _combined_extents; };
std::array<glm::vec3, 2>& getExtents() { recalcExtents(); return _extents; };
std::array<glm::vec3, 2>& getCombinedExtents() { recalcCombinedExtents(); return _combined_extents; };
World* getWorld() { return _world; };

View File

@@ -4231,12 +4231,28 @@ void MapView::onSettingsSave()
_camera.fov(math::degrees(_settings->value("fov", 54.f).toFloat()));
_debug_cam.fov(math::degrees(_settings->value("fov", 54.f).toFloat()));
int _fps_limit = _settings->value("fps_limit", 60).toInt();
int _frametime = static_cast<int>((1.f / static_cast<float>(_fps_limit)) * 1000.f);
// _update_every_event_loop.start(_frametime);
_update_every_event_loop.setInterval(_frametime);
bool vsync = _settings->value("vsync", false).toBool();
format().setSwapInterval(vsync ? 1
: Noggit::Application::NoggitApplication::instance()->getConfiguration()->GraphicsConfiguration.SwapChainInternal);
bool doAntiAliasing = _settings->value("anti_aliasing", false).toBool();
format().setSamples(doAntiAliasing ? 4
: Noggit::Application::NoggitApplication::instance()->getConfiguration()->GraphicsConfiguration.SamplesCount);
// force updating rendering
_camera_moved_since_last_draw = true;
}
void MapView::ShowContextMenu(QPoint pos)
{
// QApplication::startDragDistance() is 10
auto mouse_moved = (QApplication::startDragDistance() / 5) < (_right_click_pos - pos).manhattanLength();
bool mouse_moved = (QApplication::startDragDistance() / 5) < (_right_click_pos - pos).manhattanLength();
// don't show context menu if dragging mouse
if (mouse_moved || ImGuizmo::IsUsing())

View File

@@ -27,6 +27,80 @@ namespace misc
point.x <= extents[1].x && point.y <= extents[1].y;
}
// project 3D point to 2d screen space.
// Note : When working with noggit 3D coords, need to swap Y and Z !
glm::vec4 projectPointToScreen(const glm::vec3& point, const glm::mat4& VPmatrix, float viewport_width, float viewport_height, bool& valid)
{
glm::vec4 clipSpacePos = VPmatrix * glm::vec4(point, 1.0f);
if (clipSpacePos.w <= 0.0f)
{
valid = false; // not valid, point is behind camera
return clipSpacePos;
}
// Perspective division to move to normalized device coordinates (NDC)
float ndcX = clipSpacePos.x / clipSpacePos.w;
float ndcY = clipSpacePos.y / clipSpacePos.w;
float ndcZ = clipSpacePos.z / clipSpacePos.w;
// If the point is out of the normalized device coordinates range, it's off-screen
if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f)
{
valid = false;
return glm::vec4(-1.0f, -1.0f, -1.0f, -1.0f);
}
// Convert NDC to screen space coordinates
clipSpacePos.x = (ndcX + 1.0f) * 0.5f * viewport_width;
clipSpacePos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewport_height;
valid = true;
return clipSpacePos;
}
std::array<glm::vec2, 2> getAABBScreenBounds(const std::array<glm::vec3, 2>& extents
, const glm::mat4& VPmatrix
, float viewport_width
, float viewport_height
, bool& valid
, float scale)
{
math::aabb obj_aabb(extents[0], extents[1]);
auto corners = obj_aabb.all_corners();
glm::vec2 minScreen = glm::vec2(std::numeric_limits<float>::max());
glm::vec2 maxScreen = glm::vec2(std::numeric_limits<float>::lowest());
for (const auto& corner : corners)
{
bool point_valid;
const glm::vec4 screenPos = projectPointToScreen(corner, VPmatrix, viewport_width, viewport_height, point_valid);
if (!point_valid)
{
valid = false; // one point was outside of screen space
return { glm::vec2(0.0f), glm::vec2(0.0f) };
}
// Update min and max screen bounds if the point is valid (within screen space)
minScreen = glm::min(minScreen, glm::vec2(screenPos.x, screenPos.y));
maxScreen = glm::max(maxScreen, glm::vec2(screenPos.x, screenPos.y));
}
valid = true;
if (scale != 1.0f)
{
glm::vec2 center = (minScreen + maxScreen) * 0.5f;
glm::vec2 halfSize = (maxScreen - minScreen) * 0.5f * scale;
minScreen = center - halfSize;
maxScreen = center + halfSize;
}
return { minScreen, maxScreen };
}
void minmax(glm::vec3* a, glm::vec3* b)
{
if (a->x > b->x)

View File

@@ -56,6 +56,15 @@ namespace misc
bool vec3d_equals(glm::vec3 const& v1, glm::vec3 const& v2);
bool deg_vec3d_equals(math::degrees::vec3 const& v1, math::degrees::vec3 const& v2);
glm::vec4 projectPointToScreen(const glm::vec3& point, const glm::mat4& VPmatrix, float viewport_width, float viewport_height, bool& valid);
std::array<glm::vec2, 2> getAABBScreenBounds(const std::array<glm::vec3, 2>& extents
, const glm::mat4& VPmatrix
, float viewport_width
, float viewport_height
, bool& valid
, float scale = 1.0f);
bool pointInside(glm::vec3 point, std::array<glm::vec3, 2> const& extents);
bool pointInside(glm::vec2 point, std::array<glm::vec2, 2> const& extents);
void minmax(glm::vec3* a, glm::vec3* b);

View File

@@ -62,7 +62,7 @@ public:
void setType(int type, size_t layer);
int getType(size_t layer);
std::array<glm::vec3, 2>& getExtents() { return _extents; };
std::array<glm::vec3, 2>& getExtents() { if (needsUpdate()){ recalcExtents(); } return _extents; };
[[nodiscard]]
bool isVisible(const math::frustum& frustum) const;

View File

@@ -179,7 +179,7 @@ namespace Noggit::Rendering
GLuint const& _box_vbo = _buffers[2];
GLuint _bone_matrices_buf_tex;
std::vector<glm::vec3> _vertex_box_points;
std::array<glm::vec3, 8> _vertex_box_points;
std::vector<ModelRenderPass> _render_passes;
bool _uploaded = false;

View File

@@ -447,7 +447,7 @@ void TileRender::doTileOcclusionQuery(OpenGL::Scoped::use_program& occlusion_sha
_tile_occlusion_query_in_use = true;
gl.beginQuery(GL_ANY_SAMPLES_PASSED, _tile_occlusion_query);
occlusion_shader.uniform("aabb", _map_tile->_combined_extents.data(), _map_tile->_combined_extents.size());
occlusion_shader.uniform("aabb", _map_tile->getCombinedExtents().data(), _map_tile->getCombinedExtents().size());
gl.drawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, nullptr);
gl.endQuery(GL_ANY_SAMPLES_PASSED);
}
@@ -465,7 +465,7 @@ bool TileRender::getTileOcclusionQueryResult(glm::vec3 const& camera)
if (!_uploaded)
return !_tile_occluded;
if (misc::pointInside(camera, _map_tile->_combined_extents))
if (misc::pointInside(camera, _map_tile->getCombinedExtents()))
{
_tile_occlusion_query_in_use = false;
return true;

View File

@@ -115,7 +115,7 @@ bool WMORender::drawSkybox(const glm::mat4x4& model_view, const glm::vec3& camer
glm::vec3 aabb_max,
const std::map<int, std::pair<glm::vec3, glm::vec3>>& group_extents) const
{
if (!_wmo->skybox || !math::is_inside_of(camera_pos,aabb_min, aabb_max))
if (!_wmo->skybox || !math::is_inside_of_aabb(camera_pos,aabb_min, aabb_max))
{
return false;
}
@@ -131,7 +131,7 @@ bool WMORender::drawSkybox(const glm::mat4x4& model_view, const glm::vec3& camer
auto& extent(group_extents.at(i));
if (math::is_inside_of(camera_pos, extent.first, extent.second))
if (math::is_inside_of_aabb(camera_pos, extent.first, extent.second))
{
ModelInstance sky(_wmo->skybox.value()->file_key().filepath(), _wmo->_context);
sky.pos = camera_pos;

View File

@@ -1457,7 +1457,7 @@ void TextureSet::updateDoodadMapping()
int higher_count = 0;
int lower_count = 0;
std::array<std::array<std::uint8_t, 8>, 8> blizzard_mapping_readable;
bool debug_test = true;
bool debug_test = false;
if (debug_test)
blizzard_mapping_readable = getDoodadMappingReadable();

View File

@@ -417,11 +417,11 @@ void AssetBrowserWidget::updateModelData()
{
_model->clear();
Model::TreeManager tree_mgr = Model::TreeManager(_model);
for (auto& key_pair : Noggit::Application::NoggitApplication::instance()->clientData()->listfile()->pathToFileDataIDMap())
for (auto const& key_pair : Noggit::Application::NoggitApplication::instance()->clientData()->listfile()->pathToFileDataIDMap())
{
std::string const& filename = key_pair.first;
// std::string const& filename = key_pair.first;
QString q_path = QString(filename.c_str());
QString const q_path = QString(key_pair.first.c_str());
if (!( (ui->checkBox_WMOs->isChecked() && q_path.endsWith(".wmo") && !_wmo_group_and_lod_regex.match(q_path).hasMatch())
|| (ui->checkBox_M2s->isChecked() && q_path.endsWith(".m2"))
@@ -431,7 +431,7 @@ void AssetBrowserWidget::updateModelData()
if (!validateBrowseMode(q_path))
continue;
tree_mgr.addItem(filename.c_str());
tree_mgr.addItem(q_path);
}

View File

@@ -278,6 +278,14 @@ namespace OpenGL
gl.uniform3fv (loc, static_cast<GLsizei>(value.size()), glm::value_ptr(value[0]));
}
void use_program::uniform(std::string const& name, std::array<glm::vec3, 8> const& value)
{
GLuint loc = uniform_location(name);
if (loc < 0)
return;
gl.uniform3fv(loc, static_cast<GLsizei>(8), glm::value_ptr(value[0]));
}
void use_program::uniform(std::string const& name, std::vector<glm::vec4> const& value)
{
GLuint loc = uniform_location(name);

View File

@@ -105,6 +105,7 @@ namespace OpenGL
void uniform (std::string const& name, bool);
void uniform (GLint pos, bool);
void uniform (std::string const& name, std::vector<glm::vec3> const& value);
void uniform(std::string const& name, std::array<glm::vec3, 8> const& value);
void uniform (GLint pos, std::vector<glm::vec3> const& value);
void uniform(std::string const& name, std::vector<glm::vec4> const& value);
void uniform(GLint pos, std::vector<glm::vec4> const& value);