From e0b1d1fd53fd5b77a3391045ccbf6c82dc7d1785 Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Sat, 13 Nov 2021 14:58:30 -0500 Subject: [PATCH] added rotation to pad transformation, added pointer cursor --- config.json | 15 +++- lib/sb | 2 +- resource/button/arrow.png | Bin 0 -> 8140 bytes resource/button/home.png | Bin 0 -> 9290 bytes resource/button/inventory.png | Bin 0 -> 5505 bytes resource/button/scan.png | Bin 0 -> 10006 bytes src/Pudding.cpp | 132 ++++++++++++++++++++-------------- src/Pudding.hpp | 59 +++++++++------ 8 files changed, 132 insertions(+), 76 deletions(-) create mode 100644 resource/button/arrow.png create mode 100644 resource/button/home.png create mode 100644 resource/button/inventory.png create mode 100644 resource/button/scan.png diff --git a/config.json b/config.json index f987fb1..bd8e60b 100644 --- a/config.json +++ b/config.json @@ -79,6 +79,19 @@ }, "resource": { - "tile-path": "resource/tile" + "tile-path": "resource/tile", + "button-path": "resource/button" + }, + "interface": + { + "main-button-y": -0.75, + "main-button-single-x": 0.0, + "main-button-double-x": 0.65, + "main-button-scale": 0.25, + "camera-button-label": "scan", + "inventory-button-label": "inventory", + "arrow-button-location": [0.75, 0.0], + "arrow-button-scale": 0.1, + "arrow-button-label": "arrow" } } diff --git a/lib/sb b/lib/sb index 03d179e..54cf012 160000 --- a/lib/sb +++ b/lib/sb @@ -1 +1 @@ -Subproject commit 03d179eed4c8323576157f806806b214e42d07c7 +Subproject commit 54cf01246b0e5ec81ba5b9158248bca7492823db diff --git a/resource/button/arrow.png b/resource/button/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fbecee3fd712e3481ab7bb51939408658384204b GIT binary patch literal 8140 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 literal 0 HcmV?d00001 diff --git a/resource/button/home.png b/resource/button/home.png new file mode 100644 index 0000000000000000000000000000000000000000..7672dc342e243c832cc499bfaea2dc27b91c7684 GIT binary patch literal 9290 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 UyFG8<;UJKl)F()pgrVR60Bwg_oB#j- literal 0 HcmV?d00001 diff --git a/resource/button/inventory.png b/resource/button/inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..19e4a1246ff7d17f422e557b2e86fe1afbc39ae6 GIT binary patch literal 5505 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 - const std::vector& p_position = *p.attributes("position"); - glm::vec4 final_position = p.transformation() * glm::vec4{p_position[2].x, p_position[2].y, 0, 1}; - std::cout << p.transformation() << std::endl << final_position << std::endl; - assert(final_position == glm::vec4({w.x, w.y, 0, 1})); - sb::Texture label {"local/button/scan.png"}; - label.load(); - pad.texture(label); - pad.transform({-0.6739f, -0.74f}, 0.25f, get_display().window_box().aspect()); + load_pads(); + /* Load a pointer cursor from the system library that will be freed automatically */ + poke = std::shared_ptr(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND), SDL_FreeCursor); } /* Assign vertices, colors and texture UV coordinates to the pudding model */ -void Pudding::set_pudding_model( +void Pudding::load_pudding_model( float top_radius, float base_radius, int ring_vertex_count, int layer_count, float min_y, float max_y, float gradient_position) { size_t ii; @@ -231,17 +222,31 @@ void Pudding::load_gl_context() sb::Log::gl_errors("after uniform locations"); } -/* Read every resource/tile/.*.jpg into a GL texture, storing the texture pointer and file name in a std::map */ +/* Read every jpg in the folder at tile path into a GL texture and associate with the background object. */ void Pudding::load_tiles() { for (fs::path path : sb::glob(get_configuration()["resource"]["tile-path"].get() / ".*.jpg")) { - sb::Texture texture = sb::Texture(path); + sb::Texture texture {path}; texture.load(); background.texture(texture, path); } } +/* Load every png in the button path as a Texture and add to a map. */ +void Pudding::load_pads() +{ + for (fs::path path : sb::glob(get_configuration()["resource"]["button-path"].get() / ".*.png")) + { + labels[path.stem()] = sb::Texture(path); + labels[path.stem()].load(); + } + nlohmann::json interface = get_configuration()["interface"]; + camera_button.texture(labels["scan"]); + camera_button.transform({interface["main-button-single-x"], interface["main-button-y"]}, + interface["main-button-scale"], window_box().aspect()); +} + /* Try to create cv::VideoCapture object using device ID #0. If successful, this will create GL texture IDs and storage * for the camera frames, so it must be called after GL context has been created. Two textures will be created, so they * can be used as a double buffer. @@ -312,15 +317,31 @@ void Pudding::respond(SDL_Event& event) { background.next(); } - else if (event.type == SDL_MOUSEBUTTONDOWN) + /* Mouse interface */ + else if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEBUTTONDOWN) { - glm::vec2 gl_coordinates { - float(event.button.x) / window_box().width() * 2.0f - 1.0f, - (1.0f - float(event.button.y) / window_box().height()) * 2.0f - 1.0f + glm::vec2 mouse = event.type == SDL_MOUSEBUTTONDOWN ? glm::vec2{event.button.x, event.button.y} : + glm::vec2{event.motion.x, event.motion.y}; + glm::vec2 ndc { + float(mouse.x) / window_box().width() * 2.0f - 1.0f, (1.0f - float(mouse.y) / window_box().height()) * 2.0f - 1.0f }; - if (pad.collide(gl_coordinates)) + /* Check for collision with the camera button if camera view is open, otherwise check for collision with main viewport. */ + if ((!capture.isOpened() && camera_button.collide(ndc)) || + (capture.isOpened() && get_display().ndc_subsection(main_viewport).collide(ndc))) { - camera_switch.toggle(); + if (SDL_GetCursor() != poke.get()) + { + SDL_SetCursor(poke.get()); + } + if (event.type == SDL_MOUSEBUTTONDOWN) + { + SDL_SetCursor(SDL_GetDefaultCursor()); + camera_switch.toggle(); + } + } + else if (SDL_GetCursor() == poke.get()) + { + SDL_SetCursor(SDL_GetDefaultCursor()); } } } @@ -793,13 +814,15 @@ void Pudding::update() sb::Log::log(message); } /* viewport box will be used to tell GL where to draw */ - Box viewport_box = window_box(true); + viewport = window_box(true); /* shrink viewport if item texture or camera will be displayed */ if (item_display_active() || capture.isOpened()) { - viewport_box.drag_bottom(0.3f * viewport_box.height()); + viewport.drag_bottom(0.3f * viewport.height()); } - glViewport(viewport_box); + /* Save the main viewport dimensions */ + main_viewport = viewport; + glViewport(viewport); glDisable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -826,7 +849,7 @@ void Pudding::update() /* calculate the transformation matrix for displaying pudding in viewport */ model = glm::rotate(model, weight(get_configuration()["pudding"]["rotation-speed"].get()), Y_UNIT_NORMAL_3D); projection = glm::perspective( - glm::radians(40.0f * 1 / viewport_box.aspect()), viewport_box.aspect(), 0.1f, 100.0f); + glm::radians(40.0f * 1 / viewport.aspect()), viewport.aspect(), 0.1f, 100.0f); mvp = projection * VIEW_MATRIX * model; /* uniforms */ glUniform1f(uniform["mvp"]["time"], time_seconds); @@ -875,8 +898,8 @@ void Pudding::update() glUniform1i(uniform["flat"]["texture"], 0); glActiveTexture(GL_TEXTURE0); /* move viewport to the bottom of screen */ - viewport_box.top(viewport_box.bottom(), true); - viewport_box.bottom(window_box(true).bottom(), true); + viewport.top(viewport.bottom(), true); + viewport.bottom(window_box(true).bottom(), true); /* reset blend to display the original texture colors */ glUniform3f(uniform["flat"]["blend"], 0.0f, 0.0f, 1.0f); /* draw the current item image if we're supposed to */ @@ -885,9 +908,9 @@ void Pudding::update() /* shrink viewport to half size if camera will also be displayed */ if (capture.isOpened()) { - viewport_box.left(viewport_box.cx(), true); + viewport.left(viewport.cx(), true); } - glViewport(viewport_box); + glViewport(viewport); current_item().current_texture().bind(); plane.enable(); /* draws rectangle vertices and rectangle texture using UV coords */ @@ -896,8 +919,8 @@ void Pudding::update() /* draw the camera if the camera has been opened */ if (capture.isOpened()) { - viewport_box.left(window_box(true).left()); - glViewport(viewport_box); + viewport.left(window_box(true).left()); + glViewport(viewport); /* bind texture for drawing */ camera_view.current().bind(); camera_view.enable(); @@ -905,16 +928,17 @@ void Pudding::update() glDrawArrays(GL_TRIANGLES, 0, camera_view.attributes("position")->count()); } } - sb::Log::gl_errors("after capture, before test pad"); - /* Test Pad */ - glUseProgram(flat_program); - glUniformMatrix4fv(uniform["flat"]["transformation"], 1, GL_FALSE, &pad.transformation()[0][0]); - pad.texture().bind(); - plane.enable(); - glViewport(window_box(true)); - glDrawArrays(GL_TRIANGLES, 0, pad.attributes("position")->count()); + else + { + /* Draw the camera button if neither the camera or inventory is displayed */ + glUseProgram(flat_program); + glUniformMatrix4fv(uniform["flat"]["transformation"], 1, GL_FALSE, &camera_button.transformation()[0][0]); + camera_button.texture().bind(); + plane.enable(); + glDrawArrays(GL_TRIANGLES, 0, camera_button.attributes("position")->count()); + } SDL_GL_SwapWindow(get_window()); - sb::Log::gl_errors("after test pad"); + sb::Log::gl_errors("at end of update"); /* add a new item if a new barcode was scanned or entered */ if (current_barcode != previous_barcode) { @@ -928,21 +952,22 @@ void Pudding::update() * is relative to (0.0, 0.0), and the scale is relative to the Plane, which has opposite corners at (-1.0, -1.0) and * (1.0, 1.0). * The texture is the graphic that displays in the Pad location. The callback must be a function that * doesn't return a value or accept any arguments. */ -Pad::Pad(sb::Texture texture, glm::vec2 offset, float scale, float ratio, std::function on_connect) +Pad::Pad(sb::Texture texture, glm::vec2 offset, float scale, float ratio, std::function on_connect, float rotation) { this->texture(texture); - transform(offset, scale, ratio); + transform(offset, scale, ratio, rotation); this->on_connect(on_connect); - box.gl(true); + box.invert_y(true); } -/* Set the Pad's transformation matrix based on an offset, a scale, and an aspect ratio. The offset is amount it will - * be shifted in the (x, y) plane. The scale is a value relative to the (x, y) plane, but it is a single value because - * the aspect ratio will determine how much each axis is scaled. If the aspect ratio is above one, the x-axis's scale - * will be divided by the ratio. If the aspect ratio is below one, the y-axis's scale will be multiplied by the aspect - * ratio. If the aspect ratio of the window is given, this will force the Pad to display as a square, and the ratio - * will be relative to the shorter axis. */ -void Pad::transform(glm::vec2 offset, float scale, float ratio) +/* Set the Pad's transformation matrix based on an offset, a scale, an aspect ratio, and a rotation. The offset is the + * amount it will be shifted in the (x, y) plane. The scale is a value relative to the (x, y) plane, and it is a single + * value because the aspect ratio will determine how much each axis is scaled. If the aspect ratio is above one, the + * x-axis's scale will be divided by the ratio. If the aspect ratio is below one, the y-axis's scale will be multiplied + * by the aspect ratio. If the aspect ratio of the window is given, this will force the Pad to display as a square, and + * the ratio will be relative to the shorter axis. The rotation is an angle in radians to rotate the pad object around + * its center after it has been offset and scaled. */ +void Pad::transform(glm::vec2 offset, float scale, float ratio, float rotation) { glm::vec3 scale_components { scale, scale, 1 }; if (ratio > 1.0f) @@ -956,7 +981,8 @@ void Pad::transform(glm::vec2 offset, float scale, float ratio) box.size({scale_components.x * 2, scale_components.y * 2}); box.center(offset); std::cout << "pad box is " << box << std::endl; - Model::transform(glm::translate(glm::vec3{offset.x, offset.y, 0}) * glm::scale(scale_components)); + Model::transform(glm::translate(glm::vec3{offset.x, offset.y, 0}) * glm::scale(scale_components) * + glm::rotate(rotation, glm::vec3{0.0f, 0.0f, 1.0f})); } /* Set the function that will run when a pad object is clicked. */ diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 4d2cce7..f831d63 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -44,8 +44,6 @@ #include "utility.hpp" #include "Box.hpp" -void glViewport(Box); - /* A connection is an object containing a binary state of either on (connected) or off (not connected) * and user supplied functions that run automatically on each state change. The functions each have the * same return type, number of arguments, and argument types determined by the template arguments. @@ -180,6 +178,18 @@ public: * - Has its own response to click * - Shares mouse collision code * - Has its own translate + scale transformation + * + * Example: + * + * glm::vec3 w = glm::mat3({{1, 0, 0}, {0, 1, 0}, {-0.6739, -0.74, 1}}) * glm::mat3({{.1, 0, 0}, {0, .1 * (460.0 / 768.0), 0}, {0, 0, 1}}) * + * glm::vec3({-1, -1, 1}); + * std::cout << w << std::endl << glm::translate(glm::vec3{-0.6739, -0.74, 0}) * + * glm::scale(glm::vec3{.1, .1 * (460.0 / 768.0), 1}) * glm::vec4{-1, -1, 0, 1} << std::endl; + * Pad p {background.current(), {-0.6739f, -0.74f}, 0.1f, get_display().window_box().aspect(), std::function()}; + * const std::vector& p_position = *p.attributes("position"); + * glm::vec4 final_position = p.transformation() * glm::vec4{p_position[2].x, p_position[2].y, 0, 1}; + * std::cout << p.transformation() << std::endl << final_position << std::endl; + * assert(final_position == glm::vec4({w.x, w.y, 0, 1})); */ class Pad : public Plane { @@ -193,8 +203,8 @@ private: public: Pad() {}; - Pad(sb::Texture, glm::vec2, float, float, callback); - void transform(glm::vec2, float, float); + Pad(sb::Texture, glm::vec2, float, float, callback, float = 0.0f); + void transform(glm::vec2, float, float = 1.0f, float = 0.0f); void on_connect(callback); bool collide(const glm::vec2&) const; @@ -206,7 +216,7 @@ class Pudding : public Game private: /* Defines for effect IDs that will be passed to the shader program. Since COUNT is last and every value - * is the default integer, it will define the number of effects available */ + * is the default integer, it will be set to the number of effects available. */ enum Effect { EFFECT_NONE, @@ -223,20 +233,21 @@ private: }; typedef Game super; - const std::string OPEN_FOOD_API_URL = "https://world.openfoodfacts.org/api/v0/product/"; - const std::string OPEN_PRODUCTS_API_URL = "https://world.openproductsfacts.org/api/v0/product/"; - const std::string NUTRONIX_API_URL = "https://trackapi.nutritionix.com/v2/search/item?upc="; - const std::string BARCODE_MONSTER_API_URL = "https://barcode.monster/api/"; - const std::string BEST_BUY_API_URL_1 = "https://api.bestbuy.com/v1/products(upc="; - const std::string BEST_BUY_API_URL_2 = ")?format=json&apiKey="; - const std::string NUTRONIX_NOT_FOUND = "resource not found"; - const std::string GOOGLE_BOOKS_API_URL = "https://www.googleapis.com/books/v1/volumes?q=isbn:"; - const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key="; - const glm::vec3 ZERO_VECTOR_3D {0, 0, 0}; - const glm::vec3 Y_UNIT_NORMAL_3D {0, 1, 0}; - const glm::mat4 VIEW_MATRIX = glm::lookAt({4.0f, 2.0f, 1.0f}, {0.0f, -0.325f, 0.0f}, Y_UNIT_NORMAL_3D); - const glm::vec3 PUDDING_BROWN {0.713f, 0.359f, 0.224f}; - const glm::vec3 PUDDING_YELLOW {0.878f, 0.859f, 0.122f}; + inline static const std::string OPEN_FOOD_API_URL = "https://world.openfoodfacts.org/api/v0/product/"; + inline static const std::string OPEN_PRODUCTS_API_URL = "https://world.openproductsfacts.org/api/v0/product/"; + inline static const std::string NUTRONIX_API_URL = "https://trackapi.nutritionix.com/v2/search/item?upc="; + inline static const std::string BARCODE_MONSTER_API_URL = "https://barcode.monster/api/"; + inline static const std::string BEST_BUY_API_URL_1 = "https://api.bestbuy.com/v1/products(upc="; + inline static const std::string BEST_BUY_API_URL_2 = ")?format=json&apiKey="; + inline static const std::string NUTRONIX_NOT_FOUND = "resource not found"; + inline static const std::string GOOGLE_BOOKS_API_URL = "https://www.googleapis.com/books/v1/volumes?q=isbn:"; + inline static const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key="; + inline static const glm::vec3 ZERO_VECTOR_3D {0, 0, 0}; + inline static const glm::vec3 Y_UNIT_NORMAL_3D {0, 1, 0}; + inline static const glm::mat4 VIEW_MATRIX = glm::lookAt({4.0f, 2.0f, 1.0f}, {0.0f, -0.325f, 0.0f}, Y_UNIT_NORMAL_3D); + inline static const glm::vec3 PUDDING_BROWN {0.713f, 0.359f, 0.224f}; + inline static const glm::vec3 PUDDING_YELLOW {0.878f, 0.859f, 0.122f}; + std::shared_ptr poke; std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode; std::vector items; Carousel item_carousel; @@ -254,11 +265,14 @@ private: SDL_GLContext capture_frame_thread_context = nullptr; sb::VAO vao; sb::VBO vbo; - Pad pad; + std::map labels; + Pad camera_button, previous_button, next_button, inventory_button; + Box viewport, main_viewport; - void set_pudding_model(float, float, int, int = 1, float = -1.0f, float = 1.0f, float = 0.3f); + void load_pudding_model(float, float, int, int = 1, float = -1.0f, float = 1.0f, float = 0.3f); void load_gl_context(); void load_tiles(); + void load_pads(); void initialize_camera(); void incorporate_open_api(Item&, const std::string&); void incorporate_nutronix_api(Item&); @@ -308,4 +322,7 @@ private: /* float weighted depression rate */ }; +/* Allow a box object to be passed to glViewport instead of four vertices. */ +void glViewport(Box); + #endif