pad class with example that runs camera toggle on click

This commit is contained in:
frank 2021-11-09 23:32:48 -05:00
parent c9868db346
commit 80aebaf8de
9 changed files with 205 additions and 67 deletions

View File

@ -5,7 +5,8 @@
"framerate": 60, "framerate": 60,
"title": "Pudding", "title": "Pudding",
"debug": false, "debug": false,
"render driver": "opengl" "render driver": "opengl",
"show-cursor": true
}, },
"configuration": "configuration":
{ {

2
lib/sb

@ -1 +1 @@
Subproject commit 863db5467bfc625df916ac9a04e9d14aa13d7e55 Subproject commit 03d179eed4c8323576157f806806b214e42d07c7

View File

@ -79,21 +79,20 @@ void Item::texture(sb::Texture& texture, const std::string& name)
sb::Texture& Item::current_texture() sb::Texture& Item::current_texture()
{ {
// return image.texture().begin()->second; return carousel.current(image.textures())->second;
return carousel.current(image.texture())->second;
} }
void Item::next_texture() void Item::next_texture()
{ {
carousel.next(image.texture()); carousel.next(image.textures());
} }
void Item::previous_texture() void Item::previous_texture()
{ {
carousel.previous(image.texture()); carousel.previous(image.textures());
} }
std::size_t Item::texture_count() std::size_t Item::texture_count()
{ {
return image.texture().size(); return image.textures().size();
} }

View File

@ -56,7 +56,7 @@ std::map<std::string, std::shared_ptr<sb::Attributes>>& Model::attributes()
* access to the public interface of the attributes. */ * access to the public interface of the attributes. */
std::shared_ptr<sb::Attributes>& Model::attributes(const std::string& name) std::shared_ptr<sb::Attributes>& Model::attributes(const std::string& name)
{ {
return model_attributes.at(name); return attributes().at(name);
} }
/* Get the attributes under name, wrapped in the shared pointer held by this object. This /* Get the attributes under name, wrapped in the shared pointer held by this object. This
@ -64,12 +64,13 @@ std::shared_ptr<sb::Attributes>& Model::attributes(const std::string& name)
* object if they are wrapped in a shared pointer. */ * object if they are wrapped in a shared pointer. */
std::shared_ptr<sb::Attributes>& Model::operator[](const std::string& name) std::shared_ptr<sb::Attributes>& Model::operator[](const std::string& name)
{ {
auto element = model_attributes.find(name); auto element = attributes().find(name);
if (element == model_attributes.end()) /* add an empty Attributes at name if it doesn't exist yet */
if (element == attributes().end())
{ {
attributes(sb::Attributes{}, name); attributes(sb::Attributes{}, name);
} }
return model_attributes[name]; return attributes()[name];
} }
/* Assign name to attributes, copy and wrap in a shared pointer. The model can share /* Assign name to attributes, copy and wrap in a shared pointer. The model can share
@ -82,7 +83,7 @@ void Model::attributes(const sb::Attributes& attributes, const std::string& name
/* Assign name to attributes and share ownership. */ /* Assign name to attributes and share ownership. */
void Model::attributes(const std::shared_ptr<sb::Attributes>& attributes, const std::string& name) void Model::attributes(const std::shared_ptr<sb::Attributes>& attributes, const std::string& name)
{ {
model_attributes[name] = attributes; this->attributes()[name] = attributes;
} }
/* Enable all attributes. */ /* Enable all attributes. */
@ -104,26 +105,46 @@ void Model::disable()
} }
/* Return a reference to the texture container. */ /* Return a reference to the texture container. */
std::map<std::string, sb::Texture>& Model::texture() std::map<std::string, sb::Texture>& Model::textures()
{ {
return model_texture; return model_textures;
} }
/* Get the texture at name. This can be used to read the texture memory, share ownership of it, or /* Get the texture at name. This can be used to read the texture memory, share ownership of it, or
* anything else a Texture object can be used for with direct calls to GL functions. */ * anything else a Texture object can be used for with direct calls to GL functions. */
sb::Texture& Model::texture(const std::string& name) sb::Texture& Model::texture(const std::string& name)
{ {
return model_texture.at(name); return textures().at(name);
}
/* Get the default texture. The default texture must have previously been set with the default key as
* the name, which can be done using Model::texture(sb::Texture). */
sb::Texture& Model::texture()
{
return texture(DEFAULT_TEXTURE_NAME);
} }
/* Assign name to texture and share ownership. */ /* Assign name to texture and share ownership. */
void Model::texture(const sb::Texture& texture, const std::string& name) void Model::texture(const sb::Texture& texture, const std::string& name)
{ {
model_texture[name] = texture; textures()[name] = texture;
}
/* If no name is specified, use the default texture. This can be used to conveniently setup a model
* with only one texture. */
void Model::texture(const sb::Texture& texture)
{
this->texture(texture, DEFAULT_TEXTURE_NAME);
} }
/* Set the transformation matrix. */ /* Set the transformation matrix. */
void Model::transformation(const glm::mat4& transformation) const glm::mat4& Model::transformation() const
{
return model_transformation;
}
/* Set the transformation matrix. */
void Model::transform(const glm::mat4& transformation)
{ {
model_transformation = transformation; model_transformation = transformation;
} }
@ -149,13 +170,13 @@ Model::operator glm::mat4() const
* start over from the beginning. */ * start over from the beginning. */
void Background::next() void Background::next()
{ {
carousel.next(model_texture); carousel.next(textures());
} }
/* Return the currently active texture. */ /* Return the currently active texture. */
sb::Texture& Background::current() sb::Texture& Background::current()
{ {
return carousel.current(model_texture)->second; return carousel.current(textures())->second;
} }
CameraView::CameraView() : Plane() CameraView::CameraView() : Plane()

