Add support for model files

Model files are zip archives with a "model.toml" file at the root describing
the model and all its textures.
This commit is contained in:
Epicalert 2021-02-04 22:58:03 +08:00
parent cbbdf5ff79
commit 4770c96d92
No known key found for this signature in database
GPG key ID: CAA46F858D0979BD
19 changed files with 3140 additions and 49 deletions

View file

@ -1,5 +1,6 @@
cmake_minimum_required( VERSION 3.0 )
project( Facecam2D VERSION 0.1.0 )
find_package( libzip REQUIRED )
find_package( OpenCV REQUIRED )
message (STATUS "Found OpenCV at: " ${OpenCV_INCLUDE_DIRS} )
find_package( OpenGL REQUIRED )
@ -38,5 +39,8 @@ add_executable( fc2d
src/cv.cpp
src/paths.cpp
src/args.cpp
src/model.cpp
src/toml.c
src/tomlcpp.cpp
)
target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} FreeGLUT::freeglut GLEW::glew )
target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} FreeGLUT::freeglut GLEW::glew zip )

BIN
models/test.fma Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -6,6 +6,8 @@
#include <graphics.hpp>
#include <paths.hpp>
#include <args.hpp>
#include <cv.hpp>
#include <modelpart.hpp>
cv::Ptr<cv::face::Facemark> facemark;
cv::CascadeClassifier haarFaceDetector;
@ -101,30 +103,29 @@ void cvFrame() {
//send control information to graphics
float faceSize = landmarks[biggestFace][14].x - landmarks[biggestFace][2].x;
updateModel(
//head position
glm::vec2(
struct FaceData faceData;
faceData.positions[BIND_NULL] = glm::vec2(0.0f, 0.0f);
faceData.positions[BIND_HEAD] = glm::vec2(
(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
),
//face position
glm::vec2(
);
faceData.positions[BIND_FACE] = glm::vec2(
landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1,
landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1
),
);
faceData.triggers[TRIGGER_NULL] = false;
faceData.triggers[TRIGGER_MOUTH_OPEN] =
(landmarks[biggestFace][66].y - landmarks[biggestFace][62].y) / faceSize > 0.04f;
//rotation
atanf((float)(landmarks[biggestFace][14].y - landmarks[biggestFace][2].y) /
(float)(landmarks[biggestFace][2].x - landmarks[biggestFace][14].x)),
faceData.headRotation = atanf(
(float)(landmarks[biggestFace][14].y - landmarks[biggestFace][2].y) /
(float)(landmarks[biggestFace][2].x - landmarks[biggestFace][14].x));
faceData.scale = faceSize * 6 / (float)frame.cols;
//scale
faceSize * 6 / (float)frame.cols,
//mouth open/closed state
(landmarks[biggestFace][66].y - landmarks[biggestFace][62].y) / faceSize > 0.04f);
updateModel(faceData);
}
}

View file

@ -1,6 +1,17 @@
#ifndef CV_HPP
#define CV_HPP
#include <map>
#include <glm/vec2.hpp>
struct FaceData {
std::map<int, glm::vec2> positions;
std::map<int, bool> triggers;
float headRotation;
float scale;
};
void initCV();
void cvFrame();

View file

@ -12,21 +12,21 @@
#include <graphics.hpp>
#include <modelpart.hpp>
#include <model.hpp>
#include <paths.hpp>
#include <config.hpp>
#include <cv.hpp>
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[3];
Model* model;
void display () {
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < sizeof(parts)/sizeof(ModelPart); i++) {
parts[i].bindAndDraw();
}
model->draw();
glutSwapBuffers();
}
@ -82,10 +82,7 @@ void initGraphics () {
initShader();
parts[0] = ModelPart(resolvePath("models/test/head-base.png").c_str(), transUniform);
parts[1] = ModelPart(resolvePath("models/test/face-eyes.png").c_str(), transUniform);
parts[2] = ModelPart(resolvePath("models/test/face-mouth-closed.png").c_str(), transUniform);
parts[2].addTexture(resolvePath("models/test/face-mouth-open.png").c_str(), 1);
model = new Model(resolvePath("models/test.fma").c_str());
//enable blending for alpha textures
glEnable(GL_BLEND);
@ -100,12 +97,12 @@ void initGraphics () {
std::cout << "graphics init complete" << std::endl;
}
void initTexture (GLuint* texNum, const char* path) {
void initTexture (GLuint* texNum, unsigned char* buffer, size_t bufferLength) {
glGenTextures(1, texNum);
glBindTexture(GL_TEXTURE_2D, *texNum);
int x, y, channels;
GLubyte* pixels = stbi_load(path, &x, &y, &channels, 4);
GLubyte* pixels = stbi_load_from_memory(buffer, bufferLength, &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);
@ -175,11 +172,8 @@ void printShaderCompileLog(GLuint shader) {
std::cout << logBuffer << std::endl;
}
void initModel () {
}
void updateModel(glm::vec2 headPos, glm::vec2 facePos, float rotation, float scale, bool mouthOpen) {
void updateModel(struct FaceData faceData) {
/*
//calculate transforms
parts[0].setTransform(headPos, rotation, scale);
parts[1].setTransform(facePos, rotation, scale);
@ -187,6 +181,8 @@ void updateModel(glm::vec2 headPos, glm::vec2 facePos, float rotation, float sca
//set mouth texture to open or closed
parts[2].selectTexture(mouthOpen ? 1 : 0);
*/
model->updateTransforms(faceData);
//tell FreeGLUT to schedule a screen update
glutPostRedisplay();

View file

@ -9,18 +9,22 @@
#include <glm/vec2.hpp>
#include <cv.hpp>
extern GLuint transUniform;
void initGraphics ();
void graphicsFrame ();
void initBuffers (GLuint* vaoNum);
void initTexture (GLuint* texNum, const char* path);
void initTexture (GLuint* texNum, unsigned char* buffer, size_t bufferLength);
void initShader();
void printShaderCompileLog(GLuint shader);
void updateModel(glm::vec2 headPos, glm::vec2 facePos, float rotation, float scale, bool mouthOpen);
void updateModel(struct FaceData faceData);