diff --git a/config.json b/config.json index 72411a8..40922b8 100644 --- a/config.json +++ b/config.json @@ -18,7 +18,7 @@ "screenshot-directory": "local/screenshots", "video-directory": "local/video", "enabled": true, - "write-mp4": false, + "write-mp4": true, "video-frame-length": 33.333, "max-video-memory": 2000 }, @@ -38,7 +38,7 @@ { "json-save": true, "json-save-directory": "local/scans", - "barcode": "8001250120076", + "barcode": "", "capture-device": "/dev/video0" }, "api": diff --git a/src/Pudding.cpp b/src/Pudding.cpp index c84b45c..8c576ba 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -32,11 +32,94 @@ Pudding::Pudding() get_delegate().subscribe(&Pudding::respond, this); /* initialize a zbar image scanner for reading barcodes of any format */ image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); + /* set up pudding model */ + const std::vector pudding_top_2d = sfw::get_points_on_circle(24); + const std::vector pudding_base_2d = sfw::get_points_on_circle(24, 1.6f); + float pudding_y = 0.6f; + set_pudding_model(pudding_top_2d, pudding_base_2d, pudding_y); /* use gl context so we can draw 3D */ load_gl_context(); initialize_camera(); } +/* Fill the member variables that store pudding properties. Fill the vertices vector with 3D vertices of a pudding that can be drawn as + * GL_TRIANGLES, and fill the colors vector with RGB color values that will be passed to the fragment shader for coloring the faces of + * the pudding. */ +void Pudding::set_pudding_model(const std::vector& top_2d, const std::vector& base_2d, float y) +{ + /* start and end points of edge on a face */ + glm::vec2 start, end; + size_t ii; + pudding_colors.reserve(4 * 3 * top_2d.size()); + /* use brown for the entire top and base */ + // std::fill_n(pudding_colors.begin(), 4 * 3 * top_2d.size(), PUDDING_BROWN); + /* go through top and base points separately */ + for (const std::vector& face : {top_2d, base_2d}) + { + /* loop through points on the face */ + for (ii = 0; ii < face.size(); ii++) + { + start = face[ii]; + end = face[(ii + 1) % face.size()]; + /* triangle from the center of the face to the edge */ + pudding_vertices.push_back({start.x, y, start.y}); + pudding_vertices.push_back({end.x, y, end.y}); + pudding_vertices.push_back({0, y, 0}); + pudding_colors.push_back(PUDDING_BROWN); + pudding_colors.push_back(PUDDING_BROWN); + pudding_colors.push_back(PUDDING_BROWN); + } + y *= -1; + } + /* go through top and base points simultaneously to build side triangles */ + for (ii = 0; ii < top_2d.size(); ii++) + { + /* triangle using top edge */ + start = top_2d[ii]; + end = top_2d[(ii + 1) % top_2d.size()]; + pudding_vertices.push_back({start.x, y, start.y}); + pudding_vertices.push_back({end.x, y, end.y}); + // std::fill_n(pudding_colors.begin(), 2, PUDDING_BROWN); + pudding_colors.push_back(PUDDING_BROWN); + pudding_colors.push_back(PUDDING_BROWN); + pudding_vertices.push_back({base_2d[ii].x, -y, base_2d[ii].y}); + pudding_colors.push_back(PUDDING_YELLOW); + /* triangle using bottom edge */ + start = base_2d[ii]; + pudding_vertices.push_back({start.x, -y, start.y}); + pudding_colors.push_back(PUDDING_YELLOW); + pudding_vertices.push_back({end.x, y, end.y}); + pudding_colors.push_back(PUDDING_BROWN); + end = base_2d[(ii + 1) % base_2d.size()]; + pudding_vertices.push_back({end.x, -y, end.y}); + pudding_colors.push_back(PUDDING_YELLOW); + } +} + +/* Fill the member variable that stores pudding wireframe vertices with 3D vertices of a pudding that can + * be drawn as GL_LINE to display as wireframe */ +void Pudding::set_wireframe_pudding_vertices(const std::vector& top_2d, const std::vector& base_2d, float y) +{ + glm::vec2 start, end; + size_t ii; + for (const std::vector& face : {top_2d, base_2d}) + { + for (ii = 0; ii < face.size(); ii++) + { + start = face[ii]; + end = face[(ii + 1) % face.size()]; + wireframe_pudding_vertices.push_back({start.x, y, start.y}); + wireframe_pudding_vertices.push_back({end.x, y, end.y}); + } + y *= -1; + } + for (ii = 0; ii < top_2d.size(); ii++) + { + wireframe_pudding_vertices.push_back({top_2d[ii].x, y, top_2d[ii].y}); + wireframe_pudding_vertices.push_back({base_2d[ii].x, -y, base_2d[ii].y}); + } +} + /* Create GL context via super class and load vertices, UV data, and shaders */ void Pudding::load_gl_context() { @@ -55,42 +138,14 @@ void Pudding::load_gl_context() {0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} }}; - /* 3D vertices for a cube */ - std::array cube_vertices_as_triangles = {{ - {1, 1, 1}, {-1, 1, 1}, {-1,-1, 1}, - {-1,-1, 1}, {1,-1, 1}, {1, 1, 1}, - {1, 1, 1}, {1,-1, 1}, {1,-1,-1}, - {1,-1,-1}, {1, 1,-1}, {1, 1, 1}, - {1, 1, 1}, {1, 1,-1}, {-1, 1,-1}, - {-1, 1,-1}, {-1, 1, 1}, {1, 1, 1}, - {-1, 1, 1}, {-1, 1,-1}, {-1,-1,-1}, - {-1,-1,-1}, {-1,-1, 1}, {-1, 1, 1}, - {-1,-1,-1}, {1,-1,-1}, {1,-1, 1}, - {1,-1, 1}, {-1,-1, 1}, {-1,-1,-1}, - {1,-1,-1}, {-1,-1,-1}, {-1, 1,-1}, - {-1, 1,-1}, {1, 1,-1}, {1,-1,-1} - }}; - /* 3D vertices for a cube as line segments */ - std::array cube_vertices = {{ - // front - {-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}, - //right - {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}, - //back - {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}, - //left - {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f} - }}; - /* Generate one vertex buffer object to hold rectangle + cube 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. */ + /* 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. */ glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); - /* allocate space for vertices and UV, and copy rectangle vertices in at initialization */ - GLsizeiptr vbo_size = (rectangle_vertices.size() + rectangle_uv.size()) * sizeof(glm::vec2) + cube_vertices.size() * sizeof(glm::vec3); + /* 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) + + (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); @@ -98,10 +153,14 @@ void Pudding::load_gl_context() 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)); - /* copy cube vertices into VBO, offset to after the rectangle UV, and set up vertex attributes for 3D */ - offset = (rectangle_vertices.size() + rectangle_uv.size()) * sizeof(glm::vec2); - glBufferSubData(GL_ARRAY_BUFFER, offset, cube_vertices.size() * sizeof(glm::vec3), cube_vertices.data()); + /* copy pudding vertices into VBO, offset to after the rectangle UV, and set up vertex attributes for 3D */ + offset += rectangle_uv.size() * sizeof(glm::vec2); + glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_vertices.size() * sizeof(glm::vec3), pudding_vertices.data()); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(offset)); + /* copy pudding color values into VBO, offset to after pudding vertices and set as 3D */ + 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)); /* 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); @@ -114,9 +173,12 @@ void Pudding::load_gl_context() link_shader(flat_program); /* 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); 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"); link_shader(mvp_program); mvp_id = glGetUniformLocation(mvp_program, "MVP"); log_gl_errors(); @@ -538,30 +600,36 @@ void Pudding::update() } glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); glClearColor(0, 1.0f, 0, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw pudding model using MVP shader */ glUseProgram(mvp_program); /* 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(45.0f), viewport_box.aspect(), 0.1f, 100.0f); + projection = glm::perspective(glm::radians(37.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]); - /* disable rectangle vertices and UV and enable pudding vertices */ + /* disable rectangle attributes and enable pudding attributes */ glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); /* draw pudding model */ - glDrawArrays(GL_LINES, 0, 36); + // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_DEPTH_TEST); + glDrawArrays(GL_TRIANGLES, 0, pudding_vertices.size()); /* only do more drawing if items are downloaded or camera is enabled */ if (items.size() > 0 || capture.isOpened()) { /* switch to flat shader for item and camera */ glUseProgram(flat_program); - /* disable pudding vertices and enable rectangle */ + /* disable pudding attributes and enable rectangle attributes */ glDisableVertexAttribArray(2); + glDisableVertexAttribArray(3); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); + glDisable(GL_DEPTH_TEST); /* just need to set these once since we're drawing one texture per viewport */ GLint base_texture_location = glGetUniformLocation(flat_program, "baseTexture"); glUniform1i(base_texture_location, 0); diff --git a/src/Pudding.hpp b/src/Pudding.hpp index ef5f083..4bc20ae 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ private: const glm::vec3 ZERO_VECTOR_3D = glm::vec3(0, 0, 0); const glm::vec3 Y_UNIT_NORMAL_3D = glm::vec3(0, 1, 0); const glm::mat4 VIEW_MATRIX = glm::lookAt(glm::vec3(4, 3, 3), ZERO_VECTOR_3D, Y_UNIT_NORMAL_3D); + const glm::vec3 PUDDING_BROWN = glm::vec3(0.713f, 0.359f, 0.224f); + 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; @@ -45,7 +48,10 @@ private: zbar::ImageScanner image_scanner; GLuint vbo, flat_program, mvp_program, video_capture_texture_id, mvp_id; glm::mat4 projection, model = glm::mat4(1.0f), mvp; + std::vector wireframe_pudding_vertices, pudding_vertices, pudding_colors; + void set_pudding_model(const std::vector&, const std::vector&, float y); + void set_wireframe_pudding_vertices(const std::vector&, const std::vector&, float y); void load_gl_context(); void initialize_camera(); void incorporate_open_food_api(Item&); diff --git a/src/mvp.vert b/src/mvp.vert index fb8af35..3c75ded 100644 --- a/src/mvp.vert +++ b/src/mvp.vert @@ -1,9 +1,12 @@ #version 130 in vec3 in_Position; +in vec3 in_Color; uniform mat4 MVP; +out vec3 ex_Color; void main(void) { gl_Position = MVP * vec4(in_Position, 1); + ex_Color = in_Color; }