diff --git a/lib/sfw b/lib/sfw index 14759a1..fe3e0bf 160000 --- a/lib/sfw +++ b/lib/sfw @@ -1 +1 @@ -Subproject commit 14759a1c79096f0c84ba1b48b7cb794b1c51f439 +Subproject commit fe3e0bf27f8ab45edcb322ab89bc79a6fe15d8bf diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 8c576ba..51dd708 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -33,90 +33,98 @@ Pudding::Pudding() /* 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); + set_pudding_model(1.0f, 1.6f, 12, 5, -.6, .6, .25); /* 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) +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) { - /* 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}) + 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; + std::vector layer_top_ring, layer_base_ring; + layer_top_ring.reserve(ring_vertex_count); + layer_base_ring.reserve(ring_vertex_count); + /* y coordinates of each ring of vertices in the pudding */ + const std::map y_coords = sfw::range_percent_count(max_y, min_y, layer_count + 1); + /* loop through layers by looking at each layer's top and bottom rings simultaneously */ + for ( + auto layer_top_entry = y_coords.begin(), layer_base_entry = ++y_coords.begin(); + layer_base_entry != y_coords.end(); + layer_top_entry++, layer_base_entry++ + ) + { + layer_top_y = layer_top_entry->second; + layer_top_percent = layer_top_entry->first; + layer_base_y = layer_base_entry->second; + layer_base_percent = layer_base_entry->first; + layer_top_ring.clear(); + layer_base_ring.clear(); + sfw::points_on_circle(layer_top_ring, ring_vertex_count, layer_top_percent * (base_radius - top_radius) + top_radius); + sfw::points_on_circle(layer_base_ring, ring_vertex_count, layer_base_percent * (base_radius - top_radius) + top_radius); + /* layers above gradient position are brown, layers below are yellow, and the layer that contains gradient positon + * is a gradient from brown to yellow */ + if (layer_top_percent <= gradient_position && layer_base_percent >= gradient_position) + { + layer_top_color = &PUDDING_BROWN; + layer_bottom_color = &PUDDING_YELLOW; + } + else if (layer_top_percent <= gradient_position) + { + layer_top_color = &PUDDING_BROWN; + layer_bottom_color = &PUDDING_BROWN; + } + else + { + layer_top_color = &PUDDING_YELLOW; + layer_bottom_color = &PUDDING_YELLOW; + } + /* go through top and base ring vertices simultaneously to build side triangles */ + 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_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y}); + 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_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_colors.push_back(*layer_bottom_color); + pudding_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y}); + 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_colors.push_back(*layer_bottom_color); + } + } + 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}) { /* loop through points on the face */ for (ii = 0; ii < face.size(); ii++) { - start = face[ii]; - end = face[(ii + 1) % face.size()]; + start_vertex = &face[ii]; + end_vertex = &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({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}); - 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}); + /* single color for the entire face */ + pudding_colors.insert(pudding_colors.end(), 3 * face.size(), *face_color); + y = min_y; + face_color = &PUDDING_YELLOW; } } @@ -590,7 +598,6 @@ void Pudding::update() message << "read new barcode from config " << current_barcode; log(message.str()); } - /* viewport box will be used to tell GL where to draw */ Box viewport_box = get_window_box(); /* shrink viewport if item texture or camera will be displayed */ @@ -599,14 +606,14 @@ void Pudding::update() viewport_box.set_right(get_window_box().get_center_x(), true); } glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); - glClearColor(0, 1.0f, 0, 1.0f); + glClearColor(1.0, 0.5, 0.8, 1.0f); 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(37.0f), viewport_box.aspect(), 0.1f, 100.0f); + projection = glm::perspective(glm::radians(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]); diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 4bc20ae..86feefd 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -37,7 +37,7 @@ private: const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key="; 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::mat4 VIEW_MATRIX = glm::lookAt(glm::vec3(4, 2, 1), glm::vec3(0, -0.325, 0), 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; @@ -48,10 +48,9 @@ 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; + std::vector 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 set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f); void load_gl_context(); void initialize_camera(); void incorporate_open_food_api(Item&); diff --git a/src/mvp.frag b/src/mvp.frag new file mode 100644 index 0000000..98014fc --- /dev/null +++ b/src/mvp.frag @@ -0,0 +1,9 @@ +#version 130 + +in vec3 ex_Color; +in float x; + +void main(void) +{ + gl_FragColor = vec4(ex_Color * x, 1); +} diff --git a/src/mvp.vert b/src/mvp.vert index 3c75ded..0f69047 100644 --- a/src/mvp.vert +++ b/src/mvp.vert @@ -4,9 +4,11 @@ in vec3 in_Position; in vec3 in_Color; uniform mat4 MVP; out vec3 ex_Color; +out float x; void main(void) { gl_Position = MVP * vec4(in_Position, 1); ex_Color = in_Color; + x = 1.8 - abs(in_Position[0]); }