diff --git a/face-eyes.png b/face-eyes.png new file mode 100644 index 0000000..896359e Binary files /dev/null and b/face-eyes.png differ diff --git a/face-mouth-closed.png b/face-mouth-closed.png new file mode 100644 index 0000000..175940a Binary files /dev/null and b/face-mouth-closed.png differ diff --git a/face-mouth-open.png b/face-mouth-open.png new file mode 100644 index 0000000..d256bdb Binary files /dev/null and b/face-mouth-open.png differ diff --git a/face.png b/face.png deleted file mode 100644 index 54771e3..0000000 Binary files a/face.png and /dev/null differ diff --git a/face.xcf b/face.xcf new file mode 100644 index 0000000..d55f849 Binary files /dev/null and b/face.xcf differ diff --git a/head-face.png b/head-face.png deleted file mode 100644 index adb62ee..0000000 Binary files a/head-face.png and /dev/null differ diff --git a/src/graphics.cpp b/src/graphics.cpp index 6c59c4f..bc090f4 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -16,7 +16,7 @@ GLuint shader; //standard shader program used for all elements GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader //parts of the model (see modelpart.hpp) -ModelPart parts[2]; +ModelPart parts[3]; void display () { glClear(GL_COLOR_BUFFER_BIT); @@ -78,7 +78,9 @@ void initGraphics () { initShader(); parts[0] = ModelPart("head-base.png", transUniform); - parts[1] = ModelPart("head-face.png", transUniform); + parts[1] = ModelPart("face-eyes.png", transUniform); + parts[2] = ModelPart("face-mouth-closed.png", transUniform); + parts[2].addTexture("face-mouth-open.png", 1); //enable blending for alpha textures glEnable(GL_BLEND); @@ -173,10 +175,14 @@ void initModel () { } -void updateModel(glm::vec2 headPos, glm::vec2 facePos) { +void updateModel(glm::vec2 headPos, glm::vec2 facePos, bool mouthOpen) { //calculate transforms parts[0].setPosition(headPos); parts[1].setPosition(facePos); + parts[2].setPosition(facePos); + + //set mouth texture to open or closed + parts[2].selectTexture(mouthOpen ? 1 : 0); //tell FreeGLUT to schedule a screen update glutPostRedisplay(); diff --git a/src/graphics.hpp b/src/graphics.hpp index 8e7faa3..6c1bb0e 100644 --- a/src/graphics.hpp +++ b/src/graphics.hpp @@ -16,6 +16,6 @@ void initShader(); void printShaderCompileLog(GLuint shader); -void updateModel(glm::vec2 headPos, glm::vec2 facePos); +void updateModel(glm::vec2 headPos, glm::vec2 facePos, bool mouthOpen); #endif diff --git a/src/main.cpp b/src/main.cpp index f032a22..99b58bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,10 +3,12 @@ #include +#include + int main () { initGraphics(); - cv::CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); + cv::CascadeClassifier faceDetector ("lbpcascade_frontalface_improved.xml"); cv::Ptr facemark = cv::face::FacemarkLBF::create(); facemark->loadModel ("lbfmodel.yaml"); @@ -51,6 +53,8 @@ int main () { (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)); + cv::circle (frame, landmarks[biggestFace][66], 3, cv::Scalar (0, 255, 0)); + cv::circle (frame, landmarks[biggestFace][62], 3, cv::Scalar (0, 255, 0)); //send control information to graphics updateModel(glm::vec2( @@ -62,7 +66,8 @@ int main () { glm::vec2( landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1, landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1 - )); + ), + landmarks[biggestFace][66].y - landmarks[biggestFace][62].y > 5); } graphicsFrame (); diff --git a/src/modelpart.cpp b/src/modelpart.cpp index 7ce88e9..380016b 100644 --- a/src/modelpart.cpp +++ b/src/modelpart.cpp @@ -14,18 +14,29 @@ ModelPart::ModelPart(const char* texPath, GLuint transUniformNum) { //create vbo, ebo, vao initBuffers(&vao); //create texture - initTexture(&tex, texPath); + initTexture(&tex[0], texPath); transUniform = transUniformNum; + + empty = false; } void ModelPart::bindAndDraw() { + if (empty) { return; } glBindVertexArray(vao); - glBindTexture(GL_TEXTURE_2D, tex); + glBindTexture(GL_TEXTURE_2D, tex[texSelection]); glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(transMatrix)); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } void ModelPart::setPosition(glm::vec2 position) { - transMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(position.x, position.y, 0.0f)); + transMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(position.x, -position.y, 0.0f)); +} + +void ModelPart::addTexture(const char* texPath, size_t slot) { + initTexture(&tex[slot], texPath); +} + +void ModelPart::selectTexture(size_t slot) { + texSelection = slot; } diff --git a/src/modelpart.hpp b/src/modelpart.hpp index 68798a9..89222a4 100644 --- a/src/modelpart.hpp +++ b/src/modelpart.hpp @@ -4,8 +4,14 @@ #include class ModelPart { - GLuint vao, tex, transUniform; + GLuint vao, transUniform; + + GLuint tex[16]; //support 16 textures to switch between + size_t texSelection = 0; + glm::mat4 transMatrix = glm::mat4(1.0f); + + bool empty = true; public: ModelPart(); @@ -15,6 +21,10 @@ class ModelPart { void bindAndDraw(); void setPosition(glm::vec2 position); + + void addTexture(const char* texPath, size_t slot); + + void selectTexture(size_t slot); }; #endif