diff --git a/Makefile b/Makefile index c3f31c2..63a9354 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ $(SFW_SRC_DIR)Game.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Node.hpp Sprite. $(SFW_SRC_DIR)Animation.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Timer.hpp) $(SFW_SRC_DIR)Recorder.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp) $(SFW_SRC_DIR)Input.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Animation.hpp Configuration.hpp Delegate.hpp) -$(SFW_SRC_DIR)Configuration.o : $(addprefix $(SFW_SRC_DIR),Node.hpp) +$(SFW_SRC_DIR)Configuration.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Animation.hpp) $(SFW_SRC_DIR)Delegate.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Input.hpp) $(SFW_SRC_DIR)Display.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp) $(SFW_SRC_DIR)Box.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Segment.hpp) @@ -63,8 +63,7 @@ linux : CFLAGS = -g3 -Wall -Wextra -Og -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SD linux : CPP_FLAGS = $(CFLAGS) --std=c++17 linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs \ -L/home/frank/local/opencv/lib -Wl,-rpath,/home/frank/local/opencv/lib -Wl,--enable-new-dtags -lopencv_videoio -lopencv_core \ - -lopencv_highgui -lopencv_imgproc \ - -L/home/frank/local/zbar/lib -Wl,-rpath,/home/frank/local/zbar/lib -Wl,--enable-new-dtags -lzbar + -lopencv_highgui -lopencv_imgproc -L/home/frank/local/zbar/lib -Wl,-rpath,/home/frank/local/zbar/lib -Wl,--enable-new-dtags -lzbar linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \ $(SFW_O_FILES) $(GAME_O_FILES) $(CREATE_FONT_SYMLINK) diff --git a/config.json b/config.json index c31331f..ee3ec9b 100644 --- a/config.json +++ b/config.json @@ -7,6 +7,10 @@ "debug": false, "render driver": "opengl" }, + "configuration": + { + "auto-refresh": true + }, "keys": { "print-video-memory-size": ["CTRL", "v"], @@ -39,7 +43,7 @@ { "json-save": true, "json-save-directory": "local/scans", - "barcode": "", + "barcode": "2430373621232", "capture-device": "/dev/video0" }, "api": diff --git a/lib/sfw b/lib/sfw index fe3e0bf..c8bc86c 160000 --- a/lib/sfw +++ b/lib/sfw @@ -1 +1 @@ -Subproject commit fe3e0bf27f8ab45edcb322ab89bc79a6fe15d8bf +Subproject commit c8bc86cab729a26cc7563c7177c42f919b47df07 diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 09cf719..7a5ecd7 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -1,6 +1,6 @@ /* ______________ - //````````````\\ + by @ohsqueezy [http://ohsqueezy.itch.io] & @sleepin [http://instagram.com/sleepin] + //````````````\\ + a game by @ohsqueezy [http://ohsqueezy.itch.io] & @sleepin [http://instagram.com/sleepin] //~~~~~~~~~~~~~~\\ + custom pudding code provided by Nuggets Select [http://nugget.fun] //================\\ + available for copy, modification and redistribution [http://git.nugget.fun/pudding] // \\ @@ -39,13 +39,14 @@ Pudding::Pudding() initialize_camera(); } +/* Assign vertices, colors and texture UV coordinates to the pudding model */ void Pudding::set_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; const glm::vec3 *layer_top_color, *layer_bottom_color; const glm::vec2 *start_vertex, *end_vertex; - float layer_top_y, layer_top_percent, layer_base_y, layer_base_percent; + float layer_top_y, layer_top_percent, layer_base_y, layer_base_percent, u_step = 1.0f / ring_vertex_count, ring_start_vertex_u; std::vector layer_top_ring, layer_base_ring; layer_top_ring.reserve(ring_vertex_count); layer_base_ring.reserve(ring_vertex_count); @@ -83,46 +84,60 @@ void Pudding::set_pudding_model( layer_top_color = &PUDDING_YELLOW; layer_bottom_color = &PUDDING_YELLOW; } - /* go through top and base ring vertices simultaneously to build side triangles */ + /* u coordinate will increase toward 1.0f as we go around the ring */ + ring_start_vertex_u = 0.0f; for (ii = 0; ii < layer_top_ring.size(); ii++) { /* triangle that includes top two vertices and first base vertex */ start_vertex = &layer_top_ring[ii]; end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()]; pudding_vertices.push_back({start_vertex->x, layer_top_y, start_vertex->y}); + pudding_uv.push_back({ring_start_vertex_u, layer_top_percent}); pudding_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y}); + pudding_uv.push_back({ring_start_vertex_u + u_step, layer_top_percent}); pudding_colors.insert(pudding_colors.end(), 2, *layer_top_color); pudding_vertices.push_back({layer_base_ring[ii].x, layer_base_y, layer_base_ring[ii].y}); + pudding_uv.push_back({ring_start_vertex_u, layer_base_percent}); pudding_colors.push_back(*layer_bottom_color); /* triangle that includes bottom two vertices and second top vertex */ start_vertex = &layer_base_ring[ii]; pudding_vertices.push_back({start_vertex->x, layer_base_y, start_vertex->y}); + pudding_uv.push_back({ring_start_vertex_u, layer_base_percent}); pudding_colors.push_back(*layer_bottom_color); pudding_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y}); + pudding_uv.push_back({ring_start_vertex_u + u_step, layer_top_percent}); pudding_colors.push_back(*layer_top_color); end_vertex = &layer_base_ring[(ii + 1) % layer_base_ring.size()]; pudding_vertices.push_back({end_vertex->x, layer_base_y, end_vertex->y}); + pudding_uv.push_back({ring_start_vertex_u + u_step, layer_base_percent}); pudding_colors.push_back(*layer_bottom_color); + ring_start_vertex_u += u_step; } } + /* process the top and bottom of pudding, filling each face with a triangle fan */ layer_top_ring.clear(); - sfw::points_on_circle(layer_top_ring, ring_vertex_count, top_radius); float y = max_y; const glm::vec3* face_color = &PUDDING_BROWN; - for (const std::vector& face : {layer_top_ring, layer_base_ring}) + Box texture_box = Box({0, 0}, {1, 1}); + for (float radius : {top_radius, base_radius}) { + sfw::points_on_circle(layer_top_ring, ring_vertex_count, radius); /* loop through points on the face */ - for (ii = 0; ii < face.size(); ii++) + for (ii = 0; ii < layer_top_ring.size(); ii++) { - start_vertex = &face[ii]; - end_vertex = &face[(ii + 1) % face.size()]; - /* triangle from the center of the face to the edge */ + start_vertex = &layer_top_ring[ii]; + end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()]; + /* triangle from the center of the layer_top_ring to the edge */ pudding_vertices.push_back({start_vertex->x, y, start_vertex->y}); pudding_vertices.push_back({end_vertex->x, y, end_vertex->y}); pudding_vertices.push_back({0, y, 0}); + /* map circle points to UV points of the texture */ + pudding_uv.push_back(*start_vertex); + pudding_uv.push_back(*end_vertex); + pudding_uv.push_back({0, 0}); } - /* single color for the entire face */ - pudding_colors.insert(pudding_colors.end(), 3 * face.size(), *face_color); + /* single color for the entire layer_top_ring */ + pudding_colors.insert(pudding_colors.end(), 3 * layer_top_ring.size(), *face_color); y = min_y; face_color = &PUDDING_YELLOW; } @@ -133,18 +148,13 @@ void Pudding::load_gl_context() { super::load_gl_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("resource/mario_3_star_background.png"), SDL_FreeSurface); + 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); - // SDL_Surface* surface = zoomSurface( - // rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2), -1, 1, SMOOTHING_OFF); - /* load as an SDL surface to translate image format into pixel data, flip, and get dimensions */ - // SDL_RWops* rw = SDL_RWFromConstMem(storage.data(), storage.size()); - // SDL_Surface* surface = IMG_Load_RW(rw, 0); 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; @@ -166,15 +176,16 @@ void Pudding::load_gl_context() /* Generate one vertex buffer object to hold all vertices and rectangle UV map. Since we're using one buffer, data * will be copied in one after the other, offset to after the previous data location. The same buffer offset will * be passed to the vertex attributes for each data. */ + GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); /* allocate space for vertices, UV and colors, and copy rectangle vertices in at initialization */ - GLsizeiptr vbo_size = (rectangle_vertices.size() + rectangle_uv.size()) * sizeof(glm::vec2) + + GLsizeiptr vbo_size = (rectangle_vertices.size() + rectangle_uv.size() + pudding_uv.size()) * sizeof(glm::vec2) + (pudding_vertices.size() + pudding_colors.size()) * sizeof(glm::vec3); glBufferData(GL_ARRAY_BUFFER, vbo_size, rectangle_vertices.data(), GL_STATIC_DRAW); /* specify the rectangle vertex attributes as consecutive 2D float coords */ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - /* copy rectangle UV data into the VBO, offset to after the vertex data, set up vertex attributes */ + /* copy rectangle UV data into the VBO, offset to after the vertex data, set up attributes */ GLintptr offset = rectangle_vertices.size() * sizeof(glm::vec2); glBufferSubData(GL_ARRAY_BUFFER, offset, rectangle_uv.size() * sizeof(glm::vec2), rectangle_uv.data()); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(offset)); @@ -186,6 +197,10 @@ void Pudding::load_gl_context() offset += pudding_vertices.size() * sizeof(glm::vec3); glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_colors.size() * sizeof(glm::vec3), pudding_colors.data()); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(offset)); + /* copy pudding UV values into VBO, offset to after pudding color vertices and set as 2D */ + offset += pudding_colors.size() * sizeof(glm::vec3); + glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_uv.size() * sizeof(glm::vec2), pudding_uv.data()); + glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(offset)); /* Load two shader programs, one for rendering the flat objects, and one for rendering the 3D model. Load, configure, * and link the flat shader program first. */ GLuint vertex_shader = load_shader("src/flat.vert", GL_VERTEX_SHADER); @@ -193,8 +208,8 @@ void Pudding::load_gl_context() flat_program = glCreateProgram(); glAttachShader(flat_program, vertex_shader); glAttachShader(flat_program, fragment_shader); - glBindAttribLocation(flat_program, 0, "in_Position"); - glBindAttribLocation(flat_program, 1, "vertexUV"); + glBindAttribLocation(flat_program, 0, "in_position"); + glBindAttribLocation(flat_program, 1, "vertex_uv"); link_shader(flat_program); /* load, configure and link the 3D world program */ vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER); @@ -202,10 +217,11 @@ void Pudding::load_gl_context() mvp_program = glCreateProgram(); glAttachShader(mvp_program, vertex_shader); glAttachShader(mvp_program, fragment_shader); - glBindAttribLocation(mvp_program, 2, "in_Position"); - glBindAttribLocation(mvp_program, 3, "in_Color"); + glBindAttribLocation(mvp_program, 2, "in_position"); + glBindAttribLocation(mvp_program, 3, "in_color"); + glBindAttribLocation(mvp_program, 4, "vertex_uv"); link_shader(mvp_program); - mvp_id = glGetUniformLocation(mvp_program, "MVP"); + mvp_id = glGetUniformLocation(mvp_program, "mvp"); log_gl_errors(); } @@ -604,9 +620,6 @@ Item& Pudding::get_current_item() /* Update parameters and draw the screen */ void Pudding::update() { - /* reload the config file every frame to check for changes */ - get_root()->configuration.load("config.json"); - get_root()->configuration.merge(); if (current_config_barcode != get_configuration()["scan"]["barcode"]) { current_config_barcode = get_configuration()["scan"]["barcode"]; @@ -616,13 +629,13 @@ void Pudding::update() log(message.str()); } /* viewport box will be used to tell GL where to draw */ - Box viewport_box = get_window_box(); + Box viewport_box = window_box(); /* shrink viewport if item texture or camera will be displayed */ if (items.size() > 0 || capture.isOpened()) { - viewport_box.set_right(get_window_box().get_center_x(), true); + viewport_box.right(window_box().cx(), true); } - glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); + glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height()); glDisable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -648,7 +661,7 @@ void Pudding::update() /* 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( - glm::radians(viewport_box.get_w() > viewport_box.get_h() ? 40.0f : 45.0f), viewport_box.aspect(), 0.1f, 100.0f); + glm::radians(viewport_box.width() > viewport_box.height() ? 40.0f : 45.0f), viewport_box.aspect(), 0.1f, 100.0f); mvp = projection * VIEW_MATRIX * model; /* pass the mvp matrix to the shader */ glUniformMatrix4fv(mvp_id, 1, GL_FALSE, &mvp[0][0]); @@ -656,7 +669,18 @@ void Pudding::update() glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glEnableVertexAttribArray(2); - glEnableVertexAttribArray(3); + if (items.size() == 0) + { + glEnableVertexAttribArray(3); + } + else + { + glEnableVertexAttribArray(4); + 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()); + } /* draw pudding model */ // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glEnable(GL_DEPTH_TEST); @@ -677,7 +701,7 @@ void Pudding::update() glUniform1i(base_texture_location, 0); glActiveTexture(GL_TEXTURE0); /* move viewport to the right side of screen */ - viewport_box.set_left(get_window_box().get_center_x()); + viewport_box.left(window_box().cx()); /* reset blend to display the original texture colors */ GLint blend_min_location = glGetUniformLocation(flat_program, "blend_min_hsv"); glUniform3f(blend_min_location, 1, 0, 1); @@ -687,9 +711,9 @@ void Pudding::update() /* shrink viewport to half size if camera will also be displayed */ if (capture.isOpened()) { - viewport_box.set_top(get_window_box().get_center_y(), true); + viewport_box.top(window_box().cy(), true); } - glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); + glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height()); glBindTexture(GL_TEXTURE_2D, *get_current_item().get_active_image_texture().get()); /* draws rectangle vertices and rectangle texture using UV coords */ glDrawArrays(GL_TRIANGLES, 0, 6); @@ -698,12 +722,12 @@ void Pudding::update() if (capture.isOpened()) { capture.read(capture_frame); - viewport_box.set_top(get_window_box().get_top()); + viewport_box.top(window_box().top()); if (!capture_frame.empty()) { /* rotate the opencv matrix 180 to work with opengl coords */ cv::flip(capture_frame, capture_frame, -1); - glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); + glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height()); /* bind texture, binding it to accept pixel data and to GLSL sampler */ glBindTexture(GL_TEXTURE_2D, video_capture_texture_id); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, capture_frame.cols, capture_frame.rows, GL_BGR, GL_UNSIGNED_BYTE, capture_frame.ptr()); diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 087b0ee..16177e5 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -46,9 +46,10 @@ private: cv::VideoCapture capture; cv::Mat capture_frame; zbar::ImageScanner image_scanner; - GLuint vbo, flat_program, mvp_program, video_capture_texture_id, mvp_id, background_texture_id; + GLuint flat_program, mvp_program, video_capture_texture_id, mvp_id, background_texture_id; glm::mat4 projection, model = glm::mat4(1.0f), mvp; std::vector pudding_vertices, pudding_colors; + std::vector pudding_uv; void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f); void load_gl_context(); @@ -72,7 +73,7 @@ public: void increment_item_index(int = 1); Item& get_current_item(); void update(); - virtual std::string get_class_name() const { return "Pudding"; } + virtual std::string class_name() const { return "Pudding"; } }; diff --git a/src/flat.frag b/src/flat.frag index 8db5178..ba8a3a2 100644 --- a/src/flat.frag +++ b/src/flat.frag @@ -1,6 +1,6 @@ #version 130 -in vec2 UV; +in vec2 uv; uniform sampler2D base_texture; uniform vec3 blend_min_hsv; @@ -14,6 +14,6 @@ vec3 hsv2rgb(vec3 c) 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)); } diff --git a/src/flat.vert b/src/flat.vert index 69414b8..f0bdc63 100644 --- a/src/flat.vert +++ b/src/flat.vert @@ -1,11 +1,11 @@ #version 130 -in vec2 in_Position; -in vec2 vertexUV; -out vec2 UV; +in vec2 in_position; +in vec2 vertex_uv; +out vec2 uv; void main(void) { - gl_Position = vec4(in_Position, 0, 1); - UV = vertexUV; + gl_Position = vec4(in_position, 0, 1); + uv = vertex_uv; } diff --git a/src/mvp.frag b/src/mvp.frag index bc433c5..db5c89e 100644 --- a/src/mvp.frag +++ b/src/mvp.frag @@ -1,25 +1,25 @@ #version 130 -in vec3 ex_Color; +in vec3 ex_color; in float x; +in vec2 uv; +uniform sampler2D pudding_texture; void main(void) { - vec3 shadowed = ex_Color; - float r = min(1, shadowed[0]); - float g = min(1, shadowed[1]); - float b = min(1, shadowed[2]); - float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0; - if (int(floor(gl_FragCoord[0] / 3) + floor(gl_FragCoord[1]) / 3) % 2 == 0) - { - gl_FragColor = vec4(vec3(r, g, b) * 1.3, 1); - } - else - { - gl_FragColor = vec4(vec3(r, g, b) * 0.6, 1); - } - gl_FragColor[0] = int(gl_FragColor[0] * 4) / 4.0; - gl_FragColor[1] = int(gl_FragColor[1] * 4) / 4.0; - gl_FragColor[2] = int(gl_FragColor[2] * 4) / 4.0; - gl_FragColor *= x; + // vec3 shadowed = min(ex_color, 1.0); + // float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0; + // if (int(floor(gl_FragCoord[0] / 3) + floor(gl_FragCoord[1]) / 3) % 2 == 0) + // { + // gl_FragColor = vec4(shadowed * 1.3, 1); + // } + // else + // { + // gl_FragColor = vec4(shadowed * 0.6, 1); + // } + // gl_FragColor[0] = int(gl_FragColor[0] * 4) / 4.0; + // gl_FragColor[1] = int(gl_FragColor[1] * 4) / 4.0; + // gl_FragColor[2] = int(gl_FragColor[2] * 4) / 4.0; + // gl_FragColor *= x; + gl_FragColor = texture(pudding_texture, uv); } diff --git a/src/mvp.vert b/src/mvp.vert index 0f69047..cc81ecc 100644 --- a/src/mvp.vert +++ b/src/mvp.vert @@ -1,14 +1,17 @@ #version 130 -in vec3 in_Position; -in vec3 in_Color; -uniform mat4 MVP; -out vec3 ex_Color; +in vec3 in_position; +in vec3 in_color; +in vec2 vertex_uv; +uniform mat4 mvp; +out vec3 ex_color; out float x; +out vec2 uv; void main(void) { - gl_Position = MVP * vec4(in_Position, 1); - ex_Color = in_Color; - x = 1.8 - abs(in_Position[0]); + gl_Position = mvp * vec4(in_position, 1); + ex_color = in_color; + x = 1.8 - abs(in_position[0]); + uv = vertex_uv; }