separate face and head
- Head position is now calculated from the midpoint of points 2 and 14 (sides of head) - Face position is calculated from point 30 (nose tip)
This commit is contained in:
parent
25ebd7a387
commit
62779b6f78
157
src/graphics.cpp
157
src/graphics.cpp
|
@ -11,24 +11,37 @@
|
|||
|
||||
#include <graphics.hpp>
|
||||
|
||||
GLuint vbo; //vertex buffer
|
||||
GLuint ebo; //element buffer
|
||||
GLuint vao; //vertex array (holds shader relations etc to vertex buffer)
|
||||
//VAOs for different parts
|
||||
//TODO: make this more modular
|
||||
GLuint head; //head object
|
||||
GLuint face; //face object
|
||||
|
||||
GLuint shader; //standard shader program used for all elements
|
||||
GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader
|
||||
|
||||
GLuint texHead; //head texture
|
||||
GLuint texFace; //face texture
|
||||
|
||||
glm::mat4 matHead(1.0f); //transformation matrix for head object
|
||||
glm::mat4 matFace(1.0f); //transformation matrix for face object
|
||||
|
||||
void display () {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBindVertexArray(head);
|
||||
glBindTexture(GL_TEXTURE_2D, texHead);
|
||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(matHead));
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glBindVertexArray(face);
|
||||
glBindTexture(GL_TEXTURE_2D, texFace);
|
||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(matFace));
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
void initBuffers () {
|
||||
glewInit();
|
||||
|
||||
void initBuffers (GLuint* vaoNum) {
|
||||
//TODO: put quad stuff in header file or something
|
||||
GLfloat quad[] = {
|
||||
//vertex UV/texcoord
|
||||
|
@ -43,6 +56,73 @@ void initBuffers () {
|
|||
2, 3, 0
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, vaoNum);
|
||||
glBindVertexArray(*vaoNum);
|
||||
|
||||
GLuint vbo; //vertex buffer
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
//change to GL_DYNAMIC_DRAW when using deformable meshes
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
|
||||
|
||||
GLuint ebo; //element buffer
|
||||
glGenBuffers(1, &ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW);
|
||||
|
||||
//tell OpenGL what to put in the input vars
|
||||
GLuint posAttr = glGetAttribLocation(shader, "position");
|
||||
glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
|
||||
glEnableVertexAttribArray(posAttr);
|
||||
GLuint uvAttr = glGetAttribLocation(shader, "texcoord");
|
||||
glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(uvAttr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void initGraphics () {
|
||||
int argc = 1;
|
||||
char *argv[1] = {(char*)"fc2d"};
|
||||
|
||||
glutInit(&argc, argv);
|
||||
glutCreateWindow("FaceCam2D");
|
||||
glutInitWindowSize(512, 512);
|
||||
glutDisplayFunc(display);
|
||||
|
||||
glewInit();
|
||||
|
||||
initShader();
|
||||
|
||||
initBuffers(&head);
|
||||
initBuffers(&face);
|
||||
|
||||
initTexture(&texHead, "head-base.png");
|
||||
initTexture(&texFace, "head-face.png");
|
||||
|
||||
//enable blending for alpha textures
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//set background color
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
}
|
||||
|
||||
void initTexture (GLuint* texNum, const char* path) {
|
||||
glGenTextures(1, texNum);
|
||||
glBindTexture(GL_TEXTURE_2D, *texNum);
|
||||
|
||||
int x, y, channels;
|
||||
GLubyte* pixels = stbi_load(path, &x, &y, &channels, 4);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
void initShader() {
|
||||
const char* vsSrc =
|
||||
"#version 150\n"
|
||||
"in vec2 position;"
|
||||
|
@ -63,18 +143,6 @@ void initBuffers () {
|
|||
"color = texture(tex, uv);"
|
||||
"}";
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
//change to GL_DYNAMIC_DRAW when using deformable meshes
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW);
|
||||
|
||||
//compile vert shader
|
||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vs, 1, &vsSrc, NULL);
|
||||
|
@ -92,7 +160,6 @@ void initBuffers () {
|
|||
if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl;
|
||||
printShaderCompileLog(vs); }
|
||||
|
||||
|
||||
//link shaders into a shader program
|
||||
shader = glCreateProgram();
|
||||
glAttachShader(shader, vs);
|
||||
|
@ -101,48 +168,9 @@ void initBuffers () {
|
|||
glLinkProgram(shader);
|
||||
glUseProgram(shader);
|
||||
|
||||
|
||||
//tell OpenGL what to put in the input vars
|
||||
GLuint posAttr = glGetAttribLocation(shader, "position");
|
||||
glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
|
||||
glEnableVertexAttribArray(posAttr);
|
||||
GLuint uvAttr = glGetAttribLocation(shader, "texcoord");
|
||||
glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(uvAttr);
|
||||
|
||||
//set an identity ("do nothing") transformation matrix as default
|
||||
transUniform = glGetUniformLocation(shader, "transMatrix");
|
||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
|
||||
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
int x, y, channels;
|
||||
GLubyte* pixels = stbi_load("face.png", &x, &y, &channels, 4);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
//enable blending for alpha textures
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void initGraphics () {
|
||||
int argc = 1;
|
||||
char *argv[1] = {(char*)"fc2d"};
|
||||
|
||||
glutInit(&argc, argv);
|
||||
glutCreateWindow("FaceCam2D");
|
||||
glutInitWindowSize(512, 512);
|
||||
glutDisplayFunc(display);
|
||||
|
||||
initBuffers();
|
||||
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
}
|
||||
|
||||
void graphicsFrame () {
|
||||
|
@ -160,12 +188,11 @@ void initModel () {
|
|||
|
||||
}
|
||||
|
||||
void updateModel(glm::vec2 headPos) {
|
||||
//calculate transform
|
||||
glm::mat4 transMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(headPos.x, headPos.y, 0.0f));
|
||||
|
||||
//upload to GPU and put in transMatrix uniform var in shader program
|
||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(transMatrix));
|
||||
void updateModel(glm::vec2 headPos, glm::vec2 facePos) {
|
||||
//calculate transforms
|
||||
matHead = glm::translate(glm::mat4(1.0f), glm::vec3(headPos.x, -headPos.y, 0.0f));
|
||||
matFace = glm::translate(glm::mat4(1.0f), glm::vec3(facePos.x, -facePos.y, 0.0f));
|
||||
|
||||
//tell FreeGLUT to schedule a screen update
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
|
|
@ -8,8 +8,12 @@ void initGraphics ();
|
|||
|
||||
void graphicsFrame ();
|
||||
|
||||
void initTexture (GLuint* texNum, const char* path);
|
||||
|
||||
void initShader();
|
||||
|
||||
void printShaderCompileLog(GLuint shader);
|
||||
|
||||
void updateModel(glm::vec2 headPos);
|
||||
void updateModel(glm::vec2 headPos, glm::vec2 facePos);
|
||||
|
||||
#endif
|
||||
|
|
22
src/main.cpp
22
src/main.cpp
|
@ -43,13 +43,25 @@ int main () {
|
|||
std::vector<std::vector<cv::Point2f>> landmarks;
|
||||
|
||||
if (facemark->fit (frame, faces, landmarks)) {
|
||||
for (int i = 0; i < landmarks[biggestFace].size(); i++) {
|
||||
cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255));
|
||||
}
|
||||
//for (int i = 0; i < landmarks[biggestFace].size(); i++) {
|
||||
// cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255));
|
||||
//}
|
||||
cv::circle(frame, cv::Point2f(
|
||||
(landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2,
|
||||
(landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2
|
||||
), 6, cv::Scalar(0, 0, 255));
|
||||
cv::circle (frame, landmarks[biggestFace][30], 6, cv::Scalar (0, 255, 255));
|
||||
|
||||
//send control information to graphics
|
||||
updateModel(glm::vec2(
|
||||
((faces[biggestFace].x + (faces[biggestFace].width / 2)) * 2) / (float)frame.cols - 1,
|
||||
((faces[biggestFace].y + (faces[biggestFace].height / 2)) * 2) / -(float)frame.rows + 1
|
||||
(landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2
|
||||
* 2 / (float)frame.cols - 1,
|
||||
(landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2
|
||||
* 2 / (float)frame.rows - 1
|
||||
),
|
||||
glm::vec2(
|
||||
landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1,
|
||||
landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1
|
||||
));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue