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