From 54cf01246b0e5ec81ba5b9158248bca7492823db Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Sat, 13 Nov 2021 14:49:56 -0500 Subject: [PATCH] Display object can return ndc coordinates from a pixel coordinate box --- src/Box.cpp | 56 ++++++++++++++++++++++++++---------------------- src/Box.hpp | 7 +++--- src/Display.cpp | 44 +++++++++++++++++++++++++------------ src/Display.hpp | 2 ++ src/GLObject.cpp | 2 +- src/Node.cpp | 16 ++++++++++++-- src/Node.hpp | 10 +++++++++ 7 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/Box.cpp b/src/Box.cpp index 4e622ed..27eaf43 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -1,6 +1,6 @@ /* /\ +--------------------------------------------------------------+ ____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, | - \ / / | copy, modify and sell without restriction | + \ / / | copy, and modify without restriction | +--\ ^__^ /--+ | | | ~/ \~ | | - originally created at [http://nugget.fun] | | ~~~~~~~~~~~~ | +--------------------------------------------------------------+ @@ -10,33 +10,37 @@ #include "Box.hpp" -/* Construct a Box by giving a corner coordinate (top left in SDL coordinates, bottom left in GL coordinates) - * and size (as width, height). The gl argument indicates that the Y-coordinate increases from the bottom of +/* Construct a Box by giving a corner coordinate (top left if Y-axis is not inverted, bottom left otherwise) and + * size (as width, height). The invert_y argument indicates that the Y-coordinate increases from the bottom of * the screen to the top rather than the default case where it increases from the top to the bottom. */ -Box::Box(const glm::vec2& corner, const glm::vec2& size, bool use_gl_coordinates) +Box::Box(const glm::vec2& corner, const glm::vec2& size, bool invert_y) { x = corner.x; y = corner.y; w = size.x; h = size.y; - gl(use_gl_coordinates); + this->invert_y(invert_y); } -/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments */ -Box::Box(const SDL_Rect& rect, bool use_gl_coordinates) : Box({rect.x, rect.y}, {rect.w, rect.h}, use_gl_coordinates) {} +/* Construct a Box from float arguments: x, y, width, height. If invert_y is set, the Y-axis increases from bottom to + * top instead of top to bottom. */ +Box::Box(float x, float y, float width, float height, bool invert_y) : Box({x, y}, {width, height}, invert_y) {} -/* Set GL mode to true, meaning the Y-coordinate increases from the bottom of the screen to the top, or false, - * meaning SDL mode where the Y-coordinate increases from the top of the screen to the bottom. */ -void Box::gl(bool use_gl_coordinates) +/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments. */ +Box::Box(const SDL_Rect& rect, bool invert_y) : Box({rect.x, rect.y}, {rect.w, rect.h}, invert_y) {} + +/* Set inverted Y mode to true, meaning the Y-coordinate increases from the bottom to the top, or false, meaning the + * Y-coordinate increases from the top to the bottom. */ +void Box::invert_y(bool invert) { - this->use_gl_coordinates = use_gl_coordinates; + invert_y_state = invert; } -/* Returns true if GL coordinate mode was set, meaning the Y-coordinate increases from the bottom of the screen to - * the top, or false, meaning SDL mode where the Y-coordinate increases from the top of the screen to the bottom. */ -bool Box::gl() const +/* Returns true if Y-axis was set to inverted, meaning the Y-coordinate increases from the bottom to the top, or false, + * meaning Y-coordinate increases from the top to the bottom. */ +bool Box::inverted_y() const { - return use_gl_coordinates; + return invert_y_state; } /* Return the width */ @@ -98,7 +102,7 @@ float Box::area() const float Box::top() const { /* if Y-coordinate increases from bottom to top, use the bottom to determine this value */ - if (gl()) + if (inverted_y()) { return bottom() + height(); } @@ -119,7 +123,7 @@ float Box::right() const float Box::bottom() const { /* if Y-coordinate increases from bottom to top, use the stored Y-coordinate */ - if (gl()) + if (inverted_y()) { return y; } @@ -146,7 +150,7 @@ float Box::cx() const float Box::cy() const { /* if Y-coordinate increases from bottom to top, add from the bottom */ - if (gl()) + if (inverted_y()) { return bottom() + height() / 2.0f; } @@ -179,7 +183,7 @@ void Box::drag_top(float delta) { float new_location = top() + delta; height(std::abs(bottom() - new_location)); - if ((gl() && new_location < bottom()) || (!gl() && new_location > bottom())) + if ((inverted_y() && new_location < bottom()) || (!inverted_y() && new_location > bottom())) { bottom(new_location); } @@ -239,7 +243,7 @@ void Box::drag_bottom(float delta) { float new_location = bottom() + delta; height(std::abs(top() - new_location)); - if ((gl() && new_location > top()) || (!gl() && new_location < bottom())) + if ((inverted_y() && new_location > top()) || (!inverted_y() && new_location < bottom())) { top(new_location); } @@ -477,9 +481,9 @@ bool Box::fits(const Box& container) const { return !( - ((gl() && top() > container.top()) || (!gl() && top() < container.top())) || + ((inverted_y() && top() > container.top()) || (!inverted_y() && top() < container.top())) || right() > container.right() || - ((gl() && bottom() < container.bottom()) || (!gl() && bottom() > container.bottom())) || + ((inverted_y() && bottom() < container.bottom()) || (!inverted_y() && bottom() > container.bottom())) || left() < container.left() ); } @@ -487,7 +491,7 @@ bool Box::fits(const Box& container) const /* Removes any part of the box that is not inside the passed crop area box */ void Box::crop(const Box& area) { - if ((gl() && top() > area.top()) || (!gl() && top() < area.top())) + if ((inverted_y() && top() > area.top()) || (!inverted_y() && top() < area.top())) { top(area.top(), true); } @@ -495,7 +499,7 @@ void Box::crop(const Box& area) { right(area.right(), true); } - if ((gl() && bottom() < area.bottom()) || (!gl() && bottom() > area.bottom())) + if ((inverted_y() && bottom() < area.bottom()) || (!inverted_y() && bottom() > area.bottom())) { bottom(area.bottom(), true); } @@ -509,7 +513,7 @@ void Box::crop(const Box& area) * will return true. */ bool Box::collide(const glm::vec2& point) const { - return point.x >= left() && point.x <= right() && point.y >= (gl() ? bottom() : top()) && point.y <= (gl() ? top() : bottom()); + return point.x >= left() && point.x <= right() && point.y >= (inverted_y() ? bottom() : top()) && point.y <= (inverted_y() ? top() : bottom()); } /* Returns true if the line segment intersects the box, false otherwise. If intersection is passed and there is a @@ -557,7 +561,7 @@ bool Box::collide(const Segment& segment, glm::vec2& intersection) const bool Box::collide(const Box& box, Box* overlap) const { float top, bottom, h; - if (gl()) + if (inverted_y()) { top = std::min(this->top(), box.top()); bottom = std::max(this->bottom(), box.bottom()); diff --git a/src/Box.hpp b/src/Box.hpp index 8899550..dbef689 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -28,14 +28,15 @@ class Box : public SDL_FRect private: - bool use_gl_coordinates; + bool invert_y_state = false; public: Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}, bool = false); + Box(float, float, float, float, bool = false); Box(const SDL_Rect&, bool = false); - void gl(bool); - bool gl() const; + void invert_y(bool); + bool inverted_y() const; float width() const; void width(float); float height() const; diff --git a/src/Display.cpp b/src/Display.cpp index f3388d1..493d9a2 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -14,11 +14,23 @@ glm::ivec2 Display::window_size() const return size; } -/* Return the window dimensions as a Box object. If use_gl_coordinates is set, the lower left will be (0, 0). - * Otherwise, the top left will be (0, 0). */ -Box Display::window_box(bool use_gl_coordinates) const +/* Return the window dimensions in pixels as a Box object. If invert_y is set, the lower left will be (0, 0). + * Otherwise, the top left will be (0, 0). Setting invert will cause the values to be compatible with + * glViewport. */ +Box Display::window_box(bool invert_y) const { - return Box(glm::vec2(0, 0), window_size(), use_gl_coordinates); + return Box(glm::vec2(0, 0), window_size(), invert_y); +} + +/* Return a box object with NDC coordinates of the window subsection. The subsection should be specified in + * pixel coordinates. */ +Box Display::ndc_subsection(const Box& subsection) const +{ + Box ndc_subsection = ndc; + Box window = window_box(subsection.inverted_y()); + ndc_subsection.move({(subsection.x - window.x) / window.width() * 2.0f, (subsection.y - window.y) / window.height() * 2.0f}); + ndc_subsection.size({subsection.width() / window.width() * 2.0f, subsection.height() / window.height() * 2.0f}); + return ndc_subsection; } /* Get the pixel format of display at specified index (defaults to index 0) */ @@ -45,18 +57,22 @@ void Display::screen_pixels(unsigned char* pixels, int w, int h, int x, int y) c if (get_root()->is_gl_context) { GLenum format; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - format = GL_BGRA; -#else - format = GL_RGBA; -#endif + if constexpr (SDL_BYTEORDER == SDL_BIG_ENDIAN) + { + format = GL_BGRA; + } + else + { + format = GL_RGBA; + } glReadBuffer(GL_FRONT); glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels); - // SDL_Log("(%i, %i, %i) (%i, %i, %i, %i)", - // glCheckFramebufferStatus(GL_FRAMEBUFFER), - // glCheckFramebufferStatus(GL_READ_FRAMEBUFFER), - // glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), - // pixels[0], pixels[1], pixels[2], pixels[3]); + /* Debug statement showing the framebuffer status and first pixel read */ + std::ostringstream message; + message << "read framebuffer status: " << glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) << + ", draw framebuffer status: " << glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) << + ", upper left screen pixel value read: " << pixels[0] << " " << pixels[1] << " " << pixels[2] << " " << pixels[3]; + sb::Log::log(message, sb::Log::DEBUG); } else { diff --git a/src/Display.hpp b/src/Display.hpp index 8065379..26b8cba 100644 --- a/src/Display.hpp +++ b/src/Display.hpp @@ -17,11 +17,13 @@ class Display : public Node public: const static int bpp = 32; + inline const static Box ndc {-1.0f, -1.0f, 2.0f, 2.0f, true}; Display(Node*); glm::ivec2 window_size() const; Uint32 pixel_format(int = 0) const; Box window_box(bool = false) const; + Box ndc_subsection(const Box&) const; void screen_pixels(unsigned char*, int, int, int = 0, int = 0) const; SDL_Surface* screen_surface() const; SDL_Surface* screen_surface_from_pixels(unsigned char*, bool) const; diff --git a/src/GLObject.cpp b/src/GLObject.cpp index 033d7f4..371d35a 100644 --- a/src/GLObject.cpp +++ b/src/GLObject.cpp @@ -1,6 +1,6 @@ /* /\ +--------------------------------------------------------------+ ____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, | - \ / / | copy, modify and sell without restriction | + \ / / | copy, and modify without restriction | +--\ ^__^ /--+ | | | ~/ \~ | | - originally created at [http://nugget.fun] | | ~~~~~~~~~~~~ | +--------------------------------------------------------------+ diff --git a/src/Node.cpp b/src/Node.cpp index c181a7e..c740d7d 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -1,3 +1,13 @@ +/* /\ +--------------------------------------------------------------+ + ____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, | + \ / / | copy, and modify without restriction | + +--\ ^__^ /--+ | | + | ~/ \~ | | - originally created at [http://nugget.fun] | + | ~~~~~~~~~~~~ | +--------------------------------------------------------------+ + | SPACE ~~~~~ | / + | ~~~~~~~ BOX |/ + +-------------*/ + #include "Configuration.hpp" #include "Delegate.hpp" #include "Display.hpp" @@ -99,9 +109,11 @@ const Game* Node::get_root() const return dynamic_cast(r); } -Box Node::window_box(bool use_gl_coordinates) +/* Get the window dimensions in pixels as a box object. If invert_y is set, the bottom left will be (0, 0). + * Otherwise, it the top left will be (0, 0). */ +Box Node::window_box(bool invert_y) { - return get_display().window_box(use_gl_coordinates); + return get_display().window_box(invert_y); } void Node::suppress_input() diff --git a/src/Node.hpp b/src/Node.hpp index e0e95e4..930dcbc 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -1,3 +1,13 @@ +/* /\ +--------------------------------------------------------------+ + ____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, | + \ / / | copy, and modify without restriction | + +--\ ^__^ /--+ | | + | ~/ \~ | | - originally created at [http://nugget.fun] | + | ~~~~~~~~~~~~ | +--------------------------------------------------------------+ + | SPACE ~~~~~ | / + | ~~~~~~~ BOX |/ + +-------------*/ + #ifndef SB_NODE_H_ #define SB_NODE_H_