Remove my OSF fork from README (merged upstream)
[facial-landmarks-for-cubism.git] / example / demo.patch
... / ...
CommitLineData
1diff -pruN --exclude build ./demo_clean/CMakeLists.txt ./demo_dev/CMakeLists.txt
2--- ./demo_clean/CMakeLists.txt 2021-02-17 01:23:17.000000000 +0000
3+++ ./demo_dev/CMakeLists.txt 2021-05-16 01:44:30.838853280 +0100
4@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
5 # Set app name.
6 set(APP_NAME Demo)
7 # Set directory paths.
8-set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
9+set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../CubismSdkForNative-4-r.2)
10 set(CORE_PATH ${SDK_ROOT_PATH}/Core)
11 set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework)
12 set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/thirdParty)
13@@ -32,7 +32,7 @@ set(GLFW_INSTALL OFF CACHE BOOL "" FORCE
14 set(BUILD_UTILS OFF CACHE BOOL "" FORCE)
15
16 # Specify version of compiler.
17-set(CMAKE_CXX_STANDARD 14)
18+set(CMAKE_CXX_STANDARD 17)
19 set(CMAKE_CXX_STANDARD_REQUIRED ON)
20 set(CMAKE_CXX_EXTENSIONS OFF)
21
22@@ -64,6 +64,9 @@ target_link_libraries(Framework Live2DCu
23 # Find opengl libraries.
24 find_package(OpenGL REQUIRED)
25
26+# Add FacialLandmarksForCubism
27+add_subdirectory(../.. FacialLandmarksForCubism_build)
28+
29 # Make executable app.
30 add_executable(${APP_NAME})
31 # Add source files.
32@@ -73,9 +76,11 @@ target_link_libraries(${APP_NAME}
33 Framework
34 glfw
35 ${OPENGL_LIBRARIES}
36+ FacialLandmarksForCubism
37+ stdc++fs
38 )
39 # Specify include directories.
40-target_include_directories(${APP_NAME} PRIVATE ${STB_PATH})
41+target_include_directories(${APP_NAME} PRIVATE ${STB_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
42
43 # Copy resource directory to build directory.
44 add_custom_command(
45diff -pruN --exclude build ./demo_clean/scripts/make_gcc ./demo_dev/scripts/make_gcc
46--- ./demo_clean/scripts/make_gcc 2021-02-17 01:23:17.000000000 +0000
47+++ ./demo_dev/scripts/make_gcc 2021-05-29 02:04:17.338257917 +0100
48@@ -10,4 +10,4 @@ BUILD_PATH=$SCRIPT_PATH/../build/make_gc
49 cmake -S "$CMAKE_PATH" \
50 -B "$BUILD_PATH" \
51 -D CMAKE_BUILD_TYPE=Release
52-cd "$BUILD_PATH" && make
53+cd "$BUILD_PATH" && make -j4
54diff -pruN --exclude build ./demo_clean/src/CMakeLists.txt ./demo_dev/src/CMakeLists.txt
55--- ./demo_clean/src/CMakeLists.txt 2021-02-17 01:23:17.000000000 +0000
56+++ ./demo_dev/src/CMakeLists.txt 2021-04-28 11:49:43.166296000 +0100
57@@ -6,8 +6,6 @@ target_sources(${APP_NAME}
58 ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.hpp
59 ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp
60 ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp
61- ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.cpp
62- ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.hpp
63 ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.cpp
64 ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.hpp
65 ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.cpp
66@@ -21,6 +19,4 @@ target_sources(${APP_NAME}
67 ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp
68 ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.hpp
69 ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
70- ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp
71- ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp
72 )
73diff -pruN --exclude build ./demo_clean/src/LAppDelegate.cpp ./demo_dev/src/LAppDelegate.cpp
74--- ./demo_clean/src/LAppDelegate.cpp 2021-02-17 01:23:17.000000000 +0000
75+++ ./demo_dev/src/LAppDelegate.cpp 2021-04-28 11:49:43.166296000 +0100
76@@ -45,7 +45,8 @@ void LAppDelegate::ReleaseInstance()
77 s_instance = NULL;
78 }
79
80-bool LAppDelegate::Initialize()
81+bool LAppDelegate::Initialize(int initWindowWidth, int initWindowHeight,
82+ const char *windowTitle)
83 {
84 if (DebugLogEnable)
85 {
86@@ -63,7 +64,13 @@ bool LAppDelegate::Initialize()
87 }
88
89 // Windowの生成_
90- _window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL);
91+ _window = glfwCreateWindow(
92+ initWindowWidth ? initWindowWidth : RenderTargetWidth,
93+ initWindowHeight ? initWindowHeight : RenderTargetHeight,
94+ windowTitle ? windowTitle : "SAMPLE",
95+ NULL,
96+ NULL);
97+
98 if (_window == NULL)
99 {
100 if (DebugLogEnable)
101@@ -95,10 +102,6 @@ bool LAppDelegate::Initialize()
102 glEnable(GL_BLEND);
103 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
104
105- //コールバック関数の登録
106- glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack);
107- glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack);
108-
109 // ウィンドウサイズ記憶
110 int width, height;
111 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
112@@ -111,8 +114,6 @@ bool LAppDelegate::Initialize()
113 // Cubism3の初期化
114 InitializeCubism();
115
116- SetRootDirectory();
117-
118 //load model
119 LAppLive2DManager::GetInstance();
120
121@@ -214,49 +215,6 @@ void LAppDelegate::InitializeCubism()
122 LAppPal::UpdateTime();
123 }
124
125-void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify)
126-{
127- if (_view == NULL)
128- {
129- return;
130- }
131- if (GLFW_MOUSE_BUTTON_LEFT != button)
132- {
133- return;
134- }
135-
136- if (GLFW_PRESS == action)
137- {
138- _captured = true;
139- _view->OnTouchesBegan(_mouseX, _mouseY);
140- }
141- else if (GLFW_RELEASE == action)
142- {
143- if (_captured)
144- {
145- _captured = false;
146- _view->OnTouchesEnded(_mouseX, _mouseY);
147- }
148- }
149-}
150-
151-void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y)
152-{
153- _mouseX = static_cast<float>(x);
154- _mouseY = static_cast<float>(y);
155-
156- if (!_captured)
157- {
158- return;
159- }
160- if (_view == NULL)
161- {
162- return;
163- }
164-
165- _view->OnTouchesMoved(_mouseX, _mouseY);
166-}
167-
168 GLuint LAppDelegate::CreateShader()
169 {
170 //バーテックスシェーダのコンパイル
171@@ -299,29 +257,9 @@ GLuint LAppDelegate::CreateShader()
172 return programId;
173 }
174
175-void LAppDelegate::SetRootDirectory()
176+void LAppDelegate::SetRootDirectory(std::string rootDir)
177 {
178- char path[1024];
179- ssize_t len = readlink("/proc/self/exe", path, 1024 - 1);
180-
181- if (len != -1)
182- {
183- path[len] = '\0';
184- }
185-
186- std::string pathString(path);
187-
188- pathString = pathString.substr(0, pathString.rfind("Demo"));
189- Csm::csmVector<string> splitStrings = this->Split(pathString, '/');
190-
191- this->_rootDirectory = "";
192-
193- for(int i = 0; i < splitStrings.GetSize(); i++)
194- {
195- this->_rootDirectory = this->_rootDirectory + "/" +splitStrings[i];
196- }
197-
198- this->_rootDirectory += "/";
199+ this->_rootDirectory = rootDir + "/";
200 }
201
202 Csm::csmVector<string> LAppDelegate::Split(const std::string& baseString, char delimiter)
203diff -pruN --exclude build ./demo_clean/src/LAppDelegate.hpp ./demo_dev/src/LAppDelegate.hpp
204--- ./demo_clean/src/LAppDelegate.hpp 2021-02-17 01:23:17.000000000 +0000
205+++ ./demo_dev/src/LAppDelegate.hpp 2021-04-28 11:49:43.166296000 +0100
206@@ -40,7 +40,8 @@ public:
207 /**
208 * @brief APPに必要なものを初期化する。
209 */
210- bool Initialize();
211+ bool Initialize(int initWindowWidth = 0, int initWindowHeight = 0,
212+ const char *windowTitle = "SAMPLE");
213
214 /**
215 * @brief 解放する。
216@@ -53,25 +54,6 @@ public:
217 void Run();
218
219 /**
220- * @brief OpenGL用 glfwSetMouseButtonCallback用関数。
221- *
222- * @param[in] window コールバックを呼んだWindow情報
223- * @param[in] button ボタン種類
224- * @param[in] action 実行結果
225- * @param[in] modify
226- */
227- void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify);
228-
229- /**
230- * @brief OpenGL用 glfwSetCursorPosCallback用関数。
231- *
232- * @param[in] window コールバックを呼んだWindow情報
233- * @param[in] x x座標
234- * @param[in] y x座標
235- */
236- void OnMouseCallBack(GLFWwindow* window, double x, double y);
237-
238- /**
239 * @brief シェーダーを登録する。
240 */
241 GLuint CreateShader();
242@@ -98,8 +80,10 @@ public:
243
244 /**
245 * @brief ルートディレクトリを設定する。
246+ *
247+ * @param[in] rootDir : The root directory to set to.
248 */
249- void SetRootDirectory();
250+ void SetRootDirectory(std::string rootDir);
251
252 /**
253 * @brief ルートディレクトリを取得する。
254@@ -146,24 +130,3 @@ private:
255 int _windowWidth; ///< Initialize関数で設定したウィンドウ幅
256 int _windowHeight; ///< Initialize関数で設定したウィンドウ高さ
257 };
258-
259-class EventHandler
260-{
261-public:
262- /**
263- * @brief glfwSetMouseButtonCallback用コールバック関数。
264- */
265- static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify)
266- {
267- LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify);
268- }
269-
270- /**
271- * @brief glfwSetCursorPosCallback用コールバック関数。
272- */
273- static void OnMouseCallBack(GLFWwindow* window, double x, double y)
274- {
275- LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y);
276- }
277-
278-};
279diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.cpp ./demo_dev/src/LAppLive2DManager.cpp
280--- ./demo_clean/src/LAppLive2DManager.cpp 2021-02-17 01:23:17.000000000 +0000
281+++ ./demo_dev/src/LAppLive2DManager.cpp 2021-04-28 11:49:43.166296000 +0100
282@@ -52,11 +52,11 @@ void LAppLive2DManager::ReleaseInstance(
283
284 LAppLive2DManager::LAppLive2DManager()
285 : _viewMatrix(NULL)
286- , _sceneIndex(0)
287+ , _projScaleFactor(1.0f)
288+ , _translateX(0.0f)
289+ , _translateY(0.0f)
290 {
291 _viewMatrix = new CubismMatrix44();
292-
293- ChangeScene(_sceneIndex);
294 }
295
296 LAppLive2DManager::~LAppLive2DManager()
297@@ -100,26 +100,6 @@ void LAppLive2DManager::OnTap(csmFloat32
298 {
299 LAppPal::PrintLog("[APP]tap point: {x:%.2f y:%.2f}", x, y);
300 }
301-
302- for (csmUint32 i = 0; i < _models.GetSize(); i++)
303- {
304- if (_models[i]->HitTest(HitAreaNameHead, x, y))
305- {
306- if (DebugLogEnable)
307- {
308- LAppPal::PrintLog("[APP]hit area: [%s]", HitAreaNameHead);
309- }
310- _models[i]->SetRandomExpression();
311- }
312- else if (_models[i]->HitTest(HitAreaNameBody, x, y))
313- {
314- if (DebugLogEnable)
315- {
316- LAppPal::PrintLog("[APP]hit area: [%s]", HitAreaNameBody);
317- }
318- _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion);
319- }
320- }
321 }
322
323 void LAppLive2DManager::OnUpdate() const
324@@ -136,12 +116,15 @@ void LAppLive2DManager::OnUpdate() const
325 {
326 // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する
327 model->GetModelMatrix()->SetWidth(2.0f);
328- projection.Scale(1.0f, static_cast<float>(width) / static_cast<float>(height));
329+ projection.Scale(_projScaleFactor,
330+ _projScaleFactor * static_cast<float>(width) / static_cast<float>(height));
331 }
332 else
333 {
334- projection.Scale(static_cast<float>(height) / static_cast<float>(width), 1.0f);
335+ projection.Scale(_projScaleFactor * static_cast<float>(height) / static_cast<float>(width),
336+ _projScaleFactor);
337 }
338+ projection.Translate(_translateX, _translateY);
339
340 // 必要があればここで乗算
341 if (_viewMatrix != NULL)
342@@ -158,30 +141,14 @@ void LAppLive2DManager::OnUpdate() const
343 }
344 }
345
346-void LAppLive2DManager::NextScene()
347-{
348- csmInt32 no = (_sceneIndex + 1) % ModelDirSize;
349- ChangeScene(no);
350-}
351-
352-void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
353+void LAppLive2DManager::SetModel(std::string modelName, bool useOldParamId)
354 {
355- _sceneIndex = index;
356- if (DebugLogEnable)
357- {
358- LAppPal::PrintLog("[APP]model index: %d", _sceneIndex);
359- }
360-
361- // ModelDir[]に保持したディレクトリ名から
362- // model3.jsonのパスを決定する.
363- // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
364- std::string model = ModelDir[index];
365- std::string modelPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath + model + "/";
366- std::string modelJsonName = ModelDir[index];
367+ std::string modelPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath + modelName + "/";
368+ std::string modelJsonName = modelName;
369 modelJsonName += ".model3.json";
370
371 ReleaseAllModel();
372- _models.PushBack(new LAppModel());
373+ _models.PushBack(new LAppModel(useOldParamId));
374 _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
375
376 /*
377@@ -203,7 +170,7 @@ void LAppLive2DManager::ChangeScene(Csm:
378
379 #if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
380 // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
381- _models.PushBack(new LAppModel());
382+ _models.PushBack(new LAppModel(useOldParamId));
383 _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
384 _models[1]->GetModelMatrix()->TranslateX(0.2f);
385 #endif
386@@ -232,3 +199,20 @@ void LAppLive2DManager::SetViewMatrix(Cu
387 _viewMatrix->GetArray()[i] = m->GetArray()[i];
388 }
389 }
390+
391+void LAppLive2DManager::SetFacialLandmarkDetector(FacialLandmarkDetector *detector)
392+{
393+ for (auto it = _models.Begin(); it != _models.End(); ++it)
394+ {
395+ (*it)->SetFacialLandmarkDetector(detector);
396+ }
397+}
398+
399+void LAppLive2DManager::SetProjectionScaleTranslate(float scaleFactor,
400+ float translateX,
401+ float translateY)
402+{
403+ _projScaleFactor = scaleFactor;
404+ _translateX = translateX;
405+ _translateY = translateY;
406+}
407diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.hpp ./demo_dev/src/LAppLive2DManager.hpp
408--- ./demo_clean/src/LAppLive2DManager.hpp 2021-02-17 01:23:17.000000000 +0000
409+++ ./demo_dev/src/LAppLive2DManager.hpp 2021-04-28 11:49:43.166296000 +0100
410@@ -6,12 +6,15 @@
411 */
412 #pragma once
413
414+#include <string>
415 #include <CubismFramework.hpp>
416 #include <Math/CubismMatrix44.hpp>
417 #include <Type/csmVector.hpp>
418
419 class LAppModel;
420
421+class FacialLandmarkDetector;
422+
423 /**
424 * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス<br>
425 * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。
426@@ -72,16 +75,14 @@ public:
427 void OnUpdate() const;
428
429 /**
430- * @brief 次のシーンに切り替える<br>
431- * サンプルアプリケーションではモデルセットの切り替えを行う。
432- */
433- void NextScene();
434-
435- /**
436- * @brief シーンを切り替える<br>
437- * サンプルアプリケーションではモデルセットの切り替えを行う。
438- */
439- void ChangeScene(Csm::csmInt32 index);
440+ * @brief Set model data
441+ *
442+ * @param[in] modelName : Name of model, should be the same for both
443+ * the directory and the model3.json file
444+ * @param[in] useOldParamId : If true, translate new (Cubism 3+)
445+ * parameter IDs to old (Cubism 2.1) ones
446+ */
447+ void SetModel(std::string modelName, bool useOldParamId);
448
449 /**
450 * @brief モデル個数を得る
451@@ -94,6 +95,24 @@ public:
452 */
453 void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m);
454
455+ /**
456+ * @brief Set the pointer to the FacialLandmarkDetector instance
457+ *
458+ * @param[in] detector : Pointer to FacialLandmarkDetector instance
459+ */
460+ void SetFacialLandmarkDetector(FacialLandmarkDetector *detector);
461+
462+ /**
463+ * @brief Set projection scale factor and translation parameters
464+ *
465+ * @param[in] scaleFactor : Scale factor applied in both X and Y directions
466+ * @param[in] translateX : Translation in X direction
467+ * @param[in] translateY : Translation in Y direction
468+ */
469+ void SetProjectionScaleTranslate(float scaleFactor,
470+ float translateX,
471+ float translateY);
472+
473 private:
474 /**
475 * @brief コンストラクタ
476@@ -107,5 +126,8 @@ private:
477
478 Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列
479 Csm::csmVector<LAppModel*> _models; ///< モデルインスタンスのコンテナ
480- Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値
481+
482+ float _projScaleFactor;
483+ float _translateX;
484+ float _translateY;
485 };
486diff -pruN --exclude build ./demo_clean/src/LAppModel.cpp ./demo_dev/src/LAppModel.cpp
487--- ./demo_clean/src/LAppModel.cpp 2021-02-17 01:23:17.000000000 +0000
488+++ ./demo_dev/src/LAppModel.cpp 2021-04-28 11:49:43.166296000 +0100
489@@ -21,6 +21,8 @@
490 #include "LAppTextureManager.hpp"
491 #include "LAppDelegate.hpp"
492
493+#include "facial_landmark_detector.h"
494+
495 using namespace Live2D::Cubism::Framework;
496 using namespace Live2D::Cubism::Framework::DefaultParameterId;
497 using namespace LAppDefine;
498@@ -45,22 +47,24 @@ namespace {
499 }
500 }
501
502-LAppModel::LAppModel()
503+LAppModel::LAppModel(bool useOldParamId)
504 : CubismUserModel()
505 , _modelSetting(NULL)
506 , _userTimeSeconds(0.0f)
507+ , _detector(nullptr)
508+ , _useOldParamId(useOldParamId)
509 {
510 if (DebugLogEnable)
511 {
512 _debugMode = true;
513 }
514
515- _idParamAngleX = CubismFramework::GetIdManager()->GetId(ParamAngleX);
516- _idParamAngleY = CubismFramework::GetIdManager()->GetId(ParamAngleY);
517- _idParamAngleZ = CubismFramework::GetIdManager()->GetId(ParamAngleZ);
518- _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX);
519- _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX);
520- _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY);
521+ _idParamAngleX = CubismFramework::GetIdManager()->GetId(_(ParamAngleX));
522+ _idParamAngleY = CubismFramework::GetIdManager()->GetId(_(ParamAngleY));
523+ _idParamAngleZ = CubismFramework::GetIdManager()->GetId(_(ParamAngleZ));
524+ _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(_(ParamBodyAngleX));
525+ _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallX));
526+ _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallY));
527 }
528
529 LAppModel::~LAppModel()
530@@ -128,30 +132,6 @@ void LAppModel::SetupModel(ICubismModelS
531 DeleteBuffer(buffer, path.GetRawString());
532 }
533
534- //Expression
535- if (_modelSetting->GetExpressionCount() > 0)
536- {
537- const csmInt32 count = _modelSetting->GetExpressionCount();
538- for (csmInt32 i = 0; i < count; i++)
539- {
540- csmString name = _modelSetting->GetExpressionName(i);
541- csmString path = _modelSetting->GetExpressionFileName(i);
542- path = _modelHomeDir + path;
543-
544- buffer = CreateBuffer(path.GetRawString(), &size);
545- ACubismMotion* motion = LoadExpression(buffer, size, name.GetRawString());
546-
547- if (_expressions[name] != NULL)
548- {
549- ACubismMotion::Delete(_expressions[name]);
550- _expressions[name] = NULL;
551- }
552- _expressions[name] = motion;
553-
554- DeleteBuffer(buffer, path.GetRawString());
555- }
556- }
557-
558 //Physics
559 if (strcmp(_modelSetting->GetPhysicsFileName(), "") != 0)
560 {
561@@ -190,7 +170,7 @@ void LAppModel::SetupModel(ICubismModelS
562 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f));
563 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f));
564 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f));
565- breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f));
566+ breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(_(ParamBreath)), 0.5f, 0.5f, 3.2345f, 0.5f));
567
568 _breath->SetParameters(breathParameters);
569 }
570@@ -214,15 +194,6 @@ void LAppModel::SetupModel(ICubismModelS
571 }
572 }
573
574- // LipSyncIds
575- {
576- csmInt32 lipSyncIdCount = _modelSetting->GetLipSyncParameterCount();
577- for (csmInt32 i = 0; i < lipSyncIdCount; ++i)
578- {
579- _lipSyncIds.PushBack(_modelSetting->GetLipSyncParameterId(i));
580- }
581- }
582-
583 //Layout
584 csmMap<csmString, csmFloat32> layout;
585 _modelSetting->GetLayoutMap(layout);
586@@ -335,59 +306,57 @@ void LAppModel::Update()
587 const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
588 _userTimeSeconds += deltaTimeSeconds;
589
590- _dragManager->Update(deltaTimeSeconds);
591- _dragX = _dragManager->GetX();
592- _dragY = _dragManager->GetY();
593-
594- // モーションによるパラメータ更新の有無
595- csmBool motionUpdated = false;
596-
597- //-----------------------------------------------------------------
598- _model->LoadParameters(); // 前回セーブされた状態をロード
599- if (_motionManager->IsFinished())
600- {
601- // モーションの再生がない場合、待機モーションの中からランダムで再生する
602- StartRandomMotion(MotionGroupIdle, PriorityIdle);
603- }
604- else
605+ if (_detector)
606 {
607- motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
608- }
609- _model->SaveParameters(); // 状態を保存
610- //-----------------------------------------------------------------
611+ auto idMan = CubismFramework::GetIdManager();
612+ auto params = _detector->getParams();
613
614- // まばたき
615- if (!motionUpdated)
616- {
617- if (_eyeBlink != NULL)
618+ // NOTE: Apparently, this LoadParameters/SaveParameters pair
619+ // is needed for auto breath to work.
620+ _model->LoadParameters(); // 前回セーブされた状態をロード
621+ if (_motionManager->IsFinished() && params.randomMotion)
622 {
623- // メインモーションの更新がないとき
624- _eyeBlink->UpdateParameters(_model, deltaTimeSeconds); // 目パチ
625+ // モーションの再生がない場合、待機モーションの中からランダムで再生する
626+ StartRandomMotion(MotionGroupIdle, PriorityIdle);
627 }
628- }
629-
630- if (_expressionManager != NULL)
631- {
632- _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
633- }
634-
635- //ドラッグによる変化
636- //ドラッグによる顔の向きの調整
637- _model->AddParameterValue(_idParamAngleX, _dragX * 30); // -30から30の値を加える
638- _model->AddParameterValue(_idParamAngleY, _dragY * 30);
639- _model->AddParameterValue(_idParamAngleZ, _dragX * _dragY * -30);
640-
641- //ドラッグによる体の向きの調整
642- _model->AddParameterValue(_idParamBodyAngleX, _dragX * 10); // -10から10の値を加える
643+ else
644+ {
645+ _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
646+ }
647+ _model->SaveParameters(); // 状態を保存
648
649- //ドラッグによる目の向きの調整
650- _model->AddParameterValue(_idParamEyeBallX, _dragX); // -1から1の値を加える
651- _model->AddParameterValue(_idParamEyeBallY, _dragY);
652
653- // 呼吸など
654- if (_breath != NULL)
655- {
656- _breath->UpdateParameters(_model, deltaTimeSeconds);
657+ if (params.autoBlink && _eyeBlink)
658+ {
659+ _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
660+ }
661+ else
662+ {
663+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")),
664+ params.leftEyeOpenness);
665+ _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")),
666+ params.rightEyeOpenness);
667+ }
668+ _model->SetParameterValue(idMan->GetId(_("ParamMouthForm")),
669+ params.mouthForm);
670+ _model->SetParameterValue(idMan->GetId(_("ParamMouthOpenY")),
671+ params.mouthOpenness);
672+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLSmile")),
673+ params.leftEyeSmile);
674+ _model->SetParameterValue(idMan->GetId(_("ParamEyeRSmile")),
675+ params.rightEyeSmile);
676+ _model->SetParameterValue(idMan->GetId(_("ParamAngleX")),
677+ params.faceXAngle);
678+ _model->SetParameterValue(idMan->GetId(_("ParamAngleY")),
679+ params.faceYAngle);
680+ _model->SetParameterValue(idMan->GetId(_("ParamAngleZ")),
681+ params.faceZAngle);
682+ if (params.autoBreath && _breath)
683+ {
684+ // Note: _model->LoadParameters and SaveParameters is needed
685+ // before - see above.
686+ _breath->UpdateParameters(_model, deltaTimeSeconds);
687+ }
688 }
689
690 // 物理演算の設定
691@@ -396,22 +365,6 @@ void LAppModel::Update()
692 _physics->Evaluate(_model, deltaTimeSeconds);
693 }
694
695- // リップシンクの設定
696- if (_lipSync)
697- {
698- // リアルタイムでリップシンクを行う場合、システムから音量を取得して0〜1の範囲で値を入力します。
699- csmFloat32 value = 0.0f;
700-
701- // 状態更新/RMS値取得
702- _wavFileHandler.Update(deltaTimeSeconds);
703- value = _wavFileHandler.GetRms();
704-
705- for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
706- {
707- _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
708- }
709- }
710-
711 // ポーズの設定
712 if (_pose != NULL)
713 {
714@@ -480,7 +433,6 @@ CubismMotionQueueEntryHandle LAppModel::
715 {
716 csmString path = voice;
717 path = _modelHomeDir + path;
718- _wavFileHandler.Start(path);
719 }
720
721 if (_debugMode)
722@@ -632,3 +584,37 @@ Csm::Rendering::CubismOffscreenFrame_Ope
723 {
724 return _renderBuffer;
725 }
726+
727+void LAppModel::SetFacialLandmarkDetector(FacialLandmarkDetector *detector)
728+{
729+ _detector = detector;
730+}
731+
732+Csm::csmString LAppModel::_(std::string s)
733+{
734+ std::string ans;
735+ if (_useOldParamId)
736+ {
737+ if (s == "ParamTere")
738+ {
739+ ans = "PARAM_CHEEK";
740+ }
741+ else
742+ {
743+ for (size_t i = 0; i < s.size(); i++)
744+ {
745+ if (std::isupper(s[i]) && i != 0)
746+ {
747+ ans += '_';
748+ }
749+ ans += std::toupper(s[i]);
750+ }
751+ }
752+ }
753+ else
754+ {
755+ ans = s;
756+ }
757+ return csmString(ans.c_str());
758+}
759+
760diff -pruN --exclude build ./demo_clean/src/LAppModel.hpp ./demo_dev/src/LAppModel.hpp
761--- ./demo_clean/src/LAppModel.hpp 2021-02-17 01:23:17.000000000 +0000
762+++ ./demo_dev/src/LAppModel.hpp 2021-04-28 11:49:43.166296000 +0100
763@@ -13,7 +13,7 @@
764 #include <Type/csmRectF.hpp>
765 #include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
766
767-#include "LAppWavFileHandler.hpp"
768+#include "facial_landmark_detector.h"
769
770 /**
771 * @brief ユーザーが実際に使用するモデルの実装クラス<br>
772@@ -25,8 +25,11 @@ class LAppModel : public Csm::CubismUser
773 public:
774 /**
775 * @brief コンストラクタ
776+ *
777+ * @param[in] useOldParamId : If true, translate new (Cubism 3+)
778+ * parameter IDs to old (Cubism 2.1) ones
779 */
780- LAppModel();
781+ LAppModel(bool useOldParamId);
782
783 /**
784 * @brief デストラクタ
785@@ -114,6 +117,13 @@ public:
786 */
787 Csm::Rendering::CubismOffscreenFrame_OpenGLES2& GetRenderBuffer();
788
789+ /**
790+ * @brief Set the pointer to the FacialLandmarkDetector instance
791+ *
792+ * @param[in] detector : Pointer to FacialLandmarkDetector instance
793+ */
794+ void SetFacialLandmarkDetector(FacialLandmarkDetector *detector);
795+
796 protected:
797 /**
798 * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
799@@ -167,6 +177,17 @@ private:
800 */
801 void ReleaseExpressions();
802
803+ /**
804+ * @brief Translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) ones
805+ *
806+ * @param[in] s : New parameter ID
807+ *
808+ * @return Old parameter ID
809+ */
810+ Csm::csmString _(std::string s);
811+
812+ bool _useOldParamId;
813+
814 Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報
815 Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ
816 Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
817@@ -183,9 +204,9 @@ private:
818 const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX
819 const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY
820
821- LAppWavFileHandler _wavFileHandler; ///< wavファイルハンドラ
822-
823 Csm::Rendering::CubismOffscreenFrame_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
824+
825+ FacialLandmarkDetector *_detector;
826 };
827
828
829diff -pruN --exclude build ./demo_clean/src/LAppPal.cpp ./demo_dev/src/LAppPal.cpp
830--- ./demo_clean/src/LAppPal.cpp 2021-02-17 01:23:17.000000000 +0000
831+++ ./demo_dev/src/LAppPal.cpp 2021-04-28 11:49:43.170296000 +0100
832@@ -6,6 +6,7 @@
833 */
834
835 #include "LAppPal.hpp"
836+#include <stdexcept>
837 #include <stdio.h>
838 #include <stdlib.h>
839 #include <stdarg.h>
840@@ -45,10 +46,7 @@ csmByte* LAppPal::LoadFileAsBytes(const
841 file.open(path, std::ios::in | std::ios::binary);
842 if (!file.is_open())
843 {
844- if (DebugLogEnable)
845- {
846- PrintLog("file open error");
847- }
848+ throw std::runtime_error("Failed to open file " + filePath);
849 return NULL;
850 }
851 file.read(buf, size);
852diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.cpp ./demo_dev/src/LAppTextureManager.cpp
853--- ./demo_clean/src/LAppTextureManager.cpp 2021-02-17 01:23:17.000000000 +0000
854+++ ./demo_dev/src/LAppTextureManager.cpp 2021-04-28 11:49:43.178296000 +0100
855@@ -96,6 +96,46 @@ LAppTextureManager::TextureInfo* LAppTex
856
857 }
858
859+LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromColor(
860+ uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha
861+)
862+{
863+ int width = 8, height = 8;
864+
865+ uint8_t pixels[height][width][4];
866+ for (std::size_t h = 0; h < height; h++)
867+ {
868+ for (std::size_t w = 0; w < width; w++)
869+ {
870+ pixels[h][w][0] = red;
871+ pixels[h][w][1] = green;
872+ pixels[h][w][2] = blue;
873+ pixels[h][w][3] = alpha;
874+ }
875+ }
876+
877+ GLuint textureId;
878+ glGenTextures(1, &textureId);
879+ glBindTexture(GL_TEXTURE_2D, textureId);
880+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
881+
882+ glGenerateMipmap(GL_TEXTURE_2D);
883+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
884+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
885+ glBindTexture(GL_TEXTURE_2D, 0);
886+
887+
888+ LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo();
889+ textureInfo->fileName = "";
890+ textureInfo->width = width;
891+ textureInfo->height = height;
892+ textureInfo->id = textureId;
893+
894+ _textures.PushBack(textureInfo);
895+
896+ return textureInfo;
897+}
898+
899 void LAppTextureManager::ReleaseTextures()
900 {
901 for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++)
902diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.hpp ./demo_dev/src/LAppTextureManager.hpp
903--- ./demo_clean/src/LAppTextureManager.hpp 2021-02-17 01:23:17.000000000 +0000
904+++ ./demo_dev/src/LAppTextureManager.hpp 2021-04-28 11:49:43.178296000 +0100
905@@ -72,6 +72,8 @@ public:
906 */
907 TextureInfo* CreateTextureFromPngFile(std::string fileName);
908
909+ TextureInfo *CreateTextureFromColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255);
910+
911 /**
912 * @brief 画像の解放
913 *
914diff -pruN --exclude build ./demo_clean/src/LAppView.cpp ./demo_dev/src/LAppView.cpp
915--- ./demo_clean/src/LAppView.cpp 2021-02-17 01:23:17.000000000 +0000
916+++ ./demo_dev/src/LAppView.cpp 2021-04-28 11:49:43.178296000 +0100
917@@ -13,7 +13,6 @@
918 #include "LAppLive2DManager.hpp"
919 #include "LAppTextureManager.hpp"
920 #include "LAppDefine.hpp"
921-#include "TouchManager.hpp"
922 #include "LAppSprite.hpp"
923 #include "LAppModel.hpp"
924
925@@ -26,8 +25,6 @@ using namespace LAppDefine;
926 LAppView::LAppView():
927 _programId(0),
928 _back(NULL),
929- _gear(NULL),
930- _power(NULL),
931 _renderSprite(NULL),
932 _renderTarget(SelectTarget_None)
933 {
934@@ -35,8 +32,6 @@ LAppView::LAppView():
935 _clearColor[1] = 1.0f;
936 _clearColor[2] = 1.0f;
937 _clearColor[3] = 0.0f;
938- // タッチ関係のイベント管理
939- _touchManager = new TouchManager();
940
941 // デバイス座標からスクリーン座標に変換するための
942 _deviceToScreen = new CubismMatrix44();
943@@ -52,10 +47,7 @@ LAppView::~LAppView()
944
945 delete _viewMatrix;
946 delete _deviceToScreen;
947- delete _touchManager;
948 delete _back;
949- delete _gear;
950- delete _power;
951 }
952
953 void LAppView::Initialize()
954@@ -107,9 +99,6 @@ void LAppView::Initialize()
955 void LAppView::Render()
956 {
957 _back->Render();
958- _gear->Render();
959- _power->Render();
960-
961
962 LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
963
964@@ -151,35 +140,17 @@ void LAppView::InitializeSprite()
965 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
966
967 LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager();
968- const string resourcesPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath;
969
970- string imageName = BackImageName;
971- LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
972+
973+ LAppTextureManager::TextureInfo* backgroundTexture =
974+ textureManager->CreateTextureFromColor(0, 255, 0);
975
976 float x = width * 0.5f;
977 float y = height * 0.5f;
978- float fWidth = static_cast<float>(backgroundTexture->width * 2.0f);
979- float fHeight = static_cast<float>(height) * 0.95f;
980+ float fWidth = static_cast<float>(width);
981+ float fHeight = static_cast<float>(height);
982 _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId);
983
984- imageName = GearImageName;
985- LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
986-
987- x = static_cast<float>(width - gearTexture->width * 0.5f);
988- y = static_cast<float>(height - gearTexture->height * 0.5f);
989- fWidth = static_cast<float>(gearTexture->width);
990- fHeight = static_cast<float>(gearTexture->height);
991- _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId);
992-
993- imageName = PowerImageName;
994- LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
995-
996- x = static_cast<float>(width - powerTexture->width * 0.5f);
997- y = static_cast<float>(powerTexture->height * 0.5f);
998- fWidth = static_cast<float>(powerTexture->width);
999- fHeight = static_cast<float>(powerTexture->height);
1000- _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId);
1001-
1002 // 画面全体を覆うサイズ
1003 x = width * 0.5f;
1004 y = height * 0.5f;
1005@@ -187,52 +158,6 @@ void LAppView::InitializeSprite()
1006
1007 }
1008
1009-void LAppView::OnTouchesBegan(float px, float py) const
1010-{
1011- _touchManager->TouchesBegan(px, py);
1012-}
1013-
1014-void LAppView::OnTouchesMoved(float px, float py) const
1015-{
1016- float viewX = this->TransformViewX(_touchManager->GetX());
1017- float viewY = this->TransformViewY(_touchManager->GetY());
1018-
1019- _touchManager->TouchesMoved(px, py);
1020-
1021- LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
1022- Live2DManager->OnDrag(viewX, viewY);
1023-}
1024-
1025-void LAppView::OnTouchesEnded(float px, float py) const
1026-{
1027- // タッチ終了
1028- LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance();
1029- live2DManager->OnDrag(0.0f, 0.0f);
1030- {
1031-
1032- // シングルタップ
1033- float x = _deviceToScreen->TransformX(_touchManager->GetX()); // 論理座標変換した座標を取得。
1034- float y = _deviceToScreen->TransformY(_touchManager->GetY()); // 論理座標変換した座標を取得。
1035- if (DebugTouchLogEnable)
1036- {
1037- LAppPal::PrintLog("[APP]touchesEnded x:%.2f y:%.2f", x, y);
1038- }
1039- live2DManager->OnTap(x, y);
1040-
1041- // 歯車にタップしたか
1042- if (_gear->IsHit(px, py))
1043- {
1044- live2DManager->NextScene();
1045- }
1046-
1047- // 電源ボタンにタップしたか
1048- if (_power->IsHit(px, py))
1049- {
1050- LAppDelegate::GetInstance()->AppEnd();
1051- }
1052- }
1053-}
1054-
1055 float LAppView::TransformViewX(float deviceX) const
1056 {
1057 float screenX = _deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。
1058@@ -374,32 +299,4 @@ void LAppView::ResizeSprite()
1059 _back->ResetRect(x, y, fWidth, fHeight);
1060 }
1061 }
1062-
1063- if (_power)
1064- {
1065- GLuint id = _power->GetTextureId();
1066- LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
1067- if (texInfo)
1068- {
1069- x = static_cast<float>(width - texInfo->width * 0.5f);
1070- y = static_cast<float>(texInfo->height * 0.5f);
1071- fWidth = static_cast<float>(texInfo->width);
1072- fHeight = static_cast<float>(texInfo->height);
1073- _power->ResetRect(x, y, fWidth, fHeight);
1074- }
1075- }
1076-
1077- if (_gear)
1078- {
1079- GLuint id = _gear->GetTextureId();
1080- LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
1081- if (texInfo)
1082- {
1083- x = static_cast<float>(width - texInfo->width * 0.5f);
1084- y = static_cast<float>(height - texInfo->height * 0.5f);
1085- fWidth = static_cast<float>(texInfo->width);
1086- fHeight = static_cast<float>(texInfo->height);
1087- _gear->ResetRect(x, y, fWidth, fHeight);
1088- }
1089- }
1090 }
1091diff -pruN --exclude build ./demo_clean/src/LAppView.hpp ./demo_dev/src/LAppView.hpp
1092--- ./demo_clean/src/LAppView.hpp 2021-02-17 01:23:17.000000000 +0000
1093+++ ./demo_dev/src/LAppView.hpp 2021-04-28 11:49:43.178296000 +0100
1094@@ -14,7 +14,6 @@
1095 #include "CubismFramework.hpp"
1096 #include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
1097
1098-class TouchManager;
1099 class LAppSprite;
1100 class LAppModel;
1101
1102@@ -66,30 +65,6 @@ public:
1103 void ResizeSprite();
1104
1105 /**
1106- * @brief タッチされたときに呼ばれる。
1107- *
1108- * @param[in] pointX スクリーンX座標
1109- * @param[in] pointY スクリーンY座標
1110- */
1111- void OnTouchesBegan(float pointX, float pointY) const;
1112-
1113- /**
1114- * @brief タッチしているときにポインタが動いたら呼ばれる。
1115- *
1116- * @param[in] pointX スクリーンX座標
1117- * @param[in] pointY スクリーンY座標
1118- */
1119- void OnTouchesMoved(float pointX, float pointY) const;
1120-
1121- /**
1122- * @brief タッチが終了したら呼ばれる。
1123- *
1124- * @param[in] pointX スクリーンX座標
1125- * @param[in] pointY スクリーンY座標
1126- */
1127- void OnTouchesEnded(float pointX, float pointY) const;
1128-
1129- /**
1130 * @brief X座標をView座標に変換する。
1131 *
1132 * @param[in] deviceX デバイスX座標
1133@@ -147,13 +122,10 @@ public:
1134 void SetRenderTargetClearColor(float r, float g, float b);
1135
1136 private:
1137- TouchManager* _touchManager; ///< タッチマネージャー
1138 Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列
1139 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix
1140 GLuint _programId; ///< シェーダID
1141 LAppSprite* _back; ///< 背景画像
1142- LAppSprite* _gear; ///< ギア画像
1143- LAppSprite* _power; ///< 電源画像
1144
1145 // レンダリング先を別ターゲットにする方式の場合に使用
1146 LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画
1147diff -pruN --exclude build ./demo_clean/src/main.cpp ./demo_dev/src/main.cpp
1148--- ./demo_clean/src/main.cpp 2021-02-17 01:23:17.000000000 +0000
1149+++ ./demo_dev/src/main.cpp 2021-04-28 11:49:43.178296000 +0100
1150@@ -5,18 +5,162 @@
1151 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
1152 */
1153
1154+#include <thread>
1155+#include <stdexcept>
1156+#include <sstream>
1157+
1158+#ifdef __cpp_lib_filesystem
1159+#include <filesystem>
1160+namespace fs = std::filesystem;
1161+#else
1162+#include <experimental/filesystem>
1163+namespace fs = std::experimental::filesystem;
1164+#endif
1165+
1166+
1167 #include "LAppDelegate.hpp"
1168+#include "LAppLive2DManager.hpp"
1169+#include "facial_landmark_detector.h"
1170+
1171+struct CmdArgs
1172+{
1173+ int windowWidth;
1174+ int windowHeight;
1175+ std::string windowTitle;
1176+ std::string rootDir;
1177+ float scaleFactor;
1178+ float translateX;
1179+ float translateY;
1180+ std::string modelName;
1181+ bool oldId; // If true, translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) IDs
1182+ std::string cfgPath; // Path to config file for FacialLandmarkDetector
1183+};
1184+
1185+CmdArgs parseArgv(int argc, char *argv[])
1186+{
1187+ // I think the command-line args are simple enough to not justify using a library...
1188+ CmdArgs cmdArgs;
1189+ // Set default values
1190+ cmdArgs.windowWidth = 600;
1191+ cmdArgs.windowHeight = 600;
1192+ cmdArgs.windowTitle = "FacialLandmarksForCubism example";
1193+ cmdArgs.rootDir = fs::current_path();
1194+ cmdArgs.scaleFactor = 4.5f;
1195+ cmdArgs.translateX = 0.0f;
1196+ cmdArgs.translateY = -3.1f;
1197+ cmdArgs.modelName = "Haru";
1198+ cmdArgs.oldId = false;
1199+ cmdArgs.cfgPath = "";
1200+
1201+ int i = 1;
1202+ while (i < argc)
1203+ {
1204+ std::string arg = argv[i];
1205+ std::stringstream ss;
1206+
1207+ if (arg == "--window-width" || arg == "-W") // capital W for consistency with height
1208+ {
1209+ ss << argv[i + 1];
1210+ if (!(ss >> cmdArgs.windowWidth))
1211+ {
1212+ throw std::runtime_error("Invalid argument for window width");
1213+ }
1214+ }
1215+ else if (arg == "--window-height" || arg == "-H") // avoiding "-h", typically for help
1216+ {
1217+ ss << argv[i + 1];
1218+ if (!(ss >> cmdArgs.windowHeight))
1219+ {
1220+ throw std::runtime_error("Invalid argument for window height");
1221+ }
1222+ }
1223+ else if (arg == "--window-title" || arg == "-t")
1224+ {
1225+ cmdArgs.windowTitle = argv[i + 1];
1226+ }
1227+ else if (arg == "--root-dir" || arg == "-d")
1228+ {
1229+ cmdArgs.rootDir = argv[i + 1];
1230+ }
1231+ else if (arg == "--scale-factor" || arg == "-f")
1232+ {
1233+ ss << argv[i + 1];
1234+ if (!(ss >> cmdArgs.scaleFactor))
1235+ {
1236+ throw std::runtime_error("Invalid argument for scale factor");
1237+ }
1238+ }
1239+ else if (arg == "--translate-x" || arg == "-x")
1240+ {
1241+ ss << argv[i + 1];
1242+ if (!(ss >> cmdArgs.translateX))
1243+ {
1244+ throw std::runtime_error("Invalid argument for translate X");
1245+ }
1246+ }
1247+ else if (arg == "--translate-y" || arg == "-y")
1248+ {
1249+ ss << argv[i + 1];
1250+ if (!(ss >> cmdArgs.translateY))
1251+ {
1252+ throw std::runtime_error("Invalid argument for translate Y");
1253+ }
1254+ }
1255+ else if (arg == "--model" || arg == "-m")
1256+ {
1257+ cmdArgs.modelName = argv[i + 1];
1258+ }
1259+ else if (arg == "--config" || arg == "-c")
1260+ {
1261+ cmdArgs.cfgPath = argv[i + 1];
1262+ }
1263+ else if (arg == "--old-param-id" || arg == "-o")
1264+ {
1265+ cmdArgs.oldId = (argv[i + 1][0] == '1');
1266+ }
1267+ else
1268+ {
1269+ throw std::runtime_error("Unrecognized argument: " + arg);
1270+ }
1271+
1272+ i += 2;
1273+ }
1274+
1275+ return cmdArgs;
1276+}
1277
1278 int main(int argc, char* argv[])
1279 {
1280- // create the application instance
1281- if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE)
1282+ auto cmdArgs = parseArgv(argc, argv);
1283+
1284+ LAppDelegate *delegate = LAppDelegate::GetInstance();
1285+
1286+ if (!delegate->Initialize(cmdArgs.windowWidth,
1287+ cmdArgs.windowHeight,
1288+ cmdArgs.windowTitle.c_str()))
1289 {
1290- return 1;
1291+ throw std::runtime_error("Unable to initialize LAppDelegate");
1292 }
1293
1294- LAppDelegate::GetInstance()->Run();
1295+ delegate->SetRootDirectory(cmdArgs.rootDir);
1296+
1297+ FacialLandmarkDetector detector(cmdArgs.cfgPath);
1298+
1299+ std::thread detectorThread(&FacialLandmarkDetector::mainLoop,
1300+ &detector);
1301+
1302+ LAppLive2DManager *manager = LAppLive2DManager::GetInstance();
1303+ manager->SetModel(cmdArgs.modelName, cmdArgs.oldId);
1304+
1305+ manager->SetProjectionScaleTranslate(cmdArgs.scaleFactor,
1306+ cmdArgs.translateX,
1307+ cmdArgs.translateY);
1308+ manager->SetFacialLandmarkDetector(&detector);
1309+
1310+ delegate->Run();
1311+
1312+ detector.stop();
1313+ detectorThread.join();
1314
1315 return 0;
1316 }
1317-