diff --git a/config.json b/config.json index 0e2c3a3..ce222a1 100644 --- a/config.json +++ b/config.json @@ -17,7 +17,8 @@ "print-frame-length-history": ["CTRL", "SHIFT", "h"], "toggle-camera": ["CTRL", "c"], "toggle-item": ["CTRL", "i"], - "effect": ["CTRL", "e"] + "effect": ["CTRL", "e"], + "tile": ["CTRL", "t"] }, "recording": { @@ -72,5 +73,9 @@ "layer-count": 12, "y-range": [-0.6, 0.6], "gradient-position": 0.25 + }, + "resource": + { + "tile-path": "resource/tile" } } diff --git a/resource/mario_3_star_background.png b/resource/mario_3_star_background.png deleted file mode 100644 index 55e81e5..0000000 Binary files a/resource/mario_3_star_background.png and /dev/null differ diff --git a/resource/tile/teapot.jpg b/resource/tile/teapot.jpg new file mode 100644 index 0000000..6f9f9a4 Binary files /dev/null and b/resource/tile/teapot.jpg differ diff --git a/resource/tile/utensil1.jpg b/resource/tile/utensil1.jpg new file mode 100644 index 0000000..0b9b8d2 Binary files /dev/null and b/resource/tile/utensil1.jpg differ diff --git a/resource/tile/vase.jpg b/resource/tile/vase.jpg new file mode 100644 index 0000000..0fcd81a Binary files /dev/null and b/resource/tile/vase.jpg differ diff --git a/src/Item.hpp b/src/Item.hpp index 8284191..c21e874 100644 --- a/src/Item.hpp +++ b/src/Item.hpp @@ -19,6 +19,7 @@ #include #include #include +#include "json/json.hpp" #include "Node.hpp" class Item : public Node @@ -26,6 +27,7 @@ class Item : public Node private: + nlohmann::json json = {}; std::vector> image_textures; std::string brand_name = "", product_name = "", upc = ""; int current_image_index = 0; diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 46d549f..c210206 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -38,6 +38,7 @@ Pudding::Pudding() pudding["y-range"][0], pudding["y-range"][1], pudding["gradient-position"]); /* use gl context so we can draw 3D */ load_gl_context(); + load_tiles(); } /* Assign vertices, colors and texture UV coordinates to the pudding model */ @@ -160,18 +161,6 @@ void Pudding::load_gl_context() { log("could not create capture frame thread context"); } - /* load background as surface, generate texture to load pixel data into, allocate storage, bind and edit texture properties */ - std::unique_ptr surface(IMG_Load("local/tptile.jpg"), SDL_FreeSurface); - std::unique_ptr flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface); - glGenTextures(1, &background_texture_id); - glBindTexture(GL_TEXTURE_2D, background_texture_id); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, flipped_surface->w, flipped_surface->h); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, flipped_surface->w, flipped_surface->h, GL_RGBA, GL_UNSIGNED_BYTE, flipped_surface->pixels); - std::ostringstream message; - message << "loaded background image " << flipped_surface->w << "x" << flipped_surface->h; - log(message.str()); /* Allocate a vertex array object, bind it as current, doesn't need to be a member var because the same one is always bound */ GLuint vao; glGenVertexArrays(1, &vao); @@ -225,6 +214,8 @@ void Pudding::load_gl_context() glBindAttribLocation(flat_program, 1, "vertex_uv"); link_shader(flat_program); flat_texture_uniform_location = glGetUniformLocation(flat_program, "base_texture"); + flat_time_uniform_location = glGetUniformLocation(flat_program, "time"); + scroll_uniform_location = glGetUniformLocation(flat_program, "scroll"); /* load, configure and link the 3D world program */ vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER); fragment_shader = load_shader("src/mvp.frag", GL_FRAGMENT_SHADER); @@ -243,6 +234,30 @@ void Pudding::load_gl_context() log_gl_errors(); } +/* Read every resource/tile/.*.jpg into a GL texture, storing the texture pointer and file name in a std::map */ +void Pudding::load_tiles() +{ + for (fs::path path : sb::glob(get_configuration()["resource"]["tile-path"].get() / ".*.jpg")) + { + /* load background as surface */ + std::unique_ptr surface(IMG_Load(path.c_str()), SDL_FreeSurface); + std::unique_ptr flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface); + /* generate a GL texture, allocate space and set properties */ + std::shared_ptr texture_id(new GLuint, Pudding::destroy_texture); + glGenTextures(1, texture_id.get()); + glBindTexture(GL_TEXTURE_2D, *texture_id); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, flipped_surface->w, flipped_surface->h); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, flipped_surface->w, flipped_surface->h, GL_RGBA, GL_UNSIGNED_BYTE, flipped_surface->pixels); + log_gl_errors(); + std::ostringstream message; + message << "loaded background image " << path.stem() << " from " << path << "(" << flipped_surface->w << "x" << flipped_surface->h << ")"; + log(message.str()); + tiles.push_back(texture_id); + } +} + /* 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. @@ -319,6 +334,10 @@ void Pudding::respond(SDL_Event& event) glUseProgram(mvp_program); glUniform1i(effect_uniform_location, effect_id); } + else if (get_delegate().compare(event, "tile")) + { + current_tile_index = ++current_tile_index % tiles.size(); + } } /* Build an Item object by submitting the upc parameter to multiple APIs and taking @@ -720,6 +739,8 @@ int Pudding::capture_frame(void* game) /* Update parameters and draw the screen */ void Pudding::update() { + /* number of seconds we've been running for */ + float time_seconds = SDL_GetTicks() / 1000.0f; /* launch the camera capture thread if it is not currently running */ if (capture.isOpened() && !reading_capture_frame) { @@ -755,6 +776,7 @@ void Pudding::update() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* switch to flat shader for background */ glUseProgram(flat_program); + glUniform1f(flat_time_uniform_location, time_seconds); /* disable pudding attributes and enable rectangle attributes */ glDisableVertexAttribArray(2); glDisableVertexAttribArray(3); @@ -762,16 +784,17 @@ void Pudding::update() glEnableVertexAttribArray(1); glUniform1i(flat_texture_uniform_location, 0); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, background_texture_id); + glBindTexture(GL_TEXTURE_2D, *tiles[current_tile_index]); /* set blend to modify white part of background, color passed is in HSV format */ GLint blend_min_hsv_location = glGetUniformLocation(flat_program, "blend_min_hsv"); - /* blend min with black will create a black blackground regardless of texture */ - glUniform3f(blend_min_hsv_location, 0, 0, 0); + glUniform3f(blend_min_hsv_location, 0.0f, 0.0f, 1.0f); + glUniform1i(scroll_uniform_location, true); /* draws rectangle vertices and rectangle texture using UV coords */ glDrawArrays(GL_TRIANGLES, 0, 6); + glUniform1i(scroll_uniform_location, false); /* draw pudding model using MVP shader */ glUseProgram(mvp_program); - glUniform1f(time_uniform_location, SDL_GetTicks() / 1000.0f); + glUniform1f(time_uniform_location, time_seconds); /* 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( diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 89900ed..3f81acc 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -61,20 +61,24 @@ private: const glm::vec3 PUDDING_YELLOW = glm::vec3(0.878f, 0.859f, 0.122f); std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode; std::vector items; - int current_item_index = 0, effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0; + int current_item_index = 0, effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0, + current_tile_index = 0; cv::VideoCapture capture; zbar::ImageScanner image_scanner; GLuint flat_program, mvp_program, capture_texture_front_buffer_id, capture_texture_back_buffer_id, capture_texture_id, - mvp_uniform_location, background_texture_id, time_uniform_location, effect_uniform_location, uv_transformation_uniform_location, - flat_texture_uniform_location, coordinate_bound_uniform_location; + mvp_uniform_location, time_uniform_location, effect_uniform_location, uv_transformation_uniform_location, + flat_texture_uniform_location, coordinate_bound_uniform_location, flat_time_uniform_location, + scroll_uniform_location; glm::mat4 projection, model = glm::mat4(1.0f), mvp; std::vector pudding_vertices, pudding_colors; std::vector pudding_uv; bool show_item = false, reading_capture_frame = false; SDL_GLContext capture_frame_thread_context = nullptr; + std::vector> tiles; void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f); void load_gl_context(); + void load_tiles(); void initialize_camera(); void incorporate_open_food_api(Item&); void incorporate_nutronix_api(Item&); diff --git a/src/flat.frag b/src/flat.frag index ba8a3a2..ef87422 100644 --- a/src/flat.frag +++ b/src/flat.frag @@ -3,6 +3,8 @@ in vec2 uv; uniform sampler2D base_texture; uniform vec3 blend_min_hsv; +uniform float time; +uniform bool scroll = false; /* from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl, licensed under WTFPL */ vec3 hsv2rgb(vec3 c) @@ -14,6 +16,15 @@ vec3 hsv2rgb(vec3 c) void main(void) { - gl_FragColor = texture(base_texture, uv); + if (scroll) + { + ivec2 texture_size = textureSize(base_texture, 0); + float speed = time * 35.0; + gl_FragColor = texelFetch(base_texture, ivec2(mod(vec2(gl_FragCoord.x + speed, gl_FragCoord.y - speed), texture_size)), 0); + } + else + { + gl_FragColor = texture(base_texture, uv); + } gl_FragColor = min(gl_FragColor, vec4(hsv2rgb(blend_min_hsv), 1)); } diff --git a/src/white.frag b/src/white.frag deleted file mode 100644 index 8daf986..0000000 --- a/src/white.frag +++ /dev/null @@ -1,9 +0,0 @@ -#version 130 - -in vec3 ex_Color; -in float x; - -void main(void) -{ - gl_FragColor = vec4(1, 1, 1, 1); -}