pudding colored fragments

This commit is contained in:
frank 2021-08-02 20:15:30 -04:00
parent fb7f5390be
commit 8444f3aa16
4 changed files with 121 additions and 44 deletions

View File

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

View File

@ -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<glm::vec2> pudding_top_2d = sfw::get_points_on_circle(24);
const std::vector<glm::vec2> 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<glm::vec2>& top_2d, const std::vector<glm::vec2>& 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<glm::vec2>& 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<glm::vec2>& top_2d, const std::vector<glm::vec2>& base_2d, float y)
{
glm::vec2 start, end;
size_t ii;
for (const std::vector<glm::vec2>& 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<glm::vec3, 36> 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<glm::vec3, 24> 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<GLvoid*>(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<GLvoid*>(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<GLvoid*>(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<float>()), 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);

View File

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <memory>
#include <type_traits>
#include <filesystem>
@ -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<Item> 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<glm::vec3> wireframe_pudding_vertices, pudding_vertices, pudding_colors;
void set_pudding_model(const std::vector<glm::vec2>&, const std::vector<glm::vec2>&, float y);
void set_wireframe_pudding_vertices(const std::vector<glm::vec2>&, const std::vector<glm::vec2>&, float y);
void load_gl_context();
void initialize_camera();
void incorporate_open_food_api(Item&);

View File

@ -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;
}