From ea255f5247e2c21dcfadd891b113c7d6aaf1fb77 Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Mon, 20 Sep 2021 02:33:32 -0400 Subject: [PATCH] using texture class to store texture data --- config.json | 4 +- lib/sb | 2 +- src/Item.cpp | 8 ++-- src/Item.hpp | 13 +++---- src/Pudding.cpp | 101 ++++++++++++++++-------------------------------- src/Pudding.hpp | 18 +++++---- 6 files changed, 57 insertions(+), 89 deletions(-) diff --git a/config.json b/config.json index ce222a1..58d9eef 100644 --- a/config.json +++ b/config.json @@ -47,12 +47,12 @@ "enabled": true, "json-save": true, "json-save-directory": "local/scans", - "barcode": "", + "barcode": "613008719548", "capture-device": "/dev/video0" }, "api": { - "user-agent": "Custom pudding creation game for http://shampoo.ooo", + "user-agent": "Custom pudding creation game for http://nugget.fun", "nutronix-app-id": "ea0f2e7e", "nutronix-app-key": "39218dde526dd3349daa028deda518ae", "edamam-app-id": "c23b139f", diff --git a/lib/sb b/lib/sb index 1f8de2f..1a4b850 160000 --- a/lib/sb +++ b/lib/sb @@ -1 +1 @@ -Subproject commit 1f8de2f5f1b6a83a6c235d65030a709441f3cd37 +Subproject commit 1a4b8507e3886e02ab1b6589ed3823d7fafd1654 diff --git a/src/Item.cpp b/src/Item.cpp index eea7df1..4a765bd 100644 --- a/src/Item.cpp +++ b/src/Item.cpp @@ -22,17 +22,17 @@ void Item::set_text_property(const std::string& value, std::string& property, co } } -void Item::add_image_texture(std::shared_ptr texture_id) +void Item::add_image_texture(Texture texture) { - image_textures.push_back(texture_id); + image_textures.push_back(texture); } -const std::vector>& Item::get_image_textures() const +const std::vector& Item::get_image_textures() const { return image_textures; } -const std::shared_ptr& Item::get_active_image_texture() const +const Texture& Item::get_active_image_texture() const { return get_image_textures()[current_image_index]; } diff --git a/src/Item.hpp b/src/Item.hpp index c21e874..a8defeb 100644 --- a/src/Item.hpp +++ b/src/Item.hpp @@ -2,11 +2,7 @@ #define Item_h_ /* including so we can use GLuint type */ -#define GL_GLEXT_PROTOTYPES -#define GLEW_STATIC #if defined(__EMSCRIPTEN__) -#include -#include #include #else #include "glew/glew.h" @@ -21,6 +17,7 @@ #include #include "json/json.hpp" #include "Node.hpp" +#include "Texture.hpp" class Item : public Node { @@ -28,7 +25,7 @@ class Item : public Node private: nlohmann::json json = {}; - std::vector> image_textures; + std::vector image_textures; std::string brand_name = "", product_name = "", upc = ""; int current_image_index = 0; void set_text_property(const std::string&, std::string&, const std::string&); @@ -41,9 +38,9 @@ private: public: Item(Node*); - void add_image_texture(std::shared_ptr SDL_Texture); - const std::vector>& get_image_textures() const; - const std::shared_ptr& get_active_image_texture() const; + void add_image_texture(Texture); + const std::vector& get_image_textures() const; + const Texture& get_active_image_texture() const; void set_brand_name(const std::string&); const std::string& get_brand_name() const; void set_product_name(const std::string&); diff --git a/src/Pudding.cpp b/src/Pudding.cpp index c210206..844051d 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -239,22 +239,9 @@ 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); + Texture texture = Texture(path); + texture.load(); + tiles.push_back(texture); } } @@ -275,16 +262,10 @@ void Pudding::initialize_camera() "fps video capture device ID #" << device_id << " using " << capture.getBackendName(); /* generate two textures that will store the video frames with the intention of double buffering them * for threaded texture loading */ - for (GLuint* buffer_id : {&capture_texture_front_buffer_id, &capture_texture_back_buffer_id}) + for (Texture* texture : {&capture_texture_front_buffer, &capture_texture_back_buffer}) { - glGenTextures(1, buffer_id); - glBindTexture(GL_TEXTURE_2D, *buffer_id); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, capture.get(cv::CAP_PROP_FRAME_WIDTH), capture.get(cv::CAP_PROP_FRAME_HEIGHT)); - // glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 320, 240); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + texture->generate({capture.get(cv::CAP_PROP_FRAME_WIDTH), capture.get(cv::CAP_PROP_FRAME_HEIGHT)}); } - capture_texture_id = capture_texture_front_buffer_id; } else { @@ -390,10 +371,10 @@ void Pudding::incorporate_open_food_api(Item& item) if (json["product"].value("image_url", "") != "") { std::string url = json["product"]["image_url"]; - std::shared_ptr texture_id = texture_from_image_url(url); - if (texture_id != nullptr) + Texture texture = texture_from_image_url(url); + if (texture.generated()) { - item.add_image_texture(texture_id); + item.add_image_texture(texture); } } item.set_brand_name(json["product"].value("brands", "")); @@ -425,10 +406,10 @@ void Pudding::incorporate_nutronix_api(Item& item) { std::string url = food["photo"]["thumb"]; log("adding image listed in Nutronix API at " + url); - std::shared_ptr texture_id = texture_from_image_url(url); - if (texture_id != nullptr) + Texture texture = texture_from_image_url(url); + if (texture.generated()) { - item.add_image_texture(texture_id); + item.add_image_texture(texture); } } item.set_brand_name(food.value("brand_name", "")); @@ -459,10 +440,10 @@ void Pudding::incorporate_edamam_api(Item& item) if (food.value("image", "") != "") { std::string url = food["image"]; - std::shared_ptr texture_id = texture_from_image_url(url); - if (texture_id != nullptr) + Texture texture = texture_from_image_url(url); + if (texture.generated()) { - item.add_image_texture(texture_id); + item.add_image_texture(texture); } item.set_product_name(food.value("label", "")); } @@ -494,10 +475,10 @@ void Pudding::incorporate_best_buy_api(Item& item) if (product.value(key, "") != "") { std::string url = product[key]; - std::shared_ptr texture_id = texture_from_image_url(url); - if (texture_id != nullptr) + Texture texture = texture_from_image_url(url); + if (texture.generated()) { - item.add_image_texture(texture_id); + item.add_image_texture(texture); } } } @@ -558,7 +539,7 @@ nlohmann::json Pudding::json_from_url(const std::string& url, const std::vector< /* Store the byte buffer from the submitted URL downloaded by cURL into the supplied storage vector */ -void Pudding::curl_get_bytes(const std::string& url, std::vector& storage, const std::vector& headers) +void Pudding::curl_get_bytes(const std::string& url, std::vector& storage, const std::vector& headers) const { CURL *curl; CURLcode result; @@ -614,40 +595,26 @@ size_t Pudding::curl_write_response(std::uint8_t* buffer, size_t size, size_t co /* Allocate storage for a texture, copy the cURL response data into the storage, and return the ID that corresponds to the GL texture */ -std::shared_ptr Pudding::texture_from_image_url(const std::string& url) +Texture Pudding::texture_from_image_url(const std::string& url) const { + /* this texture will be returned whether we load pixels into it or not */ + Texture texture; log("looking up image at " + url); std::vector storage; curl_get_bytes(url, storage); if (!storage.empty()) { debug("received image data"); - /* load as an SDL surface to translate image format into pixel data, flip, and get dimensions */ + /* get a Texture by passing the bytes through an RW ops which will enable the Texture object to load a Surface */ SDL_RWops* rw = SDL_RWFromConstMem(storage.data(), storage.size()); - SDL_Surface* surface = IMG_Load_RW(rw, 0); - SDL_Surface* flipped_surface = rotozoomSurfaceXY(surface, 0, 1, -1, 0); - std::ostringstream message; - message << "image is " << flipped_surface->w << "x" << flipped_surface->h; - log(message.str()); - /* generate a GL texture, allocate space and set properties */ - std::shared_ptr texture_id = std::shared_ptr(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); - /* copy image bytes into GL texture */ - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->w, surface->h, GL_RGBA, GL_UNSIGNED_BYTE, flipped_surface->pixels); - log_gl_errors(); - SDL_FreeSurface(surface); - SDL_FreeSurface(flipped_surface); - return texture_id; + texture.load(rw); + SDL_RWclose(rw); } else { SDL_LogWarn(SDL_LOG_CATEGORY_CUSTOM, "image url returned no data"); - return nullptr; } + return texture; } /* Call GL's delete texture function, and print a debug statement for testing. This is defined as a static member @@ -701,13 +668,13 @@ int Pudding::capture_frame(void* game) /* rotate the opencv matrix 180 to work with opengl coords */ cv::flip(frame, frame, -1); /* use whichever texture ID is not being used by the main rendering thread */ - GLuint texture_id = pudding->capture_texture_id == pudding->capture_texture_front_buffer_id ? - pudding->capture_texture_back_buffer_id : pudding->capture_texture_front_buffer_id; + Texture& texture = pudding->capture_texture == pudding->capture_texture_front_buffer ? + pudding->capture_texture_back_buffer : pudding->capture_texture_front_buffer; /* bind texture for accepting pixel data */ - glBindTexture(GL_TEXTURE_2D, texture_id); + texture.bind(); /* fill texture memory with last frame's pixels */ - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame.cols, frame.rows, GL_BGR, GL_UNSIGNED_BYTE, frame.ptr()); - pudding->capture_texture_id = texture_id; + texture.load(frame.ptr(), {frame.cols, frame.rows}, GL_BGR, GL_UNSIGNED_BYTE); + pudding->capture_texture = texture; if (pudding->get_configuration()["scan"]["enabled"]) { /* convert to gray and scan with zbar */ @@ -784,7 +751,7 @@ void Pudding::update() glEnableVertexAttribArray(1); glUniform1i(flat_texture_uniform_location, 0); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, *tiles[current_tile_index]); + tiles[current_tile_index].bind(); /* 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"); glUniform3f(blend_min_hsv_location, 0.0f, 0.0f, 1.0f); @@ -819,7 +786,7 @@ void Pudding::update() GLuint pudding_texture_location = glGetUniformLocation(mvp_program, "pudding_texture"); glUniform1i(pudding_texture_location, 0); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, *get_current_item().get_active_image_texture().get()); + get_current_item().get_active_image_texture().bind(); } /* draw pudding model */ glEnable(GL_DEPTH_TEST); @@ -864,7 +831,7 @@ void Pudding::update() viewport_box.left(viewport_box.cx(), true); } glViewport(viewport_box.left(), viewport_box.bottom(), viewport_box.width(), viewport_box.height()); - glBindTexture(GL_TEXTURE_2D, *get_current_item().get_active_image_texture().get()); + get_current_item().get_active_image_texture().bind(); /* draws rectangle vertices and rectangle texture using UV coords */ glDrawArrays(GL_TRIANGLES, 0, 6); } @@ -874,7 +841,7 @@ void Pudding::update() viewport_box.left(window_box(true).left()); glViewport(viewport_box.left(), viewport_box.bottom(), viewport_box.width(), viewport_box.height()); /* bind texture for drawing */ - glBindTexture(GL_TEXTURE_2D, capture_texture_id); + capture_texture.bind(); /* draws rectangle vertices and rectangle texture using UV coords */ glDrawArrays(GL_TRIANGLES, 0, 6); } diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 3f81acc..22921a7 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -11,6 +11,8 @@ #include #include #include "SDL.h" +#include "SDL_image.h" +#include "sdl2-gfx/SDL2_gfxPrimitives.h" #include "json/json.hpp" #include "glm/vec2.hpp" #include "opencv2/core.hpp" @@ -23,6 +25,7 @@ #include "extension.hpp" #include "Item.hpp" #include "Animation.hpp" +#include "Texture.hpp" class Pudding : public Game { @@ -65,16 +68,17 @@ private: 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, 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; + GLuint flat_program, mvp_program, 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; + std::vector tiles; + Texture capture_texture_front_buffer, capture_texture_back_buffer; + Texture& capture_texture = capture_texture_front_buffer; void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f); void load_gl_context(); @@ -86,9 +90,9 @@ private: void incorporate_best_buy_api(Item&); void save_item_json(const nlohmann::json&, const Item&, const std::string&) const; nlohmann::json json_from_url(const std::string&, const std::vector& = {}); - void curl_get_bytes(const std::string& url, std::vector&, const std::vector& = {}); + void curl_get_bytes(const std::string& url, std::vector&, const std::vector& = {}) const; static size_t curl_write_response(std::uint8_t*, size_t, size_t, std::vector*); - std::shared_ptr texture_from_image_url(const std::string&); + Texture texture_from_image_url(const std::string&) const; static void destroy_texture(GLuint*); bool item_display_active() const; static int capture_frame(void*);