This library was developed and tested only on Ubuntu 18.04 using GCC 7.5.0.
However I don't think I've used anything that prevents it from being
cross-platform compatible -- it should still work as long as you have a
-recent C/C++ compiler. (The library should only require C++11. The Cubism
+recent C/C++ compiler. The library should only require C++11. The Cubism
SDK requires C++14. I have made use of one C++17 library (`<filesystem>`)
in the example program, but it should be straightforward to change this
if you don't have C++17 support.
manually. Hereafter, all build instructions will assume a Linux environment
where a shell is available.
-If your CPU does not support AVX instructions you may want to edit the
-relevant build scripts to remove the `-D USE_AVX_INSTRUCTIONS=1` variable
-(or change it the SSE3 etc). However there could be a penalty in performance.
+If your CPU does not support AVX instructions you may want to edit "build.sh"
+and "example/demo.patch" to remove the `-D USE_AVX_INSTRUCTIONS=1` variable
+(or change AVX to SSE4 or SSE2). However there could be a penalty in
+performance.
## Build instructions
git clone --recurse-submodules https://github.com/adrianiainlam/facial-landmarks-for-cubism.git
-3. To build the library only:
+3. To build the library only: (Skip this step if you want to build the example
+ program. It will be done automatically.)
cd <path of the git repo>
./build.sh
I have decided to make pretty much every parameter tweakable. The file
"config.txt" lists and documents all parameters and their default values.
You can change the values there and pass it to the example program using
-to `-c` argument. If using the library directly, the path to this file
+the `-c` argument. If using the library directly, the path to this file
should be passed to the constructor (or pass an empty string to use
default values).
+## Troubleshooting
+
+1. Example program crashes with SIGILL (Illegal instruction).
+
+ Your CPU probably doesn't support AVX instructions which is used by dlib.
+ You can confirm this by running
+
+ grep avx /proc/cpuinfo
+
+ If this is the case, try to find out if your CPU supports SSE4 or SSE2,
+ then edit "build.sh" and "example/demo.patch" to change
+ `USE_AVX_INSTRUCTIONS=1` to `USE_SSE4_INSTRUCTIONS=1` or
+ `USE_SSE2_INSTRUCTIONS=1`.
+
## License
The library itself is provided under the MIT license. By "the library itself"
diff -pruN --exclude build ./demo_clean/CMakeLists.txt ./demo_dev/CMakeLists.txt
---- ./demo_clean/CMakeLists.txt 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/CMakeLists.txt 2020-09-27 17:43:12.069477246 +0100
+++ ./demo_dev/CMakeLists.txt 2020-07-11 22:52:49.099117981 +0100
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
# Set app name.
#
# * USE_RENDER_TARGET
diff -pruN --exclude build ./demo_clean/scripts/make_gcc ./demo_dev/scripts/make_gcc
---- ./demo_clean/scripts/make_gcc 2020-07-12 16:16:33.999809687 +0100
-+++ ./demo_dev/scripts/make_gcc 2020-07-11 21:22:23.615043956 +0100
+--- ./demo_clean/scripts/make_gcc 2020-09-27 17:43:12.069477246 +0100
++++ ./demo_dev/scripts/make_gcc 2020-07-14 15:33:09.865020790 +0100
@@ -9,5 +9,6 @@ BUILD_PATH=$SCRIPT_PATH/../build/make_gc
# Run CMake.
cmake -S "$CMAKE_PATH" \
+ -D USE_AVX_INSTRUCTIONS=1
+cd "$BUILD_PATH" && make -j4
diff -pruN --exclude build ./demo_clean/src/CMakeLists.txt ./demo_dev/src/CMakeLists.txt
---- ./demo_clean/src/CMakeLists.txt 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/CMakeLists.txt 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/CMakeLists.txt 2020-07-11 17:39:18.358435702 +0100
@@ -19,6 +19,4 @@ target_sources(${APP_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp
)
diff -pruN --exclude build ./demo_clean/src/LAppDelegate.cpp ./demo_dev/src/LAppDelegate.cpp
---- ./demo_clean/src/LAppDelegate.cpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppDelegate.cpp 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/LAppDelegate.cpp 2020-07-11 17:35:02.414902548 +0100
@@ -45,7 +45,8 @@ void LAppDelegate::ReleaseInstance()
s_instance = NULL;
Csm::csmVector<string> LAppDelegate::Split(const std::string& baseString, char delimiter)
diff -pruN --exclude build ./demo_clean/src/LAppDelegate.hpp ./demo_dev/src/LAppDelegate.hpp
---- ./demo_clean/src/LAppDelegate.hpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppDelegate.hpp 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/LAppDelegate.hpp 2020-07-11 17:34:40.778602504 +0100
@@ -40,7 +40,8 @@ public:
/**
-
-};
diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.cpp ./demo_dev/src/LAppLive2DManager.cpp
---- ./demo_clean/src/LAppLive2DManager.cpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppLive2DManager.cpp 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/LAppLive2DManager.cpp 2020-07-11 23:20:11.548419176 +0100
@@ -52,9 +52,10 @@ void LAppLive2DManager::ReleaseInstance(
+ _translateY = translateY;
+}
diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.hpp ./demo_dev/src/LAppLive2DManager.hpp
---- ./demo_clean/src/LAppLive2DManager.hpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppLive2DManager.hpp 2020-09-27 17:43:12.069477246 +0100
+++ ./demo_dev/src/LAppLive2DManager.hpp 2020-07-11 23:21:17.969484538 +0100
@@ -6,12 +6,15 @@
*/
+ float _translateY;
};
diff -pruN --exclude build ./demo_clean/src/LAppModel.cpp ./demo_dev/src/LAppModel.cpp
---- ./demo_clean/src/LAppModel.cpp 2020-07-12 16:16:33.999809687 +0100
-+++ ./demo_dev/src/LAppModel.cpp 2020-07-11 15:57:43.784019311 +0100
+--- ./demo_clean/src/LAppModel.cpp 2020-09-27 17:43:12.069477246 +0100
++++ ./demo_dev/src/LAppModel.cpp 2020-09-27 17:40:16.401166244 +0100
@@ -21,6 +21,8 @@
#include "LAppTextureManager.hpp"
#include "LAppDelegate.hpp"
//Physics
if (strcmp(_modelSetting->GetPhysicsFileName(), "") != 0)
{
-@@ -174,27 +152,6 @@ void LAppModel::SetupModel(ICubismModelS
- DeleteBuffer(buffer, path.GetRawString());
- }
-
-- //EyeBlink
-- if (_modelSetting->GetEyeBlinkParameterCount() > 0)
-- {
-- _eyeBlink = CubismEyeBlink::Create(_modelSetting);
-- }
--
-- //Breath
-- {
-- _breath = CubismBreath::Create();
--
-- csmVector<CubismBreath::BreathParameterData> breathParameters;
--
-- breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleX, 0.0f, 15.0f, 6.5345f, 0.5f));
-- breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f));
-- breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f));
-- breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f));
-- breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f));
--
-- _breath->SetParameters(breathParameters);
-- }
--
- //UserData
- if (strcmp(_modelSetting->GetUserDataFile(), "") != 0)
- {
-@@ -205,24 +162,6 @@ void LAppModel::SetupModel(ICubismModelS
- DeleteBuffer(buffer, path.GetRawString());
+@@ -214,15 +192,6 @@ void LAppModel::SetupModel(ICubismModelS
+ }
}
-- // EyeBlinkIds
-- {
-- csmInt32 eyeBlinkIdCount = _modelSetting->GetEyeBlinkParameterCount();
-- for (csmInt32 i = 0; i < eyeBlinkIdCount; ++i)
-- {
-- _eyeBlinkIds.PushBack(_modelSetting->GetEyeBlinkParameterId(i));
-- }
-- }
--
- // LipSyncIds
- {
- csmInt32 lipSyncIdCount = _modelSetting->GetLipSyncParameterCount();
//Layout
csmMap<csmString, csmFloat32> layout;
_modelSetting->GetLayoutMap(layout);
-@@ -230,14 +169,6 @@ void LAppModel::SetupModel(ICubismModelS
-
- _model->SaveParameters();
-
-- for (csmInt32 i = 0; i < _modelSetting->GetMotionGroupCount(); i++)
-- {
-- const csmChar* group = _modelSetting->GetMotionGroupName(i);
-- PreloadMotionGroup(group);
-- }
--
-- _motionManager->StopAllMotions();
--
- _updating = false;
- _initialized = true;
- }
-@@ -335,59 +266,29 @@ void LAppModel::Update()
+@@ -335,59 +304,57 @@ void LAppModel::Update()
const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
_userTimeSeconds += deltaTimeSeconds;
- StartRandomMotion(MotionGroupIdle, PriorityIdle);
- }
- else
-- {
++ if (_detector)
+ {
- motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
- }
- _model->SaveParameters(); // 状態を保存
- //-----------------------------------------------------------------
--
++ auto idMan = CubismFramework::GetIdManager();
++ auto params = _detector->getParams();
+
- // まばたき
- if (!motionUpdated)
- {
- if (_eyeBlink != NULL)
-- {
++ // NOTE: Apparently, this LoadParameters/SaveParameters pair
++ // is needed for auto breath to work.
++ _model->LoadParameters(); // 前回セーブされた状態をロード
++ if (_motionManager->IsFinished() && params.randomMotion)
+ {
- // メインモーションの更新がないとき
- _eyeBlink->UpdateParameters(_model, deltaTimeSeconds); // 目パチ
-- }
++ // モーションの再生がない場合、待機モーションの中からランダムで再生する
++ StartRandomMotion(MotionGroupIdle, PriorityIdle);
+ }
- }
-
- if (_expressionManager != NULL)
-+ if (_detector)
- {
+- {
- _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
- }
-
-
- //ドラッグによる体の向きの調整
- _model->AddParameterValue(_idParamBodyAngleX, _dragX * 10); // -10から10の値を加える
--
++ else
++ {
++ _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
++ }
++ _model->SaveParameters(); // 状態を保存
+
- //ドラッグによる目の向きの調整
- _model->AddParameterValue(_idParamEyeBallX, _dragX); // -1から1の値を加える
- _model->AddParameterValue(_idParamEyeBallY, _dragY);
-+ auto idMan = CubismFramework::GetIdManager();
-+ auto params = _detector->getParams();
- // 呼吸など
- if (_breath != NULL)
- {
- _breath->UpdateParameters(_model, deltaTimeSeconds);
-+ _model->SetParameterValue(idMan->GetId("ParamEyeLOpen"),
-+ params.leftEyeOpenness);
-+ _model->SetParameterValue(idMan->GetId("ParamEyeROpen"),
-+ params.rightEyeOpenness);
++ if (params.autoBlink && _eyeBlink)
++ {
++ _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
++ }
++ else
++ {
++ _model->SetParameterValue(idMan->GetId("ParamEyeLOpen"),
++ params.leftEyeOpenness);
++ _model->SetParameterValue(idMan->GetId("ParamEyeROpen"),
++ params.rightEyeOpenness);
++ }
+ _model->SetParameterValue(idMan->GetId("ParamMouthForm"),
+ params.mouthForm);
+ _model->SetParameterValue(idMan->GetId("ParamMouthOpenY"),
+ params.faceYAngle);
+ _model->SetParameterValue(idMan->GetId("ParamAngleZ"),
+ params.faceZAngle);
++ if (params.autoBreath && _breath)
++ {
++ // Note: _model->LoadParameters and SaveParameters is needed
++ // before - see above.
++ _breath->UpdateParameters(_model, deltaTimeSeconds);
++ }
}
// 物理演算の設定
-@@ -396,17 +297,6 @@ void LAppModel::Update()
+@@ -396,17 +363,6 @@ void LAppModel::Update()
_physics->Evaluate(_model, deltaTimeSeconds);
}
// ポーズの設定
if (_pose != NULL)
{
-@@ -626,3 +516,9 @@ Csm::Rendering::CubismOffscreenFrame_Ope
+@@ -626,3 +582,9 @@ Csm::Rendering::CubismOffscreenFrame_Ope
{
return _renderBuffer;
}
+}
+
diff -pruN --exclude build ./demo_clean/src/LAppModel.hpp ./demo_dev/src/LAppModel.hpp
---- ./demo_clean/src/LAppModel.hpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppModel.hpp 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/LAppModel.hpp 2020-07-11 15:40:18.977286166 +0100
@@ -13,6 +13,7 @@
#include <Type/csmRectF.hpp>
diff -pruN --exclude build ./demo_clean/src/LAppPal.cpp ./demo_dev/src/LAppPal.cpp
---- ./demo_clean/src/LAppPal.cpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppPal.cpp 2020-09-27 17:43:12.081477263 +0100
+++ ./demo_dev/src/LAppPal.cpp 2020-07-11 23:29:09.084910139 +0100
@@ -6,6 +6,7 @@
*/
}
file.read(buf, size);
diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.cpp ./demo_dev/src/LAppTextureManager.cpp
---- ./demo_clean/src/LAppTextureManager.cpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppTextureManager.cpp 2020-09-27 17:43:12.085477268 +0100
+++ ./demo_dev/src/LAppTextureManager.cpp 2020-07-11 22:22:18.004965003 +0100
@@ -96,6 +96,46 @@ LAppTextureManager::TextureInfo* LAppTex
{
for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++)
diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.hpp ./demo_dev/src/LAppTextureManager.hpp
---- ./demo_clean/src/LAppTextureManager.hpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppTextureManager.hpp 2020-09-27 17:43:12.069477246 +0100
+++ ./demo_dev/src/LAppTextureManager.hpp 2020-07-11 17:36:31.180131039 +0100
@@ -72,6 +72,8 @@ public:
*/
* @brief 画像の解放
*
diff -pruN --exclude build ./demo_clean/src/LAppView.cpp ./demo_dev/src/LAppView.cpp
---- ./demo_clean/src/LAppView.cpp 2020-07-12 16:16:34.003809759 +0100
+--- ./demo_clean/src/LAppView.cpp 2020-09-27 17:43:12.085477268 +0100
+++ ./demo_dev/src/LAppView.cpp 2020-07-11 17:38:06.905451955 +0100
@@ -13,7 +13,6 @@
#include "LAppLive2DManager.hpp"
- }
}
diff -pruN --exclude build ./demo_clean/src/LAppView.hpp ./demo_dev/src/LAppView.hpp
---- ./demo_clean/src/LAppView.hpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/LAppView.hpp 2020-09-27 17:43:12.069477246 +0100
+++ ./demo_dev/src/LAppView.hpp 2020-07-11 17:38:25.541708705 +0100
@@ -14,7 +14,6 @@
#include "CubismFramework.hpp"
// レンダリング先を別ターゲットにする方式の場合に使用
LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画
diff -pruN --exclude build ./demo_clean/src/main.cpp ./demo_dev/src/main.cpp
---- ./demo_clean/src/main.cpp 2020-07-12 16:16:33.999809687 +0100
+--- ./demo_clean/src/main.cpp 2020-09-27 17:43:12.069477246 +0100
+++ ./demo_dev/src/main.cpp 2020-07-12 15:06:29.194034887 +0100
@@ -5,18 +5,156 @@
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.