Compare commits

...

10 commits

Author SHA1 Message Date
Epicalert 4084e5007e
Update model format docs to 0.5 2021-11-13 11:25:09 +08:00
Epicalert 293154034e
Add author and license info to test model 2021-11-13 09:14:14 +08:00
Epicalert fe75856701
Add keyboard input and model info keybind
Pressing 'i' will show a dialog box with the model info
2021-11-13 09:07:37 +08:00
Epicalert 972a0cc9b9
Add authors and license to model file 2021-11-13 00:43:45 +08:00
Epicalert 678393ccb1
Clean up model format version
Commit 09c60db8 should have incrememnted the model format version but
didn't. Also added "since version x.x" in the model format docs.
2021-11-12 20:12:06 +08:00
Epicalert f077ca5b5f
Complete documentation for Model format 0.3 2021-11-12 19:51:26 +08:00
Epicalert 57ad5cd47a
Fix crash when eye roi outside of view 2021-11-12 19:08:21 +08:00
Epicalert c06f6beae6
Fix flickering on some renderers
GLUT apparently doesn't do double buffers by default, (at least
sometimes) so we need to explicitly set it in init.
2021-11-12 01:15:29 +08:00
Epicalert eb4bf55cda
Update TODO 2021-11-12 01:12:46 +08:00
Epicalert 583ec11ee5
Add default model
Default-chan is the new default model that will be used instead of the
`test` placeholder.
2021-11-11 23:12:34 +08:00
29 changed files with 272 additions and 11 deletions

View file

@ -47,6 +47,7 @@ file(
DESTINATION DESTINATION
${PROJECT_BINARY_DIR} ) ${PROJECT_BINARY_DIR} )
file( MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/models ) file( MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/models )
pack_model( "default" )
pack_model( "test" ) pack_model( "test" )
pack_model( "rms" ) pack_model( "rms" )
if (APPLE) if (APPLE)
@ -69,6 +70,7 @@ add_executable( fc2d
src/error.cpp src/error.cpp
src/eye.cpp src/eye.cpp
src/configfile.cpp src/configfile.cpp
src/input.cpp
packaging/fc2d.rc packaging/fc2d.rc
) )
target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${WEBP_LIBRARIES} target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${WEBP_LIBRARIES}

View file

@ -5,10 +5,9 @@
- demo video? - demo video?
## models ## models
- better default model - clipping (alpha stencil)
## Bugs ## Bugs
- crash when eye goes outside of roi
- incorrect appdata location on Windows - incorrect appdata location on Windows
# Whenever # Whenever
@ -19,3 +18,7 @@
## vision ## vision
- eye open/closed - eye open/closed
## graphics
- in-window text rendering

View file

@ -1,4 +1,4 @@
.TH FC2D_MODEL 5 "Facecam2D Model Format 0.3 Manual" .TH FC2D_MODEL 5 "Facecam2D Model Format 0.5 Manual"
. .
.SH NAME .SH NAME
fc2d_model \- Facecam2D model file format fc2d_model \- Facecam2D model file format
@ -65,6 +65,23 @@ Unnecessary files should not be present in the archive, but archives with
unnecessary files are still valid. unnecessary files are still valid.
. .
. .
.SH FORMAT VERSION
.PP
.
Every Facecam2D model has a version code in the
.B model.toml
in the format "major.minor".
A given version of Facecam2D can read model files with the same
major version as the version it is compatible with.
For example, if Facecam2D can read the model format up to version 0.3,
the same build of Facecam2D can also read a model written in format 0.2,
but cannot play a model written in format 1.2 or 0.5.
It is only backwards compatible with the same major version.
Higher minor versions of the model format indicate that there are newer
optional features available, but does not break compatibility with formats
of the same major version.
.
.
.SH KEYS .SH KEYS
.SS format .SS format
.TP .TP
@ -85,6 +102,27 @@ String: The name of the model (will be displayed in the window title).
version version
String: A version string for the model (currently unused). String: A version string for the model (currently unused).
. .
.TP
artist
.ft B
(Since version 0.5)
.ft
String: Name of artist or photographer
.
.TP
modeler
.ft B
(Since version 0.5)
.ft
String: Name of modeler or rigger
.
.TP
license
.ft B
(Since version 0.5)
.ft
String: SPDX license identifier (if none model is assumed to be proprietary)
.
. .
.SS part .SS part
.TP .TP
@ -114,6 +152,54 @@ Float: How far the part will move towards the
point. point.
If negative, the part will move in the opposite direction. If negative, the part will move in the opposite direction.
. .
.TP
rot_factor, scale_factor
.ft B
(Since version 0.2)
.ft
Float: How much the part will rotate/scale.
Default is 1.0.
Higher values result in more exaggerated rotation or scaling.
.
.TP
offset_factor
.ft B
(Since version 0.4)
.ft
float: How much the part will be moved by the offset bind.
See
.B offset_bind.
.
.TP
origin
.ft B
(Since version 0.3)
.ft
Float Array: Origin (pivot point) of the model defined in
normalized coordinates.
Default is [0.0, 0.0].
.
.TP
pos_offset, scale_offset
.ft B
(Since version 0.3)
.ft
Float Array: Positional offset or scale of a part.
Default is [0.0, 0.0] for
.B pos_offset
and [1.0, 1.0] for
.B scale_offset.
.
.TP
offset_bind
.ft B
(Since version 0.4)
.ft
String: Offsets are vectors instead of actual points on the image.
You can bind to an offset with this property, which will
offset the part's position according to the vector.
Possible values: offset-eyes
.
.SS textures .SS textures
.TP .TP
file file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
models/default/body.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
models/default/clothes.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
models/default/collar.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
models/default/eye.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
models/default/head.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
models/default/iris.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

91
models/default/model.toml Normal file
View file

@ -0,0 +1,91 @@
[format]
version_major = 0
version_minor = 4
[model_info]
name = "Default-chan"
version = "1.0"
[[part]]
texture = "back hair.webp"
bind = "head"
follow = "face"
factor = -0.1
[[part]]
texture = "body.webp"
bind = "head"
rot_factor=0.3
[[part]]
texture = "clothes.webp"
bind = "head"
follow = "face"
factor = 0.1
rot_factor=0.3
[[part]]
texture = "collar.webp"
bind = "head"
rot_factor=0.3
[[part]]
texture = "head.webp"
bind = "head"
[[part]]
texture = "nose.webp"
bind = "head"
follow = "face"
factor = 0.35
[[part]]
texture = "eye.webp"
bind = "head"
follow = "face"
factor = 0.35
[[part]]
texture = "iris.webp"
bind = "head"
follow = "face"
factor = 0.35
offset_bind = "offset-eyes"
offset_factor = 0.03
[[part]]
texture = "eye lids.webp"
bind = "head"
follow = "face"
factor = 0.35
[[part]]
bind = "head"
follow = "face"
factor = 0.35
[[part.textures]]
file = "mouth closed.webp"
[[part.textures]]
file = "mouth open.webp"
trigger = "mouth-open"
[[part]]
texture = "side hair.webp"
bind = "head"
follow = "face"
factor = 0.1
[[part]]
texture = "front hair.webp"
bind = "head"
follow = "face"
factor = 0.2
[[part]]
texture = "eye brows.webp"
bind = "head"
follow = "face"
factor = 0.35

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
models/default/nose.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
models/default/source.kra Normal file

Binary file not shown.

View file

@ -1,10 +1,13 @@
[format] [format]
version_major = 0 version_major = 0
version_minor = 2 version_minor = 5
[model_info] [model_info]
name = "Richard Stallman" name = "Richard Stallman"
version = "1.0" version = "1.1"
artist = "Ruben Rodriguez"
modeler = "Epicalert"
license = "CC-BY-4.0"
[[part]] [[part]]
texture = "bg.webp" texture = "bg.webp"

View file

@ -1,11 +1,13 @@
[format] [format]
version_major = 0 version_major = 0
version_minor = 1 version_minor = 5
[model_info] [model_info]
name = "Test Model" name = "Test Model"
version = "1.0" version = "1.0"
artist = "Epicalert"
modeler = "Epicalert"
license = "GPL-3.0-only"
[[part]] [[part]]
texture = "head-base.png" texture = "head-base.png"

View file

@ -36,7 +36,7 @@ struct optData optData = {
false, false,
false, false,
false, false,
"test", "default",
0, 0,
}; };

View file

@ -170,13 +170,20 @@ void cvFrame() {
cv::rectangle(frame, eyeRect, cv::Scalar(255, 255, 255)); cv::rectangle(frame, eyeRect, cv::Scalar(255, 255, 255));
cv::Mat eyeROI; cv::Mat eyeROI;
glm::vec2 eyeVector(0,0);
// prevent assertion failed when eye is partly outside of image
if(eyeRect.x < 0 || eyeRect.x >= gray.cols || eyeRect.y < 0 || eyeRect.y >= gray.rows ||
eyeRect.x + eyeRect.width >= gray.cols || eyeRect.y - eyeRect.height >= gray.rows) goto noeye;
eyeROI = gray(eyeRect); eyeROI = gray(eyeRect);
glm::vec2 eyeVector(0,0);
if (!optData.noEyes) { if (!optData.noEyes) {
eyeVector = eyeDirection(eyeROI); // run pupil tracking algorithm and get look direction eyeVector = eyeDirection(eyeROI); // run pupil tracking algorithm and get look direction
} }
noeye:
//send control information to graphics //send control information to graphics
float faceSize = landmarks[biggestFace][14].x - landmarks[biggestFace][2].x; float faceSize = landmarks[biggestFace][14].x - landmarks[biggestFace][2].x;

View file

@ -23,6 +23,12 @@
#include <cv.hpp> #include <cv.hpp>
#include <args.hpp> #include <args.hpp>
#include <error.hpp> #include <error.hpp>
#include <input.hpp>
#ifndef NO_GRAPHICAL_DIALOG
#include <boxer/boxer.h>
#endif
GLuint shader; //standard shader program used for all elements GLuint shader; //standard shader program used for all elements
GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader
@ -94,8 +100,12 @@ void initGraphics () {
char *argv[1] = {(char*)"fc2d"}; char *argv[1] = {(char*)"fc2d"};
glutInit(&argc, argv); glutInit(&argc, argv);
glutCreateWindow(PROJECT_NAME); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(512, 512); glutInitWindowSize(512, 512);
glutCreateWindow(PROJECT_NAME);
// input callback
glutKeyboardFunc(keyInput);
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
glewInit(); glewInit();
@ -236,3 +246,7 @@ void updateModel(struct FaceData faceData) {
//tell FreeGLUT to schedule a screen update //tell FreeGLUT to schedule a screen update
glutPostRedisplay(); glutPostRedisplay();
} }
void showModelInfo() {
boxer::show(model->getInfoString().c_str(), "Model info", boxer::Style::Info);
}

View file

@ -10,6 +10,8 @@
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <cv.hpp> #include <cv.hpp>
#include <model.hpp>
#include <modelpart.hpp>
extern GLuint transUniform; extern GLuint transUniform;
extern float windowAspectRatio; extern float windowAspectRatio;
@ -28,4 +30,6 @@ void printShaderCompileLog(GLuint shader);
void updateModel(struct FaceData faceData); void updateModel(struct FaceData faceData);
void showModelInfo();
#endif #endif

12
src/input.cpp Normal file
View file

@ -0,0 +1,12 @@
#include <input.hpp>
#include <graphics.hpp>
void keyInput(unsigned char key, int x, int y) {
switch(key) {
case 'i': // model info
showModelInfo();
break;
default:
break;
}
}

6
src/input.hpp Normal file
View file

@ -0,0 +1,6 @@
#ifndef INPUT_HPP
#define INPUT_HPP
void keyInput(unsigned char key, int x, int y);
#endif

View file

@ -12,7 +12,7 @@
#define BUFFER_SIZE_TEXTURE 16777220 // 16 MiB #define BUFFER_SIZE_TEXTURE 16777220 // 16 MiB
#define SUPPORTED_MODEL_MAJOR 0 #define SUPPORTED_MODEL_MAJOR 0
#define SUPPORTED_MODEL_MINOR 3 #define SUPPORTED_MODEL_MINOR 5
void textureFromArchive(zip_t* archive, const char* path, ModelPart* part, size_t slot, std::string triggerName) { void textureFromArchive(zip_t* archive, const char* path, ModelPart* part, size_t slot, std::string triggerName) {
zip_file_t* textureFile = zip_fopen(archive, path, 0); zip_file_t* textureFile = zip_fopen(archive, path, 0);
@ -90,8 +90,30 @@ Model::Model(const char* path) {
} else { } else {
name = nameResult.second; name = nameResult.second;
} }
// get authors
// artist (or photographer if image)
auto artistResult = modelInfo->getString("artist");
if (artistResult.first) {
artist = artistResult.second;
}
// rigger/modeler
auto modelerResult = modelInfo->getString("modeler");
if (modelerResult.first) {
modeler = modelerResult.second;
}
// get license (SPDX identifier, if not present file is assumed to be proprietary)
auto licenseResult = modelInfo->getString("license");
if (licenseResult.first) {
license = licenseResult.second;
}
} }
// parse parts // parse parts
auto partsDescArray = modelDesc.table->getArray("part"); auto partsDescArray = modelDesc.table->getArray("part");
@ -212,3 +234,7 @@ std::string Model::getName() {
return name; return name;
} }
std::string Model::getInfoString() {
return fmt::format("{}\n{}\n\nArtist: {}\nModeler: {}",
name, license, artist, modeler);
}

View file

@ -10,6 +10,10 @@ class Model {
std::string name; std::string name;
std::string artist;
std::string modeler;
std::string license;
public: public:
Model(const char* path); Model(const char* path);
@ -18,6 +22,7 @@ class Model {
void updateTransforms(struct FaceData faceData); void updateTransforms(struct FaceData faceData);
std::string getName(); std::string getName();
std::string getInfoString();
}; };
#endif #endif