using texture class to store texture data

This commit is contained in:
frank 2021-09-20 02:33:32 -04:00
parent b22302a021
commit ea255f5247
6 changed files with 57 additions and 89 deletions

View File

@ -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",

2
lib/sb

@ -1 +1 @@
Subproject commit 1f8de2f5f1b6a83a6c235d65030a709441f3cd37
Subproject commit 1a4b8507e3886e02ab1b6589ed3823d7fafd1654

View File

@ -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<GLuint> texture_id)
void Item::add_image_texture(Texture texture)
{
image_textures.push_back(texture_id);
image_textures.push_back(texture);
}
const std::vector<std::shared_ptr<GLuint>>& Item::get_image_textures() const
const std::vector<Texture>& Item::get_image_textures() const
{
return image_textures;
}
const std::shared_ptr<GLuint>& Item::get_active_image_texture() const
const Texture& Item::get_active_image_texture() const
{
return get_image_textures()[current_image_index];
}

View File

@ -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 <emscripten.h>
#include <emscripten/html5.h>
#include <GL/glew.h>
#else
#include "glew/glew.h"
@ -21,6 +17,7 @@
#include <extension.hpp>
#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<std::shared_ptr<GLuint>> image_textures;
std::vector<Texture> 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<GLuint> SDL_Texture);
const std::vector<std::shared_ptr<GLuint>>& get_image_textures() const;
const std::shared_ptr<GLuint>& get_active_image_texture() const;
void add_image_texture(Texture);
const std::vector<Texture>& 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&);

View File

@ -239,22 +239,9 @@ void Pudding::load_tiles()
{
for (fs::path path : sb::glob(get_configuration()["resource"]["tile-path"].get<fs::path>() / ".*.jpg"))
{
/* load background as surface */
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> surface(IMG_Load(path.c_str()), SDL_FreeSurface);
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface);
/* generate a GL texture, allocate space and set properties */
std::shared_ptr<GLuint> 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<GLuint> 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<GLuint> 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<GLuint> 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<GLuint> 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<std::uint8_t>& storage, const std::vector<std::string>& headers)
void Pudding::curl_get_bytes(const std::string& url, std::vector<std::uint8_t>& storage, const std::vector<std::string>& 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<GLuint> 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<std::uint8_t> 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<GLuint> texture_id = std::shared_ptr<GLuint>(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);
}

View File

@ -11,6 +11,8 @@
#include <filesystem>
#include <curl/curl.h>
#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<glm::vec3> pudding_vertices, pudding_colors;
std::vector<glm::vec2> pudding_uv;
bool show_item = false, reading_capture_frame = false;
SDL_GLContext capture_frame_thread_context = nullptr;
std::vector<std::shared_ptr<GLuint>> tiles;
std::vector<Texture> 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<std::string>& = {});
void curl_get_bytes(const std::string& url, std::vector<std::uint8_t>&, const std::vector<std::string>& = {});
void curl_get_bytes(const std::string& url, std::vector<std::uint8_t>&, const std::vector<std::string>& = {}) const;
static size_t curl_write_response(std::uint8_t*, size_t, size_t, std::vector<std::uint8_t>*);
std::shared_ptr<GLuint> 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*);