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);
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +159,6 @@ void initBuffers () {
 | 
			
		|||
	glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
 | 
			
		||||
	if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl;
 | 
			
		||||
				 printShaderCompileLog(vs); }
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	//link shaders into a shader program
 | 
			
		||||
	shader = glCreateProgram();
 | 
			
		||||
| 
						 | 
				
			
			@ -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