View File

@ -30,10 +30,11 @@
class Model class Model
{ {
protected: private:
inline static const std::string DEFAULT_TEXTURE_NAME = "default";
std::map<std::string, sb::Texture> model_textures;
std::map<std::string, std::shared_ptr<sb::Attributes>> model_attributes; std::map<std::string, std::shared_ptr<sb::Attributes>> model_attributes;
std::map<std::string, sb::Texture> model_texture;
glm::mat4 model_transformation = glm::mat4(1); glm::mat4 model_transformation = glm::mat4(1);
public: public:
@ -49,10 +50,13 @@ public:
std::shared_ptr<sb::Attributes>& operator[](const std::string&); std::shared_ptr<sb::Attributes>& operator[](const std::string&);
void enable(); void enable();
void disable(); void disable();
std::map<std::string, sb::Texture>& texture(); std::map<std::string, sb::Texture>& textures();
sb::Texture& texture(const std::string&); sb::Texture& texture(const std::string&);
sb::Texture& texture();
void texture(const sb::Texture&, const std::string&); void texture(const sb::Texture&, const std::string&);
void transformation(const glm::mat4&); void texture(const sb::Texture&);
const glm::mat4& transformation() const;
void transform(const glm::mat4&);
std::size_t size(); std::size_t size();
operator glm::mat4() const; operator glm::mat4() const;
@ -64,7 +68,7 @@ class Plane : public Model
public: public:
inline const static std::shared_ptr<sb::Attributes> position = std::make_shared<sb::Attributes>(sb::Attributes{ inline const static std::shared_ptr<sb::Attributes> position = std::make_shared<sb::Attributes>(sb::Attributes{
{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f},
{1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f} {1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f}
}); });
inline const static std::shared_ptr<sb::Attributes> uv = std::make_shared<sb::Attributes>(sb::Attributes{ inline const static std::shared_ptr<sb::Attributes> uv = std::make_shared<sb::Attributes>(sb::Attributes{

View File

@ -29,15 +29,29 @@ Pudding::Pudding()
{ {
/* subscribe to command events */ /* subscribe to command events */
get_delegate().subscribe(&Pudding::respond, this); get_delegate().subscribe(&Pudding::respond, this);
get_delegate().subscribe(&Pudding::respond, this, SDL_MOUSEBUTTONDOWN);
/* initialize a zbar image scanner for reading barcodes of any format */ /* initialize a zbar image scanner for reading barcodes of any format */
image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
/* set up pudding model */ /* set up pudding model */
nlohmann::json pudding = get_configuration()["pudding"]; nlohmann::json pudding = get_configuration()["pudding"];
set_pudding_model(pudding["top-radius"], pudding["base-radius"], pudding["ring-vertex-count"], pudding["layer-count"], set_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"]); pudding["y-range"][0], pudding["y-range"][1], pudding["gradient-position"]);
/* use gl context so we can draw 3D */ /* loading GL context instead of SDL context for 3D */
load_gl_context(); load_gl_context();
load_tiles(); 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());
} }
/* Assign vertices, colors and texture UV coordinates to the pudding model */ /* Assign vertices, colors and texture UV coordinates to the pudding model */
@ -204,12 +218,16 @@ void Pudding::load_gl_context()
uniform["flat"]["time"] = glGetUniformLocation(flat_program, "time"); uniform["flat"]["time"] = glGetUniformLocation(flat_program, "time");
uniform["flat"]["scroll"] = glGetUniformLocation(flat_program, "scroll"); uniform["flat"]["scroll"] = glGetUniformLocation(flat_program, "scroll");
uniform["flat"]["blend"] = glGetUniformLocation(flat_program, "blend_min_hsv"); uniform["flat"]["blend"] = glGetUniformLocation(flat_program, "blend_min_hsv");
uniform["flat"]["transformation"] = glGetUniformLocation(flat_program, "transformation");
uniform["mvp"]["mvp"] = glGetUniformLocation(mvp_program, "mvp"); uniform["mvp"]["mvp"] = glGetUniformLocation(mvp_program, "mvp");
uniform["mvp"]["time"] = glGetUniformLocation(mvp_program, "time"); uniform["mvp"]["time"] = glGetUniformLocation(mvp_program, "time");
uniform["mvp"]["effect"] = glGetUniformLocation(mvp_program, "effect"); uniform["mvp"]["effect"] = glGetUniformLocation(mvp_program, "effect");
uniform["mvp"]["uv transformation"] = glGetUniformLocation(mvp_program, "uv_transformation"); uniform["mvp"]["uv transformation"] = glGetUniformLocation(mvp_program, "uv_transformation");
uniform["mvp"]["coordinate bound"] = glGetUniformLocation(mvp_program, "coordinate_bound"); uniform["mvp"]["coordinate bound"] = glGetUniformLocation(mvp_program, "coordinate_bound");
uniform["mvp"]["pudding texture"] = glGetUniformLocation(mvp_program, "pudding_texture"); uniform["mvp"]["pudding texture"] = glGetUniformLocation(mvp_program, "pudding_texture");
/* enable alpha rendering */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
sb::Log::gl_errors("after uniform locations"); sb::Log::gl_errors("after uniform locations");
} }
@ -294,6 +312,17 @@ void Pudding::respond(SDL_Event& event)
{ {
background.next(); background.next();
} }
else if (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
};
if (pad.collide(gl_coordinates))
{
camera_switch.toggle();
}
}
} }
/* Build an Item object by submitting the upc parameter to multiple APIs and taking /* Build an Item object by submitting the upc parameter to multiple APIs and taking
@ -729,6 +758,7 @@ int Pudding::capture_frame(void* game)
frame.release(); frame.release();
} }
SDL_GL_MakeCurrent(pudding->window, nullptr); SDL_GL_MakeCurrent(pudding->window, nullptr);
sb::Log::gl_errors("in capture thread, after capturing frame");
} }
pudding->reading_capture_frame = false; pudding->reading_capture_frame = false;
return 0; return 0;
@ -752,6 +782,7 @@ void Pudding::update()
reading_capture_frame = true; reading_capture_frame = true;
} }
} }
sb::Log::gl_errors("in main thread, after capturing frame");
/* if the config is set to refresh automatically, there may be a new barcode available */ /* if the config is set to refresh automatically, there may be a new barcode available */
if (current_config_barcode != get_configuration()["scan"]["barcode"]) if (current_config_barcode != get_configuration()["scan"]["barcode"])
{ {
@ -768,7 +799,7 @@ void Pudding::update()
{ {
viewport_box.drag_bottom(0.3f * viewport_box.height()); viewport_box.drag_bottom(0.3f * viewport_box.height());
} }
glViewport(viewport_box.left(), viewport_box.bottom(), viewport_box.width(), viewport_box.height()); glViewport(viewport_box);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -780,22 +811,25 @@ void Pudding::update()
glUniform1i(uniform["flat"]["texture"], 0); glUniform1i(uniform["flat"]["texture"], 0);
glUniform3f(uniform["flat"]["blend"], 0.0f, 0.0f, 1.0f); glUniform3f(uniform["flat"]["blend"], 0.0f, 0.0f, 1.0f);
glUniform1i(uniform["flat"]["scroll"], true); glUniform1i(uniform["flat"]["scroll"], true);
glUniformMatrix4fv(uniform["flat"]["transformation"], 1, GL_FALSE, &glm::mat4(1)[0][0]);
/* disable pudding attributes and enable background attributes */ /* disable pudding attributes and enable background attributes */
pudding_model.disable(); pudding_model.disable();
background.enable(); background.enable();
background.current().bind(); background.current().bind();
/* draws bg vertices and texture */ /* draws bg vertices and texture */
glDrawArrays(GL_TRIANGLES, 0, background.attributes("position")->count()); glDrawArrays(GL_TRIANGLES, 0, background.attributes("position")->count());
/* turn off scrolling */
glUniform1i(uniform["flat"]["scroll"], false); glUniform1i(uniform["flat"]["scroll"], false);
sb::Log::gl_errors("after background, before pudding");
/* draw pudding model using MVP shader */ /* draw pudding model using MVP shader */
glUseProgram(mvp_program); glUseProgram(mvp_program);
glUniform1f(uniform["mvp"]["time"], time_seconds);
/* calculate the transformation matrix for displaying pudding in viewport */ /* 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); model = glm::rotate(model, weight(get_configuration()["pudding"]["rotation-speed"].get<float>()), Y_UNIT_NORMAL_3D);
projection = glm::perspective( projection = glm::perspective(
glm::radians(40.0f * 1 / viewport_box.aspect()), viewport_box.aspect(), 0.1f, 100.0f); glm::radians(40.0f * 1 / viewport_box.aspect()), viewport_box.aspect(), 0.1f, 100.0f);
mvp = projection * VIEW_MATRIX * model; mvp = projection * VIEW_MATRIX * model;
/* pass the mvp matrix to the shader */ /* uniforms */
glUniform1f(uniform["mvp"]["time"], time_seconds);
glUniformMatrix4fv(uniform["mvp"]["mvp"], 1, GL_FALSE, &mvp[0][0]); glUniformMatrix4fv(uniform["mvp"]["mvp"], 1, GL_FALSE, &mvp[0][0]);
/* disable bg attributes and enable pudding attributes */ /* disable bg attributes and enable pudding attributes */
background.disable(); background.disable();
@ -803,12 +837,12 @@ void Pudding::update()
if (items.size() == 0) if (items.size() == 0)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
pudding_model.attributes("color")->enable(); // pudding_model.attributes("color")->enable();
} }
else else
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
pudding_model.attributes("color")->enable(); // pudding_model.attributes("color")->enable();
pudding_model.attributes("uv")->enable(); pudding_model.attributes("uv")->enable();
glUniform1i(uniform["mvp"]["pudding texture"], 0); glUniform1i(uniform["mvp"]["pudding texture"], 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -818,6 +852,7 @@ void Pudding::update()
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
/* draw the sides of the pudding */ /* draw the sides of the pudding */
glDrawArrays(GL_TRIANGLES, 0, pudding_triangle_vertex_count); glDrawArrays(GL_TRIANGLES, 0, pudding_triangle_vertex_count);
sb::Log::gl_errors("after pudding sides, before pudding top/bottom");
/* enable squircling and draw the top and bottom of pudding */ /* enable squircling and draw the top and bottom of pudding */
glUniform1i(uniform["mvp"]["uv transformation"], UV_SQUIRCLE); glUniform1i(uniform["mvp"]["uv transformation"], UV_SQUIRCLE);
glUniform1f(uniform["mvp"]["coordinate bound"], get_configuration()["pudding"]["top-radius"]); glUniform1f(uniform["mvp"]["coordinate bound"], get_configuration()["pudding"]["top-radius"]);
@ -828,6 +863,7 @@ void Pudding::update()
glUniform1i(uniform["mvp"]["uv transformation"], UV_NONE); glUniform1i(uniform["mvp"]["uv transformation"], UV_NONE);
/* regular fill mode enabled for all other drawing */ /* regular fill mode enabled for all other drawing */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
sb::Log::gl_errors("after pudding, before item or camera view");
/* only do more drawing if items are downloaded or camera is enabled */ /* only do more drawing if items are downloaded or camera is enabled */
if (item_display_active() || capture.isOpened()) if (item_display_active() || capture.isOpened())
{ {
@ -851,7 +887,7 @@ void Pudding::update()
{ {
viewport_box.left(viewport_box.cx(), true); viewport_box.left(viewport_box.cx(), true);
} }
glViewport(viewport_box.left(), viewport_box.bottom(), viewport_box.width(), viewport_box.height()); glViewport(viewport_box);
current_item().current_texture().bind(); current_item().current_texture().bind();
plane.enable(); plane.enable();
/* draws rectangle vertices and rectangle texture using UV coords */ /* draws rectangle vertices and rectangle texture using UV coords */
@ -861,7 +897,7 @@ void Pudding::update()
if (capture.isOpened()) if (capture.isOpened())
{ {
viewport_box.left(window_box(true).left()); viewport_box.left(window_box(true).left());
glViewport(viewport_box.left(), viewport_box.bottom(), viewport_box.width(), viewport_box.height()); glViewport(viewport_box);
/* bind texture for drawing */ /* bind texture for drawing */
camera_view.current().bind(); camera_view.current().bind();
camera_view.enable(); camera_view.enable();
@ -869,8 +905,16 @@ void Pudding::update()
glDrawArrays(GL_TRIANGLES, 0, camera_view.attributes("position")->count()); 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());
SDL_GL_SwapWindow(get_window()); SDL_GL_SwapWindow(get_window());
sb::Log::gl_errors("after update loop"); sb::Log::gl_errors("after test pad");
/* add a new item if a new barcode was scanned or entered */ /* add a new item if a new barcode was scanned or entered */
if (current_barcode != previous_barcode) if (current_barcode != previous_barcode)
{ {
@ -878,3 +922,57 @@ void Pudding::update()
previous_barcode = current_barcode; previous_barcode = current_barcode;
} }
} }
/* Construct a Pad using a texture, an offset, a scale, and a callback function. A Pad is a Plane which can be clicked
* to launch an arbitrary user function. It can be sized and placed by setting the offset and scale values. The offset
* 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)
{
this->texture(texture);
transform(offset, scale, ratio);
this->on_connect(on_connect);
box.gl(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)
{
glm::vec3 scale_components { scale, scale, 1 };
if (ratio > 1.0f)
{
scale_components.x /= ratio;
}
else if (ratio < 1.0f)
{
scale_components.y *= 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));
}
/* Set the function that will run when a pad object is clicked. */
void Pad::on_connect(std::function<void()> on_connect)
{
connection.on_connect(on_connect);
}
/* Returns true if the point at position collides with the box containing the pad object, which is the box the pad
* object fits inside after the transform is applied. */
bool Pad::collide(const glm::vec2& position) const
{
return box.collide(position);
}
void glViewport(Box box)
{
glViewport(box.left(), box.bottom(), box.width(), box.height());
}

View File

@ -42,6 +42,9 @@
#include "Item.hpp" #include "Item.hpp"
#include "Model.hpp" #include "Model.hpp"
#include "utility.hpp" #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) /* 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 * and user supplied functions that run automatically on each state change. The functions each have the
@ -170,6 +173,33 @@ public:
}; };
/* Drawable class that is a plane containing a connection. Each instance:
*
* - Shares vertices and UV in VBO
* - Has its own Texture representing the button on-screen
* - Has its own response to click
* - Shares mouse collision code
* - Has its own translate + scale transformation
*/
class Pad : public Plane
{
private:
using callback = std::function<void()>;
Connection<> connection;
Box box;
public:
Pad() {};
Pad(sb::Texture, glm::vec2, float, float, callback);
void transform(glm::vec2, float, float);
void on_connect(callback);
bool collide(const glm::vec2&) const;
};
class Pudding : public Game class Pudding : public Game
{ {
@ -202,11 +232,11 @@ private:
const std::string NUTRONIX_NOT_FOUND = "resource not found"; 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 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 std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key=";
const glm::vec3 ZERO_VECTOR_3D = glm::vec3(0, 0, 0); const glm::vec3 ZERO_VECTOR_3D {0, 0, 0};
const glm::vec3 Y_UNIT_NORMAL_3D = glm::vec3(0, 1, 0); const glm::vec3 Y_UNIT_NORMAL_3D {0, 1, 0};
const glm::mat4 VIEW_MATRIX = glm::lookAt(glm::vec3(4, 2, 1), glm::vec3(0, -0.325, 0), Y_UNIT_NORMAL_3D); 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 = glm::vec3(0.713f, 0.359f, 0.224f); const glm::vec3 PUDDING_BROWN {0.713f, 0.359f, 0.224f};
const glm::vec3 PUDDING_YELLOW = glm::vec3(0.878f, 0.859f, 0.122f); const glm::vec3 PUDDING_YELLOW {0.878f, 0.859f, 0.122f};
std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode; std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode;
std::vector<Item> items; std::vector<Item> items;
Carousel item_carousel; Carousel item_carousel;
@ -215,7 +245,7 @@ private:
zbar::ImageScanner image_scanner; zbar::ImageScanner image_scanner;
std::map<std::string, std::map<std::string, GLuint>> uniform; std::map<std::string, std::map<std::string, GLuint>> uniform;
GLuint flat_program, mvp_program; GLuint flat_program, mvp_program;
glm::mat4 projection, model = glm::mat4(1.0f), mvp; glm::mat4 projection, model {1.0f}, mvp;
Model pudding_model; Model pudding_model;
Plane plane; Plane plane;
Background background; Background background;
@ -224,8 +254,9 @@ private:
SDL_GLContext capture_frame_thread_context = nullptr; SDL_GLContext capture_frame_thread_context = nullptr;
sb::VAO vao; sb::VAO vao;
sb::VBO vbo; sb::VBO vbo;
Pad pad;
void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f); void set_pudding_model(float, float, int, int = 1, float = -1.0f, float = 1.0f, float = 0.3f);
void load_gl_context(); void load_gl_context();
void load_tiles(); void load_tiles();
void initialize_camera(); void initialize_camera();
@ -262,37 +293,19 @@ public:
/* Apply force until reaching a threshold. Use a connection object to run user functions /* Apply force until reaching a threshold. Use a connection object to run user functions
* when force reaches threshold and when force goes below threshold. */ * when force reaches threshold and when force goes below threshold. */
template<typename return_type, typename ...arguments>
class Button class Button
{ {
private: private:
Connection<> connection; Connection<return_type, arguments...> connection;
/* threshold */
/* force */
/* close */
/* open */
/* apply */
/* remove */
/* weighted depression rate */
};
/* Drawable class that is a plane containing a button. Each instance:
*
* - Shares vertices and UV in VBO
* - Has its own Texture representing the button on-screen
* - Has its own response to click
* - Shares mouse collision code
* - Has its own translate + scale transformation
*/
class Pad : public Plane
{
private:
Button button;
/* float threshold = 1.0f */
/* float force = 0.0f */
/* apply() */
/* remove() */
/* float weighted depression rate */
}; };
#endif #endif

View File

@ -35,5 +35,6 @@ void main(void)
{ {
gl_FragColor = texture(base_texture, uv); gl_FragColor = texture(base_texture, uv);
} }
gl_FragColor = min(gl_FragColor, vec4(hsv2rgb(blend_min_hsv), 1)); /* apply blending, leaving alpha unchanged */
gl_FragColor.xyz = min(gl_FragColor.xyz, hsv2rgb(blend_min_hsv));
} }

View File

@ -12,9 +12,10 @@
in vec2 in_position; in vec2 in_position;
in vec2 vertex_uv; in vec2 vertex_uv;
out vec2 uv; out vec2 uv;
uniform mat4 transformation;
void main(void) void main(void)
{ {
gl_Position = vec4(in_position, 0, 1); gl_Position = transformation * vec4(in_position, 0, 1);
uv = vertex_uv; uv = vertex_uv;
} }