added rotation to pad transformation, added pointer cursor
This commit is contained in:
parent
80aebaf8de
commit
e0b1d1fd53
15
config.json
15
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"
|
||||
}
|
||||
}
|
||||
|
|
2
lib/sb
2
lib/sb
|
@ -1 +1 @@
|
|||
Subproject commit 03d179eed4c8323576157f806806b214e42d07c7
|
||||
Subproject commit 54cf01246b0e5ec81ba5b9158248bca7492823db
|
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
132
src/Pudding.cpp
132
src/Pudding.cpp
|
@ -29,33 +29,24 @@ Pudding::Pudding()
|
|||
{
|
||||
/* subscribe to command events */
|
||||
get_delegate().subscribe(&Pudding::respond, this);
|
||||
get_delegate().subscribe(&Pudding::respond, this, SDL_MOUSEMOTION);
|
||||
get_delegate().subscribe(&Pudding::respond, this, SDL_MOUSEBUTTONDOWN);
|
||||
/* initialize a zbar image scanner for reading barcodes of any format */
|
||||
image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
|
||||
/* set up pudding model */
|
||||
nlohmann::json pudding = get_configuration()["pudding"];
|
||||
set_pudding_model(pudding["top-radius"], pudding["base-radius"], pudding["ring-vertex-count"], pudding["layer-count"],
|
||||
load_pudding_model(pudding["top-radius"], pudding["base-radius"], pudding["ring-vertex-count"], pudding["layer-count"],
|
||||
pudding["y-range"][0], pudding["y-range"][1], pudding["gradient-position"]);
|
||||
/* loading GL context instead of SDL context for 3D */
|
||||
load_gl_context();
|
||||
load_tiles();
|
||||
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<void()>()};
|
||||
const std::vector<glm::vec2>& 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_Cursor>(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<fs::path>() / ".*.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<fs::path>() / ".*.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<float>()), 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<void()> on_connect)
|
||||
Pad::Pad(sb::Texture texture, glm::vec2 offset, float scale, float ratio, std::function<void()> 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. */
|
||||
|
|
|
@ -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<void()>()};
|
||||
* const std::vector<glm::vec2>& 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<SDL_Cursor> poke;
|
||||
std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode;
|
||||
std::vector<Item> 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<std::string, sb::Texture> 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
|
||||
|
|
Loading…
Reference in New Issue