diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..57de3e2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.bat text eol=crlf +*.rc text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2958703 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Core directory files +/Core/**/*.a +/Core/**/*.bundle +/Core/**/*.dll +/Core/**/*.dylib +/Core/**/*.lib +/Core/**/*.so + +# Sample build directories +/Samples/**/build/ +# Sample third party files +/Samples/**/thirdParty/* +!/Samples/**/thirdParty/scripts/* +!/Samples/OpenGL/thirdParty/stb/* +!/Samples/Metal/thirdParty/stb/* +!/Samples/Vulkan/thirdParty/stb/* +# Other files +/build/ +.vs/ +.vscode/ +.idea/ +*.iml +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ba3b2d2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + + +## [5-r.1-beta.1] - 2023-10-17 + +### Added + +* New released! diff --git a/Core/CHANGELOG.md b/Core/CHANGELOG.md new file mode 100644 index 0000000..c56ee77 --- /dev/null +++ b/Core/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + + +## 2023-10-17 + +### Changed + +* Upgrade Core version to 05.00.0002. + +### Fixed + +* Fix a calculation bug within the `csmMotionSync_Analyze()`. + + +## 2023-09-28 + +### Added + +* Add library for Android. +* Add library for ios. +* Add logging functions. + * `csmMotionSync_SetLogFunction()` + * `csmMotionSync_GetLogFunction()` + + +### Changed + +* Upgrade Core version to 05.00.0001. +* Change `csmMotionSync_Analyze()` argument name. + * `analyzeConfiguration` -> `analysisConfiguration` + + +## 2023-08-17 + +### Added + +* New released! diff --git a/Core/CRI/LICENSE.md b/Core/CRI/LICENSE.md new file mode 100644 index 0000000..77253b3 --- /dev/null +++ b/Core/CRI/LICENSE.md @@ -0,0 +1,7 @@ +## Live2D Proprietary Software License + +Live2D Cubism MotionSync Core is available under Live2D Proprietary Software License. + +* [Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html) +* [Live2D Proprietary Software 使用許諾契約書](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_jp.html) +* [Live2D Proprietary Software 使用授权协议](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_cn.html) diff --git a/Core/CRI/RedistributableFiles.txt b/Core/CRI/RedistributableFiles.txt new file mode 100644 index 0000000..3892723 --- /dev/null +++ b/Core/CRI/RedistributableFiles.txt @@ -0,0 +1,9 @@ +The following is a list of files available for redistribution +under the terms of the Live2D Proprietary Software License Agreement: + +- dll/macos/libLive2DCubismMotionSyncEngine_CRI.dylib +- dll/macos/Live2DCubismMotionSyncEngine_CRI.bundle +- dll/windows/x86/Live2DCubismMotionSyncEngine_CRI.dll +- dll/windows/x86/Live2DCubismMotionSyncEngine_CRI.lib +- dll/windows/x86_64/Live2DCubismMotionSyncEngine_CRI.dll +- dll/windows/x86_64/Live2DCubismMotionSyncEngine_CRI.lib diff --git a/Core/CRIWARELOGO_1.png b/Core/CRIWARELOGO_1.png new file mode 100644 index 0000000..24dd4ff Binary files /dev/null and b/Core/CRIWARELOGO_1.png differ diff --git a/Core/LICENSE.md b/Core/LICENSE.md new file mode 100644 index 0000000..c749db5 --- /dev/null +++ b/Core/LICENSE.md @@ -0,0 +1,27 @@ +## Definitions + +## Live2D Open Software License + +Live2D Cubism Components is available under Live2D Open Software License. + +* [Live2D Open Software License](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html) +* [Live2D Open Software 使用許諾契約書](https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html) +* [Live2D Open Software 使用授权协议](https://www.live2d.com/eula/live2d-open-software-license-agreement_cn.html) + +## Cubism SDK Release License + +*All business* users must obtain a Cubism SDK Release License. "Business" means an entity with the annual gross revenue more than ten million (10,000,000) JPY for the most recent fiscal year. + +* [Cubism SDK Release License](https://www.live2d.com/en/download/cubism-sdk/release-license/) + +直近会計年度の売上高が 1000 万円以上の事業者様がご利用になる場合は、Cubism SDK リリースライセンス(出版許諾契約)に同意していただく必要がございます。 + +* [Cubism SDK リリースライセンス](https://www.live2d.com/ja/download/cubism-sdk/release-license/) + +如果您的企业在最近一个会计年度的销售额达到或超过1000万日元,您必须得到Cubism SDK的出版授权许可(出版许可协议)。 + +* [Cubism SDK发行许可证](https://www.live2d.com/zh-CHS/download/cubism-sdk/release-license/) + +--- + +Please contact us from [here](https://www.live2d.jp/contact/) for more license information. diff --git a/Core/README.md b/Core/README.md new file mode 100644 index 0000000..3946637 --- /dev/null +++ b/Core/README.md @@ -0,0 +1,24 @@ +# Live2D Cubism MotionSync Engine + +This folder contains header files and platform-specific library files for using the motion sync plug-in. + + +## Library List + +| Platform | Architecture | dll | lib | Path | Note | +| --- | --- | --- | --- | --- | --- | +| macOS | ARM64 | ✓ | | macos/arm64 | | +| macOS | x86_64 | ✓ | | macos/x86_64 | | +| Windows | x86 | ✓ | | windows/x86 | | +| Windows | x86_64 | ✓ | | windows/x86_64 | | + + +### Calling convention + +When using the dynamic library of *Windows/x86*, explicitly use `__stdcall` as the calling convention. + +--- + +[![CRIWARE for Games](CRIWARELOGO_1.png)](https://game.criware.jp/) + +Powered by "CRIWARE".CRIWARE is a trademark of CRI Middleware Co., Ltd. diff --git a/Core/include/Live2DCubismMotionSyncEngine.h b/Core/include/Live2DCubismMotionSyncEngine.h new file mode 100644 index 0000000..a9a316d --- /dev/null +++ b/Core/include/Live2DCubismMotionSyncEngine.h @@ -0,0 +1,198 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#ifndef LIVE2D_CUBISM_MOTIONSYNC_ENGINE_H +#define LIVE2D_CUBISM_MOTIONSYNC_ENGINE_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + + /* ------- * + * DEFINES * + * ------- */ + + /** MotionSync API attribute. */ +#if !defined(csmMotionSyncApi) +#define csmMotionSyncApi +#endif + + /* ----- * + * TYPES * + * ----- */ + + /** Context of Analysis. */ + typedef void* csmMotionSync_Context; + + /** Engine version identifier. */ + typedef unsigned int csmMotionSyncVersion; + + + /** Booleans. */ + enum + { + csmMotionSyncFalse = 0, + csmMotionSyncTrue = 1 + }; + + /** + * Result of analysis. + */ + typedef struct + { + /** Value Array of CubismParameter */ + float* Values; + + /** Number of values used in the analysis. */ + int ValuesCount; + + /** Number of samples used in the analysis. */ + unsigned int ProcessedSampleCount; + } csmMotionSync_AnalysisResult; + + /** Mapping Information of AudioParameter. */ + typedef struct + { + /** ID of AudioParameter. */ + const char* AudioParameterId; + + /** Array of ID of ModelParameter linked to the AudioParameter. */ + const char** ModelParameterIds; + + /** Array of ModelParameter Value. */ + float* ModelParameterValues; + + /** Number of ModelParameter. */ + unsigned int ModelParameterCount; + + /** Scaling value for CubismParameter. */ + float Scale; + + /** Enable / Disable for applying.*/ + unsigned int Enabled; + } csmMotionSync_MappingInfo; + + /** Log handler. + * + * @param message Null-terminated string message to log. + */ + typedef void (*csmMotionSyncLogFunction)(const char* message); + + /** Calling conventions for each platform. */ +#if CSM_MOTIONSYNC_ENGINE_WIN32_DLL +#define csmMotionSyncCallingConvention __stdcall +#else +#define csmMotionSyncCallingConvention +#endif + + /* ------- * + * VERSION * + * ------- */ + + /** + * Queries the version of Engine. + * + * @return Version of Engine. + */ + csmMotionSyncApi csmMotionSyncVersion csmMotionSyncCallingConvention csmMotionSync_GetEngineVersion(); + + /** + * Queries the name of Engine. + * + * @return Name of Engine. + */ + csmMotionSyncApi const char* csmMotionSyncCallingConvention csmMotionSync_GetEngineName(); + + /* ------- * + * LOGGING * + * ------- */ + + /** + * Queries log handler. + * + * @return Log handler. + */ + csmMotionSyncApi csmMotionSyncLogFunction csmMotionSyncCallingConvention csmMotionSync_GetLogFunction(); + + /** + * Sets log handler. + * + * @param handler Handler to use. + */ + csmMotionSyncApi void csmMotionSyncCallingConvention csmMotionSync_SetLogFunction(csmMotionSyncLogFunction handler); + + /* ------- * + * METHOD * + * ------- */ + + /** + * Initializes the Engine. + + * @param engineConfiguration Congifuration parameter for engine initialization. Set to `NULL` to use default parameter. + * + * @return `1` if Engine is available. + */ + csmMotionSyncApi int csmMotionSyncCallingConvention csmMotionSync_InitializeEngine(const void* engineConfiguration); + + /** + * Disposes the Engine. + */ + csmMotionSyncApi void csmMotionSyncCallingConvention csmMotionSync_DisposeEngine(); + + /** + * Makes the context of Analysis. + * + * @param contextConfiguration Congifuration parameter for engine initialization. Set to `NULL` to use default parameter. + * @param mappingInformations Array of Mapping Information of AudioParameter. + * @param mappingInformationCount Length of `mappingInformations`. + * + * @return Valid pointer on success; '0' otherwise. + */ + csmMotionSyncApi csmMotionSync_Context csmMotionSyncCallingConvention csmMotionSync_CreateContext(const void* contextConfiguration, const csmMotionSync_MappingInfo* mappingInformations, const int mappingInformationCount); + + /** + * Resets the context of Analysis for reusing. + * + * @param context Context to reset. + */ + csmMotionSyncApi void csmMotionSyncCallingConvention csmMotionSync_ClearContext(const csmMotionSync_Context context); + + /** + * Destroys the context of Analysis. + * + * @param context Context to destroy. + */ + csmMotionSyncApi void csmMotionSyncCallingConvention csmMotionSync_DeleteContext(csmMotionSync_Context context); + + /** + * Gets the number of samples to analyze at a time. + * + * @param context Context to query. + * + * @return Number of samples. + */ + csmMotionSyncApi unsigned int csmMotionSyncCallingConvention csmMotionSync_GetRequireSampleCount(const csmMotionSync_Context context); + + /** + * Analyzes the samples for conversion to the CubismParameter. + * + * @param context Context to analyze. + * @param samples Array of sample to analyze. + * @param sampleCount Number of samples. + * @param analysisResult Array to store results. + * @param analysisConfiguration Configuration of analysis. + * + * @return `1` if succeeded the analysis. + */ + csmMotionSyncApi int csmMotionSyncCallingConvention csmMotionSync_Analyze(const csmMotionSync_Context context, const float* samples, const unsigned int sampleCount, csmMotionSync_AnalysisResult* analysisResult, const void* analysisConfiguration); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt new file mode 100644 index 0000000..4cb2517 --- /dev/null +++ b/Framework/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.10) + +# Set directory paths. +set(LIB_NAME MotionSyncFramework) +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/..) +set(FRAMEWORK_SRC_PATH "$CACHE{NATIVE_PATH}/Framework/src") + + +# Force static library. +add_library(${LIB_NAME} STATIC) + +add_subdirectory(src) + +# Add Cubism Native Framework. +target_include_directories(${LIB_NAME} + PUBLIC + ${FRAMEWORK_SRC_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework +) + +# Add include path. +target_include_directories(${LIB_NAME} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + PRIVATE + ${RENDER_INCLUDE_PATH} +) + +# Deprecated functions +# The following expressions are written for compatibility +# and will be removed in a future release. + +# Add Motion Sync cri include. +target_include_directories(${LIB_NAME} + PRIVATE + ${SDK_ROOT_PATH}/Core/CRI/include +) + +# Add Motion Sync include. +target_include_directories(${LIB_NAME} + PRIVATE + ${SDK_ROOT_PATH}/Core/include +) + +# Add definitions. +target_compile_definitions(${LIB_NAME} + PRIVATE + ${MOTIONSYNC_FRAMEWORK_DEFINITIOINS} +) diff --git a/Framework/README.ja.md b/Framework/README.ja.md new file mode 100644 index 0000000..e0f3f7d --- /dev/null +++ b/Framework/README.ja.md @@ -0,0 +1,85 @@ +[English](README.md) / [日本語](README.ja.md) + +--- + +# Cubism Native MotionSync Framework + +Live2D Cubism Editor で出力したモーションシンク機能を扱ったモデルをアプリケーションで利用するためのフレームワークです。 +モデルに使用されているモーションシンク機能を利用するための各種機能を提供します。 + +モデルの表示や操作機能は[Cubism Native Framework](https://github.com/Live2D/CubismNativeFramework)が提供します。 + + +## ライセンス + +本フレームワークを使用する前に、[ライセンス](LICENSE.md)をご確認ください。 + + +## コンポーネント + +### Lib + +モーションシンク機能を利用するために必要なLive2D Cubism MotionSync CoreライブラリをFrameworkで利用できるようにするためのコンポーネントです。 + + +## Cubism SDK for Native + +本プラグインは、Cubism SDK for Native用のCubism SDKプラグインです。 + +利用するにはCubism SDK for Nativeのパッケージが必要となります。 +SDKパッケージのダウンロードページをお探しの場合は、[ダウンロードページ](https://www.live2d.com/sdk/download/native/)にアクセスしてください。 +このリポジトリと同じ階層にCubism SDK for Nativeのパッケージを置いてください。 + + +## Live2D Cubism Core for Native + +当リポジトリには Live2D Cubism Core for Native は同梱されていません。 + +ダウンロードするには[こちら](https://www.live2d.com/download/cubism-sdk/download-native/)のページを参照ください。 + + +## Live2D Cubism MotionSync Core + +モーションシンク機能を提供するライブラリです。当リポジトリにはLive2D Cubism MotionSync Coreは同梱されていません。 + +Live2D Cubism MotionSync Coreを同梱したプラグインパッケージをダウンロードするには[こちら](https://www.live2d.com/sdk/download/motionsync/)のページを参照ください。 + + +## サンプル + +標準的なアプリケーションの実装例については、Samplesディレクトリを参照ください。 + + +## マニュアル + +[Cubism SDK Manual](https://docs.live2d.com/cubism-sdk-manual/top/) + + +## 変更履歴 + +当リポジトリの変更履歴については [CHANGELOG.md](CHANGELOG.md) を参照ください。 + + +## プロジェクトへの貢献 + +プロジェクトに貢献する方法はたくさんあります。バグのログの記録、このGitHubでのプルリクエストの送信、Live2Dコミュニティでの問題の報告と提案の作成です。 + +### フォークとプルリクエスト + +修正、改善、さらには新機能をもたらすかどうかにかかわらず、プルリクエストに感謝します。ただし、ラッパーは可能な限り軽量で浅くなるように設計されているため、バグ修正とメモリ/パフォーマンスの改善のみを行う必要があることに注意してください。メインリポジトリを可能な限りクリーンに保つために、必要に応じて個人用フォークと機能ブランチを作成してください。 + +### バグ + +Live2Dコミュニティでは、問題のレポートと機能リクエストを定期的にチェックしています。バグレポートを提出する前に、Live2Dコミュニティで検索して、問題のレポートまたは機能リクエストがすでに投稿されているかどうかを確認してください。問題がすでに存在する場合は、関連するコメントを追記してください。 + +### 提案 + +SDKの将来についてのフィードバックにも関心があります。Live2Dコミュニティで提案や機能のリクエストを送信できます。このプロセスをより効果的にするために、それらをより明確に定義するのに役立つより多くの情報を含めるようお願いしています。 + + +## フォーラム + +ユーザー同士でCubism SDKの活用方法の提案や質問をしたい場合は、是非フォーラムをご活用ください。 + +- [Live2D 公式クリエイターズフォーラム](https://creatorsforum.live2d.com/) +- [Live2D Creator's Forum(English)](https://community.live2d.com/) diff --git a/Framework/README.md b/Framework/README.md new file mode 100644 index 0000000..ac153cd --- /dev/null +++ b/Framework/README.md @@ -0,0 +1,98 @@ +[English](README.md) / [日本語](README.ja.md) + +--- + +# Cubism Native MotionSync Framework + +This is a framework for using models that utilize the motion-sync functionality produced in Live2D Cubism Editor within your application. +It offers various features for using the motion sync functionality employed by the model. + +The display and manipulation features of the model are provided by the [Cubism Native Framework](https://github.com/Live2D/CubismNativeFramework). + + +## License + +Please read the [license](LICENSE.md) before use. + + +## Components + +### Lib + +This is a component for making the Live2D Cubism MotionSync Core library available in the framework, allowing you to use the motion sync feature. + + +## Cubism SDK for Native + +This plugin is a Cubism SDK plugin for the Cubism SDK for Native. + +The Cubism SDK for Native package is required for use. + +If you are looking for the download page of the SDK package, please go to the [download page](https://www.live2d.com/sdk/download/native/). + + +## Live2D Cubism Core for Native + +A library for loading the model. +Live2D Cubism Core for Native is not included in this repository. + +To download, please refer to [this](https://www.live2d.com/download/cubism-sdk/download-native/) page. +Copy the contents of the downloaded ZIP file to the `Core` directory of this repository and link it to the program. + + +## Live2D Cubism MotionSync Core + +This library provides the motion-sync function. Live2D Cubism MotionSync Core is not included in this repository. + +To download the plugin package that includes Live2D Cubism MotionSync Core, please refer to [this](https://www.live2d.com/sdk/download/motionsync/) page. + + +## Sample + +For examples of standard application implementations, please refer to the Samples directory. + + +## SDK manual + +[Cubism SDK Manual](https://docs.live2d.com/en/cubism-sdk-manual/top/) + + +## Changelog + +Please refer to [CHANGELOG.md](CHANGELOG.md) for the changelog of this repository. + + +## Contribution to the project + +There are many ways to contribute to the project: logging bugs, submitting pull requests on this GitHub, and reporting issues and making suggestions in Live2D Community. + +### Forking and Pull Requests + +We very much appreciate your pull requests, whether they bring fixes, improvements, or even new features. Note, however, that the wrapper is designed to be as lightweight and shallow as possible and should therefore only be subject to bug fixes and memory/performance improvements. To keep the main repository as clean as possible, please create a personal fork and feature branch as needed. + +### Bugs + +We are regularly checking bug reports and feature requests at Live2D Community. Before submitting a bug report, please search the Live2D Community to see if the bug report or feature request has already been submitted. Add your comment to the relevant issue if it already exists. + +### Suggestions + +We're also interested in your feedback for the future of the SDK. You can submit a suggestion or feature request at Live2D Community. To make this process more effective, we're asking that you include more information to help define them more clearly. + +## Coding Guidelines + +### Naming + +Try to stick to the [Microsoft guidelines](https://msdn.microsoft.com/en-us/library/ms229002(v=vs.110).aspx) whenever possible. Private fields are named in lowercase, starting with an underscore. + +### Style + +- In the Unity Editor extension, try to write expressive code with LINQ and all the other fancy stuff. +- Otherwise, do not use LINQ and prefer `for` to `foreach`. +- Try to make the access modifier explicit. Use `private void Update()` instead of `void Update()`. + +## Forum + +If you have any questions, please join the official Live2D forum and discuss with other users. + +- [Live2D Creator's Forum](https://community.live2d.com/) +- [Live2D 公式クリエイターズフォーラム (Japanese)](https://creatorsforum.live2d.com/) diff --git a/Framework/src/CMakeLists.txt b/Framework/src/CMakeLists.txt new file mode 100644 index 0000000..dc275f9 --- /dev/null +++ b/Framework/src/CMakeLists.txt @@ -0,0 +1,31 @@ +target_sources(${LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CubismModelMotionSyncSettingJson.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismModelMotionSyncSettingJson.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSync.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSync.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncData.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncData.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncDataJson.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncDataJson.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineAnalysisResult.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineAnalysisResult.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineController.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineController.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineCri.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineCri.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineMappingInfo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineMappingInfo.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineVersion.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineVersion.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncProcessorCri.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncProcessorCri.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ICubismMotionSyncEngine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ICubismMotionSyncEngine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ICubismMotionSyncProcessor.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ICubismMotionSyncProcessor.hpp +) + +# Add sub directories. +add_subdirectory(Lib) diff --git a/Framework/src/CubismModelMotionSyncSettingJson.cpp b/Framework/src/CubismModelMotionSyncSettingJson.cpp new file mode 100644 index 0000000..406f8d2 --- /dev/null +++ b/Framework/src/CubismModelMotionSyncSettingJson.cpp @@ -0,0 +1,50 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismModelMotionSyncSettingJson.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +namespace { +const csmChar* FileReferences = "FileReferences"; +const csmChar* MotionSync = "MotionSync"; +} + +CubismModelMotionSyncSettingJson::CubismModelMotionSyncSettingJson(const csmByte* buffer, csmSizeInt size) : + CubismModelSettingJson(buffer, size) +{ +} + +CubismModelMotionSyncSettingJson::~CubismModelMotionSyncSettingJson() +{ +} + +const csmChar* CubismModelMotionSyncSettingJson::GetMotionSyncJsonFileName() +{ + return _json->GetRoot()[FileReferences][MotionSync].GetRawString(); +} + +csmVector CubismModelMotionSyncSettingJson::GetMotionSyncSoundFileList() +{ + csmVector list; + const csmChar* groupName; + + for (csmUint32 i = 0; i < GetMotionGroupCount(); i++) + { + groupName = GetMotionGroupName(i); + + for (csmUint32 j = 0; j < GetMotionCount(groupName); j++) + { + list.PushBack(GetMotionSoundFileName(groupName, j)); + } + } + + return list; +} + +}}}} diff --git a/Framework/src/CubismModelMotionSyncSettingJson.hpp b/Framework/src/CubismModelMotionSyncSettingJson.hpp new file mode 100644 index 0000000..469d518 --- /dev/null +++ b/Framework/src/CubismModelMotionSyncSettingJson.hpp @@ -0,0 +1,48 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismModelSettingJson.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismModelMotionSyncSettingJson : public CubismModelSettingJson +{ +public: + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + */ + CubismModelMotionSyncSettingJson(const csmByte* buffer, csmSizeInt size); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismModelMotionSyncSettingJson(); + + /** + * @brief motionsync3.jsonのファイル名を取得 + * + * @return motionsync3.jsonのファイル名 + */ + const csmChar* GetMotionSyncJsonFileName(); + + /** + * @brief モーションシンクで使う音声データのファイルパスリストを取得 + * + * @return 音声データのファイルパスリスト + */ + csmVector GetMotionSyncSoundFileList(); +}; + +}}}} diff --git a/Framework/src/CubismMotionSync.cpp b/Framework/src/CubismMotionSync.cpp new file mode 100644 index 0000000..93c1593 --- /dev/null +++ b/Framework/src/CubismMotionSync.cpp @@ -0,0 +1,264 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSync.hpp" +#include "CubismMotionSyncDataJson.hpp" +#include "CubismMotionSyncEngineController.hpp" +#include "CubismMotionSyncEngineCri.hpp" +#include "CubismMotionSyncDefine.hpp" +#include "Math/CubismMath.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +CubismMotionSync* CubismMotionSync::Create(CubismModel *model, const csmByte *buffer, const csmSizeInt size, csmInt32 samplesPerSec, csmString executeAbsolutePath) +{ + CubismMotionSyncData *data = CubismMotionSyncData::Create(model, buffer, size); + + if (!data) + { + return NULL; + } + + // エンジンインストールとプロセッサ作成 + csmVector processorList; + for (csmInt32 i = 0; i < data->GetMeta().settingCount; i++) + { + ICubismMotionSyncEngine *engine = NULL; + ICubismMotionSyncProcessor *processor = NULL; + EngineType engineType = data->GetSetting(i).analysisType; + + switch(engineType) + { + case EngineType_Cri: + engine = CubismMotionSyncEngineController::GetEngine(engineType); + if (!engine) + { + engine = CubismMotionSyncEngineController::InstallEngine(executeAbsolutePath + MOTIONSYNC_CORE_CRI_LIB_FILE); + } + if (engine) + { + processor = dynamic_cast(engine)->CreateProcessor(data->GetMappingInfo(i), samplesPerSec); + } + break; + default: + break; + } + if (processor) + { + processorList.PushBack(processor); + } + } + + CubismMotionSync* motionSync = CSM_NEW CubismMotionSync(model, data, processorList); + + return motionSync; +} + +void CubismMotionSync::Delete(CubismMotionSync* instance) +{ + CSM_DELETE_SELF(CubismMotionSync, instance); +} + +void CubismMotionSync::SetSoundBuffer(csmUint32 processIndex, csmVector* buffer) +{ + if(processIndex < _processorInfoList.GetSize()) + { + _processorInfoList[processIndex]._samplesBuff = buffer; + _processorInfoList[processIndex]._samplesBuffIndex = 0; + } +} + +void CubismMotionSync::UpdateParameters(CubismModel *model, csmFloat32 deltaTimeSeconds) +{ + // 設定から時間を変更すると、経過時間がマイナスになることがあるので、経過時間0として対応。 + if (deltaTimeSeconds < 0.0f) + { + deltaTimeSeconds = 0.0f; + } + + for (csmUint32 processIndex = 0; processIndex < _processorInfoList.GetSize(); processIndex++) + { + _processorInfoList[processIndex]._currentRemainTime += deltaTimeSeconds; + + // Check each time assuming it may have been updated. + csmFloat32 fps = _processorInfoList[processIndex]._sampleRate; + + csmFloat32 processorDeltaTime = 1.0f / fps; + + // If the specified frame time is not reached, no analysis is performed. + if (_processorInfoList[processIndex]._currentRemainTime < processorDeltaTime) + { + for (csmUint32 targetIndex = 0; targetIndex < _data->GetSetting(processIndex).cubismParameterList.GetSize(); targetIndex++) + { + if (isnan(_processorInfoList[processIndex]._analysisResult->GetValues()[targetIndex])) + { + continue; + } + + // Overwrite parameter values every frame to prevent data from replacing itself + model->SetParameterValue(_data->GetSetting(processIndex).cubismParameterList[targetIndex].parameterIndex, _processorInfoList[processIndex]._lastDampedList[targetIndex]); + } + continue; + } + + Analyze(model, processIndex); + + // Reset counter. + _processorInfoList[processIndex]._currentRemainTime = fmod(_processorInfoList[processIndex]._currentRemainTime, processorDeltaTime); + + for (csmUint32 targetIndex = 0; targetIndex < _data->GetSetting(processIndex).cubismParameterList.GetSize(); targetIndex++) + { + if (isnan(_processorInfoList[processIndex]._analysisResult->GetValues()[targetIndex])) + { + continue; + } + + // Overwrite parameter values every frame to prevent data from replacing itself + model->SetParameterValue(_data->GetSetting(processIndex).cubismParameterList[targetIndex].parameterIndex, _processorInfoList[processIndex]._lastDampedList[targetIndex]); + } + } +} + +void CubismMotionSync::SetBlendRatio(csmUint32 processIndex, csmFloat32 blendRatio) +{ + if (processIndex < _processorInfoList.GetSize()) + { + _processorInfoList[processIndex]._blendRatio = blendRatio; + } +} + +void CubismMotionSync::SetSmoothing(csmUint32 processIndex, csmInt32 smoothing) +{ + if (processIndex < _processorInfoList.GetSize()) + { + _processorInfoList[processIndex]._smoothing = smoothing; + } +} + +void CubismMotionSync::SetSampleRate(csmUint32 processIndex, csmFloat32 sampleRate) +{ + if (processIndex < _processorInfoList.GetSize()) + { + _processorInfoList[processIndex]._sampleRate = sampleRate; + } +} + +void CubismMotionSync::SetAudioLevelEffectRatio(csmUint32 processIndex, csmFloat32 audioLevelEffectRatio) +{ + if (processIndex < _processorInfoList.GetSize()) + { + _processorInfoList[processIndex]._audioLevelEffectRatio = audioLevelEffectRatio; + } +} + +EngineType CubismMotionSync::ToEngineType(csmString engineName) +{ + EngineType engineType = EngineType_Unknown; + + if (engineName == "CRI") + { + engineType = EngineType_Cri; + } + + return engineType; +} + +void CubismMotionSync::Analyze(CubismModel* model, csmUint32 processIndex) +{ + ICubismMotionSyncProcessor* processor = _processorInfoList[processIndex]._processor; + csmVector *samples = _processorInfoList[processIndex]._samplesBuff; + csmInt32& beginIndex = _processorInfoList[processIndex]._samplesBuffIndex; + + if (!processor || !_processorInfoList[processIndex]._samplesBuff) + { + return; + } + + CubismMotionSyncEngineAnalysisResult* analysis = NULL; + + csmFloat32 blendRatio = _processorInfoList[processIndex]._blendRatio; + csmInt32 smoothing = _processorInfoList[processIndex]._smoothing; + csmFloat32 audioLevelEffectRatio = _processorInfoList[processIndex]._audioLevelEffectRatio; + + do + { + if (samples->GetSize() == 0 || samples->GetSize() <= beginIndex) + { + break; + } + + switch (processor->GetType()) + { + case EngineType_Cri: + analysis = dynamic_cast(processor)->Analyze(*samples, beginIndex, blendRatio, smoothing, audioLevelEffectRatio, _processorInfoList[processIndex]._analysisResult); + break; + default: + break; + } + + if (!analysis) + { + break; + } + + beginIndex += analysis->GetProcessedSampleCount(); + + // モーションシンクライブラリで計算した内容をモデルに繁栄 + for (csmUint32 targetIndex = 0; targetIndex < _data->GetSetting(processIndex).cubismParameterList.GetSize(); targetIndex++) + { + csmFloat32 cacheValue = analysis->GetValues()[targetIndex]; + + if (isnan(cacheValue)) + { + continue; + } + + const csmFloat32 smooth = static_cast(_data->GetSetting(processIndex).cubismParameterList[targetIndex].smooth); + const csmFloat32 damper = _data->GetSetting(processIndex).cubismParameterList[targetIndex].damper; + + // Smoothing + cacheValue = ((100.0f - smooth) * cacheValue + _processorInfoList[processIndex]._lastSmoothedList[targetIndex] * smooth) / 100.0f; + + // Assign value after smoothing + _processorInfoList[processIndex]._lastSmoothedList[targetIndex] = cacheValue; + + // Dampening + if (CubismMath::AbsF(cacheValue - _processorInfoList[processIndex]._lastDampedList[targetIndex]) < damper) + { + cacheValue = _processorInfoList[processIndex]._lastDampedList[targetIndex]; + } + + // Assign value after dampening. + _processorInfoList[processIndex]._lastDampedList[targetIndex] = cacheValue; + } + } + while (analysis); +} + +CubismMotionSync::CubismMotionSync(CubismModel* model, CubismMotionSyncData *data, csmVector processorList) : + _data(data) +{ + for (csmUint32 i = 0; i < processorList.GetSize(); i++) + { + _processorInfoList.PushBack(CubismProcessorInfo(processorList[i], model, data->GetSetting(i))); + _processorInfoList[i].Init(data->GetSetting(i)); + } +} + +CubismMotionSync::~CubismMotionSync() +{ + CubismMotionSyncData::Delete(_data); + for (csmUint32 i = 0; i < _processorInfoList.GetSize(); i++) + { + if (_processorInfoList[i]._processor) + { + _processorInfoList[i]._processor->Close(); + } + } +} + +}}}} diff --git a/Framework/src/CubismMotionSync.hpp b/Framework/src/CubismMotionSync.hpp new file mode 100644 index 0000000..7c32093 --- /dev/null +++ b/Framework/src/CubismMotionSync.hpp @@ -0,0 +1,205 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "ICubismMotionSyncEngine.hpp" +#include "CubismMotionSyncData.hpp" +#include "CubismMotionSyncEngineAnalysisResult.hpp" +#include "ICubismMotionSyncProcessor.hpp" +#include "Type/csmVector.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +/** + * @brief モーションシンク機能 + * + * モーションシンク機能を提供する。 + */ +class CubismMotionSync +{ +public: + /** + * @brief インスタンスの作成 + * + * インスタンスを作成する。 + * + * @param[in] model モデル情報 + * @param[in] buffer motionsync3.jsonが読み込まれているバッファ + * @param[in] size バッファのサイズ + * @param[in] samplesPerSec サンプリング周波数 + * @param[in] executeAbsolutePath 実行中のプログラムファイルパス + */ + static CubismMotionSync* Create(CubismModel *model, const csmByte *buffer, const csmSizeInt size, csmInt32 samplesPerSec, csmString executeAbsolutePath = ""); + + /** + * @brief インスタンスの破棄 + * + * インスタンスを破棄する。 + * + * @param[in] instance 対象のCubismBreath + */ + static void Delete(CubismMotionSync* instance); + + /** + * @brief 音声バッファのポインタを設定する + * + * 音声バッファのポインタを設定する + * + * @param[in] processIndex プロセッサーインデックス + * @param[in] buffer バッファ + */ + void SetSoundBuffer(csmUint32 processIndex, csmVector* buffer); + + /** + * @brief モデルのパラメータの更新 + * + * モデルのパラメータを更新する。 + * + * @param[in] model 対象のモデル + * @param[in] deltaTimeSeconds デルタ時間[秒] + */ + void UpdateParameters(CubismModel *model, csmFloat32 deltaTimeSeconds); + + /** + * @brief プロセッサのblendRatioeを設定 + * + * @param[in] processIndex インデックス + * @param[in] blendRatio 設定する値 + */ + void SetBlendRatio(csmUint32 processIndex, csmFloat32 blendRatio); + + /** + * @brief プロセッサのsmoothingを設定 + * + * @param[in] processIndex インデックス + * @param[in] smoothing 設定する値 + */ + void SetSmoothing(csmUint32 processIndex, csmInt32 smoothing); + + /** + * @brief プロセッサのsampleRateを設定 + * + * @param[in] processIndex インデックス + * @param[in] sampleRate 設定する値 + */ + void SetSampleRate(csmUint32 processIndex, csmFloat32 sampleRate); + + /** + * @brief プロセッサのaudioLevelEffectRatioを設定 + * + * @param[in] processIndex インデックス + * @param[in] audioLevelEffectRatio 設定する値 + */ + void SetAudioLevelEffectRatio(csmUint32 processIndex, csmFloat32 audioLevelEffectRatio); + +private: + struct CubismProcessorInfo + { + /** + * @brief コンストラクタ + * + * @param[in] processor プロセッサ + * @param[in] setting jsonから読んだ中身 + * + */ + CubismProcessorInfo(ICubismMotionSyncProcessor* processor, CubismModel* model, CubismMotionSyncDataSetting setting) : + _processor(processor), + _blendRatio(0.0f), + _smoothing(1), + _sampleRate(30.0f), + _audioLevelEffectRatio(0.0f), + _samplesBuff(NULL), + _samplesBuffIndex(0), + _model(model), + _currentRemainTime(0.0f) + { + Init(setting); + _analysisResult = _processor->CreateAnalysisResult(); + } + + /** + * @brief デストラクタ + */ + virtual ~CubismProcessorInfo() + {} + + /** + * @brief 値の初期化 + * + * @param[in] model jsonから読んだ中身 + * @param[in] setting jsonから読んだ中身 + * + */ + void Init(CubismMotionSyncDataSetting setting) + { + _currentRemainTime = 0.0f; + for (csmUint32 i = 0; i < setting.cubismParameterList.GetSize(); i++) + { + _lastSmoothedList.PushBack(_model->GetParameterValue(setting.cubismParameterList[i].parameterIndex)); + _lastDampedList.PushBack(_model->GetParameterValue(setting.cubismParameterList[i].parameterIndex)); + } + _blendRatio = setting.blendRatio; + _smoothing = setting.smoothing; + _sampleRate = setting.sampleRate; + } + + ICubismMotionSyncProcessor *_processor; + csmFloat32 _blendRatio; + csmInt32 _smoothing; + csmFloat32 _sampleRate; + csmFloat32 _audioLevelEffectRatio; + csmVector* _samplesBuff; + csmInt32 _samplesBuffIndex; + CubismModel *_model; + CubismMotionSyncEngineAnalysisResult *_analysisResult; + csmFloat32 _currentRemainTime; + csmVector _lastSmoothedList; + csmVector _lastDampedList; + }; + + CubismMotionSyncData *_data; + csmVector _processorInfoList; + + /** + * @brief jsonに書かれてるエンジン名からEngineTypeを求める + * + * @param[in] engineName エンジン名 + * + * @return EngineType + */ + static EngineType ToEngineType(csmString engineName); + + /** + * @brief モデルのパラメータの更新 + * + * モデルのパラメータを更新する。 + * + * @param[in] model 対象のモデル + * @param[in] processIndex インデックス + */ + void Analyze(CubismModel *model, csmUint32 processIndex); + + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + * @param[in] model モデルデータ + * @param[in] data jsonから読み込んだデータ + */ + CubismMotionSync(CubismModel* model, CubismMotionSyncData *data, csmVector processorList); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSync(); +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncData.cpp b/Framework/src/CubismMotionSyncData.cpp new file mode 100644 index 0000000..ecda194 --- /dev/null +++ b/Framework/src/CubismMotionSyncData.cpp @@ -0,0 +1,143 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncData.hpp" +#include + + //--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +CubismMotionSyncData* CubismMotionSyncData::Create(CubismModel* model, const csmByte* buffer, csmSizeInt size) +{ + CubismMotionSyncDataJson* json = CSM_NEW CubismMotionSyncDataJson(buffer, size); + + // motionsync3.jsonの読み取りに失敗したらNULLを返す + if (!json->IsValid()) + { + CSM_DELETE(json); + return NULL; + } + + csmInt32 version = json->GetVersion(); + CubismMotionSyncDataMeta meta = json->GetMeta(); + csmVector settingList = json->GetSettingList(); + + CSM_DELETE(json); + + if (meta.dictionary.GetSize() == 0 || settingList.GetSize() == 0) + { + return NULL; + } + + // パーツIDを特定しておく + for (csmUint32 i = 0; i < settingList.GetSize(); i++) + { + for (csmUint32 j = 0; j < settingList[i].cubismParameterList.GetSize(); j++) + { + csmUint32 partIndex = model->GetParameterCount(); + + for (csmUint32 k = 0; k < model->GetParameterCount(); k++) + { + if (model->GetParameterId(k)->GetString() == settingList[i].cubismParameterList[j].id) + { + partIndex = k; + break; + } + } + + settingList[i].cubismParameterList[j].parameterIndex = partIndex; + } + } + + return CSM_NEW CubismMotionSyncData(version, meta, settingList); +} + +void CubismMotionSyncData::Delete(CubismMotionSyncData* motionSyncData) +{ + CSM_DELETE_SELF(CubismMotionSyncData, motionSyncData); +} + +csmInt32 CubismMotionSyncData::GetVersion() +{ + return _version; +} + +CubismMotionSyncDataMeta CubismMotionSyncData::GetMeta() +{ + return _meta; +} + +CubismMotionSyncDataSetting CubismMotionSyncData::GetSetting(const csmUint32 index) +{ + if (_settingList.GetSize() <= index) + { + return _settingList[0]; + } + + return _settingList[index]; +} + +csmVector CubismMotionSyncData::GetMappingInfo(const csmInt32 index) +{ + csmVector mappingInfoList; + + if (_settingList.GetSize() <= index) + { + return mappingInfoList; + } + + CubismMotionSyncDataSetting setting = _settingList[index]; + + for (csmUint32 j = 0; j < setting.audioParameterList.GetSize(); j++) + { + // AudioParameterId + csmString audioParameterId = setting.audioParameterList[j].id; + + // ModelParameterIds & ModelParameterValues + csmVector modelParameterIds; + csmVector modelParameterValues; + // IDが一致するか確認する + for (csmUint32 searchPos = 0; searchPos < setting.audioParameterList.GetSize(); searchPos++) + { + if (audioParameterId == setting.mapping[searchPos].id) + { + for (csmUint32 k = 0; k < setting.cubismParameterList.GetSize(); k++) + { + // ModelParameterIds + modelParameterIds.PushBack(setting.mapping[searchPos].targetList[k].id); + + // ModelParameterValues + modelParameterValues.PushBack(setting.mapping[searchPos].targetList[k].value); + } + break; + } + } + + // Scale + csmFloat32 scale = setting.audioParameterList[j].scale; + + // Enabled + csmBool enabled = setting.audioParameterList[j].enabled; + + mappingInfoList.PushBack(CubismMotionSyncEngineMappingInfo(audioParameterId, modelParameterIds, modelParameterValues, scale, enabled)); + } + + return mappingInfoList; +} + +CubismMotionSyncData::CubismMotionSyncData(csmInt32 version, CubismMotionSyncDataMeta meta, csmVector settingList) : + _version(version), + _meta(meta), + _settingList(settingList) +{ +} + +CubismMotionSyncData::~CubismMotionSyncData() +{ +} + +}}}} diff --git a/Framework/src/CubismMotionSyncData.hpp b/Framework/src/CubismMotionSyncData.hpp new file mode 100644 index 0000000..6196bf6 --- /dev/null +++ b/Framework/src/CubismMotionSyncData.hpp @@ -0,0 +1,184 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismMotionSyncEngineMappingInfo.hpp" +#include "ICubismMotionSyncEngine.hpp" +#include "Model/CubismUserModel.hpp" +#include "Type/csmVector.hpp" + +#define SMOOTHING_MIN_VALUE 1 +#define SMOOTHING_MAX_VALUE 100 +#define SAMPLE_RATE_MIN_VALUE 1.0f +#define SAMPLE_RATE_MAX_VALUE 120.0f + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +struct CubismMotionSyncDataMetaDictionary +{ + csmString id; + csmString name; +}; + +struct CubismMotionSyncDataMeta +{ + csmInt32 settingCount; + csmVector dictionary; +}; + +enum CubismMotionSyncDataUseCase +{ + UseCase_Mouth, + UseCase_Unknown, +}; + +struct CubismMotionSyncDataCubismParameter +{ + csmString name; + csmString id; + csmFloat32 min; + csmFloat32 max; + csmFloat32 damper; + csmInt32 smooth; + + csmUint32 parameterIndex; +}; + +struct CubismMotionSyncDataAudioParameter +{ + csmString name; + csmString id; + csmFloat32 min; + csmFloat32 max; + csmFloat32 scale; + csmBool enabled; +}; + +enum CubismMotionSyncDataMappingType +{ + MappingType_Shape, + MappingType_Unknown, +}; + +struct CubismMotionSyncDataMappingTarget +{ + csmString id; + csmFloat32 value; +}; + +struct CubismMotionSyncDataMapping +{ + CubismMotionSyncDataMappingType type; + csmString id; + csmVector targetList; +}; + +struct CubismMotionSyncDataSetting +{ +public: + csmString id; + EngineType analysisType; + CubismMotionSyncDataUseCase useCase; + csmVector cubismParameterList; + csmVector audioParameterList; + csmVector mapping; + csmFloat32 blendRatio; + csmInt32 smoothing; + csmFloat32 sampleRate; +}; + +class CubismMotionSyncData +{ +public: + + /** + * @brief インスタンスの作成 + * + * インスタンスを作成する。 + * + * @param[in] buffer userdata3.jsonが読み込まれいるバッファ + * @param[in] size バッファのサイズ + * @return 作成されたインスタンス + */ + static CubismMotionSyncData* Create(CubismModel* model, const csmByte* buffer, csmSizeInt size); + + /** + * @brief インスタンスの破棄 + * + * インスタンスを破棄する。 + * + * @param[in] motionSyncData 破棄するインスタンス + */ + static void Delete(CubismMotionSyncData*motionSyncData); + + /** + * @brief バージョンを取得 + * + * バージョンを取得 + * + * @return バージョン + */ + csmInt32 GetVersion(); + + /** + * @brief metaを取得 + * + * metaを取得 + * + * @return meta + */ + CubismMotionSyncDataMeta GetMeta(); + + /** + * @brief settingを取得 + * + * settingを取得 + * + * @param[in] index 取得したい位置 + * + * @return setting + */ + CubismMotionSyncDataSetting GetSetting(const csmUint32 index); + + /** + * @brief MappingInfoを取得 + * + * MappingInfoを取得 + * + * @param[in] index 取得したい位置 + * + * @return MappingInfo + */ + csmVector GetMappingInfo(const csmInt32 index); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncData(); + +private: + csmInt32 _version; + CubismMotionSyncDataMeta _meta; + csmVector _settingList; + + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + * @param[in] version motionsync3.jsonのバージョン + * @param[in] meta motionsync3.jsonに含まれているmeta + * @param[in] settings motionsync3.jsonに含まれているsettings + */ + CubismMotionSyncData(csmInt32 version, CubismMotionSyncDataMeta meta, csmVector settingList); +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncDataJson.cpp b/Framework/src/CubismMotionSyncDataJson.cpp new file mode 100644 index 0000000..fd6a0a0 --- /dev/null +++ b/Framework/src/CubismMotionSyncDataJson.cpp @@ -0,0 +1,176 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncDataJson.hpp" +#include + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +namespace { +const csmChar* Version = "Version"; +const csmChar* Meta = "Meta"; +const csmChar* SettingCount = "SettingCount"; +const csmChar* Dictionary = "Dictionary"; +const csmChar* Id = "Id"; +const csmChar* Name = "Name"; +const csmChar* Settings = "Settings"; +const csmChar* AnalysisType = "AnalysisType"; +const csmChar* UseCase = "UseCase"; +const csmChar* CubismParameters = "CubismParameters"; +const csmChar* Min = "Min"; +const csmChar* Max = "Max"; +const csmChar* Damper = "Damper"; +const csmChar* Smooth = "Smooth"; +const csmChar* AudioParameters = "AudioParameters"; +const csmChar* Scale = "Scale"; +const csmChar* Enabled = "Enabled"; +const csmChar* Mappings = "Mappings"; +const csmChar* Type = "Type"; +const csmChar* Targets = "Targets"; +const csmChar* Value = "Value"; +const csmChar* PostProcessing = "PostProcessing"; +const csmChar* BlendRatio = "BlendRatio"; +const csmChar* Smoothing = "Smoothing"; +const csmChar* SampleRate = "SampleRate"; +} + +CubismMotionSyncDataJson::CubismMotionSyncDataJson(const csmByte* buffer, csmSizeInt size) +{ + CreateCubismJson(buffer, size); +} + +CubismMotionSyncDataJson::~CubismMotionSyncDataJson() +{ + DeleteCubismJson(); +} + +csmInt32 CubismMotionSyncDataJson::GetVersion() const +{ + return _json->GetRoot()[Version].ToInt(); +} + +CubismMotionSyncDataMeta CubismMotionSyncDataJson::GetMeta() const +{ + CubismMotionSyncDataMeta meta; + + meta.settingCount = _json->GetRoot()[Meta][SettingCount].ToInt(); + for (csmInt32 i = 0; i < meta.settingCount; i++) + { + CubismMotionSyncDataMetaDictionary dictionary; + dictionary.id = _json->GetRoot()[Meta][Dictionary][i].GetString(); + dictionary.name = _json->GetRoot()[Meta][Dictionary][i].GetString(); + meta.dictionary.PushBack(dictionary); + } + + return meta; +} + +csmVector CubismMotionSyncDataJson::GetSettingList() const +{ + csmVector settingList; + csmInt32 settingCount = _json->GetRoot()[Meta][SettingCount].ToInt(); + + for (csmInt32 i = 0; i < settingCount; i++) + { + CubismMotionSyncDataSetting setting; + + // Id + setting.id = _json->GetRoot()[Settings][i][Id].GetString(); + + // Analysis type + csmString analysisTypeStr = _json->GetRoot()[Settings][i][AnalysisType].GetString(); + if (analysisTypeStr == "CRI") + { + setting.analysisType = EngineType_Cri; + } + else + { + setting.analysisType = EngineType_Unknown; + } + + // Set use case + csmString useCaseStr = _json->GetRoot()[Settings][i][UseCase].GetString(); + if (useCaseStr == "Mouth") + { + setting.useCase = UseCase_Mouth; + } + else + { + setting.useCase = UseCase_Unknown; + } + + // Set CubismParameter + for (csmInt32 j = 0; j < _json->GetRoot()[Settings][i][CubismParameters].GetSize(); j++) + { + CubismMotionSyncDataCubismParameter cubismParameter; + + cubismParameter.name = _json->GetRoot()[Settings][i][CubismParameters][j][Name].GetString(); + cubismParameter.id = _json->GetRoot()[Settings][i][CubismParameters][j][Id].GetString(); + cubismParameter.min = _json->GetRoot()[Settings][i][CubismParameters][j][Min].ToFloat(); + cubismParameter.max = _json->GetRoot()[Settings][i][CubismParameters][j][Max].ToFloat(); + cubismParameter.damper = _json->GetRoot()[Settings][i][CubismParameters][j][Damper].ToFloat(); + cubismParameter.smooth = _json->GetRoot()[Settings][i][CubismParameters][j][Smooth].ToInt(); + + setting.cubismParameterList.PushBack(cubismParameter); + } + + // Set audio parameters + for (csmInt32 j = 0; j < _json->GetRoot()[Settings][i][AudioParameters].GetSize(); j++) + { + CubismMotionSyncDataAudioParameter audioParameter; + + audioParameter.name = _json->GetRoot()[Settings][i][AudioParameters][j][Name].GetString(); + audioParameter.id = _json->GetRoot()[Settings][i][AudioParameters][j][Id].GetString(); + audioParameter.min = _json->GetRoot()[Settings][i][AudioParameters][j][Min].ToFloat(); + audioParameter.max = _json->GetRoot()[Settings][i][AudioParameters][j][Max].ToFloat(); + audioParameter.scale = _json->GetRoot()[Settings][i][AudioParameters][j][Scale].ToFloat(); + audioParameter.enabled = _json->GetRoot()[Settings][i][AudioParameters][j][Enabled].ToBoolean(); + + setting.audioParameterList.PushBack(audioParameter); + } + + // Set mappings + for (csmInt32 j = 0; j < _json->GetRoot()[Settings][i][Mappings].GetSize(); j++) + { + CubismMotionSyncDataMapping mapping; + + csmString mappingTypeStr = _json->GetRoot()[Settings][i][Mappings][j][Type].GetString(); + if (mappingTypeStr == "Shape") + { + mapping.type = MappingType_Shape; + } + else + { + mapping.type = MappingType_Unknown; + } + mapping.id = _json->GetRoot()[Settings][i][Mappings][j][Id].GetString(); + for (csmInt32 k = 0; k < _json->GetRoot()[Settings][i][Mappings][j][Targets].GetSize(); k++) + { + CubismMotionSyncDataMappingTarget target; + + target.id = _json->GetRoot()[Settings][i][Mappings][j][Targets][k][Id].GetString(); + target.value = _json->GetRoot()[Settings][i][Mappings][j][Targets][k][Value].ToFloat(); + + mapping.targetList.PushBack(target); + } + + setting.mapping.PushBack(mapping); + } + + // Set post processing + setting.blendRatio = CubismMath::ClampF(_json->GetRoot()[Settings][i][PostProcessing][BlendRatio].ToFloat(), 0.0f, 1.0f); + setting.smoothing = CubismMath::Clamp(_json->GetRoot()[Settings][i][PostProcessing][Smoothing].ToInt(), SMOOTHING_MIN_VALUE, SMOOTHING_MAX_VALUE); + setting.sampleRate = CubismMath::ClampF(_json->GetRoot()[Settings][i][PostProcessing][SampleRate].ToFloat(), SAMPLE_RATE_MIN_VALUE, SAMPLE_RATE_MAX_VALUE); + + settingList.PushBack(setting); + } + + return settingList; +} + +}}}} diff --git a/Framework/src/CubismMotionSyncDataJson.hpp b/Framework/src/CubismMotionSyncDataJson.hpp new file mode 100644 index 0000000..a8a5151 --- /dev/null +++ b/Framework/src/CubismMotionSyncDataJson.hpp @@ -0,0 +1,65 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismJsonHolder.hpp" +#include "CubismMotionSyncData.hpp" +#include "CubismMotionSyncEngineMappingInfo.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncDataJson : public CubismJsonHolder +{ +public: + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + * @param[in] buffer motionsync3.jsonが読み込まれているバッファ + * @param[in] size バッファのサイズ + */ + CubismMotionSyncDataJson(const csmByte* buffer, csmSizeInt size); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncDataJson(); + + /** + * @brief バージョンを取得 + * + * motionsync3.jsonのバージョンを取得 + * + * @return バージョン + */ + csmInt32 GetVersion() const; + + /** + * @brief Meta情報を取得 + * + * motionsync3.jsonのMeta情報を取得 + * + * @return Meta情報 + */ + CubismMotionSyncDataMeta GetMeta() const; + + /** + * @brief Settings情報を取得 + * + * motionsync3.jsonのSettings情報を取得 + * + * @return Settings情報 + */ + csmVector GetSettingList() const; +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncDefine.hpp b/Framework/src/CubismMotionSyncDefine.hpp new file mode 100644 index 0000000..081970f --- /dev/null +++ b/Framework/src/CubismMotionSyncDefine.hpp @@ -0,0 +1,22 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#ifdef _WIN32 +#define MOTIONSYNC_CORE_CRI_LIB_NAME "Live2DCubismMotionSyncEngine_CRI.dll" +#elif __MACH__ +#define MOTIONSYNC_CORE_CRI_LIB_NAME "libLive2DCubismMotionSyncEngine_CRI.dylib" +#endif + +#define MOTIONSYNC_CORE_CRI_LIB_FILE MOTIONSYNC_CORE_CRI_LIB_PATH MOTIONSYNC_CORE_CRI_LIB_NAME + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineAnalysisResult.cpp b/Framework/src/CubismMotionSyncEngineAnalysisResult.cpp new file mode 100644 index 0000000..c4e6832 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineAnalysisResult.cpp @@ -0,0 +1,57 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineAnalysisResult.hpp" +#include "CubismFramework.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { +csmFloat32* CubismMotionSyncEngineAnalysisResult::GetValues() +{ + return _values; +} + +csmInt32 CubismMotionSyncEngineAnalysisResult::GetValuesCount() +{ + return _valuesCount; +} + +void CubismMotionSyncEngineAnalysisResult::SetProcessedSampleCount(csmInt32 sampleCount) +{ + _processedSampleCount = sampleCount; +} + +csmInt32 CubismMotionSyncEngineAnalysisResult::GetProcessedSampleCount() +{ + return _processedSampleCount; +} + + +CubismMotionSyncEngineAnalysisResult::CubismMotionSyncEngineAnalysisResult(csmInt32 valuesSize) +{ + _values = static_cast(CSM_MALLOC(sizeof(csmFloat32) * valuesSize)); + _valuesCount = valuesSize; + _processedSampleCount = 0; +} + +CubismMotionSyncEngineAnalysisResult::CubismMotionSyncEngineAnalysisResult(const CubismMotionSyncEngineAnalysisResult &result) +{ + _values = static_cast(CSM_MALLOC(sizeof(csmFloat32) * result._valuesCount)); + for (csmInt32 i = 0; i < result._valuesCount; i++) + { + _values[i] = result._values[i]; + } + _valuesCount = result._valuesCount; + _processedSampleCount = result._processedSampleCount; +} + +CubismMotionSyncEngineAnalysisResult::~CubismMotionSyncEngineAnalysisResult() +{ + CSM_FREE(_values); +} + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineAnalysisResult.hpp b/Framework/src/CubismMotionSyncEngineAnalysisResult.hpp new file mode 100644 index 0000000..9688c52 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineAnalysisResult.hpp @@ -0,0 +1,72 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "Type/CubismBasicType.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncEngineAnalysisResult +{ +public: + /** + * @brief 解析された値の配列を取得する + * + * @return values 値の配列 + */ + csmFloat32* GetValues(); + + /** + * @brief 解析された値の配列の大きさを取得する + * + * @return values 値の配列 + */ + csmInt32 GetValuesCount(); + + /** + * @brief 解析されたサンプルの数を設定する + * + */ + void SetProcessedSampleCount(csmInt32 sampleCount); + + /** + * @brief 解析されたサンプルの数を取得する + * + * @return processedSampleCount 解析されたサンプルの数 + */ + csmInt32 GetProcessedSampleCount(); + + /** + * @brief コンストラクタ + * + * コンストラクタ + */ + CubismMotionSyncEngineAnalysisResult(csmInt32 valuesSize); + + /** + * @brief コピーコンストラクタ + * + * コピーコンストラクタ + */ + CubismMotionSyncEngineAnalysisResult(const CubismMotionSyncEngineAnalysisResult &result); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncEngineAnalysisResult(); + +private: + csmFloat32* _values; + csmInt32 _valuesCount; + csmInt32 _processedSampleCount; +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineController.cpp b/Framework/src/CubismMotionSyncEngineController.cpp new file mode 100644 index 0000000..d43f703 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineController.cpp @@ -0,0 +1,149 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineController.hpp" +#include +#include "CubismMotionSyncEngineVersion.hpp" +#include "CubismMotionSyncEngineCri.hpp" +#include "Lib/CubismMotionSyncEngineLib.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +csmMap CubismMotionSyncEngineController::_engineMap; + +ICubismMotionSyncEngine* CubismMotionSyncEngineController::InstallEngine(csmString dllFilePath) +{ + struct stat statBuf; + + // 渡されたパスにファイルが存在するかチェック + if (stat(dllFilePath.GetRawString(), &statBuf) != 0) + { + return NULL; + } + + CubismMotionSyncEngineLib* engineHandle = CSM_NEW CubismMotionSyncEngineLib(); + if (!engineHandle->LoadLibrary(dllFilePath.GetRawString())) + { + CSM_DELETE(engineHandle); + return NULL; + } + + csmString engineName = engineHandle->GetEngineName(); + EngineType engineType = ToEngineType(engineName); + csmInt32 nativeVersion = engineHandle->GetEngineVersion(); + CubismMotionSyncEngineVersion version = CubismMotionSyncEngineVersion(nativeVersion); + + // 同じ種類のエンジンが2回以上呼ばれた場合はunloadEngine()を行う。 + if (_engineMap.IsExist(engineType)) + { + engineHandle->UnloadLibrary(); + CSM_DELETE(engineHandle); + return NULL; + } + // 初期化 + csmInt32 isInitialized = engineHandle->InitializeEngine(NULL); + if (isInitialized == 0) + { + //unloadEngineを呼びだす + engineHandle->UnloadLibrary(); + CSM_DELETE(engineHandle); + return NULL; + } + + ICubismMotionSyncEngine *engine = NULL; + switch (engineType) + { + case EngineType_Cri: + engine = CSM_NEW CubismMotionSyncEngineCri(engineHandle, engineType, engineName, version); + break; + default: + engineHandle->DisposeEngine(); + engineHandle->UnloadLibrary(); + CSM_DELETE(engineHandle); + return NULL; + } + _engineMap[engineType] = engine; + + return engine; +} + +ICubismMotionSyncEngine* CubismMotionSyncEngineController::GetEngine(EngineType type) +{ + if (_engineMap.IsExist(type)) + { + return _engineMap[type]; + } + + return NULL; +} + +csmVector CubismMotionSyncEngineController::GetEngines() +{ + csmVector vector; + + for (csmMap::const_iterator iter = _engineMap.Begin(); iter != _engineMap.End(); iter++) + { + vector.PushBack(iter->Second); + } + return vector; +} + +void CubismMotionSyncEngineController::ReleaseEngine(ICubismMotionSyncEngine *engine) +{ + ReleaseEngine(engine, false); +} + +void CubismMotionSyncEngineController::ReleaseEngine(ICubismMotionSyncEngine *engine, csmBool isForce) +{ + engine->Close(isForce); +} + +void CubismMotionSyncEngineController::DeleteAssociation(ICubismMotionSyncEngine *engine) +{ + for (csmMap::const_iterator iter = _engineMap.Begin(); iter != _engineMap.End(); iter++) + { + if (iter->First == engine->GetType()) + { + CSM_DELETE(engine); + _engineMap.Erase(iter); + break; + } + } +} + +void CubismMotionSyncEngineController::DeleteAllEngine() +{ + csmVector engines = GetEngines(); + + for (csmUint32 i = 0; i < engines.GetSize(); i++) + { + engines[i]->Close(true); + } + + _engineMap.Clear(); +} + + +EngineType CubismMotionSyncEngineController::ToEngineType(csmString engineName) +{ + EngineType engineType = EngineType_Unknown; + + if (engineName == "Live2DCubismMotionSyncEngine_CRI") + { + engineType = EngineType_Cri; + } + + return engineType; +} + +CubismMotionSyncEngineController::CubismMotionSyncEngineController() +{ } + +CubismMotionSyncEngineController::~CubismMotionSyncEngineController() +{ } + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineController.hpp b/Framework/src/CubismMotionSyncEngineController.hpp new file mode 100644 index 0000000..81b76d6 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineController.hpp @@ -0,0 +1,100 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "Model/CubismModel.hpp" +#include "Id/CubismId.hpp" +#include "ICubismMotionSyncEngine.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncEngineController +{ +public: + /** + * @brief 指定したファイルパスのDLLをロード + * + * @param[in] dllFilePath DLLファイルパス + * + * @return + */ + static ICubismMotionSyncEngine* InstallEngine(csmString dllFilePath); + + /** + * @brief 指定された種類のエンジンを返す + * + * @param[in] type 取得するエンジンの種類 + * + * @return 指定した種類のエンジンインスタンス。見つからなければNULLを返す + */ + static ICubismMotionSyncEngine* GetEngine(EngineType type); + + /** + * @brief インストールされているエンジンをリストで返す + * エンジンが1つもインストールされていない場合は空のリストを返します + * + * @return インストールされているエンジンのリスト + */ + static csmVector GetEngines(); + + /** + * @brief エンジンを解放する + * + * @param[in] engine 解放したいエンジン + */ + static void ReleaseEngine(ICubismMotionSyncEngine *engine); + + /** + * @brief エンジンを解放する + * + * @param[in] engine 解放したいエンジン + * @param[in] isForce 強制的に解放するか + */ + static void ReleaseEngine(ICubismMotionSyncEngine *engine, csmBool isForce); + + /** + * 対象のエンジンとの関連を削除する。 + * + * @param engine 対象のエンジン + */ + static void DeleteAssociation(ICubismMotionSyncEngine *engine); + + /** + * エンジンを全て削除する。 + * + */ + static void DeleteAllEngine(); + +private: + static csmMap _engineMap; + + /** + * @brief エンジン名からEngineTypeを求める + * + * @param[in] engineName エンジン名 + * + * @return EngineType + */ + static EngineType ToEngineType(csmString engineName); + + /** + * @brief コンストラクタ + * + * コンストラクタ。 + */ + CubismMotionSyncEngineController(); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncEngineController(); +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineCri.cpp b/Framework/src/CubismMotionSyncEngineCri.cpp new file mode 100644 index 0000000..350a192 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineCri.cpp @@ -0,0 +1,62 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineCri.hpp" +#include "Lib/CubismMotionSyncConfig.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { +namespace +{ +csmUint32 SampleRateMin = 16000; +csmUint32 SampleRateMax = 128000; +} + +CubismMotionSyncProcessorCRI* CubismMotionSyncEngineCri::CreateProcessor(csmVector mappingInfoArray, csmInt32 sampleRate) +{ + if (IsClosed()) + { + return NULL; + } + + if (mappingInfoArray.GetSize() < 6) + { + return NULL; + } + if (!(SampleRateMin <= sampleRate && sampleRate <= SampleRateMax)) + { + return NULL; + } + + const MotionSyncContextConfig_CRI contextConfig(sampleRate, DEFAULT_AUDIO_BIT_DEPTH); + MappingInfoListMapper* const mapper = CSM_NEW MappingInfoListMapper(); + mapper->SetJObject(mappingInfoArray); + + CubismMotionSyncContext context = GetEngineHandle()->CreateContext(&contextConfig, mapper->Data(), mapper->Count()); + if (context == NULL) + { + CubismLogError("Failed to create a motion sync processor. Make sure there are no problems with the arguments."); + CSM_DELETE(mapper); + return NULL; + } + MotionSyncContext* contextHandle = CSM_NEW MotionSyncContext(context, mapper); + + CubismMotionSyncProcessorCRI *processor = CSM_NEW CubismMotionSyncProcessorCRI(this, contextHandle, mappingInfoArray, sampleRate, DEFAULT_AUDIO_BIT_DEPTH); + _processors.PushBack(processor); + + return processor; +} + +CubismMotionSyncEngineCri::CubismMotionSyncEngineCri(CubismMotionSyncEngineLib* engineHandle, EngineType type, csmString name, CubismMotionSyncEngineVersion version) : + ICubismMotionSyncEngine(engineHandle, type, name, version) +{ +} + +CubismMotionSyncEngineCri::~CubismMotionSyncEngineCri() +{ +} + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineCri.hpp b/Framework/src/CubismMotionSyncEngineCri.hpp new file mode 100644 index 0000000..9b70099 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineCri.hpp @@ -0,0 +1,48 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismMotionSyncProcessorCRI.hpp" +#include "ICubismMotionSyncEngine.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncEngineCri : public ICubismMotionSyncEngine +{ +public: + /** + * @brief 音声解析のためのプロセッサーを作成する。 + * + * @param mappingInfoArray マッピング情報の配列(length >= 6) + * @param sampleRate サンプリングレート(16000~128000) + * @return プロセッサーのインスタンス + */ + CubismMotionSyncProcessorCRI* CreateProcessor(csmVector mappingInfoArray, csmInt32 sampleRate); + + /** + * @brief コンストラクタ + * + * コンストラクタ + * + * @param[in] engineHandle エンジンのハンドル + * @param[in] type エンジンの種類 + * @param[in] name エンジンの名前 + * @param[in] version エンジンのバージョン + */ + CubismMotionSyncEngineCri(CubismMotionSyncEngineLib* engineHandle, EngineType type, csmString name, CubismMotionSyncEngineVersion version); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncEngineCri(); +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineMappingInfo.cpp b/Framework/src/CubismMotionSyncEngineMappingInfo.cpp new file mode 100644 index 0000000..55eee8f --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineMappingInfo.cpp @@ -0,0 +1,67 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineMappingInfo.hpp" + + //--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +csmString CubismMotionSyncEngineMappingInfo::GetAudioParameterId() +{ + return _audioParameterId; +} + +csmVector CubismMotionSyncEngineMappingInfo::GetModelParameterIds() +{ + return _modelParameterIds; +} + +csmVector CubismMotionSyncEngineMappingInfo::GetModelParameterValues() +{ + return _modelParameterValues; +} + +csmFloat32 CubismMotionSyncEngineMappingInfo::GetScale() +{ + return _scale; +} + +csmBool CubismMotionSyncEngineMappingInfo::IsEnabled() +{ + return _enabled; +} + +CubismMotionSyncEngineMappingInfo::CubismMotionSyncEngineMappingInfo(csmString audioParameterId, csmVector modelParameterIds, csmVector modelParameterValues, csmFloat32 scale, csmBool enabled) : + _audioParameterId(audioParameterId), + _modelParameterIds(modelParameterIds), + _modelParameterValues(modelParameterValues), + _scale(scale), + _enabled(enabled) +{ + if (audioParameterId.GetLength() == 0) + { + CubismLogError("The audio parameter ID is null."); + } + if (modelParameterIds.GetSize() != modelParameterValues.GetSize()) + { + CubismLogError("The array length of IDs differs from the array length of parameter values. Please make them the same."); + } + if (modelParameterIds.GetSize() == 0) + { + CubismLogError("The model parameter ID array or the model parameter value array length is 0."); + } + if (!(0.1 <= scale && scale <= 10.0)) + { + CubismLogError("The value of scale is incorrect. The value is limited to between 0.1 and 10.0."); + } +} + +CubismMotionSyncEngineMappingInfo::~CubismMotionSyncEngineMappingInfo() +{ +} + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineMappingInfo.hpp b/Framework/src/CubismMotionSyncEngineMappingInfo.hpp new file mode 100644 index 0000000..bbf60da --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineMappingInfo.hpp @@ -0,0 +1,81 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "Type/csmVector.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncEngineMappingInfo +{ +public: + /** + * @brief マッピング情報の口形素IDを文字列で返す + * + * @return マッピング情報の口形素ID + */ + csmString GetAudioParameterId(); + + /** + * @brief モデルのパラメータIDの配列を返す + * + * @return パラメータIDの配列 + */ + csmVector GetModelParameterIds(); + + /** + * @brief モデルのパラメータ値の配列を返す + * + * @return パラメータ値の配列 + */ + csmVector GetModelParameterValues(); + + /** + * @brief スケール値を返す + * + * @return スケール値 + */ + csmFloat32 GetScale(); + + /** + * @brief このマッピング情報が有効かどうかを返す + * + * @return マッピング情報の有効・無効。有効ならtrue + */ + csmBool IsEnabled(); + + /** + * @brief コンストラクタ + * + * コンストラクタ + * + * @param audioParameterId 口形素ID + * @param modelParameterIds モデルのパラメータIDの配列 + * @param modelParameterValues モデルのパラメータ値 + * @param scale 倍率(0.1~10.0) + * @param enabled マッピング情報の有効・無効 + */ + CubismMotionSyncEngineMappingInfo(csmString audioParameterId, csmVector modelParameterIds, csmVector modelParameterValues, csmFloat32 scale, csmBool enabled); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncEngineMappingInfo(); + +private: + csmString _audioParameterId; + csmVector _modelParameterIds; + csmVector _modelParameterValues; + csmFloat32 _scale; + csmBool _enabled; +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineVersion.cpp b/Framework/src/CubismMotionSyncEngineVersion.cpp new file mode 100644 index 0000000..dabf09d --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineVersion.cpp @@ -0,0 +1,49 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineVersion.hpp" +#include + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +CubismMotionSyncEngineVersion::CubismMotionSyncEngineVersion(csmInt32 version) : + _versionNumber(version), + _major((version >> 24) & 0xFF), + _minor((version >> 16) & 0xFF), + _patch(version & 0xFF) +{ +} + +csmInt32 CubismMotionSyncEngineVersion::GetMajor() +{ + return _major; +} + +csmInt32 CubismMotionSyncEngineVersion::GetMinor() +{ + return _minor; +} + +csmInt32 CubismMotionSyncEngineVersion::GetPatch() +{ + return _patch; +} + +csmInt32 CubismMotionSyncEngineVersion::GetVersionNumber() +{ + return _versionNumber; +} + +csmString CubismMotionSyncEngineVersion::ToString() +{ + csmChar buff[64]; + sprintf(buff, "%02d.%02d.%04d (%d)", _major, _minor, _patch, _versionNumber); + return buff; +} + +}}}} diff --git a/Framework/src/CubismMotionSyncEngineVersion.hpp b/Framework/src/CubismMotionSyncEngineVersion.hpp new file mode 100644 index 0000000..e6d85d2 --- /dev/null +++ b/Framework/src/CubismMotionSyncEngineVersion.hpp @@ -0,0 +1,74 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "Type/csmString.hpp" +#include "Type/CubismBasicType.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +/** + * Cubism MotionSync Engineのバージョン情報を扱うクラス。 + * フォーマットは xx.yy.zzzz となる。 + */ +class CubismMotionSyncEngineVersion +{ +public: + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + * @param[in] version エンジンから取得した生のバージョン情報 + */ + CubismMotionSyncEngineVersion(csmInt32 version); + + /** + * @brief Cubism MotionSync Engineのメジャーバージョンを返す。 + * + * @return メジャーバージョン + */ + csmInt32 GetMajor(); + + /** + * @brief Cubism MotionSync Engineのマイナーバージョンを返す。 + * + * @return マイナーバージョン + */ + csmInt32 GetMinor(); + + /** + * @brief Cubism MotionSync Engineのパッチ番号を返す。 + * + * @return パッチ番号 + */ + csmInt32 GetPatch(); + + /** + * @brief Cubism MotionSync Engineのバージョン番号を返す。 + * + * @return バージョン番号 + */ + csmInt32 GetVersionNumber(); + + /** + * @brief Cubism MotionSync Engineのバージョン情報を返す。 + * + * @return バージョン情報 + */ + csmString ToString(); + +private: + csmInt32 _versionNumber; + csmInt32 _major; + csmInt32 _minor; + csmInt32 _patch; +}; + +}}}} diff --git a/Framework/src/CubismMotionSyncProcessorCRI.cpp b/Framework/src/CubismMotionSyncProcessorCRI.cpp new file mode 100644 index 0000000..70b60e4 --- /dev/null +++ b/Framework/src/CubismMotionSyncProcessorCRI.cpp @@ -0,0 +1,96 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncProcessorCRI.hpp" +#include "Lib/CubismMotionSyncConfig.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +csmInt32 CubismMotionSyncProcessorCRI::GetSampleRate() +{ + return _sampleRate; +} + +csmInt32 CubismMotionSyncProcessorCRI::GetBitDepth() +{ + return _bitDepth; +} + +CubismMotionSyncEngineAnalysisResult* CubismMotionSyncProcessorCRI::Analyze(csmVector &samples, csmInt32 beginIndex, csmFloat32 blendRatio, csmInt32 smoothing, csmFloat32 audioLevelEffectRatio, CubismMotionSyncEngineAnalysisResult *result) +{ + if (IsClosed()) + { + return NULL; + } + + if (samples.GetSize() == 0) + { + CubismLogError("The argument is invalid. Please check that the samples is the correct value."); + return NULL; + } + if (!(0 <= beginIndex && beginIndex < samples.GetSize())) + { + CubismLogError("The value of beginIndex is incorrect. It should be less than the length of samples."); + return NULL; + } + if (!(0.0f <= blendRatio && blendRatio <= 1.0f)) + { + CubismLogError("The value of blend ratio is incorrect. The value is limited to between 0.0 and 1.0."); + } + if (!(1 <= smoothing && smoothing <= 100)) + { + CubismLogError("The value of smoothing is incorrect. The value is limited to between 1 and 100."); + return NULL; + } + if (!(0.0f <= audioLevelEffectRatio && audioLevelEffectRatio <= 1.0f)) + { + CubismLogError("The value of audio level effect ratio is incorrect. The value is limited to between 0.0 and 1.0."); + return NULL; + } + if (result == NULL) + { + CubismLogError("The result instance is null."); + return NULL; + } + + const csmInt32 samplesCount = samples.GetSize(); + + CubismMotionSyncAnalysisResult analysisResult(result->GetValues(), result->GetValuesCount(), 0); + MotionSyncAnalysisConfig_CRI analysisConfig(blendRatio, smoothing, audioLevelEffectRatio); + + const csmBool ret = _engine->GetEngineHandle()->Analyze(GetContextHandle()->Context(), samples.GetPtr() + beginIndex, samplesCount - beginIndex, &analysisResult, &analysisConfig); + + result->SetProcessedSampleCount(analysisResult.ProcessedSampleCount); + + if (!ret) + { + return NULL; + } + + return result; +} + +CubismMotionSyncEngineAnalysisResult* CubismMotionSyncProcessorCRI::Analyze(csmVector &samples, csmInt32 beginIndex, csmFloat32 blendRatio, csmInt32 smoothing, csmFloat32 audioLevelEffectRatio) +{ + CubismMotionSyncEngineAnalysisResult *result = CreateAnalysisResult(); + Analyze(samples, beginIndex, blendRatio, smoothing, audioLevelEffectRatio, result); + return result; +} + +CubismMotionSyncProcessorCRI::CubismMotionSyncProcessorCRI(ICubismMotionSyncEngine *engine, MotionSyncContext *contextHandle, csmVector mappingInfoArray, csmInt32 sampleRate, csmInt32 bitDepth) : + ICubismMotionSyncProcessor(engine, contextHandle, mappingInfoArray), + _sampleRate(sampleRate), + _bitDepth(bitDepth) +{ +} + +CubismMotionSyncProcessorCRI::~CubismMotionSyncProcessorCRI() +{ +} + +}}}} diff --git a/Framework/src/CubismMotionSyncProcessorCRI.hpp b/Framework/src/CubismMotionSyncProcessorCRI.hpp new file mode 100644 index 0000000..7ac674b --- /dev/null +++ b/Framework/src/CubismMotionSyncProcessorCRI.hpp @@ -0,0 +1,88 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "ICubismMotionSyncEngine.hpp" +#include "ICubismMotionSyncProcessor.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class CubismMotionSyncProcessorCRI : public ICubismMotionSyncProcessor +{ +public: + /** + * @brief このプロセッサーが保持するサンプルレートの値を返す。 + * + * @return サンプルレートの値 + */ + csmInt32 GetSampleRate(); + + /** + * @brief このプロセッサーが保持する音声のビットデプスの値を返す。 + * + * @return 音声のビットデプス + */ + csmInt32 GetBitDepth(); + + /** + * @brief 音声データから口形素を解析する。 + * 解析結果のインスタンスをメソッド内で作成する。 + * + * @param samples 解析したい音声データ + * @param beginIndex 解析を開始するオフセット + * @param blendRatio ブレンド率(0.0~1.0) + * @param smoothing スムージングの値(1~100) + * @param audioLevelEffectRatio 音量の大きさが口の開閉に与える影響度(0.0~1.0) + * @param result 解析結果のインスタンス + * + * @return 解析結果のインスタンス + */ + CubismMotionSyncEngineAnalysisResult* Analyze(csmVector &samples, csmInt32 beginIndex, csmFloat32 blendRatio, csmInt32 smoothing, csmFloat32 audioLevelEffectRatio, CubismMotionSyncEngineAnalysisResult* result); + + /** + * @brief 音声データから口形素を解析する + * 解析結果のインスタンスをメソッド内で作成する + * NOTE: メモリ効率を考慮する必要がある場合には、解析結果のインスタンスを引数に取る方のメソッドを使用すること + * + * @param samples 解析したい音声データ + * @param beginIndex 解析を開始するオフセット + * @param blendRatio ブレンド率(0.0f~1.0f) + * @param smoothing スムージングの値(1~100) + * @param audioLevelEffectRatio 音量の大きさが口の開閉に与える影響度(0.0~1.0) + * + * @return 解析結果のインスタンス + */ + CubismMotionSyncEngineAnalysisResult* Analyze(csmVector &samples, csmInt32 beginIndex, csmFloat32 blendRatio, csmInt32 smoothing, csmFloat32 audioLevelEffectRatio); + + /** + * @brief コンストラクタ + * + * コンストラクタ + * + * @param engine モーションシンクエンジンのインスタンス + * @param nativeHandle ネイティブハンドル + * @param mappingInfoArray マッピング情報の配列 + * @param sampleRate サンプリングレート(16000~128000で設定すること) + * @param bitDepth 音声のビットデプス(16,32bit) + */ + CubismMotionSyncProcessorCRI(ICubismMotionSyncEngine *engine, MotionSyncContext *contextHandle, csmVector mappingInfoArray, csmInt32 sampleRate, csmInt32 bitDepth); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~CubismMotionSyncProcessorCRI(); + +private: + csmInt32 _sampleRate; + csmInt32 _bitDepth; +}; + +}}}} diff --git a/Framework/src/ICubismMotionSyncEngine.cpp b/Framework/src/ICubismMotionSyncEngine.cpp new file mode 100644 index 0000000..1c8ebf4 --- /dev/null +++ b/Framework/src/ICubismMotionSyncEngine.cpp @@ -0,0 +1,111 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "ICubismMotionSyncEngine.hpp" +#include "ICubismMotionSyncProcessor.hpp" +#include "CubismMotionSyncEngineController.hpp" + +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +EngineType ICubismMotionSyncEngine::GetType() +{ + return _type; +} + +csmString ICubismMotionSyncEngine::GetName() +{ + return _name; +} + +CubismMotionSyncEngineVersion ICubismMotionSyncEngine::GetVersion() +{ + return _version; +} + +csmBool ICubismMotionSyncEngine::IsClosed() +{ + return _engineHandle == NULL; +} + +csmVector ICubismMotionSyncEngine::GetProcessors() +{ + return _processors; +} + +void ICubismMotionSyncEngine::ReleaseAllProcessor() +{ + if (IsClosed()) + { + return; + } + + // Close内でDeleteAssociationが呼ばれている + csmVector deleteProcessors = _processors; + + for (csmUint32 i = 0; i < deleteProcessors.GetSize(); i++) + { + deleteProcessors[i]->Close(); + } +} + +CubismMotionSyncEngineLib* ICubismMotionSyncEngine::GetEngineHandle() +{ + return _engineHandle; +} + +void ICubismMotionSyncEngine::Close(csmBool isForce) +{ + if (IsClosed()) + { + return; + } + + if (0 < _processors.GetSize()) + { + if (isForce) + { + ReleaseAllProcessor(); + } + else + { + return; + } + } + + _engineHandle->DisposeEngine(); + _engineHandle->UnloadLibrary(); + CSM_DELETE(_engineHandle); + _engineHandle = NULL; + CubismMotionSyncEngineController::DeleteAssociation(this); +} + +void ICubismMotionSyncEngine::DeleteAssociation(ICubismMotionSyncProcessor *processor) +{ + for (csmUint32 i = 0; i < _processors.GetSize(); i++) + { + if (_processors[i] == processor) + { + CSM_DELETE(_processors[i]); + _processors.Remove(i); + break; + } + } +} + +ICubismMotionSyncEngine::ICubismMotionSyncEngine(CubismMotionSyncEngineLib *engineHandle, EngineType type, csmString name, CubismMotionSyncEngineVersion version) : + _engineHandle(engineHandle), + _type(type), + _name(name), + _version(version) +{ +} + +ICubismMotionSyncEngine::~ICubismMotionSyncEngine() +{ +} + +}}}} diff --git a/Framework/src/ICubismMotionSyncEngine.hpp b/Framework/src/ICubismMotionSyncEngine.hpp new file mode 100644 index 0000000..e0bdb96 --- /dev/null +++ b/Framework/src/ICubismMotionSyncEngine.hpp @@ -0,0 +1,115 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismMotionSyncEngineVersion.hpp" +#include "Lib/CubismMotionSyncEngineLib.hpp" +#include "Lib/CubismMotionSyncUtil.hpp" +#include "Type/csmVector.hpp" + +#define DEFAULT_AUDIO_BIT_DEPTH 32 + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class ICubismMotionSyncProcessor; + +class ICubismMotionSyncEngine +{ +public: + /** + * @brief モーションシンクエンジンの種別を返す + * + * @return name モーションシンクエンジンの種別 + */ + EngineType GetType(); + + /** + * @brief モーションシンクエンジンの名前を返す + * + * @return エンジン名 + */ + csmString GetName(); + + /** + * @brief モーションシンクエンジンのバージョンを返す + * + * @return version バージョン + */ + CubismMotionSyncEngineVersion GetVersion(); + + /** + * @brief モーションシンクエンジンが解放されているかをチェックする + * + * @return version バージョン + */ + csmBool IsClosed(); + + /** + * @brief プロセッサーのリストを返す + * + * @return プロセッサーのリスト + */ + csmVector GetProcessors(); + + /** + * @brief モーションシンクエンジンが持つプロセッサーをすべて解放する + */ + void ReleaseAllProcessor(); + + /** + * @brief モーションシンクエンジンのネイティブ側のハンドルを返す + * + * @return モーションシンクエンジンのネイティブハンドル + */ + CubismMotionSyncEngineLib* GetEngineHandle(); + + /** + * @brief モーションシンクエンジンを解放する。 + * + * @param isForce 解放フラグ + */ + void Close(csmBool isForce); + + /** + * @brief 対象のプロセッサーとエンジンとの関連を削除する + * + * @param processor 対象のプロセッサー + */ + void DeleteAssociation(ICubismMotionSyncProcessor* processor); + + /** + * @brief コンストラクタ + * + * コンストラクタ + * + * @param[in] engineHandle エンジンのハンドル + * @param[in] type エンジンの種類 + * @param[in] name エンジンの名前 + * @param[in] version エンジンのバージョン + */ + ICubismMotionSyncEngine(CubismMotionSyncEngineLib *engineHandle, EngineType type, csmString name, CubismMotionSyncEngineVersion version); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~ICubismMotionSyncEngine(); + +protected: + csmVector _processors; + +private: + CubismMotionSyncEngineLib *_engineHandle; + EngineType _type; + csmString _name; + CubismMotionSyncEngineVersion _version; +}; + +}}}} diff --git a/Framework/src/ICubismMotionSyncProcessor.cpp b/Framework/src/ICubismMotionSyncProcessor.cpp new file mode 100644 index 0000000..85515b6 --- /dev/null +++ b/Framework/src/ICubismMotionSyncProcessor.cpp @@ -0,0 +1,69 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "ICubismMotionSyncProcessor.hpp" +#include "ICubismMotionSyncEngine.hpp" + + //--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +CubismMotionSyncEngineAnalysisResult* ICubismMotionSyncProcessor::CreateAnalysisResult() +{ + if (IsClosed() || _mappingInfoArray.GetSize() == 0) + { + return CSM_NEW CubismMotionSyncEngineAnalysisResult(0); + } + + return CSM_NEW CubismMotionSyncEngineAnalysisResult(_mappingInfoArray[0].GetModelParameterValues().GetSize()); +} + +Framework::csmVector ICubismMotionSyncProcessor::GetMappingInfoArray() +{ + return _mappingInfoArray; +} + +EngineType ICubismMotionSyncProcessor::GetType() +{ + return _engine->GetType(); +} + +Framework::csmBool ICubismMotionSyncProcessor::IsClosed() +{ + return _contextHandle == NULL; +} + +void ICubismMotionSyncProcessor::Close() +{ + // 解放済みなら何もしない。 + if (_contextHandle == NULL) + { + return; + } + + _engine->GetEngineHandle()->DeleteContext(_contextHandle->Context()); + CSM_DELETE(_contextHandle); + _contextHandle = NULL; + _engine->DeleteAssociation(this); +} + +MotionSyncContext* ICubismMotionSyncProcessor::GetContextHandle() +{ + return _contextHandle; +} + +ICubismMotionSyncProcessor::ICubismMotionSyncProcessor(ICubismMotionSyncEngine *engine, MotionSyncContext *contextHandle, Framework::csmVector mappingInfoArray) : + _engine(engine), + _contextHandle(contextHandle), + _mappingInfoArray(mappingInfoArray) +{ +} + +ICubismMotionSyncProcessor::~ICubismMotionSyncProcessor() +{ +} + +}}}} diff --git a/Framework/src/ICubismMotionSyncProcessor.hpp b/Framework/src/ICubismMotionSyncProcessor.hpp new file mode 100644 index 0000000..d8befe0 --- /dev/null +++ b/Framework/src/ICubismMotionSyncProcessor.hpp @@ -0,0 +1,83 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismMotionSyncEngineAnalysisResult.hpp" +#include "Lib/CubismMotionSyncUtil.hpp" + +//--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +class ICubismMotionSyncEngine; + +class ICubismMotionSyncProcessor +{ +public: + /** + * @brief 解析結果を格納するクラスを生成する + * + * @return 解析結果を格納するクラス + */ + CubismMotionSyncEngineAnalysisResult* CreateAnalysisResult(); + + /** + * @brief モーションシンクの解析時に使用するマッピング情報のクラスを取得する + * + * @return モーションシンクの解析時に使用するマッピング情報のクラス + */ + csmVector GetMappingInfoArray(); + + /** + * @brief プロセッサーのを作成したエンジンのタイプを取得 + * + * @return プロセッサーのを作成したエンジンのタイプ + */ + EngineType GetType(); + + /** + * @brief プロセッサーの状態(解放済みかどうか)を返す + * + * @return プロセッサーの状態 + */ + csmBool IsClosed(); + + /** + * @brief モーションシンクのコンテキストを解放する + */ + void Close(); + + /** + * @brief モーションシンクのコンテキストのネイティブハンドルを取得する + * + * @return nativeHandle モーションシンクのコンテキストのネイティブハンドル + */ + MotionSyncContext* GetContextHandle(); + + /** + * @brief コンストラクタ + * + * コンストラクタ + */ + ICubismMotionSyncProcessor(ICubismMotionSyncEngine *engine, MotionSyncContext *contextHandle, csmVector mappingInfoArray); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~ICubismMotionSyncProcessor(); + +protected: + ICubismMotionSyncEngine* _engine; + +private: + csmVector _mappingInfoArray; + MotionSyncContext *_contextHandle; + }; + +}}}} diff --git a/Framework/src/Lib/CMakeLists.txt b/Framework/src/Lib/CMakeLists.txt new file mode 100644 index 0000000..fe2b317 --- /dev/null +++ b/Framework/src/Lib/CMakeLists.txt @@ -0,0 +1,10 @@ +target_sources(${LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncConfig.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineLib.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineLib.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncUtil.hpp +) + +# Add sub directories. +add_subdirectory(impl) \ No newline at end of file diff --git a/Framework/src/Lib/CubismMotionSyncConfig.hpp b/Framework/src/Lib/CubismMotionSyncConfig.hpp new file mode 100644 index 0000000..06f03fc --- /dev/null +++ b/Framework/src/Lib/CubismMotionSyncConfig.hpp @@ -0,0 +1,81 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#ifndef LIVE2D_1FE7D7637C5F467DA22BF0137A413974_INCLUDED +#define LIVE2D_1FE7D7637C5F467DA22BF0137A413974_INCLUDED +#include + + /************************************************************************ + * Cと互換性のある構造体として定義 + * Live2DCubismMotionSyncConfiguration_XXX.h と同じ構造体として定義すること。 + ************************************************************************/ + + //TODO: [SK] 必要であれば有効にする +#if 0 +struct MotionSyncEngineConfig_CRI +{ + MotionSyncEngineConfig_CRI( + void* allocator = NULL + , void* deallocator = NULL) + : Allocator(allocator) + , Deallocator(deallocator) + { + } + + /** Audio sample rate. */ + void* Allocator; + + /** Deallocator. */ + void* Deallocator; +}; +#endif + +/* + * Context cofiguration for CRI. + */ +struct MotionSyncContextConfig_CRI +{ + MotionSyncContextConfig_CRI( + Csm::csmInt32 sampleRate = 0 + , Csm::csmInt32 bitDepth = 0) + : SampleRate(sampleRate) + , BitDepth(bitDepth) + { + } + /** Audio sample rate. */ + Csm::csmInt32 SampleRate; + + /** Audio bit depth. */ + Csm::csmInt32 BitDepth; +}; + +/* + * Analyze cofiguration for CRI. + */ +struct MotionSyncAnalysisConfig_CRI +{ + MotionSyncAnalysisConfig_CRI( + Csm::csmFloat32 blendRatio = 0.0f + , Csm::csmInt32 smoothing = 0 + , Csm::csmFloat32 audioLevelEffectRatio = 0.0f) + : BlendRatio(blendRatio) + , Smoothing(smoothing) + , AudioLevelEffectRatio(audioLevelEffectRatio) + { + } + + /** Blending ratio for vieseme. */ + Csm::csmFloat32 BlendRatio; + + /** Smoothing value. */ + Csm::csmInt32 Smoothing; + + /** Audio level effect ratio. */ + Csm::csmFloat32 AudioLevelEffectRatio; +}; + +#endif // LIVE2D_1FE7D7637C5F467DA22BF0137A413974_INCLUDED diff --git a/Framework/src/Lib/CubismMotionSyncEngineLib.cpp b/Framework/src/Lib/CubismMotionSyncEngineLib.cpp new file mode 100644 index 0000000..aae03b8 --- /dev/null +++ b/Framework/src/Lib/CubismMotionSyncEngineLib.cpp @@ -0,0 +1,131 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineLib.hpp" +#include +#include "CubismFramework.hpp" +#include "impl/CubismMotionSyncEngineLoader.hpp" + +#define CSM_ENSURE(COND) \ + if (!(COND)) { return; } else {} +#define CSM_ENSURE2(COND, RET_VALUE) \ + if (!(COND)) { return RET_VALUE; } else {} + +inline Csm::csmBool ConvertMotionSyncBool(Csm::csmInt32 value) +{ + if (value == csmMotionSyncTrue) + { + return true; + } + else + { + return false; + } +} + +CubismMotionSyncEngineLib::CubismMotionSyncEngineLib() +{ + _engineIf = CSM_NEW CubismMotionSyncEngineLoader(); +} + +CubismMotionSyncEngineLib::~CubismMotionSyncEngineLib() +{ + UnloadLibrary(); + + CSM_DELETE(_engineIf); + _engineIf = NULL; +} + +Csm::csmBool CubismMotionSyncEngineLib::LoadLibrary(const Csm::csmChar* dllPath) +{ + //既にロード済みの場合は何もせずに返る + CSM_ENSURE2(!_engineIf->isValid(), true); + return _engineIf->LoadLib(dllPath); +} + +void CubismMotionSyncEngineLib::UnloadLibrary() +{ + CSM_ENSURE(_engineIf->isValid()); + _engineIf->UnloadLib(); +} + +CubismMotionSyncVersion CubismMotionSyncEngineLib::GetEngineVersion() +{ + CSM_ENSURE2(_engineIf->isValid(), 0); + return _engineIf->GetEngineVersion(); +} + +const Csm::csmChar* CubismMotionSyncEngineLib::GetEngineName() +{ + CSM_ENSURE2(_engineIf->isValid(), ""); + return _engineIf->GetEngineName(); +} + +Csm::csmBool CubismMotionSyncEngineLib::InitializeEngine(const void* engineConfig) +{ + CSM_ENSURE2(_engineIf->isValid(), false); + const int ret = _engineIf->InitializeEngine(engineConfig); + return ConvertMotionSyncBool(ret); +} + +void CubismMotionSyncEngineLib::DisposeEngine() +{ + CSM_ENSURE(_engineIf->isValid()); + _engineIf->DisposeEngine(); +} + +CubismMotionSyncContext CubismMotionSyncEngineLib::CreateContext( + const void* contextConfig + , const CubismMotionSyncMappingInfo* mappingInfoList + , Csm::csmInt32 mappingInfoListCount +) +{ + CSM_ENSURE2(_engineIf->isValid(), NULL); + return _engineIf->CreateContext( + contextConfig + , reinterpret_cast(mappingInfoList) + , mappingInfoListCount + ); +} + +void CubismMotionSyncEngineLib::ClearContext(CubismMotionSyncContext context) +{ + CSM_ENSURE(_engineIf->isValid()); + _engineIf->ClearContext(context); +} + +void CubismMotionSyncEngineLib::DeleteContext(CubismMotionSyncContext context) +{ + CSM_ENSURE(_engineIf->isValid()); + _engineIf->DeleteContext(context); +} + +Csm::csmUint32 CubismMotionSyncEngineLib::GetRequireSampleCount(CubismMotionSyncContext context) +{ + CSM_ENSURE2(_engineIf->isValid(), 0); + return _engineIf->GetRequireSampleCount(context); +} + +Csm::csmBool CubismMotionSyncEngineLib::Analyze( + CubismMotionSyncContext context + , const Csm::csmFloat32* samples + , Csm::csmUint32 sampleCount + , CubismMotionSyncAnalysisResult* analysisResult + , const void* analyzeConfig +) +{ + CSM_ENSURE2(_engineIf->isValid(), false); + const Csm::csmInt32 ret = _engineIf->Analyze( + context + , samples + , sampleCount + , reinterpret_cast(analysisResult) + , analyzeConfig + ); + + return ConvertMotionSyncBool(ret); +} diff --git a/Framework/src/Lib/CubismMotionSyncEngineLib.hpp b/Framework/src/Lib/CubismMotionSyncEngineLib.hpp new file mode 100644 index 0000000..ff548d5 --- /dev/null +++ b/Framework/src/Lib/CubismMotionSyncEngineLib.hpp @@ -0,0 +1,186 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#ifndef LIVE2D_446C6AB6A76D465FBEB5EAA18FAA3141_INCLUDED +#define LIVE2D_446C6AB6A76D465FBEB5EAA18FAA3141_INCLUDED +#include +#include + +class CubismMotionSyncEngineLoader; + +/************************************************************************ + * Cと互換性のある構造体として定義 + * Live2DCubismMotionSyncEngine.h と同じ構造体として定義すること。 + ************************************************************************/ + /** Context of Analysis. */ +typedef void* CubismMotionSyncContext; + +/** Engine version identifier. */ +typedef Csm::csmUint32 CubismMotionSyncVersion; + +/** + * Result of analysis. + */ +struct CubismMotionSyncAnalysisResult +{ + CubismMotionSyncAnalysisResult( + Csm::csmFloat32* values = NULL + , Csm::csmInt32 valuesCount = NULL + , Csm::csmUint32 processedSampleCount = 0) + : Values(values), + ValuesCount(valuesCount), + ProcessedSampleCount(processedSampleCount) {} + + /** Value Array of CubismParameter */ + Csm::csmFloat32* Values; + + /** Number of values used in the analysis. */ + Csm::csmInt32 ValuesCount; + + /** Number of samples used in the analysis. */ + Csm::csmUint32 ProcessedSampleCount; +}; + +/** Mapping Information of AudioParameter. */ +struct CubismMotionSyncMappingInfo +{ + CubismMotionSyncMappingInfo( + const Csm::csmChar* audioParameterId = NULL + , const Csm::csmChar** modelParameterIds = NULL + , Csm::csmFloat32* modelParameterValues = NULL + , Csm::csmUint32 modelParameterCount = 0 + , Csm::csmFloat32 scale = 0.0f + , Csm::csmUint32 enabled = 0) + : AudioParameterId(audioParameterId), + ModelParameterIds(modelParameterIds), + ModelParameterValues(modelParameterValues), + ModelParameterCount(modelParameterCount), + Scale(scale), + Enabled(enabled) {} + ~CubismMotionSyncMappingInfo() + { + int a = 0; + } + + /** ID of AudioParameter. */ + const Csm::csmChar* AudioParameterId; + + /** Array of ID of ModelParameter linked to the AudioParameter. */ + const Csm::csmChar** ModelParameterIds; + + /** Array of ModelParameter Value. */ + Csm::csmFloat32* ModelParameterValues; + + /** Number of ModelParameter. */ + Csm::csmUint32 ModelParameterCount; + + /** Scaling value for CubismParameter. */ + Csm::csmFloat32 Scale; + + /** Enable / Disable for applying.*/ + Csm::csmUint32 Enabled; +}; + + +class CubismMotionSyncEngineLib +{ +public: + CubismMotionSyncEngineLib(); + ~CubismMotionSyncEngineLib(); + + Csm::csmBool LoadLibrary(const Csm::csmChar* dllPath); + void UnloadLibrary(); + + /** + * Queries the version of Engine. + * + * @return Version of Engine. + */ + CubismMotionSyncVersion GetEngineVersion(); + + /** + * Queries the name of Engine. + * + * @return Name of Engine. + */ + const Csm::csmChar* GetEngineName(); + + /** + * Initializes the Engine. + + * @param engineConfig Congifuration parameter for engine initialization. Set to `NULL` to use default parameter. + * + * @return `true` if Engine is available. + */ + Csm::csmBool InitializeEngine(const void* engineConfig); + + /** + * Disposes the Engine. + */ + void DisposeEngine(); + + /** + * Makes the context of Analysis. + * + * @param contextConfig Congifuration parameter for engine initialization. Set to `NULL` to use default parameter. + * @param mappingInfoList Array of Mapping Information of AudioParameter. + * @param mappingInfoListCount Length of `mappingInfoList`. + * + * @return Valid pointer on success; '0' otherwise. + */ + CubismMotionSyncContext CreateContext( + const void* contextConfig + , const CubismMotionSyncMappingInfo* mappingInfoList + , Csm::csmInt32 mappingInfoListCount + ); + + /** + * Resets the context of Analysis for reusing. + * + * @param context Context to reset. + */ + void ClearContext(CubismMotionSyncContext context); + + /** + * Destroys the context of Analysis. + * + * @param context Context to destroy. + */ + void DeleteContext(CubismMotionSyncContext context); + + /** + * Gets the number of samples to analyze at a time. + * + * @param context Context to query. + * + * @return Number of samples. + */ + Csm::csmUint32 GetRequireSampleCount(CubismMotionSyncContext context); + + /** + * Analyzes the samples for conversion to the CubismParameter. + * + * @param context Context to analyze. + * @param samples Array of sample to analyze. + * @param sampleCount Number of samples. + * @param analysisResult Array to store results. + * + * @return `true` if succeeded the analysis. + */ + Csm::csmBool Analyze( + CubismMotionSyncContext context + , const Csm::csmFloat32* samples + , Csm::csmUint32 sampleCount + , CubismMotionSyncAnalysisResult* analysisResult + , const void* analyzeConfig + ); + +private: + CubismMotionSyncEngineLoader* _engineIf; +}; + +#endif diff --git a/Framework/src/Lib/CubismMotionSyncUtil.hpp b/Framework/src/Lib/CubismMotionSyncUtil.hpp new file mode 100644 index 0000000..25649bf --- /dev/null +++ b/Framework/src/Lib/CubismMotionSyncUtil.hpp @@ -0,0 +1,146 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#define _CRT_SECURE_NO_WARNINGS + +#include "CubismMotionSyncEngineLib.hpp" +#include "CubismMotionSyncEngineMappingInfo.hpp" + + //--------- LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace MotionSync { + +enum EngineType +{ + EngineType_Cri, + EngineType_Unknown, +}; + +class MappingInfoListMapper +{ +public: + // ----------- コンストラクタ・デストラクタ ----------- + MappingInfoListMapper() + {} + + ~MappingInfoListMapper() + { + DeleteMappingInfoList(); + } + +// ----------- メンバ関数 ----------- +public: + void SetJObject(csmVector infoList) + { + DeleteMappingInfoList(); + ConvertObjectToNative(infoList); + } + + const CubismMotionSyncMappingInfo* Data() + { + return _infoList.GetPtr(); + } + + csmUint32 Count() const + { + return _infoList.GetSize(); + } + +private: + void ConvertObjectToNative(csmVector mapInfoList) + { + const csmInt32 infoListCount = mapInfoList.GetSize(); + + + for (csmInt32 infoIdx = 0; infoIdx < infoListCount; infoIdx++) + { + CubismMotionSyncEngineMappingInfo& mapInfo = mapInfoList[infoIdx]; + CubismMotionSyncMappingInfo info; + // Enabled + info.Enabled = mapInfo.IsEnabled(); + // Scale + info.Scale = mapInfo.GetScale(); + // AudioParameterId + csmChar* buff = static_cast(CSM_MALLOC(sizeof(csmChar) * (mapInfo.GetAudioParameterId().GetLength() + 1))); + strcpy(buff, mapInfo.GetAudioParameterId().GetRawString()); + info.AudioParameterId = buff; + // ModelParameterValues + info.ModelParameterValues = static_cast(CSM_MALLOC(sizeof(csmFloat32) * mapInfo.GetModelParameterValues().GetSize())); + for (csmUint32 i = 0; i < mapInfo.GetModelParameterValues().GetSize(); i++) + { + info.ModelParameterValues[i] = mapInfo.GetModelParameterValues()[i]; + } + // ModelParameterIds + info.ModelParameterCount = mapInfo.GetModelParameterIds().GetSize(); + csmChar** buffs = static_cast(CSM_MALLOC(sizeof(csmChar*) * mapInfo.GetModelParameterIds().GetSize())); + for (csmUint32 i = 0; i < mapInfo.GetModelParameterIds().GetSize(); i++) + { + buffs[i] = static_cast(CSM_MALLOC(sizeof(csmChar) * (mapInfo.GetModelParameterIds()[i].GetLength() + 1))); + strcpy(buffs[i], mapInfo.GetModelParameterIds()[i].GetRawString()); + } + info.ModelParameterIds = const_cast(buffs); + + _infoList.PushBack(info); + } + } + + void DeleteMappingInfoList() + { + for (csmUint32 infoIdx = 0; infoIdx < _infoList.GetSize(); ++infoIdx) + { + const CubismMotionSyncMappingInfo& info = _infoList[infoIdx]; + + CSM_FREE(const_cast(info.AudioParameterId)); + CSM_FREE(info.ModelParameterValues); + + for (csmUint32 paramIdx = 0; paramIdx < info.ModelParameterCount; ++paramIdx) + { + CSM_FREE(const_cast(info.ModelParameterIds[paramIdx])); + } + CSM_FREE(info.ModelParameterIds); + } + + _infoList.Clear(); + } + +// ----------- メンバ変数 ----------- +private: + csmVector _infoList; +}; + +struct MotionSyncContext +{ +public: + MotionSyncContext(CubismMotionSyncContext context, MappingInfoListMapper* mapper) + : _context(context), _mapper(mapper) + { + } + + ~MotionSyncContext() + { + CSM_DELETE(_mapper); + _mapper = NULL; + _context = NULL; + } + + CubismMotionSyncContext Context() const + { + return _context; + } + + MappingInfoListMapper* Mapper() const + { + return _mapper; + } + +private: + CubismMotionSyncContext _context; + MappingInfoListMapper* _mapper; +}; + +}}}} diff --git a/Framework/src/Lib/impl/CMakeLists.txt b/Framework/src/Lib/impl/CMakeLists.txt new file mode 100644 index 0000000..7fc6b27 --- /dev/null +++ b/Framework/src/Lib/impl/CMakeLists.txt @@ -0,0 +1,15 @@ +if(WIN32) + set(LIBRARY_LOADER "Win") +elseif(CMAKE_HOST_APPLE) + set(LIBRARY_LOADER "Mac") +else() + +endif() + +target_sources(${LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineLoader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionSyncEngineLoader.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LibraryLoader_${LIBRARY_LOADER}.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LibraryLoader.h +) diff --git a/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.cpp b/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.cpp new file mode 100644 index 0000000..bbb4265 --- /dev/null +++ b/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.cpp @@ -0,0 +1,91 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismMotionSyncEngineLoader.hpp" +#include "LibraryLoader.h" + +CubismMotionSyncEngineLoader::CubismMotionSyncEngineLoader() +{ + _loader = CSM_NEW LibraryLoader; + ResetFuncPtr(); +} + +CubismMotionSyncEngineLoader::~CubismMotionSyncEngineLoader() +{ + UnloadLib(); + + CSM_DELETE(_loader); + _loader = NULL; +} + +Csm::csmBool CubismMotionSyncEngineLoader::isValid() const +{ + return _loader->isValid(); +} + +Csm::csmBool CubismMotionSyncEngineLoader::LoadLib(const Csm::csmChar* dllPath) +{ + //DLLロード済みの場合 + if (isValid()) + { + return true; + } + + const Csm::csmBool isLoadSucceed = _loader->Load(dllPath); + if (!isLoadSucceed) + { + return false; + } + + GetEngineVersion = _loader->GetFuncPtr("csmMotionSync_GetEngineVersion"); + GetEngineName = _loader->GetFuncPtr("csmMotionSync_GetEngineName"); + InitializeEngine = _loader->GetFuncPtr("csmMotionSync_InitializeEngine"); + DisposeEngine = _loader->GetFuncPtr("csmMotionSync_DisposeEngine"); + CreateContext = _loader->GetFuncPtr("csmMotionSync_CreateContext"); + ClearContext = _loader->GetFuncPtr("csmMotionSync_ClearContext"); + DeleteContext = _loader->GetFuncPtr("csmMotionSync_DeleteContext"); + GetRequireSampleCount = _loader->GetFuncPtr("csmMotionSync_GetRequireSampleCount"); + Analyze = _loader->GetFuncPtr("csmMotionSync_Analyze"); + + const Csm::csmBool isFuncValid = + GetEngineVersion && GetEngineName && InitializeEngine + && DisposeEngine && CreateContext + && ClearContext && DeleteContext + && GetRequireSampleCount && Analyze; + + if (!isFuncValid) + { + UnloadLib(); + return false; + } + + return true; +} + +void CubismMotionSyncEngineLoader::UnloadLib() +{ + if (!isValid()) + { + return; + } + + ResetFuncPtr(); + _loader->Unload(); +} + +void CubismMotionSyncEngineLoader::ResetFuncPtr() +{ + GetEngineVersion = NULL; + GetEngineName = NULL; + InitializeEngine = NULL; + DisposeEngine = NULL; + CreateContext = NULL; + ClearContext = NULL; + DeleteContext = NULL; + GetRequireSampleCount = NULL; + Analyze = NULL; +} diff --git a/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.hpp b/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.hpp new file mode 100644 index 0000000..ff6f4b2 --- /dev/null +++ b/Framework/src/Lib/impl/CubismMotionSyncEngineLoader.hpp @@ -0,0 +1,88 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#ifndef LIVE2D_C3B887DF018044E384CCF1FFF892970A_INCLUDED +#define LIVE2D_C3B887DF018044E384CCF1FFF892970A_INCLUDED + +#include "Live2DCubismMotionSyncEngine.h" +#include "CubismFramework.hpp" + +#ifdef _WIN32 +#ifndef _WIN64 +#define csmMotionSyncCallingPtr __stdcall +#endif +#endif + +#ifndef csmMotionSyncCallingPtr +#define csmMotionSyncCallingPtr +#endif + +class LibraryLoader; + +typedef csmMotionSyncVersion(csmMotionSyncCallingPtr *csmMotionSync_GetEngineVersionFunc)(); + +typedef const Csm::csmChar* (csmMotionSyncCallingPtr *csmMotionSync_GetEngineNameFunc)(); + +typedef Csm::csmInt32 (csmMotionSyncCallingPtr *csmMotionSync_InitializeEngineFunc)( + const void* engineConfiguration + ); + +typedef void (csmMotionSyncCallingPtr *csmMotionSync_DisposeEngineFunc)(); + +typedef csmMotionSync_Context(csmMotionSyncCallingPtr *csmMotionSync_CreateContextFunc)( + const void* contextConfiguration, + const csmMotionSync_MappingInfo* mappingInformations, + Csm::csmInt32 mappingInformationCount + ); + +typedef void (csmMotionSyncCallingPtr *csmMotionSync_ClearContextFunc)( + csmMotionSync_Context context + ); + +typedef void (csmMotionSyncCallingPtr *csmMotionSync_DeleteContextFunc)( + csmMotionSync_Context context + ); + +typedef Csm::csmUint32 (csmMotionSyncCallingPtr *csmMotionSync_GetRequireSampleCountFunc)( + csmMotionSync_Context context + ); + +typedef Csm::csmInt32 (csmMotionSyncCallingPtr *csmMotionSync_AnalyzeFunc)( + csmMotionSync_Context context, + const Csm::csmFloat32* samples, + Csm::csmUint32 sampleCount, + csmMotionSync_AnalysisResult* analysisResult, + const void* analysisConfig + ); + +class CubismMotionSyncEngineLoader +{ +public: + CubismMotionSyncEngineLoader(); + ~CubismMotionSyncEngineLoader(); + csmMotionSync_GetEngineVersionFunc GetEngineVersion; + csmMotionSync_GetEngineNameFunc GetEngineName; + csmMotionSync_InitializeEngineFunc InitializeEngine; + csmMotionSync_DisposeEngineFunc DisposeEngine; + csmMotionSync_CreateContextFunc CreateContext; + csmMotionSync_ClearContextFunc ClearContext; + csmMotionSync_DeleteContextFunc DeleteContext; + csmMotionSync_GetRequireSampleCountFunc GetRequireSampleCount; + csmMotionSync_AnalyzeFunc Analyze; + + Csm::csmBool isValid() const; + + Csm::csmBool LoadLib(const Csm::csmChar* dllPath); + void UnloadLib(); + +private: + void ResetFuncPtr(); + + LibraryLoader* _loader; +}; + +#endif // LIVE2D_C3B887DF018044E384CCF1FFF892970A_INCLUDED diff --git a/Framework/src/Lib/impl/LibraryLoader.h b/Framework/src/Lib/impl/LibraryLoader.h new file mode 100644 index 0000000..fc693fd --- /dev/null +++ b/Framework/src/Lib/impl/LibraryLoader.h @@ -0,0 +1,45 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#ifndef LIVE2D_0BA1D179C7E84EEE9FBFD714C7B87282_INCLUDED +#define LIVE2D_0BA1D179C7E84EEE9FBFD714C7B87282_INCLUDED +#include +#include + +typedef void* csmDllModule; + +class LibraryLoader +{ +public: + LibraryLoader() + : module_(NULL) + {} + ~LibraryLoader() + { + Unload(); + } + + Csm::csmBool Load(const Csm::csmChar* dllPath); + void Unload(); + template + T GetFuncPtr(const Csm::csmChar* funcName) + { + return reinterpret_cast(GetFuncPtrInternal(funcName)); + } + + Csm::csmBool isValid() const + { + return module_; + } + +private: + void* GetFuncPtrInternal(const Csm::csmChar* funcName); + + csmDllModule module_; +}; + +#endif // LIVE2D_0BA1D179C7E84EEE9FBFD714C7B87282_INCLUDED diff --git a/Framework/src/Lib/impl/LibraryLoader_Mac.cpp b/Framework/src/Lib/impl/LibraryLoader_Mac.cpp new file mode 100644 index 0000000..e5b08ac --- /dev/null +++ b/Framework/src/Lib/impl/LibraryLoader_Mac.cpp @@ -0,0 +1,49 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LibraryLoader.h" + +#include + +#define DYNAMIC_LIBRARY_LOAD(X) dlopen(X,RTLD_NOW) +#define DYNAMIC_LIBRARY_INSTANCE void* +#define DYNAMIC_LIBRARY_FREE dlclose +#define DYNAMIC_LIBRARY_LOAD_PROC dlsym + + +bool LibraryLoader::Load(const char* dllPath) +{ + //DLLロード済みの場合 + if (isValid()) + { + return true; + } + + module_ = DYNAMIC_LIBRARY_LOAD(dllPath); + + return module_; +} + +void LibraryLoader::Unload() +{ + if (!isValid()) + { + return; + } + + DYNAMIC_LIBRARY_FREE((DYNAMIC_LIBRARY_INSTANCE)module_); + module_ = NULL; +} + +void* LibraryLoader::GetFuncPtrInternal(const char* funcName) +{ + if (!isValid()) + { + return NULL; + } + return DYNAMIC_LIBRARY_LOAD_PROC(module_, funcName); +} diff --git a/Framework/src/Lib/impl/LibraryLoader_Win.cpp b/Framework/src/Lib/impl/LibraryLoader_Win.cpp new file mode 100644 index 0000000..2be49bb --- /dev/null +++ b/Framework/src/Lib/impl/LibraryLoader_Win.cpp @@ -0,0 +1,61 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LibraryLoader.h" +#include + +#define DYNAMIC_LIBRARY_LOAD(X) ::LoadLibraryW(X) +#define DYNAMIC_LIBRARY_INSTANCE ::HMODULE +#define DYNAMIC_LIBRARY_FREE ::FreeLibrary +#define DYNAMIC_LIBRARY_LOAD_PROC ::GetProcAddress + + // UTF8→UTF16文字列を変換する + // 変換された文字列は、delete[] で解放する必要がある。 +static wchar_t* ConvertUtf8ToUtf16(const Csm::csmChar* utf8String) +{ + // 変換後のwchar_t配列の要素数(null終端を含む)を取得 + const Csm::csmInt32 size = ::MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0); + wchar_t* utf16String = static_cast(CSM_MALLOC(sizeof(wchar_t) * size)); + ::MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, utf16String, size); + + return utf16String; +} + +Csm::csmBool LibraryLoader::Load(const Csm::csmChar* dllPath) +{ + //DLLロード済みの場合 + if (isValid()) + { + return true; + } + + wchar_t* u16DllPath = ConvertUtf8ToUtf16(dllPath); + module_ = DYNAMIC_LIBRARY_LOAD(u16DllPath); + CSM_FREE(u16DllPath); + + return module_; +} + +void LibraryLoader::Unload() +{ + if (!isValid()) + { + return; + } + + DYNAMIC_LIBRARY_FREE((DYNAMIC_LIBRARY_INSTANCE)module_); + module_ = NULL; +} + +void* LibraryLoader::GetFuncPtrInternal(const Csm::csmChar* funcName) +{ + if (!isValid()) + { + return NULL; + } + return DYNAMIC_LIBRARY_LOAD_PROC(reinterpret_cast(module_), funcName); +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..68c3ce3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,62 @@ +## Definitions + +### Live2D Cubism Components + +Cubism Native MotionSync Components is included in Live2D Cubism Components. + +Cubism Native MotionSync Components は Live2D Cubism Components に含まれます。 + +Cubism Native MotionSync Components 包括在 Live2D Cubism Components 中。 + +## Cubism SDK Release License + +*All business* users must obtain a Cubism SDK Release License. "Business" means an entity with the annual gross revenue more than ten million (10,000,000) JPY for the most recent fiscal year. + +* [Cubism SDK Release License](https://www.live2d.com/en/download/cubism-sdk/release-license/) + +直近会計年度の売上高が 1000 万円以上の事業者様がご利用になる場合は、Cubism SDK リリースライセンス(出版許諾契約)に同意していただく必要がございます。 + +* [Cubism SDK リリースライセンス](https://www.live2d.com/ja/download/cubism-sdk/release-license/) + +如果您的企业在最近一个会计年度的销售额达到或超过1000万日元,您必须得到Cubism SDK的出版授权许可(出版许可协议)。 + +* [Cubism SDK发行许可证](https://www.live2d.com/zh-CHS/download/cubism-sdk/release-license/) + + +## Live2D Open Software License + +Live2D Cubism Components is available under Live2D Open Software License. + +* [Live2D Open Software License Agreement](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html) +* [Live2D Open Software 使用許諾契約書](https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html) +* [Live2D Open Software 使用授权协议](https://www.live2d.com/eula/live2d-open-software-license-agreement_cn.html) + + +## Live2D Proprietary Software License + +Live2D Cubism Core is available under Live2D Proprietary Software License. + +* [Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html) +* [Live2D Proprietary Software 使用許諾契約書](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_jp.html) +* [Live2D Proprietary Software 使用授权协议](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_cn.html) + + +## Free Material License + +Live2D models listed below are available under Free Material License. + +* [Free Material License Agreement](https://www.live2d.com/eula/live2d-free-material-license-agreement_en.html) +* [無償提供マテリアルの使用許諾契約書](https://www.live2d.com/eula/live2d-free-material-license-agreement_jp.html) +* [无偿提供素材使用授权协议](https://www.live2d.com/eula/live2d-free-material-license-agreement_cn.html) + +``` +Samples/Resources/Kei_basic +Samples/Resources/Kei_vowels +``` + +If you use these models, you must agree to the terms of a contract set [here](https://docs.live2d.com/cubism-editor-manual/sample-model/) for each model. + + +--- + +Please contact us from [here](https://www.live2d.jp/contact/) for more license information. diff --git a/NOTICE.ja.md b/NOTICE.ja.md new file mode 100644 index 0000000..97529bd --- /dev/null +++ b/NOTICE.ja.md @@ -0,0 +1,25 @@ +[English](NOTICE.md) / [日本語](NOTICE.ja.md) + +--- + +# お知らせ + +## [制限事項] Cubism SDK MotionSync Plugin for Native の対応環境について (2023-10-17) + +本プラグインのバージョン R1 beta1 (5-r.1-beta.1) 時点では以下の環境のみ動作を確認しております。 + +* Windows + * x86 + * x86_64 +* macOS + * x86_64 + * ARM64 + +以下の環境については、順次対応を行います。 + +* Android +* iOS + +--- + +©Live2D diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..af03fb2 --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,25 @@ +[English](NOTICE.md) / [日本語](NOTICE.ja.md) + +--- + +# Notices + +## [Restrictions] Supported environments for Cubism SDK MotionSync Plugin for Native (2023-10-17) + +As of version R1 beta1 (5-r.1-beta.1) of this plugin, only the following environments have been confirmed to work: + +* Windows + * x86 + * x86_64 +* macOS + * x86_64 + * ARM64 + +The following environments will be supported in due course: + +* Android +* iOS + +--- + +©Live2D diff --git a/README.ja.md b/README.ja.md new file mode 100644 index 0000000..c21e6b5 --- /dev/null +++ b/README.ja.md @@ -0,0 +1,139 @@ +[English](README.md) / [日本語](README.ja.md) + +--- + + +# Cubism MotionSync Plugin for Native + +Cubism SDK for Native上で、モーションシンク機能を利用するためのCubism SDKプラグインです。 + + +## ライセンス + +本 SDK を使用する前に[ライセンス](LICENSE.md)をご確認ください。 + + +## お知らせ + +本 SDK を使用する前に [お知らせ](NOTICE.ja.md)をご確認ください。 + + +## 構造 + +### 依存関係 + +#### Cubism SDK for Native + +Live2D Cubism Editor で出力したモーションシンク対応モデルを表示するアプリケーションのサンプル実装です。 + +利用するにはCubism SDK for Nativeのパッケージが必要となります。 +SDKパッケージのダウンロードページをお探しの場合は、[ダウンロードページ](https://www.live2d.com/sdk/download/native/)にアクセスしてください。 +このリポジトリと同じ階層にCubism SDK for Nativeのパッケージを置いてください。 + +#### Live2D Cubism MotionSync Core + +モーションシンク機能を提供するライブラリです。当リポジトリにはLive2D Cubism MotionSync Coreは同梱されていません。 + +Live2D Cubism MotionSync Coreを同梱したプラグインパッケージをダウンロードするには[こちら](https://www.live2d.com/sdk/download/motionsync/)のページを参照ください。 + + +## Cubism 5新機能や過去バージョンとの互換性について + +本 SDK はCubism 5に対応した製品です。 +Cubism 5 Editorに搭載された新機能のSDK対応については [こちら](https://docs.live2d.com/cubism-sdk-manual/cubism-5-new-functions/)をご確認ください。 +過去バージョンのCubism SDKとの互換性については [こちら](https://docs.live2d.com/cubism-sdk-manual/compatibility-with-cubism-5/)をご確認ください。 + + +## ディレクトリ構成 + +``` +. +├─ Core # Live2D Cubism Motion Sync Core が含まれるディレクトリ +├─ Framework # Motion Sync用のレンダリングやアニメーション機能などのソースコードが含まれるディレクトリ +└─ Samples + └─ OpenGL # OpenGL のサンプルプロジェクトが含まれるディレクトリ +``` + + +## ビルド方法 + +ビルド方法についてはサンプルプロジェクトによって異なります。 +各サンプルプロジェクトに同梱された `README.md` を参照ください。 + + +### サンプルプロジェクトの成果物の生成場所 + +本サンプルでは、CMake プロジェクトの成果物は `bin` ディレクトリに生成されます。 + +例)OpenGL サンプルの macOS プロジェクトのビルドを `make_gcc` スクリプトを使用して行なった場合 +``` +Demo +└─ proj.mac.cmake + └─ build + └─ make_gcc + └─ bin + └─ Demo + ├─ Resources # Samples/Resources と同じ + └─ Demo # 実行可能なアプリケーション +``` + + +## SDKマニュアル + +[Cubism SDK Manual](https://docs.live2d.com/cubism-sdk-manual/top/) + + +## 変更履歴 + +当リポジトリの変更履歴については [CHANGELOG.md](CHANGELOG.md) を参照ください。 + + +## 開発環境 + +| 開発ツール | バージョン | +| --- | --- | +| CMake | 3.27.1 | +| Visual Studio 2013 | Update 5 | +| Visual Studio 2015 | Update 3 | +| Visual Studio 2017 | 15.9.56 | +| Visual Studio 2019 | 16.11.29 | +| Visual Studio 2022 | 17.7.0 | +| Xcode | 14.3.1 | + + +## 動作確認環境 + +| プラットフォーム | バージョン | +| --- | --- | +| macOS | 13.6 | +| Windows 10 | 22H2 | +| Windows 11 | 22H2 | +ほかのプラットフォームは順次対応します。 + + +## プロジェクトへの貢献 + +プロジェクトに貢献する方法はたくさんあります。バグのログの記録、このGitHubでのプルリクエストの送信、Live2Dコミュニティでの問題の報告と提案の作成です。 + + +### フォークとプルリクエスト + +修正、改善、さらには新機能をもたらすかどうかにかかわらず、プルリクエストに感謝します。ただし、ラッパーは可能な限り軽量で浅くなるように設計されているため、バグ修正とメモリ/パフォーマンスの改善のみを行う必要があることに注意してください。メインリポジトリを可能な限りクリーンに保つために、必要に応じて個人用フォークと機能ブランチを作成してください。 + + +### バグ + +Live2Dコミュニティでは、問題のレポートと機能リクエストを定期的にチェックしています。バグレポートを提出する前に、Live2Dコミュニティで検索して、問題のレポートまたは機能リクエストがすでに投稿されているかどうかを確認してください。問題がすでに存在する場合は、関連するコメントを追記してください。 + + +### 提案 + +SDKの将来についてのフィードバックにも関心があります。Live2Dコミュニティで提案や機能のリクエストを送信できます。このプロセスをより効果的にするために、それらをより明確に定義するのに役立つより多くの情報を含めるようお願いしています。 + + +## コミュニティ + +ユーザー同士でCubism SDKの活用方法の提案や質問をしたい場合は、是非コミュニティをご活用ください。 + +- [Live2D 公式コミュニティ](https://creatorsforum.live2d.com/) +- [Live2D community(English)](https://community.live2d.com/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd95704 --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +[English](README.md) / [日本語](README.ja.md) + + +# Cubism MotionSync Plugin for Native + +This is a Cubism SDK plugin for using the motion-sync function on the Cubism SDK for Native. + + +## License + +Please read the [license](LICENSE.md) before use. + + +## Notice + +Please read the [notices](NOTICE.md) before use. + + +## Structure + +### Dependencies + +#### Cubism SDK for Native + +This plugin is a Cubism SDK plugin for the Cubism SDK for Native. + +The Cubism SDK for Native package is required for use. + +If you are looking for the download page of the SDK package, please go to the [download page](https://www.live2d.com/en/sdk/download/native/). + +Please place the Cubism SDK for Native package at the same level as this repository. + +#### Live2D Cubism MotionSync Core + +This library provides the motion-sync function. Live2D Cubism MotionSync Core is not included in this repository. + +To download the plugin package that includes Live2D Cubism MotionSync Core, please refer to [this](https://www.live2d.com/en/sdk/download/motionsync/) page. + + +## Directory structure + +``` +. +├─ Core # Directory containing Live2D Cubism Motion Sync Core +├─ Framework # Directory containing source code for rendering and animation functions for motion-sync +└─ Samples + └─ OpenGL # Directory containing the OpenGL sample project +``` + + +## How to build + +The build method depends on the sample project. +Please refer to the `README.md` included with each sample project. + +### Where to generate the sample project deliverables + +In this sample, the deliverables of CMake projects except Android are generated in the `bin` directory. + +E.g. When building a macOS project of the OpenGL sample using the `make_gcc` script +``` +Demo +└─ proj.mac.cmake + └─ build + └─ make_gcc + └─ bin + └─ Demo + ├─ Resources # Same as Samples/Resources + └─ Demo # Executable applications +``` + + +## SDK manual + +[Cubism SDK Manual](https://docs.live2d.com/en/cubism-sdk-manual/top/) + + +## Changelog + +Please refer to [CHANGELOG.md](CHANGELOG.md) for the changelog of this repository. + + +## Development environment + +| Development Tool | Version | +| --- | --- | +| CMake | 3.27.1 | +| Visual Studio 2013 | Update 5 | +| Visual Studio 2015 | Update 3 | +| Visual Studio 2017 | 15.9.56 | +| Visual Studio 2019 | 16.11.29 | +| Visual Studio 2022 | 17.7.0 | +| Xcode | 14.3.1 | + + +## Operation environment + +| Platform | Version | +| --- | --- | +| macOS | 13.6 | +| Windows 10 | 22H2 | +| Windows 11 | 22H2 | +We will gradually support other platforms. + +## Contribution to the project + +There are many ways to contribute to the project: logging bugs, submitting pull requests on this GitHub, and reporting issues and making suggestions in Live2D Community. + +### Forking and Pull Requests + +We very much appreciate your pull requests, whether they bring fixes, improvements, or even new features. Note, however, that the wrapper is designed to be as lightweight and shallow as possible and should therefore only be subject to bug fixes and memory/performance improvements. To keep the main repository as clean as possible, please create a personal fork and feature branch as needed. + +### Bugs + +We are regularly checking bug reports and feature requests at Live2D Community. Before submitting a bug report, please search the Live2D Community to see if the bug report or feature request has already been submitted. Add your comment to the relevant issue if it already exists. + +### Suggestions + +We're also interested in your feedback for the future of the SDK. You can submit a suggestion or feature request at Live2D Community. To make this process more effective, we're asking that you include more information to help define them more clearly. + +## Coding Guidelines + +### Naming + +Try to stick to the [Microsoft guidelines](https://msdn.microsoft.com/en-us/library/ms229002(v=vs.110).aspx) whenever possible. Private fields are named in lowercase, starting with an underscore. + +### Style + +- In the Unity Editor extension, try to write expressive code with LINQ and all the other fancy stuff. +- Otherwise, do not use LINQ and prefer `for` to `foreach`. +- Try to make the access modifier explicit. Use `private void Update()` instead of `void Update()`. + +## Forum + +If you have any questions, please join the official Live2D forum and discuss with other users. + +- [Live2D Creator's Forum](https://community.live2d.com/) +- [Live2D 公式クリエイターズフォーラム (Japanese)](https://creatorsforum.live2d.com/) diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt new file mode 100644 index 0000000..284b73b --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt @@ -0,0 +1,150 @@ +cmake_minimum_required(VERSION 3.16) + +# Set app name. +set(APP_NAME Demo) +# Set directory paths. +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +file(GLOB NATIVE_DIR "${SDK_ROOT_PATH}/../CubismNativeSamples") +# Find non-zip file. +if(NOT NATIVE_DIR) + file(GLOB TMP_DIR "${SDK_ROOT_PATH}/../CubismSdkForNative*") + foreach(DIR ${TMP_DIR}) + get_filename_component(LASTNAME ${DIR} NAME) + if(NOT "${LASTNAME}" MATCHES "\\.zip$") + set(NATIVE_DIR ${DIR}) + break() + endif() + endforeach() +endif() +set(NATIVE_PATH ${NATIVE_DIR} CACHE PATH [[Native File Path]] FORCE) +set(NATIVE_CORE_PATH $CACHE{NATIVE_PATH}/Core) +set(NATIVE_FRAMEWORK_PATH $CACHE{NATIVE_PATH}/Framework) +set(MOTIONSYNC_FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) +set(THIRD_PARTY_PATH $CACHE{NATIVE_PATH}/Samples/OpenGL/thirdParty) +set(STB_PATH ${THIRD_PARTY_PATH}/stb) +set(GLEW_PATH ${THIRD_PARTY_PATH}/glew) +set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) +set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(MOTIONSYNC_CORE_DIR MotionSyncCore) +set(MOTIONSYNC_CRI_LIB_PATH ${SDK_ROOT_PATH}/Core/CRI/dll/macOS) + +# Set project. +project(${APP_NAME}) + +# Define output directory. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/${APP_NAME}) +# Set configuration (Release and Debug only). +set(CMAKE_CONFIGURATION_TYPES Debug Release + CACHE STRING "Configurations" FORCE +) +# Suppress generation of ZERO_CHECK project. +set(CMAKE_SUPPRESS_REGENERATION ON) + +# Surpress GLEW and GLFW process. +set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) +set(BUILD_UTILS OFF CACHE BOOL "" FORCE) + +# Specify version of compiler. +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Add Cubism Core. +# Import as static library. +add_library(Live2DCubismCore STATIC IMPORTED) +# Get architecture. +EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE ) +# Set library path and inlude path. +set_target_properties(Live2DCubismCore + PROPERTIES + IMPORTED_LOCATION ${NATIVE_CORE_PATH}/lib/macos/${ARCHITECTURE}/libLive2DCubismCore.a + INTERFACE_INCLUDE_DIRECTORIES ${NATIVE_CORE_PATH}/include +) + +# Add GLEW ,GLFW. +add_subdirectory(${GLEW_PATH}/build/cmake ${CMAKE_CURRENT_BINARY_DIR}/glew) +add_subdirectory(${GLFW_PATH} ${CMAKE_CURRENT_BINARY_DIR}/glfw) + +# Specify Cubism Framework rendering. +set(FRAMEWORK_SOURCE OpenGL) +# Add Cubism Native Framework. +add_subdirectory(${NATIVE_FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework) +# Add rendering definition to framework. +target_compile_definitions(Framework PUBLIC CSM_TARGET_MAC_GL) +# Add include path of GLEW to framework. +target_include_directories(Framework PUBLIC ${GLEW_PATH}/include) +# Link libraries to framework. +target_link_libraries(Framework Live2DCubismCore glew_s) + +# Specify Cubism MotionSync Framework rendering. +set(MOTIONSYNC_FRAMEWORK_SOURCE OpenGL) +# Add Cubism Native MotionSync Framework. +add_subdirectory(${MOTIONSYNC_FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/MotionSyncFramework) +# Add rendering definition to MotionSync framework. +target_compile_definitions(MotionSyncFramework PUBLIC CSM_TARGET_MAC_GL) +# Add include path of GLEW to MotionSync framework. +target_include_directories(MotionSyncFramework PUBLIC ${GLEW_PATH}/include) +# Link libraries to MotionSync framework. +target_link_libraries(MotionSyncFramework Live2DCubismCore glew_s) + +# Find opengl libraries. +find_package(OpenGL REQUIRED) + +# Find libraries. +find_library(AUDIOTOOLBOX_LIBRARY AudioToolBox) + +# Set macro to MotionSync Framework. +target_compile_definitions(MotionSyncFramework PRIVATE MOTIONSYNC_CORE_CRI_LIB_PATH="${MOTIONSYNC_CORE_DIR}/") + +# Make executable app. +add_executable(${APP_NAME}) +# Add source files. +add_subdirectory(src) +# Link libraries to app. +target_link_libraries(${APP_NAME} + Framework + MotionSyncFramework + glfw + ${OPENGL_LIBRARIES} + ${AUDIOTOOLBOX_LIBRARY} +) +# Specify include directories. +target_include_directories(${APP_NAME} PRIVATE ${STB_PATH}) + +# Copy resource directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${RES_PATH} $/Resources +) + +# Copy MotionSync Lib directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${MOTIONSYNC_CRI_LIB_PATH} $/${MOTIONSYNC_CORE_DIR} +) + +# You can change target that renderer draws by enabling following definition. +# +# * USE_RENDER_TARGET +# Renderer draws to target of LAppView. +# * USE_MODEL_RENDER_TARGET +# Renderer draws to target of each LAppModel. +# * default +# Renderer draws to default main framebuffer. +# +# INFO: USE_RENDER_TARGET has higher priority than USE_MODEL_RENDER_TARGET. +# +# target_compile_definitions(${APP_NAME} +# PRIVATE +# USE_RENDER_TARGET +# USE_MODEL_RENDER_TARGET +# ) diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/scripts/make_xcode b/Samples/OpenGL/Demo/proj.mac.cmake/scripts/make_xcode new file mode 100644 index 0000000..72f735c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/scripts/make_xcode @@ -0,0 +1,13 @@ +#!/usr/bin/env sh + +set -ue + +SCRIPT_PATH=$(cd $(dirname $0) && pwd) +CMAKE_PATH=$SCRIPT_PATH/.. +BUILD_PATH=$SCRIPT_PATH/../build/make_xcode + +# Run CMake. +cmake -S "$CMAKE_PATH" \ + -B "$BUILD_PATH" \ + -D CMAKE_BUILD_TYPE=Release +cd "$BUILD_PATH" && make diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/scripts/proj_xcode b/Samples/OpenGL/Demo/proj.mac.cmake/scripts/proj_xcode new file mode 100644 index 0000000..cee3b6d --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/scripts/proj_xcode @@ -0,0 +1,12 @@ +#!/usr/bin/env sh + +set -ue + +SCRIPT_PATH=$(cd $(dirname $0) && pwd) +CMAKE_PATH=$SCRIPT_PATH/.. +BUILD_PATH=$SCRIPT_PATH/../build/proj_xcode + +# Run CMake. +cmake -S "$CMAKE_PATH" \ + -B "$BUILD_PATH" \ + -G Xcode diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt new file mode 100644 index 0000000..8f2062a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt @@ -0,0 +1,31 @@ +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) +set(NATIVE_SRC_PATH $CACHE{NATIVE_PATH}/Samples/OpenGL/Demo/proj.mac.cmake/src) + +target_include_directories(${APP_NAME} PUBLIC ${NATIVE_SRC_PATH}) + +target_sources(${APP_NAME} + PRIVATE + ${NATIVE_SRC_PATH}/LAppAllocator.cpp + ${NATIVE_SRC_PATH}/LAppAllocator.hpp + ${NATIVE_SRC_PATH}/LAppDefine.cpp + ${NATIVE_SRC_PATH}/LAppDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncDefine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncModel.hpp + ${NATIVE_SRC_PATH}/LAppPal.cpp + ${NATIVE_SRC_PATH}/LAppPal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPlaySound.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPlaySound.hpp + ${NATIVE_SRC_PATH}/LAppSprite.cpp + ${NATIVE_SRC_PATH}/LAppSprite.hpp + ${NATIVE_SRC_PATH}/LAppTextureManager.cpp + ${NATIVE_SRC_PATH}/LAppTextureManager.hpp + ${NATIVE_SRC_PATH}/LAppWavFileHandler.cpp + ${NATIVE_SRC_PATH}/LAppWavFileHandler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/mainMotionSync.cpp + ${NATIVE_SRC_PATH}/CubismSampleViewMatrix.cpp + ${NATIVE_SRC_PATH}/CubismSampleViewMatrix.hpp +) diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp new file mode 100644 index 0000000..28c12b4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp @@ -0,0 +1,582 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppDelegate.hpp" +#include +#include +#include +#include +#include +#include +#include "CubismMotionSyncEngineController.hpp" +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppMotionSyncDefine.hpp" +#include "LAppMotionSyncModel.hpp" +#include "LAppTextureManager.hpp" +#include "LAppPlaySound.hpp" + +using namespace Csm; +using namespace std; +using namespace LAppDefine; +using namespace LAppMotionSyncDefine; + +namespace { + LAppDelegate* s_instance = NULL; + + int CompareCsmString(const void* a, const void* b) + { + return strcmp(reinterpret_cast(a)->GetRawString(), + reinterpret_cast(b)->GetRawString()); + } +} + +LAppDelegate* LAppDelegate::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppDelegate(); + } + + return s_instance; +} + +void LAppDelegate::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + +bool LAppDelegate::Initialize() +{ + LAppPal::PrintLog("START"); + + // GLFWの初期化 + if (glfwInit() == GL_FALSE) + { + LAppPal::PrintLog("Can't initilize GLFW"); + + return GL_FALSE; + } + + // Windowの生成 + _window = glfwCreateWindow(LAppDefine::RenderTargetWidth, LAppDefine::RenderTargetHeight, "SIMPLE_SAMPLE", NULL, NULL); + if (_window == NULL) + { + LAppPal::PrintLog("Can't create GLFW window."); + + glfwTerminate(); + return GL_FALSE; + } + + // Windowのコンテキストをカレントに設定 + glfwMakeContextCurrent(_window); + glfwSwapInterval(1); + + if (glewInit() != GLEW_OK) { + LAppPal::PrintLog("Can't initilize glew."); + + glfwTerminate(); + return GL_FALSE; + } + + //テクスチャサンプリング設定 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //透過設定 + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // コールバック関数の登録 + glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); + glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); + + // ウィンドウサイズ記憶 + glfwGetWindowSize(_window, &_windowWidth, &_windowHeight); + + // Cubism SDK の初期化 + InitializeCubism(); + + _textureManager = new LAppTextureManager(); + + // 実行中のプログラムファイルパスを設定 + SetExecuteAbsolutePath(); + + // モデルの初期化 + LoadModelName(); + _modelIndex = 0; + LoadModel(); + + // 画像設定 + LoadGraph(); + + // ウインドウ設定 + _back->SetWindowSize(_windowWidth, _windowHeight); + _fastForward->SetWindowSize(_windowWidth, _windowHeight); + _gear->SetWindowSize(_windowWidth, _windowHeight); + _power->SetWindowSize(_windowWidth, _windowHeight); + + return GL_TRUE; +} + +void LAppDelegate::Release() +{ + // レンダラの解放 + _userModel->DeleteRenderer(); + + // モデルデータの解放 + delete _userModel; + + // ボタンや背景削除 + delete _back; + delete _fastForward; + delete _gear; + delete _power; + + // テクスチャマネージャーの解放 + delete _textureManager; + + // Windowの削除 + glfwDestroyWindow(_window); + + // OpenGLの処理を終了 + glfwTerminate(); + + // Cubism SDK の解放 + Csm::CubismFramework::Dispose(); +} + +void LAppDelegate::Run() +{ + //メインループ + while (glfwWindowShouldClose(_window) == GL_FALSE && !_isEnd) + { + int width, height; + + // ウィンドウサイズ記憶 + glfwGetWindowSize(_window, &width, &height); + if ((_windowWidth != width || _windowHeight != height) && width > 0 && height > 0) + { + // スプライトサイズを再設定 + ResizeSprite(); + // サイズを保存しておく + _windowWidth = width; + _windowHeight = height; + + // ウインドウ更新 + _back->SetWindowSize(_windowWidth, _windowHeight); + _fastForward->SetWindowSize(_windowWidth, _windowHeight); + _gear->SetWindowSize(_windowWidth, _windowHeight); + _power->SetWindowSize(_windowWidth, _windowHeight); + } + + // 時間更新 + LAppPal::UpdateTime(); + + // 画面の初期化 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearDepth(1.0); + + // 画像描画 + _back->Render(); + _fastForward->Render(); + _gear->Render(); + _power->Render(); + + // モデルの更新及び描画 + _userModel->ModelOnUpdate(); + + // バッファの入れ替え + glfwSwapBuffers(_window); + + // Poll for and process events + glfwPollEvents(); + } + + Release(); + + ReleaseInstance(); +} + +LAppDelegate::LAppDelegate(): + _cubismOption(), + _window(NULL), + _captured(false), + _mouseX(0.0f), + _mouseY(0.0f), + _isEnd(false), + _back(NULL), + _fastForward(NULL), + _gear(NULL), + _power(NULL), + _userModel(NULL), + _windowWidth(0), + _windowHeight(0) +{ + _textureManager = new LAppTextureManager(); +} + +LAppDelegate::~LAppDelegate() +{ + MotionSync::CubismMotionSyncEngineController::DeleteAllEngine(); +} + +void LAppDelegate::InitializeCubism() +{ + //setup cubism + _cubismOption.LogFunction = LAppPal::PrintMessage; + _cubismOption.LoggingLevel = Csm::CubismFramework::Option::LogLevel_Verbose; + Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); + + //Initialize cubism + Csm::CubismFramework::Initialize(); +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +{ + if (GLFW_MOUSE_BUTTON_LEFT != button) + { + return; + } + + if (GLFW_PRESS == action) + { + _captured = true; + OnTouchesBegan(_mouseX, _mouseY); + } + else if (GLFW_RELEASE == action) + { + if (_captured) + { + _captured = false; + OnTouchesEnded(_mouseX, _mouseY); + } + } +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (!_captured) + { + return; + } + + OnTouchesMoved(_mouseX, _mouseY); +} + +void LAppDelegate::OnTouchesBegan(float px, float py) +{ +} + +void LAppDelegate::OnTouchesMoved(float px, float py) +{ +} + +void LAppDelegate::OnTouchesEnded(float px, float py) +{ + // 早送りにタップしたか + if (_fastForward->IsHit(px, py)) + { + _userModel->ChangeNextIndexSound(); + } + + // 歯車にタップしたか + if (_gear->IsHit(px, py)) + { + ChangeNextModel(); + } + + // 電源ボタンにタップしたか + if (_power->IsHit(px, py)) + { + AppEnd(); + } +} + +GLuint LAppDelegate::CreateShader() +{ + //バーテックスシェーダのコンパイル + GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); + const char* vertexShader = + "#version 120\n" + "attribute vec3 position;" + "attribute vec2 uv;" + "varying vec2 vuv;" + "void main(void){" + " gl_Position = vec4(position, 1.0);" + " vuv = uv;" + "}"; + glShaderSource(vertexShaderId, 1, &vertexShader, NULL); + glCompileShader(vertexShaderId); + if (!CheckShader(vertexShaderId)) + { + return 0; + } + + //フラグメントシェーダのコンパイル + GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); + const char* fragmentShader = + "#version 120\n" + "varying vec2 vuv;" + "uniform sampler2D texture;" + "uniform vec4 baseColor;" + "void main(void){" + " gl_FragColor = texture2D(texture, vuv) * baseColor;" + "}"; + glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); + glCompileShader(fragmentShaderId); + if (!CheckShader(fragmentShaderId)) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + return programId; +} + +bool LAppDelegate::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +void LAppDelegate::LoadModelName() +{ + // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 + // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + struct dirent *dirent; + + csmString crawlPath(_executeAbsolutePath.c_str()); + crawlPath += ResourcesPath; + + DIR *pDir = opendir(crawlPath.GetRawString()); + if (pDir == NULL) return; + + _modelNameList.Clear(); + + while ((dirent = readdir(pDir)) != NULL) + { + if ((dirent->d_type & DT_DIR) && strcmp(dirent->d_name, "..") != 0) + { + // フォルダと同名の.model3.jsonがあるか探索する + struct dirent *dirent2; + + csmString modelName(dirent->d_name); + + csmString modelPath(crawlPath); + modelPath += modelName; + modelPath.Append(1, '/'); + + csmString model3jsonName(modelName); + model3jsonName += ".model3.json"; + + DIR *pDir2 = opendir(modelPath.GetRawString()); + while ((dirent2 = readdir(pDir2)) != NULL) + { + if (strcmp(dirent2->d_name, model3jsonName.GetRawString()) == 0) + { + _modelNameList.PushBack(csmString(dirent->d_name)); + } + } + closedir(pDir2); + } + } + closedir(pDir); + qsort(_modelNameList.GetPtr(), _modelNameList.GetSize(), sizeof(csmString), CompareCsmString); +} + +void LAppDelegate::LoadModel() +{ + if (_userModel) + { + // レンダラの解放 + _userModel->DeleteRenderer(); + + delete _userModel; + } + + // モデルデータの新規生成 + _userModel = new LAppMotionSyncModel(_executeAbsolutePath.c_str()); + + if (_modelIndex < _modelNameList.GetSize()) + { + // モデルデータの読み込み及び生成とセットアップを行う + _userModel->LoadAssets(_modelNameList[_modelIndex]); + } +} + +void LAppDelegate::ChangeNextModel() +{ + if (0 < _modelNameList.GetSize()) + { + _modelIndex = (_modelIndex + 1) % _modelNameList.GetSize(); + LoadModel(); + } +} + +void LAppDelegate::LoadGraph() +{ + GLuint programId = CreateShader(); + + int width, height; + glfwGetWindowSize(_window, &width, &height); + + const std::string resourcesPath = _executeAbsolutePath + std::string(LAppDefine::ResourcesPath); + + std::string imageName = LAppDefine::BackImageName; + LAppTextureManager::TextureInfo* backgroundTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + float x = width * 0.5f; + float y = height * 0.5f; + float fWidth = static_cast(backgroundTexture->width * 2.0f); + float fHeight = static_cast(height * 0.95f); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); + + imageName = LAppMotionSyncDefine::FastForwardImageName; + LAppTextureManager::TextureInfo* fastForwardTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(fastForwardTexture->width * 0.5f); + y = static_cast(height - fastForwardTexture->height * 0.5f); + fWidth = static_cast(fastForwardTexture->width); + fHeight = static_cast(fastForwardTexture->height); + _fastForward = new LAppSprite(x, y, fWidth, fHeight, fastForwardTexture->id, programId); + + imageName = LAppDefine::GearImageName; + LAppTextureManager::TextureInfo* gearTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(width - gearTexture->width * 0.5f); + y = static_cast(height - gearTexture->height * 0.5f); + fWidth = static_cast(gearTexture->width); + fHeight = static_cast(gearTexture->height); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); + + imageName = LAppDefine::PowerImageName; + LAppTextureManager::TextureInfo* powerTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(width - powerTexture->width * 0.5f); + y = static_cast(powerTexture->height * 0.5f); + fWidth = static_cast(powerTexture->width); + fHeight = static_cast(powerTexture->height); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); +} + +void LAppDelegate::ResizeSprite() +{ + if (!_textureManager) + { + return; + } + + // 描画領域サイズ + int width, height; + glfwGetWindowSize(_window, &width, &height); + + float x = 0.0f; + float y = 0.0f; + float fWidth = 0.0f; + float fHeight = 0.0f; + + if (_back) + { + GLuint id = _back->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = width * 0.5f; + y = height * 0.5f; + fWidth = static_cast(texInfo->width * 2); + fHeight = static_cast(height) * 0.95f; + _back->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_power) + { + GLuint id = _power->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->width * 0.5f); + y = static_cast(texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _power->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_gear) + { + GLuint id = _gear->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->width * 0.5f); + y = static_cast(height - texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _gear->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_fastForward) + { + GLuint id = _fastForward->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(texInfo->width * 0.5f); + y = static_cast(height - texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _fastForward->ResetRect(x, y, fWidth, fHeight); + } + } +} + +void LAppDelegate::SetExecuteAbsolutePath() +{ + char path[1024]; + uint32_t size = sizeof(path); + _NSGetExecutablePath(path, &size); + this->_executeAbsolutePath = dirname(path); + this->_executeAbsolutePath += "/"; +} diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp new file mode 100644 index 0000000..6290c3e --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp @@ -0,0 +1,229 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include +#include "LAppAllocator.hpp" +#include "LAppMotionSyncModel.hpp" +#include "LAppSprite.hpp" + +class LAppView; +class LAppTextureManager; + +/** +* @brief アプリケーションクラス。 +* Cubism SDK の管理を行う。 +*/ +class LAppDelegate +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppDelegate* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief APPに必要なものを初期化する。 + */ + bool Initialize(); + + /** + * @brief 解放する。 + */ + void Release(); + + /** + * @brief 実行処理。 + */ + void Run(); + + /** + * @brief OpenGL用 glfwSetMouseButtonCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] button ボタン種類 + * @param[in] action 実行結果 + * @param[in] modify + */ + void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + + /** + * @brief OpenGL用 glfwSetCursorPosCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] x x座標 + * @param[in] y y座標 + */ + void OnMouseCallBack(GLFWwindow* window, double x, double y); + + /** + * @brief Window情報を取得する。 + */ + GLFWwindow* GetWindow() { return _window; } + + /** + * @brief アプリケーションを終了するかどうか。 + */ + bool GetIsEnd() { return _isEnd; } + + /** + * @brief アプリケーションを終了する。 + */ + void AppEnd() { _isEnd = true; } + + LAppTextureManager* GetTextureManager() { return _textureManager; } + + /** + * @brief 実行中のプログラムファイルパスを取得する。 + */ + std::string GetExecuteAbsolutePath(){ return _executeAbsolutePath;} + +private: + /** + * @brief コンストラクタ + */ + LAppDelegate(); + + /** + * @brief デストラクタ + */ + ~LAppDelegate(); + + /** + * @brief Cubism SDK の初期化 + */ + void InitializeCubism(); + + /** + * @brief タッチされたときに呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesBegan(float pointX, float pointY); + + /** + * @brief タッチしているときにポインタが動いたら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesMoved(float pointX, float pointY); + + /** + * @brief タッチが終了したら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesEnded(float pointX, float pointY); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief モデル名リストの読み込み + * + * モデル名リストの読み込み処理を行う + * + */ + void LoadModelName(); + + /** + * @brief モデルの読み込み + * + * モデルデータの読み込み処理を行う + * + */ + void LoadModel(); + + /** + * @brief 次のモデルに切り替え + * + */ + void ChangeNextModel(); + + /** + * @brief 背景とボタンの読み込み + * + * 背景とボタンの読み込み処理を行う + * + */ + void LoadGraph(); + + /** + * @brief スプライト系のサイズ再設定 + */ + void ResizeSprite(); + + /** + * @brief シェーダーを登録する。 + */ + GLuint CreateShader(); + + /** + * @brief 実行中のプログラムファイルパスを設定する + */ + void SetExecuteAbsolutePath(); + + GLFWwindow* _window; ///< OpenGL ウィンドウ + int _windowWidth; ///< ウィンドウサイズ幅の保存 + int _windowHeight; ///< ウィンドウサイズ高さの保存 + LAppTextureManager* _textureManager; ///< テクスチャマネージャー + + LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator + Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option + bool _captured; ///< クリックしているか + float _mouseX; ///< マウスX座標 + float _mouseY; ///< マウスY座標 + bool _isEnd; ///< APP終了しているか + + std::string _executeAbsolutePath; ///< 実行中のプログラムファイルパス + LAppSprite* _back; ///< 背景画像 + LAppSprite* _fastForward; ///< 早送り画像 + LAppSprite* _gear; ///< ギア画像 + LAppSprite* _power; ///< 電源画像 + LAppMotionSyncModel* _userModel; ///< ユーザーが実際に使用するモデル + + Csm::csmVector _modelNameList; ///< モデルディレクトリ名のリスト + Csm::csmInt32 _modelIndex; ///< 表示するシーンモデル名のインデックス値 +}; + +class EventHandler +{ +public: + /** + * @brief glfwSetMouseButtonCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify); + } + + /** + * @brief glfwSetCursorPosCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, double x, double y) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); + } + +}; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.cpp new file mode 100644 index 0000000..6e28c48 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.cpp @@ -0,0 +1,29 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppMotionSyncDefine.hpp" + +namespace LAppMotionSyncDefine { + + using namespace Csm; + + // AudioQueue の再生バッファ数 + const csmInt32 AudioQueueBufferCount = 2; + + // AudioQueue の再生バッファに設定されるサンプル数 + const csmInt32 AudioQueueBufferSampleCount = 2048; + + // 早送り + const csmChar* FastForwardImageName = "icon_fastForward.png"; + + // チャンネル数 + const csmInt32 Channels = 2; + // サンプリング周波数 + const csmInt32 SamplesPerSec = 48000; + // ビット深度 + const csmInt32 BitDepth = 16; +} diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.hpp new file mode 100644 index 0000000..555c564 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncDefine.hpp @@ -0,0 +1,28 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ +#pragma once + +#include + +/** +* @brief Sample Appで使用する定数 +* +*/ +namespace LAppMotionSyncDefine { + + using namespace Csm; + + extern const csmInt32 AudioQueueBufferCount; ///< AudioQueue の再生バッファ数 + extern const csmInt32 AudioQueueBufferSampleCount; ///< AudioQueue の再生バッファに設定されるサンプル数 + + extern const csmChar* FastForwardImageName; ///< 早送りファイル + + // 音声設定 + extern const csmInt32 Channels; ///< チャンネル数 + extern const csmInt32 SamplesPerSec; ///< サンプリング周波数 + extern const csmInt32 BitDepth; ///< ビット深度 +} diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.cpp new file mode 100644 index 0000000..598f78b --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.cpp @@ -0,0 +1,266 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppMotionSyncModel.hpp" +#include "CubismModelMotionSyncSettingJson.hpp" +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppMotionSyncDefine.hpp" +#include "LAppPal.hpp" +#include "LAppTextureManager.hpp" +#include "Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp" + +using namespace Csm; +using namespace MotionSync; +using namespace LAppDefine; +using namespace LAppMotionSyncDefine; + +namespace { + csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) + { + if (LAppDefine::DebugLogEnable) + { + LAppPal::PrintLog("[APP]create buffer: %s ", path); + } + return LAppPal::LoadFileAsBytes(path, size); + } + + void DeleteBuffer(csmByte* buffer, const csmChar* path = "") + { + if (DebugLogEnable) + { + LAppPal::PrintLog("[APP]delete buffer: %s", path); + } + LAppPal::ReleaseBytes(buffer); + } +} + +LAppMotionSyncModel::LAppMotionSyncModel(csmString executeAbsolutePath) + : CubismUserModel() + , _executeAbsolutePath(executeAbsolutePath) + , _modelSetting(NULL) + , _motionSync(NULL) + , _soundIndex(0) +{ +} + +LAppMotionSyncModel::~LAppMotionSyncModel() +{ + if (_modelSetting) + { + delete _modelSetting; + } + + if (_motionSync) + { + _soundData.Release(); + CubismMotionSync::Delete(_motionSync); + } +} + +void LAppMotionSyncModel::LoadAssets(const csmString fileName) +{ + _modelHomeDir = _executeAbsolutePath + csmString(ResourcesPath) + fileName + "/"; + + if (_debugMode) + { + LAppPal::PrintLog("[APP]load model setting: %s", fileName.GetRawString()); + } + + csmSizeInt size; + const csmString path = _modelHomeDir + fileName + ".model3.json"; + + csmByte* buffer = CreateBuffer(path.GetRawString(), &size); + _modelSetting = new CubismModelMotionSyncSettingJson(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + + SetupModel(); + + if (_model == NULL) + { + LAppPal::PrintLog("Failed to LoadAssets()."); + return; + } + + CreateRenderer(); + + // テクスチャのセットアップ + SetupTextures(); +} + +void LAppMotionSyncModel::ModelOnUpdate() +{ + int width, height; + // ウィンドウサイズを取得 + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + + Csm::CubismMatrix44 projection; + // 念のため単位行列に初期化 + projection.LoadIdentity(); + + if (_model->GetCanvasWidth() > 1.0f && width < height) + { + // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する + GetModelMatrix()->SetWidth(2.0f); + projection.Scale(1.0f, static_cast(width) / static_cast(height)); + } + else + { + projection.Scale(static_cast(height) / static_cast(width), 1.0f); + } + + // モデルのパラメータを更新 + ModelParamUpdate(); + + // モデルの描画を更新 + Draw(projection); ///< 参照渡しなのでprojectionは変質する +} + +void LAppMotionSyncModel::ChangeNextIndexSound() +{ + if (0 < _soundFileList.GetSize()) + { + _soundIndex = (_soundIndex + 1) % _soundFileList.GetSize(); + PlayIndexSound(); + } +} + +void LAppMotionSyncModel::SetupModel() +{ + _updating = true; + _initialized = false; + + csmByte* buffer; + csmSizeInt size; + + //Cubism Model + if (strcmp(_modelSetting->GetModelFileName(), "") != 0) + { + csmString path = _modelSetting->GetModelFileName(); + path = _modelHomeDir + path; + + if (_debugMode) + { + LAppPal::PrintLog("[APP]create model: %s", _modelSetting->GetModelFileName()); + } + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadModel(buffer, size, _mocConsistency); + DeleteBuffer(buffer, path.GetRawString()); + } + + if (_modelSetting == NULL || _modelMatrix == NULL) + { + LAppPal::PrintLog("Failed to SetupModel()."); + return; + } + + //Layout + csmMap layout; + _modelSetting->GetLayoutMap(layout); + _modelMatrix->SetupFromLayout(layout); + + // パラメータを保存 + _model->SaveParameters(); + + _updating = false; + _initialized = true; + + // MotionSync + const csmChar* fileName = _modelSetting->GetMotionSyncJsonFileName(); + + if (_debugMode) + { + LAppPal::PrintLog("[APP]load motionSync setting: %s", fileName); + } + + const csmString path = csmString(_modelHomeDir) + fileName; + buffer = CreateBuffer(path.GetRawString(), &size); + + _motionSync = CubismMotionSync::Create(_model, buffer, size, SamplesPerSec, _executeAbsolutePath); + + if (!_motionSync) + { + LAppPal::PrintLog("Failed to SetupModel()."); + return; + } + + DeleteBuffer(buffer, path.GetRawString()); + + // 音声データ + _soundFileList = _modelSetting->GetMotionSyncSoundFileList(); + _soundIndex = 0; + PlayIndexSound(); +} + +void LAppMotionSyncModel::SetupTextures() +{ + for (csmInt32 modelTextureNumber = 0; modelTextureNumber < _modelSetting->GetTextureCount(); modelTextureNumber++) + { + // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ + if (!strcmp(_modelSetting->GetTextureFileName(modelTextureNumber), "")) + { + continue; + } + + // OpenGLのテクスチャユニットにテクスチャをロードする + csmString texturePath = _modelSetting->GetTextureFileName(modelTextureNumber); + texturePath = _modelHomeDir + texturePath; + + LAppTextureManager::TextureInfo* texture = LAppDelegate::GetInstance()->GetTextureManager()->CreateTextureFromPngFile(texturePath.GetRawString()); + const csmInt32 glTextueNumber = texture->id; + + // OpenGL + GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); + } + + // 乗算済みアルファ値の有効化・無効化を設定 + GetRenderer()->IsPremultipliedAlpha(false); +} + +void LAppMotionSyncModel::ModelParamUpdate() +{ + const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime(); + _userTimeSeconds += deltaTimeSeconds; + + // 不透明度 + _opacity = _model->GetModelOpacity(); + + // モーションシンクプラグイン + if (_motionSync != NULL) + { + _motionSync->UpdateParameters(_model, deltaTimeSeconds); + } + + _model->Update(); +} + +void LAppMotionSyncModel::PlayIndexSound() +{ + if (_soundIndex < _soundFileList.GetSize()) + { + _soundData.LoadFile(_modelHomeDir + _soundFileList[_soundIndex], 0); + _motionSync->SetSoundBuffer(0, _soundData.GetBuffer()); + } +} + +void LAppMotionSyncModel::Draw(Csm::CubismMatrix44& matrix) +{ + if (!_model) + { + return; + } + + // 現在の行列に行列を乗算 + matrix.MultiplyByMatrix(_modelMatrix); + + // 行列をモデルビュープロジェクション行列を設定 + GetRenderer()->SetMvpMatrix(&matrix); + + // モデルの描画を命令・実行する + GetRenderer()->DrawModel(); +} diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.hpp new file mode 100644 index 0000000..6a2d4f0 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppMotionSyncModel.hpp @@ -0,0 +1,96 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include "CubismMotionSync.hpp" +#include "CubismModelMotionSyncSettingJson.hpp" +#include "LAppPlaySound.hpp" + +/** + * @brief ユーザーが実際に使用するモデルの実装クラス
+ * モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。 + * + */ +class LAppMotionSyncModel : public Csm::CubismUserModel +{ +public: + /** + * @brief コンストラクタ + */ + LAppMotionSyncModel(Csm::csmString executeAbsolutePath); + + /** + * @brief デストラクタ + * + */ + virtual ~LAppMotionSyncModel(); + + /** + * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する + * + */ + void LoadAssets(const Csm::csmString fileName); + + /** + * @brief モデルの更新 + * + * モデルの状態や描画を更新する + */ + void ModelOnUpdate(); + + /** + * @brief 次の音声ファイルを再生する + * + */ + void ChangeNextIndexSound(); + +private: + Csm::csmString _executeAbsolutePath; ///< 実行中のプログラムファイルパス + Csm::MotionSync::CubismModelMotionSyncSettingJson* _modelSetting; ///< モデルセッティング情報 + Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + Csm::MotionSync::CubismMotionSync* _motionSync; ///< モーションシンク + LAppPlaySound _soundData; ///< モーションシンクで使用する音声データ + Csm::csmVector _soundFileList; ///< 音声データファイルのリスト + Csm::csmInt32 _soundIndex; ///< 再生する音声データのインデックス値 + + /** + * @brief model3.jsonからモデルを生成する。
+ * model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う。 + * + */ + void SetupModel(); + + /** + * @brief OpenGLのテクスチャユニットにテクスチャをロードする + * + */ + void SetupTextures(); + + /** + * @brief モデルのパラメータ情報の更新 + * + * モデルのパラメータの情報を更新する + */ + void ModelParamUpdate(); + + /** + * @brief 現在のインデックスの音声ファイルを再生する + * + */ + void PlayIndexSound(); + + /** + * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す + * + * @param[in] matrix View-Projection行列 + */ + void Draw(Csm::CubismMatrix44& matrix); +}; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.cpp new file mode 100644 index 0000000..072ebc4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.cpp @@ -0,0 +1,152 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppPlaySound.hpp" +#include "LAppWavFileHandler.hpp" + +using namespace Csm; + +csmBool LAppPlaySound::LoadFile(csmString path, csmUint32 useChannel) +{ + // 初期化 + Release(); + + AudioStreamBasicDescription format; + AudioQueueBufferRef buffers[LAppMotionSyncDefine::AudioQueueBufferCount]; + OSStatus status; + + // WAVファイルをロード + LAppWavFileHandler wavHandler; + wavHandler.Start(path); + LAppWavFileHandler::WavFileInfo wavHandlerInfo = wavHandler.GetWavFileInfo(); + _wavSamples = wavHandler.GetPcmData(); + + // 再生設定 + format.mSampleRate = wavHandlerInfo._samplingRate; + format.mFormatID = kAudioFormatLinearPCM; + format.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; + format.mBitsPerChannel = sizeof(csmFloat32) * 8; + format.mChannelsPerFrame = wavHandlerInfo._numberOfChannels; + format.mBytesPerFrame = sizeof(csmFloat32) * format.mChannelsPerFrame; + format.mFramesPerPacket = 1; + format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket; + format.mReserved = 0; + + _channels = wavHandlerInfo._numberOfChannels; + _bitDepth = wavHandlerInfo._bitsPerSample; + _queueBufferSize = LAppMotionSyncDefine::AudioQueueBufferSampleCount * format.mBytesPerFrame; + _queueBufferSampleCount = LAppMotionSyncDefine::AudioQueueBufferSampleCount; + _wavWritePos = 0; + + if (_useChannel < _channels) + { + _useChannel = useChannel; + } + else + { + _useChannel = _channels - 1; + } + + + status = AudioQueueNewOutput(&format, CallBack, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &_queue); + + if (status != noErr) + { + return false; + } + + + for (csmUint32 i = 0; i < LAppMotionSyncDefine::AudioQueueBufferCount; i++) + { + status = AudioQueueAllocateBuffer(_queue, _queueBufferSize, &buffers[i]); + + if (status != noErr) + { + return false; + } + + buffers[i]->mAudioDataByteSize = _queueBufferSize; + + // キューをキックして音を鳴らす。 + CallBack(this, _queue, buffers[i]); + } + + // 音声再生 + status = AudioQueueStart(_queue, NULL); + + if (status != noErr) + { + return false; + } + + + return true; +} + +csmVector* LAppPlaySound::GetBuffer() +{ + return &_buffer; +} + +csmBool LAppPlaySound::IsPlay() +{ + return (_wavWritePos < _wavSamples.GetSize()); +} + +void LAppPlaySound::Release() +{ + AudioQueueStop(_queue, true); + AudioQueueDispose(_queue, true); + _buffer.Clear(); +} + +LAppPlaySound::LAppPlaySound() : + _queueBufferSize(0), + _queueBufferSampleCount(0), + _wavWritePos(0), + _useChannel(0), + _channels(1), + _bitDepth(8) +{ +} + +LAppPlaySound::~LAppPlaySound() +{ + Release(); +} + +void LAppPlaySound::CallBack(void* customData, AudioQueueRef queue, AudioQueueBufferRef buffer) +{ + LAppPlaySound* data = reinterpret_cast(customData); + csmFloat32 *samples = reinterpret_cast(buffer->mAudioData); + + if (data->_wavSamples.GetSize() <= data->_wavWritePos) + { + return; + } + + for (csmUint64 i = 0; i < data->_queueBufferSampleCount * data->_channels; i++) + { + if (data->_wavWritePos < data->_wavSamples.GetSize()) + { + samples[i] = data->_wavSamples[data->_wavWritePos++]; + } + else + { + samples[i] = 0.0f; + } + + // 解析に指定しているチャンネルのサンプルを送る。 + if ((i % 2) == data->_useChannel) + { + data->_buffer.PushBack(samples[i]); + } + } + + AudioQueueEnqueueBuffer(queue, buffer, 0, NULL); +} + diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.hpp new file mode 100644 index 0000000..0ca8ceb --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppPlaySound.hpp @@ -0,0 +1,80 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include "LAppMotionSyncDefine.hpp" +#include "Type/csmString.hpp" +#include "Type/csmVector.hpp" + +class LAppPlaySound +{ +public: + /** + * @brief 音声ファイル読み込み + * + * @param[in] path 音声ファイル + * @param[in] useChannel 使用するチャンネル + * + * @return 読み込み結果 + */ + Csm::csmBool LoadFile(Csm::csmString path, Csm::csmUint32 useChannel); + + /** + * @brief 再生したバッファの格納先の設定 + * + * @return バッファ + */ + Csm::csmVector* GetBuffer(); + + /** + * @brief 再生中か確認 + * + * @return 再生中か + */ + Csm::csmBool IsPlay(); + + /** + * @brief 解放処理 + * + */ + void Release(); + + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + */ + LAppPlaySound(); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~LAppPlaySound(); + +private: + AudioQueueRef _queue; + Csm::csmUint32 _queueBufferSize; + Csm::csmUint32 _queueBufferSampleCount; + Csm::csmVector _wavSamples; + Csm::csmUint32 _wavWritePos; + Csm::csmUint32 _useChannel; + Csm::csmInt32 _channels; + Csm::csmInt32 _bitDepth; + Csm::csmVector _buffer; + + /** + * @brief コールバック処理 + * + */ + static void CallBack(void* customData, AudioQueueRef queue, AudioQueueBufferRef buffer); + +}; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/mainMotionSync.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/mainMotionSync.cpp new file mode 100644 index 0000000..6c13726 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/mainMotionSync.cpp @@ -0,0 +1,23 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include +#include +#include "LAppDelegate.hpp" + +int main() +{ + // create the application instance + if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE) + { + return 1; + } + + LAppDelegate::GetInstance()->Run(); + + return 0; +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt new file mode 100644 index 0000000..fafdd74 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt @@ -0,0 +1,206 @@ +cmake_minimum_required(VERSION 3.16) + +option( + CORE_CRL_MD + "Use Cubism Core that is multithread-specific and DLL-specific version" + OFF +) + +# Set app name. +set(APP_NAME Demo) +# Set directory paths. +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +file(GLOB NATIVE_DIR "${SDK_ROOT_PATH}/../CubismNativeSamples") +# Find non-zip file. +if(NOT NATIVE_DIR) + file(GLOB TMP_DIR "${SDK_ROOT_PATH}/../CubismSdkForNative*") + foreach(DIR ${TMP_DIR}) + get_filename_component(LASTNAME ${DIR} NAME) + if(NOT "${LASTNAME}" MATCHES "\\.zip$") + set(NATIVE_DIR ${DIR}) + break() + endif() + endforeach() +endif() +set(NATIVE_PATH ${NATIVE_DIR} CACHE PATH [[Native File Path]] FORCE) +set(NATIVE_CORE_PATH $CACHE{NATIVE_PATH}/Core) +set(MOTIONSYNC_CRI_CORE_PATH ${SDK_ROOT_PATH}/Core/CRI/dll/windows) +set(NATIVE_FRAMEWORK_PATH $CACHE{NATIVE_PATH}/Framework) +set(MOTIONSYNC_FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) +set(THIRD_PARTY_PATH $CACHE{NATIVE_PATH}/Samples/OpenGL/thirdParty) +set(STB_PATH ${THIRD_PARTY_PATH}/stb) +set(GLEW_PATH ${THIRD_PARTY_PATH}/glew) +set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) +set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(MOTIONSYNC_CORE_DIR MotionSyncCore) + +# Set project. +project(${APP_NAME}) + +# Set Visual Studio startup project. +set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT ${APP_NAME}) + +# Define output directory. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/${APP_NAME}) +# Set configuration (Release and Debug only). +set(CMAKE_CONFIGURATION_TYPES Debug Release + CACHE STRING "Configurations" FORCE +) +# Suppress generation of ZERO_CHECK project. +set(CMAKE_SUPPRESS_REGENERATION ON) + +# Surpress GLEW and GLFW process. +set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) +set(BUILD_UTILS OFF CACHE BOOL "" FORCE) + +# Specify version of compiler. +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Detect architecture. +if(CMAKE_EXE_LINKER_FLAGS STREQUAL "/machine:x64") + set(ARCH x86_64) + set(MOTIONSYNC_CRI_LIB_PATH ${MOTIONSYNC_CRI_CORE_PATH}/x86_64) +elseif(CMAKE_EXE_LINKER_FLAGS STREQUAL "/machine:X86") + set(ARCH x86) + set(MOTIONSYNC_CRI_LIB_PATH ${MOTIONSYNC_CRI_CORE_PATH}/x86) +else() + message(FATAL_ERROR "[${APP_NAME}] Invalid linker flag ${CMAKE_EXE_LINKER_FLAGS}.") +endif() +# Detect compiler. +if(MSVC_VERSION MATCHES 1800) + # Visual Studio 2013 + set(COMPILER 120) +elseif(MSVC_VERSION MATCHES 1900) + # Visual Studio 2015 + set(COMPILER 140) +elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) + # Visual Studio 2017 + set(COMPILER 141) +elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) + # Visual Studio 2019 + set(COMPILER 142) +elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) + # Visual Studio 2022 + set(COMPILER 143) +elseif(MSVC) + message(FATAL_ERROR "[${APP_NAME}] Unsupported Visual C++ compiler used.") +else() + message(FATAL_ERROR "[${APP_NAME}] Unsupported compiler used.") +endif() +# Detect core crt. +if(CORE_CRL_MD) + set(CRT MD) +else() + set(CRT MT) +endif() + +# Add Cubism Core. +# Import as static library. +add_library(Live2DCubismCore STATIC IMPORTED) +# Find library path. +set(CORE_LIB_SUFFIX ${NATIVE_CORE_PATH}/lib/windows/${ARCH}/${COMPILER}) +set_target_properties(Live2DCubismCore + PROPERTIES + IMPORTED_LOCATION_DEBUG + ${CORE_LIB_SUFFIX}/Live2DCubismCore_${CRT}d.lib + IMPORTED_LOCATION_RELEASE + ${CORE_LIB_SUFFIX}/Live2DCubismCore_${CRT}.lib + INTERFACE_INCLUDE_DIRECTORIES ${NATIVE_CORE_PATH}/include +) + +# Add GLEW ,GLFW. +add_subdirectory(${GLEW_PATH}/build/cmake ${CMAKE_CURRENT_BINARY_DIR}/glew) +add_subdirectory(${GLFW_PATH} ${CMAKE_CURRENT_BINARY_DIR}/glfw) + +# Specify Cubism Framework rendering. +set(FRAMEWORK_SOURCE OpenGL) +# Add Cubism Native Framework. +add_subdirectory(${NATIVE_FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework) +# Add rendering definition to framework. +target_compile_definitions(Framework PUBLIC CSM_TARGET_WIN_GL) +# Add include path of GLEW to framework. +target_include_directories(Framework PUBLIC ${GLEW_PATH}/include) +# Link libraries to framework. +target_link_libraries(Framework Live2DCubismCore glew_s) + +# Specify Cubism MotionSync Framework rendering. +set(MOTIONSYNC_FRAMEWORK_SOURCE OpenGL) +# Add Cubism Native MotionSync Framework. +add_subdirectory(${MOTIONSYNC_FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/MotionSyncFramework) +# Add rendering definition to motionsync framework. +target_compile_definitions(MotionSyncFramework PUBLIC CSM_TARGET_WIN_GL) +# Add include path of GLEW to motionsync framework. +target_include_directories(MotionSyncFramework PUBLIC ${GLEW_PATH}/include) +# Link libraries to motionSync framework. +target_link_libraries(MotionSyncFramework Live2DCubismCore glew_s) + +# Find opengl libraries. +find_package(OpenGL REQUIRED) + +# Set macro to MotionSync Framework. +target_compile_definitions(MotionSyncFramework PRIVATE MOTIONSYNC_CORE_CRI_LIB_PATH="${MOTIONSYNC_CORE_DIR}/") + +# Make executable app. +add_executable(${APP_NAME}) +# Add source files. +add_subdirectory(src) +# Link libraries to app. +target_link_libraries(${APP_NAME} + Framework + MotionSyncFramework + glfw + ${OPENGL_LIBRARIES} + # Solve the MSVCRT confliction. + debug -NODEFAULTLIB:libcmtd.lib + optimized -NODEFAULTLIB:libcmt.lib +) +# Specify include directories. +target_include_directories(${APP_NAME} PRIVATE ${STB_PATH}) +# Build in multi-process. +target_compile_options(${APP_NAME} PRIVATE /MP) + +# Copy resource directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${RES_PATH} $/Resources +) + +# Copy Motion Sync Lib directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${MOTIONSYNC_CRI_LIB_PATH} $/${MOTIONSYNC_CORE_DIR} +) + +# Set project properties. +set_target_properties(${APP_NAME} PROPERTIES + VS_DEBUGGER_WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/bin/${APP_NAME}/${CMAKE_CFG_INTDIR} +) + +# You can change target that renderer draws by enabling following definition. +# +# * USE_RENDER_TARGET +# Renderer draws to target of LAppView. +# * USE_MODEL_RENDER_TARGET +# Renderer draws to target of each LAppModel. +# * default +# Renderer draws to default main framebuffer. +# +# INFO: USE_RENDER_TARGET has higher priority than USE_MODEL_RENDER_TARGET. +# +# target_compile_definitions(${APP_NAME} +# PRIVATE +# USE_RENDER_TARGET +# USE_MODEL_RENDER_TARGET +# ) diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/_msvc_common.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/_msvc_common.bat new file mode 100644 index 0000000..a1fb6f5 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/_msvc_common.bat @@ -0,0 +1,108 @@ +@echo off + +setlocal +set VARIABLE_EXISTS=TRUE +if "%MSVC_VERSION%" equ "" set VARIABLE_EXISTS=FALSE +if "%MSVC_NUMBER%" equ "" set VARIABLE_EXISTS=FALSE +if "%VCVARSALL%" equ "" set VARIABLE_EXISTS=FALSE +if "%GENERATOR%" equ "" set VARIABLE_EXISTS=FALSE +if "%VARIABLE_EXISTS%" equ "FALSE" ( + echo [CubismNativeSamples] Invalid batch call. + exit /b 1 +) +endlocal + +cd %~dp0 + +rem ============== +rem Dialog Options +rem ============== + +rem Architecture selection +echo. +echo Select which architecture to use. +echo ************************************************** +echo 1. x86 (Win32) +echo 2. x64 (Win64) +echo. +choice /c:12 /n /m ">" +set SELECTED=%errorlevel% +if "%SELECTED%" equ "1" ( + set ARCHITECTURE=x86 + set CMAKE_A_OPTION=Win32 +) else if "%SELECTED%" equ "2" ( + set ARCHITECTURE=x64 + set CMAKE_A_OPTION=x64 +) else ( + echo [CubismNativeSamples] Invalid option. + exit /b 1 +) + +rem Core C Runtime selection +echo. +echo Select which cubism core c runtime library to use +echo ************************************************** +echo 1. use the multithread-specific and DLL-specific version of the run-time library (MD) +echo 2. use the multithread, static version of the run-time library (MT) +echo. +choice /c:12 /n /m ">" +set SELECTED=%errorlevel% +if "%SELECTED%" equ "1" ( + set CORE_CRL_MD=ON +) else if "%SELECTED%" equ "2" ( + set CORE_CRL_MD=OFF +) else ( + echo [CubismNativeSamples] Invalid option. + exit /b 1 +) + +rem ======== +rem Validate +rem ======== + +rem Make sure toolchain exists. +if not exist "%VCVARSALL%" ( + echo [CubismNativeSamples] Visual C++ Compiler %MSVC_VERSION% not found. + exit /b 1 +) + +rem ===== +rem Build +rem ===== + +rem Execute build. +echo Building %ARCHITECTURE% with Visual C++ Compiler %MSVC_VERSION%... + +rem Initialize Visual Studio toolchain. +call "%VCVARSALL%" %ARCHITECTURE% +if %errorlevel% neq 0 exit /b %errorlevel% + +rem Build for native development. +if "%CORE_CRL_MD%" equ "ON" ( + set CORE_CRL=md +) else ( + set CORE_CRL=mt +) + +set BUILD_PATH=..\build\%GENERATOR%_msvc%MSVC_VERSION%_%ARCHITECTURE%_%CORE_CRL% + +if "%GENERATOR%" equ "nmake" ( + cmake -S .. -B "%BUILD_PATH%" ^ + -G "NMake Makefiles" ^ + -D CMAKE_BUILD_TYPE="Release" ^ + -D CORE_CRL_MD=%CORE_CRL_MD% + if %errorlevel% neq 0 exit /b %errorlevel% + cd "%BUILD_PATH%" && nmake + if %errorlevel% neq 0 exit /b %errorlevel% +) else if "%GENERATOR%" equ "proj" ( + cmake -S .. -B "%BUILD_PATH%" ^ + -G "Visual Studio %MSVC_NUMBER% %MSVC_VERSION%" ^ + -A %CMAKE_A_OPTION% ^ + -D CORE_CRL_MD=%CORE_CRL_MD% + if %errorlevel% neq 0 exit /b %errorlevel% +) else ( + echo [CubismNativeSamples] Invalid option. + goto :error +) + +exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat new file mode 100644 index 0000000..50de20f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat @@ -0,0 +1,14 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2013 +set MSVC_NUMBER=12 +set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat +set GENERATOR=nmake + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2015.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2015.bat new file mode 100644 index 0000000..3d32e50 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2015.bat @@ -0,0 +1,14 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2015 +set MSVC_NUMBER=14 +set VCVARSALL=%VS140COMNTOOLS%..\..\VC\vcvarsall.bat +set GENERATOR=nmake + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2017.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2017.bat new file mode 100644 index 0000000..61ef1a5 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2017.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2017 +set MSVC_NUMBER=15 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=nmake + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2019.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2019.bat new file mode 100644 index 0000000..e997557 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2019.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2019 +set MSVC_NUMBER=16 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=nmake + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2022.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2022.bat new file mode 100644 index 0000000..bc6e128 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2022.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2022 +set MSVC_NUMBER=17 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=nmake + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat new file mode 100644 index 0000000..d11674f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat @@ -0,0 +1,14 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2013 +set MSVC_NUMBER=12 +set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat +set GENERATOR=proj + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2015.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2015.bat new file mode 100644 index 0000000..e1549b2 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2015.bat @@ -0,0 +1,14 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2015 +set MSVC_NUMBER=14 +set VCVARSALL=%VS140COMNTOOLS%..\..\VC\vcvarsall.bat +set GENERATOR=proj + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2017.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2017.bat new file mode 100644 index 0000000..23522b9 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2017.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2017 +set MSVC_NUMBER=15 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=proj + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2019.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2019.bat new file mode 100644 index 0000000..f54d52c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2019.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2019 +set MSVC_NUMBER=16 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=proj + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2022.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2022.bat new file mode 100644 index 0000000..01031f4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2022.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +set SCRIPT_PATH=%~dp0 +set MSVC_VERSION=2022 +set MSVC_NUMBER=17 +set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +set /a _MSVC_RANGE_S=MSVC_NUMBER +set /a _MSVC_RANGE_E=MSVC_NUMBER+1 +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( + set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat +) +set GENERATOR=proj + +call "%SCRIPT_PATH%_msvc_common.bat" +if %errorlevel% neq 0 pause & exit /b %errorlevel% + +pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt new file mode 100644 index 0000000..62dd5c6 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt @@ -0,0 +1,31 @@ +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) +set(NATIVE_SRC_PATH $CACHE{NATIVE_PATH}/Samples/OpenGL/Demo/proj.win.cmake/src) + +target_include_directories(${APP_NAME} PUBLIC ${NATIVE_SRC_PATH}) + +target_sources(${APP_NAME} + PRIVATE + ${NATIVE_SRC_PATH}/LAppAllocator.cpp + ${NATIVE_SRC_PATH}/LAppAllocator.hpp + ${NATIVE_SRC_PATH}/LAppDefine.cpp + ${NATIVE_SRC_PATH}/LAppDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncDefine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppMotionSyncModel.hpp + ${NATIVE_SRC_PATH}/LAppPal.cpp + ${NATIVE_SRC_PATH}/LAppPal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPlaySound.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPlaySound.hpp + ${NATIVE_SRC_PATH}/LAppSprite.cpp + ${NATIVE_SRC_PATH}/LAppSprite.hpp + ${NATIVE_SRC_PATH}/LAppTextureManager.cpp + ${NATIVE_SRC_PATH}/LAppTextureManager.hpp + ${NATIVE_SRC_PATH}/LAppWavFileHandler.cpp + ${NATIVE_SRC_PATH}/LAppWavFileHandler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/mainMotionSync.cpp + ${NATIVE_SRC_PATH}/CubismSampleViewMatrix.cpp + ${NATIVE_SRC_PATH}/CubismSampleViewMatrix.hpp +) diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp new file mode 100644 index 0000000..a2657f1 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp @@ -0,0 +1,571 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#define GLFW_EXPOSE_NATIVE_WIN32 +#include "LAppDelegate.hpp" +#include +#include +#include +#include +#include "CubismMotionSyncEngineController.hpp" +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppMotionSyncDefine.hpp" +#include "LAppMotionSyncModel.hpp" +#include "LAppTextureManager.hpp" +#include "LAppPlaySound.hpp" + +using namespace Csm; +using namespace std; +using namespace LAppDefine; +using namespace LAppMotionSyncDefine; + +namespace { + LAppDelegate* s_instance = NULL; + + int CompareCsmString(const void* a, const void* b) + { + return strcmp(reinterpret_cast(a)->GetRawString(), + reinterpret_cast(b)->GetRawString()); + } +} + +LAppDelegate* LAppDelegate::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppDelegate(); + } + + return s_instance; +} + +void LAppDelegate::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + +bool LAppDelegate::Initialize() +{ + LAppPal::PrintLog("START"); + + // GLFWの初期化 + if (glfwInit() == GL_FALSE) + { + LAppPal::PrintLog("Can't initilize GLFW"); + + return GL_FALSE; + } + + // Windowの生成 + _window = glfwCreateWindow(LAppDefine::RenderTargetWidth, LAppDefine::RenderTargetHeight, "SIMPLE_SAMPLE", NULL, NULL); + if (_window == NULL) + { + LAppPal::PrintLog("Can't create GLFW window."); + + glfwTerminate(); + return GL_FALSE; + } + + // Windowのコンテキストをカレントに設定 + glfwMakeContextCurrent(_window); + glfwSwapInterval(1); + + if (glewInit() != GLEW_OK) { + LAppPal::PrintLog("Can't initilize glew."); + + glfwTerminate(); + return GL_FALSE; + } + + //テクスチャサンプリング設定 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //透過設定 + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // コールバック関数の登録 + glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); + glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); + + // ウィンドウサイズ記憶 + glfwGetWindowSize(_window, &_windowWidth, &_windowHeight); + glViewport(0, 0, _windowWidth, _windowHeight); + + // サウンド初期化 + LAppPlaySound::Init(glfwGetWin32Window(_window), Channels, SamplesPerSec, BitDepth); + + // Cubism SDK の初期化 + InitializeCubism(); + + _textureManager = new LAppTextureManager(); + + // モデルの初期化 + LoadModelName(); + _modelIndex = 0; + LoadModel(); + + // 画像設定 + LoadGraph(); + + // ウインドウ設定 + _back->SetWindowSize(_windowWidth, _windowHeight); + _fastForward->SetWindowSize(_windowWidth, _windowHeight); + _gear->SetWindowSize(_windowWidth, _windowHeight); + _power->SetWindowSize(_windowWidth, _windowHeight); + + return GL_TRUE; +} + +void LAppDelegate::Release() +{ + // レンダラの解放 + _userModel->DeleteRenderer(); + + // モデルデータの解放 + delete _userModel; + + // ボタンや拝啓削除 + delete _back; + delete _fastForward; + delete _gear; + delete _power; + + // テクスチャマネージャーの解放 + delete _textureManager; + + // Windowの削除 + glfwDestroyWindow(_window); + + // OpenGLの処理を終了 + glfwTerminate(); + + // サウンドリリース + LAppPlaySound::Close(); + + // Cubism SDK の解放 + Csm::CubismFramework::Dispose(); +} + +void LAppDelegate::Run() +{ + //メインループ + while (glfwWindowShouldClose(_window) == GL_FALSE && !_isEnd) + { + int width, height; + + // ビューポートを現在のウィンドウサイズに設定 + glViewport(0, 0, _windowWidth, _windowHeight); + + // ウィンドウサイズ記憶 + glfwGetWindowSize(_window, &width, &height); + if ((_windowWidth != width || _windowHeight != height) && width > 0 && height > 0) + { + // スプライトサイズを再設定 + ResizeSprite(); + // サイズを保存しておく + _windowWidth = width; + _windowHeight = height; + + // ビューポート変更 + glViewport(0, 0, width, height); + + // ウインドウ更新 + _back->SetWindowSize(_windowWidth, _windowHeight); + _fastForward->SetWindowSize(_windowWidth, _windowHeight); + _gear->SetWindowSize(_windowWidth, _windowHeight); + _power->SetWindowSize(_windowWidth, _windowHeight); + } + + // 時間更新 + LAppPal::UpdateTime(); + + // 画面の初期化 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearDepth(1.0); + + // 画像描画 + _back->Render(); + _fastForward->Render(); + _gear->Render(); + _power->Render(); + + // モデルの更新及び描画 + _userModel->ModelOnUpdate(); + + // バッファの入れ替え + glfwSwapBuffers(_window); + + // Poll for and process events + glfwPollEvents(); + } + + Release(); + + ReleaseInstance(); +} + +LAppDelegate::LAppDelegate(): + _cubismOption(), + _window(NULL), + _captured(false), + _mouseX(0.0f), + _mouseY(0.0f), + _isEnd(false), + _back(NULL), + _fastForward(NULL), + _gear(NULL), + _power(NULL), + _userModel(NULL), + _windowWidth(0), + _windowHeight(0) +{ + _textureManager = new LAppTextureManager(); +} + +LAppDelegate::~LAppDelegate() +{ + MotionSync::CubismMotionSyncEngineController::DeleteAllEngine(); +} + +void LAppDelegate::InitializeCubism() +{ + //setup cubism + _cubismOption.LogFunction = LAppPal::PrintMessage; + _cubismOption.LoggingLevel = Csm::CubismFramework::Option::LogLevel_Verbose; + Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); + + //Initialize cubism + Csm::CubismFramework::Initialize(); +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +{ + if (GLFW_MOUSE_BUTTON_LEFT != button) + { + return; + } + + if (GLFW_PRESS == action) + { + _captured = true; + OnTouchesBegan(_mouseX, _mouseY); + } + else if (GLFW_RELEASE == action) + { + if (_captured) + { + _captured = false; + OnTouchesEnded(_mouseX, _mouseY); + } + } +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (!_captured) + { + return; + } + + OnTouchesMoved(_mouseX, _mouseY); +} + +void LAppDelegate::OnTouchesBegan(float px, float py) +{ +} + +void LAppDelegate::OnTouchesMoved(float px, float py) +{ +} + +void LAppDelegate::OnTouchesEnded(float px, float py) +{ + // 早送りにタップしたか + if (_fastForward->IsHit(px, py)) + { + _userModel->ChangeNextIndexSound(); + } + + // 歯車にタップしたか + if (_gear->IsHit(px, py)) + { + ChangeNextModel(); + } + + // 電源ボタンにタップしたか + if (_power->IsHit(px, py)) + { + AppEnd(); + } +} + +GLuint LAppDelegate::CreateShader() +{ + //バーテックスシェーダのコンパイル + GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); + const char* vertexShader = + "#version 120\n" + "attribute vec3 position;" + "attribute vec2 uv;" + "varying vec2 vuv;" + "void main(void){" + " gl_Position = vec4(position, 1.0);" + " vuv = uv;" + "}"; + glShaderSource(vertexShaderId, 1, &vertexShader, NULL); + glCompileShader(vertexShaderId); + if (!CheckShader(vertexShaderId)) + { + return 0; + } + + //フラグメントシェーダのコンパイル + GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); + const char* fragmentShader = + "#version 120\n" + "varying vec2 vuv;" + "uniform sampler2D texture;" + "uniform vec4 baseColor;" + "void main(void){" + " gl_FragColor = texture2D(texture, vuv) * baseColor;" + "}"; + glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); + glCompileShader(fragmentShaderId); + if (!CheckShader(fragmentShaderId)) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + return programId; +} + +bool LAppDelegate::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +void LAppDelegate::LoadModelName() +{ + // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 + // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + csmString crawlPath(ResourcesPath); + crawlPath += "*.*"; + + struct _finddata_t fdata; + intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); + if (fh == -1) return; + + _modelNameList.Clear(); + + while (_findnext(fh, &fdata) == 0) + { + if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) + { + // フォルダと同名の.model3.jsonがあるか探索する + csmString model3jsonPath(ResourcesPath); + model3jsonPath += fdata.name; + model3jsonPath.Append(1, '/'); + model3jsonPath += fdata.name; + model3jsonPath += ".model3.json"; + + struct _finddata_t fdata2; + if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) + { + _modelNameList.PushBack(csmString(fdata.name)); + } + } + } + qsort(_modelNameList.GetPtr(), _modelNameList.GetSize(), sizeof(csmString), CompareCsmString); +} + +void LAppDelegate::LoadModel() +{ + if (_userModel) + { + // レンダラの解放 + _userModel->DeleteRenderer(); + + delete _userModel; + } + + // モデルデータの新規生成 + _userModel = new LAppMotionSyncModel(); + + if (_modelIndex < _modelNameList.GetSize()) + { + // モデルデータの読み込み及び生成とセットアップを行う + _userModel->LoadAssets(_modelNameList[_modelIndex]); + } +} + +void LAppDelegate::ChangeNextModel() +{ + if (0 < _modelNameList.GetSize()) + { + _modelIndex = (_modelIndex + 1) % _modelNameList.GetSize(); + LoadModel(); + } +} + +void LAppDelegate::LoadGraph() +{ + GLuint programId = CreateShader(); + + int width, height; + glfwGetWindowSize(_window, &width, &height); + + const std::string resourcesPath = std::string(LAppDefine::ResourcesPath) + "/"; + + std::string imageName = LAppDefine::BackImageName; + LAppTextureManager::TextureInfo* backgroundTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + float x = width * 0.5f; + float y = height * 0.5f; + float fWidth = static_cast(backgroundTexture->width * 2.0f); + float fHeight = static_cast(height * 0.95f); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); + + imageName = LAppMotionSyncDefine::FastForwardImageName; + LAppTextureManager::TextureInfo* fastForwardTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(fastForwardTexture->width * 0.5f); + y = static_cast(height - fastForwardTexture->height * 0.5f); + fWidth = static_cast(fastForwardTexture->width); + fHeight = static_cast(fastForwardTexture->height); + _fastForward = new LAppSprite(x, y, fWidth, fHeight, fastForwardTexture->id, programId); + + imageName = LAppDefine::GearImageName; + LAppTextureManager::TextureInfo* gearTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(width - gearTexture->width * 0.5f); + y = static_cast(height - gearTexture->height * 0.5f); + fWidth = static_cast(gearTexture->width); + fHeight = static_cast(gearTexture->height); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); + + imageName = LAppDefine::PowerImageName; + LAppTextureManager::TextureInfo* powerTexture = _textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = static_cast(width - powerTexture->width * 0.5f); + y = static_cast(powerTexture->height * 0.5f); + fWidth = static_cast(powerTexture->width); + fHeight = static_cast(powerTexture->height); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); +} + +void LAppDelegate::ResizeSprite() +{ + if (!_textureManager) + { + return; + } + + // 描画領域サイズ + int width, height; + glfwGetWindowSize(_window, &width, &height); + + float x = 0.0f; + float y = 0.0f; + float fWidth = 0.0f; + float fHeight = 0.0f; + + if (_back) + { + GLuint id = _back->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = width * 0.5f; + y = height * 0.5f; + fWidth = static_cast(texInfo->width * 2); + fHeight = static_cast(height) * 0.95f; + _back->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_power) + { + GLuint id = _power->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->width * 0.5f); + y = static_cast(texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _power->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_gear) + { + GLuint id = _gear->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->width * 0.5f); + y = static_cast(height - texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _gear->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_fastForward) + { + GLuint id = _fastForward->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = _textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(texInfo->width * 0.5f); + y = static_cast(height - texInfo->height * 0.5f); + fWidth = static_cast(texInfo->width); + fHeight = static_cast(texInfo->height); + _fastForward->ResetRect(x, y, fWidth, fHeight); + } + } +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp new file mode 100644 index 0000000..099146f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp @@ -0,0 +1,218 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include +#include "LAppAllocator.hpp" +#include "LAppMotionSyncModel.hpp" +#include "LAppSprite.hpp" + +class LAppView; +class LAppTextureManager; + +/** +* @brief アプリケーションクラス。 +* Cubism SDK の管理を行う。 +*/ +class LAppDelegate +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppDelegate* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief APPに必要なものを初期化する。 + */ + bool Initialize(); + + /** + * @brief 解放する。 + */ + void Release(); + + /** + * @brief 実行処理。 + */ + void Run(); + + /** + * @brief OpenGL用 glfwSetMouseButtonCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] button ボタン種類 + * @param[in] action 実行結果 + * @param[in] modify + */ + void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + + /** + * @brief OpenGL用 glfwSetCursorPosCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnMouseCallBack(GLFWwindow* window, double x, double y); + + /** + * @brief Window情報を取得する。 + */ + GLFWwindow* GetWindow() { return _window; } + + /** + * @brief アプリケーションを終了するかどうか。 + */ + bool GetIsEnd() { return _isEnd; } + + /** + * @brief アプリケーションを終了する。 + */ + void AppEnd() { _isEnd = true; } + + LAppTextureManager* GetTextureManager() { return _textureManager; } + +private: + /** + * @brief コンストラクタ + */ + LAppDelegate(); + + /** + * @brief デストラクタ + */ + ~LAppDelegate(); + + /** + * @brief Cubism SDK の初期化 + */ + void InitializeCubism(); + + /** + * @brief タッチされたときに呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesBegan(float pointX, float pointY); + + /** + * @brief タッチしているときにポインタが動いたら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesMoved(float pointX, float pointY); + + /** + * @brief タッチが終了したら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesEnded(float pointX, float pointY); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief モデル名リストの読み込み + * + * モデル名リストの読み込み処理を行う + * + */ + void LoadModelName(); + + /** + * @brief モデルの読み込み + * + * モデルデータの読み込み処理を行う + * + */ + void LoadModel(); + + /** + * @brief 次のモデルに切り替え + * + */ + void ChangeNextModel(); + + /** + * @brief 背景とボタンの読み込み + * + * 背景とボタンの読み込み処理を行う + * + */ + void LoadGraph(); + + /** + * @brief スプライト系のサイズ再設定 + */ + void ResizeSprite(); + + /** + * @brief シェーダーを登録する。 + */ + GLuint CreateShader(); + + GLFWwindow* _window; ///< OpenGL ウィンドウ + int _windowWidth; ///< ウィンドウサイズ幅の保存 + int _windowHeight; ///< ウィンドウサイズ高さの保存 + LAppTextureManager* _textureManager; ///< テクスチャマネージャー + + LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator + Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option + bool _captured; ///< クリックしているか + float _mouseX; ///< マウスX座標 + float _mouseY; ///< マウスY座標 + bool _isEnd; ///< APP終了しているか + + LAppSprite* _back; ///< 背景画像 + LAppSprite* _fastForward; ///< 早送り画像 + LAppSprite* _gear; ///< ギア画像 + LAppSprite* _power; ///< 電源画像 + LAppMotionSyncModel* _userModel; ///< ユーザーが実際に使用するモデル + + Csm::csmVector _modelNameList; ///< モデルディレクトリ名のリスト + Csm::csmInt32 _modelIndex; ///< 表示するシーンモデル名のインデックス値 +}; + +class EventHandler +{ +public: + /** + * @brief glfwSetMouseButtonCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify); + } + + /** + * @brief glfwSetCursorPosCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, double x, double y) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); + } + +}; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.cpp new file mode 100644 index 0000000..6d8ccb4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.cpp @@ -0,0 +1,26 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppMotionSyncDefine.hpp" + +namespace LAppMotionSyncDefine { + + using namespace Csm; + + // DirectSount の再生バッファに設定されるサンプル数 + const csmUint32 DirectSoundBufferSampleCount = 8192; + + // 早送り + const csmChar* FastForwardImageName = "icon_fastForward.png"; + + // チャンネル数 + const csmInt32 Channels = 2; + // サンプリング周波数 + const csmInt32 SamplesPerSec = 48000; + // ビット深度 + const csmInt32 BitDepth = 16; +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.hpp new file mode 100644 index 0000000..e075121 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncDefine.hpp @@ -0,0 +1,27 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ +#pragma once + +#include + +/** +* @brief Sample Appで使用する定数 +* +*/ +namespace LAppMotionSyncDefine { + + using namespace Csm; + + extern const csmUint32 DirectSoundBufferSampleCount; ///< DirectSount の再生バッファに設定されるサンプル数 + + extern const csmChar* FastForwardImageName; ///< 早送りファイル + + // 音声設定 + extern const csmInt32 Channels; ///< チャンネル数 + extern const csmInt32 SamplesPerSec; ///< サンプリング周波数 + extern const csmInt32 BitDepth; ///< ビット深度 +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.cpp new file mode 100644 index 0000000..5d0e3a1 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.cpp @@ -0,0 +1,268 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppMotionSyncModel.hpp" +#include "CubismModelMotionSyncSettingJson.hpp" +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppMotionSyncDefine.hpp" +#include "LAppPal.hpp" +#include "LAppTextureManager.hpp" +#include "Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp" + +using namespace Csm; +using namespace MotionSync; +using namespace LAppDefine; +using namespace LAppMotionSyncDefine; + +namespace { + csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) + { + if (LAppDefine::DebugLogEnable) + { + LAppPal::PrintLog("[APP]create buffer: %s ", path); + } + return LAppPal::LoadFileAsBytes(path, size); + } + + void DeleteBuffer(csmByte* buffer, const csmChar* path = "") + { + if (DebugLogEnable) + { + LAppPal::PrintLog("[APP]delete buffer: %s", path); + } + LAppPal::ReleaseBytes(buffer); + } +} + +LAppMotionSyncModel::LAppMotionSyncModel() + : CubismUserModel() + , _modelSetting(NULL) + , _motionSync(NULL) + , _soundIndex(0) +{ +} + +LAppMotionSyncModel::~LAppMotionSyncModel() +{ + if (_modelSetting) + { + delete _modelSetting; + } + + if (_motionSync) + { + _soundData.Release(); + CubismMotionSync::Delete(_motionSync); + } +} + +void LAppMotionSyncModel::LoadAssets(const csmString fileName) +{ + _modelHomeDir = csmString(ResourcesPath) + "/" + fileName + "/"; + + if (_debugMode) + { + LAppPal::PrintLog("[APP]load model setting: %s", fileName); + } + + csmSizeInt size; + const csmString path = _modelHomeDir + fileName + ".model3.json"; + + csmByte* buffer = CreateBuffer(path.GetRawString(), &size); + _modelSetting = new CubismModelMotionSyncSettingJson(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + + SetupModel(); + + if (_model == NULL) + { + LAppPal::PrintLog("Failed to LoadAssets()."); + return; + } + + CreateRenderer(); + + // テクスチャのセットアップ + SetupTextures(); +} + +void LAppMotionSyncModel::ModelOnUpdate() +{ + int width, height; + // ウィンドウサイズを取得 + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + + Csm::CubismMatrix44 projection; + // 念のため単位行列に初期化 + projection.LoadIdentity(); + + if (_model->GetCanvasWidth() > 1.0f && width < height) + { + // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する + GetModelMatrix()->SetWidth(2.0f); + projection.Scale(1.0f, static_cast(width) / static_cast(height)); + } + else + { + projection.Scale(static_cast(height) / static_cast(width), 1.0f); + } + + // 音声データ更新 + _soundData.Update(); + + // モデルのパラメータを更新 + ModelParamUpdate(); + + // モデルの描画を更新 + Draw(projection); ///< 参照渡しなのでprojectionは変質する +} + +void LAppMotionSyncModel::ChangeNextIndexSound() +{ + if (0 < _soundFileList.GetSize()) + { + _soundIndex = (_soundIndex + 1) % _soundFileList.GetSize(); + PlayIndexSound(); + } +} + +void LAppMotionSyncModel::SetupModel() +{ + _updating = true; + _initialized = false; + + csmByte* buffer; + csmSizeInt size; + + //Cubism Model + if (strcmp(_modelSetting->GetModelFileName(), "") != 0) + { + csmString path = _modelSetting->GetModelFileName(); + path = _modelHomeDir + path; + + if (_debugMode) + { + LAppPal::PrintLog("[APP]create model: %s", _modelSetting->GetModelFileName()); + } + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadModel(buffer, size, _mocConsistency); + DeleteBuffer(buffer, path.GetRawString()); + } + + if (_modelSetting == NULL || _modelMatrix == NULL) + { + LAppPal::PrintLog("Failed to SetupModel()."); + return; + } + + //Layout + csmMap layout; + _modelSetting->GetLayoutMap(layout); + _modelMatrix->SetupFromLayout(layout); + + // パラメータを保存 + _model->SaveParameters(); + + _updating = false; + _initialized = true; + + // MotionSync + const csmChar* fileName = _modelSetting->GetMotionSyncJsonFileName(); + + if (_debugMode) + { + LAppPal::PrintLog("[APP]load motionSync setting: %s", fileName); + } + + const csmString path = csmString(_modelHomeDir) + fileName; + buffer = CreateBuffer(path.GetRawString(), &size); + + _motionSync = CubismMotionSync::Create(_model, buffer, size, SamplesPerSec); + + if (!_motionSync) + { + LAppPal::PrintLog("Failed to SetupModel()."); + return; + } + + DeleteBuffer(buffer, path.GetRawString()); + + // 音声データ + _soundFileList = _modelSetting->GetMotionSyncSoundFileList(); + _soundIndex = 0; + PlayIndexSound(); +} + +void LAppMotionSyncModel::SetupTextures() +{ + for (csmInt32 modelTextureNumber = 0; modelTextureNumber < _modelSetting->GetTextureCount(); modelTextureNumber++) + { + // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ + if (!strcmp(_modelSetting->GetTextureFileName(modelTextureNumber), "")) + { + continue; + } + + // OpenGLのテクスチャユニットにテクスチャをロードする + csmString texturePath = _modelSetting->GetTextureFileName(modelTextureNumber); + texturePath = _modelHomeDir + texturePath; + + LAppTextureManager::TextureInfo* texture = LAppDelegate::GetInstance()->GetTextureManager()->CreateTextureFromPngFile(texturePath.GetRawString()); + const csmInt32 glTextueNumber = texture->id; + + // OpenGL + GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); + } + + // 乗算済みアルファ値の有効化・無効化を設定 + GetRenderer()->IsPremultipliedAlpha(false); +} + +void LAppMotionSyncModel::ModelParamUpdate() +{ + const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime(); + _userTimeSeconds += deltaTimeSeconds; + + // 不透明度 + _opacity = _model->GetModelOpacity(); + + // モーションシンクプラグイン + if (_motionSync != NULL) + { + _motionSync->UpdateParameters(_model, deltaTimeSeconds); + } + + _model->Update(); +} + +void LAppMotionSyncModel::PlayIndexSound() +{ + if (_soundIndex < _soundFileList.GetSize()) + { + _soundData.LoadFile(_modelHomeDir + _soundFileList[_soundIndex], 0); + _motionSync->SetSoundBuffer(0, _soundData.GetBuffer()); + } +} + +void LAppMotionSyncModel::Draw(Csm::CubismMatrix44& matrix) +{ + if (!_model) + { + return; + } + + // 現在の行列に行列を乗算 + matrix.MultiplyByMatrix(_modelMatrix); + + // 行列をモデルビュープロジェクション行列を設定 + GetRenderer()->SetMvpMatrix(&matrix); + + // モデルの描画を命令・実行する + GetRenderer()->DrawModel(); +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.hpp new file mode 100644 index 0000000..79829eb --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppMotionSyncModel.hpp @@ -0,0 +1,95 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include "CubismMotionSync.hpp" +#include "CubismModelMotionSyncSettingJson.hpp" +#include "LAppPlaySound.hpp" + +/** + * @brief ユーザーが実際に使用するモデルの実装クラス
+ * モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。 + * + */ +class LAppMotionSyncModel : public Csm::CubismUserModel +{ +public: + /** + * @brief コンストラクタ + */ + LAppMotionSyncModel(); + + /** + * @brief デストラクタ + * + */ + virtual ~LAppMotionSyncModel(); + + /** + * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する + * + */ + void LoadAssets(const Csm::csmString fileName); + + /** + * @brief モデルの更新 + * + * モデルの状態や描画を更新する + */ + void ModelOnUpdate(); + + /** + * @brief 次の音声ファイルを再生する + * + */ + void ChangeNextIndexSound(); + +private: + Csm::MotionSync::CubismModelMotionSyncSettingJson* _modelSetting; ///< モデルセッティング情報 + Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + Csm::MotionSync::CubismMotionSync* _motionSync; ///< モーションシンク + LAppPlaySound _soundData; ///< モーションシンクで使用する音声データ + Csm::csmVector _soundFileList; ///< 音声データファイルのリスト + Csm::csmInt32 _soundIndex; ///< 再生する音声データのインデックス値 + + /** + * @brief model3.jsonからモデルを生成する。
+ * model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う。 + * + */ + void SetupModel(); + + /** + * @brief OpenGLのテクスチャユニットにテクスチャをロードする + * + */ + void SetupTextures(); + + /** + * @brief モデルのパラメータ情報の更新 + * + * モデルのパラメータの情報を更新する + */ + void ModelParamUpdate(); + + /** + * @brief 現在のインデックスの音声ファイルを再生する + * + */ + void PlayIndexSound(); + + /** + * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す + * + * @param[in] matrix View-Projection行列 + */ + void Draw(Csm::CubismMatrix44& matrix); +}; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.cpp new file mode 100644 index 0000000..7262d9c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.cpp @@ -0,0 +1,337 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppPlaySound.hpp" +#include +#include "LAppWavFileHandler.hpp" + +#pragma comment(lib, "dsound.lib") + +using namespace Csm; + +namespace +{ +LPDIRECTSOUND8 _directSound = NULL; +LPDIRECTSOUNDBUFFER _primary = NULL; +} + +csmBool LAppPlaySound::Init(HWND window, csmInt32 channels, csmInt32 samplesPerSec, csmInt32 bitDepth) +{ + HRESULT result; + + // COMの初期化 + result = CoInitialize(NULL); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to CoInitialize() in LAppPlaySound::%s()", __func__); + return false; + } + + // DirectSound8を作成 + result = DirectSoundCreate8(NULL, &_directSound, NULL); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to DirectSoundCreate8() in LAppPlaySound::%s()", __func__); + return false; + } + + // 強調モード + result = _directSound->SetCooperativeLevel(window, DSSCL_EXCLUSIVE | DSSCL_PRIORITY); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to SetCooperativeLevel() in LAppPlaySound::%s()", __func__); + return false; + } + + // プライマリサウンドバッファの作成 + WAVEFORMATEX waveFormat; + DSBUFFERDESC dsdesc; + ZeroMemory(&dsdesc, sizeof(DSBUFFERDESC)); + dsdesc.dwSize = sizeof(DSBUFFERDESC); + dsdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsdesc.dwBufferBytes = 0; + dsdesc.lpwfxFormat = NULL; + result = _directSound->CreateSoundBuffer(&dsdesc, &_primary, NULL); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to CreateSoundBuffer() in LAppPlaySound::%s()", __func__); + return false; + } + + // プライマリバッファのステータスを決定 + ZeroMemory(&waveFormat, sizeof(WAVEFORMATEX)); + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nChannels = channels; + waveFormat.nSamplesPerSec = samplesPerSec; + waveFormat.wBitsPerSample = bitDepth; + waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + result = _primary->SetFormat(&waveFormat); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to SetFormat() in LAppPlaySound::%s()", __func__); + return false; + } + + return true; +} + +csmBool LAppPlaySound::Close() +{ + if (_primary) + { + _primary->Release(); + _primary = NULL; + } + + if (_directSound) + { + _directSound->Release(); + _directSound = NULL; + } + + // COMの終了 + CoUninitialize(); + + return true; +} + +csmBool LAppPlaySound::LoadFile(csmString path, csmUint32 useChannel) +{ + // 初期化 + Release(); + + HRESULT result; + LPWAVEFORMATEX waveFormat; + LAppWavFileHandler wavHandler; + + // WAVファイルをロード + wavHandler.Start(path); + LAppWavFileHandler::WavFileInfo wavHandlerInfo = wavHandler.GetWavFileInfo(); + + // ヘッダメモリ確保と情報設定 + waveFormat = reinterpret_cast(CSM_MALLOC(sizeof(WAVEFORMATEX))); + if (!waveFormat) + { + CubismLogError("[APP]Failed malloc to 'waveFormat' in LAppPlaySound::%s()", __func__); + return false; + } + waveFormat->wFormatTag = WAVE_FORMAT_PCM; + waveFormat->nChannels = wavHandlerInfo._numberOfChannels; + _channels = wavHandlerInfo._numberOfChannels; + waveFormat->nSamplesPerSec = wavHandlerInfo._samplingRate; + waveFormat->nAvgBytesPerSec = wavHandlerInfo._avgBytesPerSec; + _bufferSampleBytes = LAppMotionSyncDefine::DirectSoundBufferSampleCount * wavHandlerInfo._blockAlign; + waveFormat->nBlockAlign = wavHandlerInfo._blockAlign; + waveFormat->wBitsPerSample = wavHandlerInfo._bitsPerSample; + _bitDepth = wavHandlerInfo._bitsPerSample; + waveFormat->cbSize = 0; + + // 生の音声データを取得 + _dataSize = wavHandler.GetRawDataSize(); + _data = reinterpret_cast(CSM_MALLOC(sizeof(csmByte) * _dataSize)); + if (!_data) + { + CubismLogError("[APP]Failed malloc to '_data' in LAppPlaySound::%s()", __func__); + CSM_FREE(waveFormat); + return false; + } + for (csmUint32 i = 0; i < _dataSize; i++) + { + _data[i] = wavHandler.GetRawData()[i]; + } + + // サウンドバッファの作成 + DSBUFFERDESC dsdesc; + ZeroMemory(&dsdesc, sizeof(DSBUFFERDESC)); + dsdesc.dwSize = sizeof(DSBUFFERDESC); + dsdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC | DSBCAPS_LOCDEFER; + dsdesc.dwBufferBytes = _bufferSampleBytes; + dsdesc.lpwfxFormat = waveFormat; + dsdesc.guid3DAlgorithm = DS3DALG_DEFAULT; + result = _directSound->CreateSoundBuffer(&dsdesc, &_secondary, NULL); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to CreateSoundBuffer() in LAppPlaySound::%s()", __func__); + CSM_FREE(waveFormat); + return false; + } + + // 初期データを前半だけ書き込み + _writePosition = WritePosition_Front; + _dataPos = 0; + LPVOID soundBuffer1, soundBuffer2; + DWORD soundBufferSize1, soundBufferSize2; + csmUint32 bufferBytes = _bufferSampleBytes / 2; + result = _secondary->Lock(0, bufferBytes, &soundBuffer1, &soundBufferSize1, &soundBuffer2, &soundBufferSize2, DSBLOCK_ENTIREBUFFER); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to Lock() in LAppPlaySound::%s()", __func__); + return false; + } + for (DWORD i = 0; i < soundBufferSize1 && _dataPos < _dataSize; i++) + { + reinterpret_cast(soundBuffer1)[i] = _data[_dataPos]; + _dataPos++; + } + _secondary->Unlock(soundBuffer1, soundBufferSize1, soundBuffer2, soundBufferSize2); + + // 口形に影響を与えたい音声のチャンネルを保存 + if (_channels <= useChannel) + { + useChannel = _channels - 1; + } + _samplesSize = wavHandlerInfo._samplesPerChannel; + _samples = reinterpret_cast(CSM_MALLOC(sizeof(csmFloat32) * _samplesSize)); + if (!_samples) + { + CubismLogError("[APP]Failed malloc to '_samples' in LAppPlaySound::%s()", __func__); + CSM_FREE(waveFormat); + return false; + } + wavHandler.GetPcmDataChannel(_samples, useChannel); + + // ヘッダ用メモリを開放 + CSM_FREE(waveFormat); + + _secondary->Play(0, 0, DSBPLAY_LOOPING); + + return true; +} + +csmBool LAppPlaySound::Update() +{ + HRESULT result; + DWORD playCursor; + LPVOID soundBuffer1, soundBuffer2; + DWORD soundBufferSize1, soundBufferSize2; + csmUint32 bufferBytes = _bufferSampleBytes / 2; + + result = _secondary->GetCurrentPosition(&playCursor, NULL); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to GetCurrentPosition() in LAppPlaySound::%s()", __func__); + return false; + } + + // 音声データをオーディオ側に書き込み + if (_writePosition == WritePosition_Back && bufferBytes <= playCursor) + { + // 前半書き込み + _writePosition = WritePosition_Front; + result = _secondary->Lock(0, bufferBytes, &soundBuffer1, &soundBufferSize1, &soundBuffer2, &soundBufferSize2, 0); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to Lock() in LAppPlaySound::%s()", __func__); + return false; + } + for (DWORD i = 0; i < soundBufferSize1 && _dataPos < _dataSize; i++) + { + reinterpret_cast(soundBuffer1)[i] = _data[_dataPos]; + _dataPos++; + } + _secondary->Unlock(soundBuffer1, soundBufferSize1, soundBuffer2, soundBufferSize2); + + // 生の音声データがなくなったら再生終了 + if (_dataSize <= _dataPos) + { + _secondary->Stop(); + } + } + else if (_writePosition == WritePosition_Front && playCursor < bufferBytes) + { + // 後半書き込み + _writePosition = WritePosition_Back; + result = _secondary->Lock(bufferBytes, bufferBytes * 2, &soundBuffer1, &soundBufferSize1, &soundBuffer2, &soundBufferSize2, 0); + if (FAILED(result)) + { + CubismLogError("[APP]Failed to Lock() in LAppPlaySound::%s()", __func__); + return false; + } + for (DWORD i = 0; i < soundBufferSize1 && _dataPos < _dataSize; i++) + { + reinterpret_cast(soundBuffer1)[i] = _data[_dataPos]; + _dataPos++; + } + _secondary->Unlock(soundBuffer1, soundBufferSize1, soundBuffer2, soundBufferSize2); + + // 生の音声データがなくなったら再生終了 + if (_dataSize <= _dataPos) + { + _secondary->Stop(); + } + } + + // 音声データを口形バッファに書き込み + csmUint32 pos = _dataPos / _channels / (_bitDepth / 8); + for (csmUint32 i = _buffer.GetSize(); i < pos; i++) + { + if (i < _samplesSize) + { + // MotionSyncへサンプルを送る。 + _buffer.PushBack(_samples[i]); + } + else + { + // 再生終了 + _secondary->Stop(); + break; + } + } + + return true; +} + +csmVector* LAppPlaySound::GetBuffer() +{ + return &_buffer; +} + +csmBool LAppPlaySound::IsPlay() +{ + DWORD status; + _secondary->GetStatus(&status); + return status & DSBSTATUS_PLAYING; +} + +void LAppPlaySound::Release() +{ + if (_secondary) + { + _secondary->Stop(); + _secondary->Release(); + _secondary = NULL; + } + if (_data) + { + CSM_FREE(_data); + _data = NULL; + } + if (_samples) + { + CSM_FREE(_samples); + _samples = NULL; + } + _buffer.Clear(); +} + +LAppPlaySound::LAppPlaySound() : + _secondary(NULL), + _channels(1), + _bitDepth(8), + _data(NULL), + _dataSize(0), + _dataPos(0), + _samples(NULL), + _samplesSize(0) +{ +} + +LAppPlaySound::~LAppPlaySound() +{ + Release(); +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.hpp new file mode 100644 index 0000000..3c1e13c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPlaySound.hpp @@ -0,0 +1,104 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include "LAppMotionSyncDefine.hpp" +#include "Type/csmString.hpp" +#include "Type/csmVector.hpp" + +class LAppPlaySound +{ +public: + /** + * @brief 音声機能を使うための初期化 + * + * @param[in] data 音声機能を使うために必要なデータ + * + * @return 初期化結果 + */ + static Csm::csmBool Init(HWND window, Csm::csmInt32 channels, Csm::csmInt32 samplesPerSec, Csm::csmInt32 bitDepth); + + /** + * @brief 音声機能を終了 + * + * @return 終了結果 + */ + static Csm::csmBool Close(); + + /** + * @brief 音声ファイル読み込み + * + * @param[in] path 音声ファイル + * @param[in] useChannel 使用するチャンネル + * + * @return 読み込み結果 + */ + Csm::csmBool LoadFile(Csm::csmString path, Csm::csmUint32 useChannel); + + /** + * @brief 音声の更新 + * + * @return 更新結果 + */ + Csm::csmBool Update(); + + /** + * @brief 再生したバッファの格納先の設定 + * + * @return バッファ + */ + Csm::csmVector* GetBuffer(); + + /** + * @brief 再生中か確認 + * + * @return 再生中か + */ + Csm::csmBool IsPlay(); + + /** + * @brief 解放処理 + * + */ + void Release(); + + /** + * @brief コンストラクタ + * + * コンストラクタ。 + * + */ + LAppPlaySound(); + + /** + * @brief デストラクタ + * + * デストラクタ。 + */ + virtual ~LAppPlaySound(); + +private: + enum WritePosition + { + WritePosition_Front, + WritePosition_Back, + }; + + LPDIRECTSOUNDBUFFER _secondary; + Csm::csmInt32 _channels; + Csm::csmInt32 _bitDepth; + WritePosition _writePosition; + Csm::csmUint32 _bufferSampleBytes; + Csm::csmByte* _data; + Csm::csmUint64 _dataSize; + Csm::csmUint64 _dataPos; + Csm::csmFloat32* _samples; + Csm::csmUint32 _samplesSize; + Csm::csmVector _buffer; +}; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/mainMotionSync.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/mainMotionSync.cpp new file mode 100644 index 0000000..6c13726 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/mainMotionSync.cpp @@ -0,0 +1,23 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include +#include +#include "LAppDelegate.hpp" + +int main() +{ + // create the application instance + if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE) + { + return 1; + } + + LAppDelegate::GetInstance()->Run(); + + return 0; +} diff --git a/Samples/OpenGL/README.ja.md b/Samples/OpenGL/README.ja.md new file mode 100644 index 0000000..f135574 --- /dev/null +++ b/Samples/OpenGL/README.ja.md @@ -0,0 +1,58 @@ +[English](README.md) / [日本語](README.ja.md) + +--- + +# Cubism Native MotionSync Samples for OpenGL + +OpenGL で実装したモーションシンク機能を扱うアプリケーションのサンプル実装です。 + + +## 開発環境 + +| サードパーティ | バージョン | +| --- | --- | +| [GLEW] | 2.2.0 | +| [GLFW] | 3.3.8 | +| [stb_image.h] | 2.28 | + +その他の開発環境・動作確認環境はトップディレクトリにある [README.md](/README.ja.md) を参照してください。 + + +## ディレクトリ構造 + +``` +. +└─ Demo + ├─ proj.mac.cmake # CMake project for macOS + └─ proj.win.cmake # CMake project for Windows +``` + + +## Demo + +モーションシンクに対応したサンプルです。 + +このディレクトリ内に含まれるものは以下の通りです。 + +### proj.mac.cmake + +macOS 用の CMake プロジェクトです。 + +`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます + +| スクリプト名 | 生成物 | +| --- | --- | +| `make_xcode` | 実行可能なアプリケーション | +| `proj_xcode` | Xcode プロジェクト | + + +### proj.win.cmake + +Windows 用の CMake プロジェクトです。 + +`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます + +| スクリプト名 | 生成物 | +| --- | --- | +| `nmake_msvcXXXX.bat` | 実行可能なアプリケーション | +| `proj_msvcXXXX.bat` | Visual Studio プロジェクト | diff --git a/Samples/OpenGL/README.md b/Samples/OpenGL/README.md new file mode 100644 index 0000000..24cbba5 --- /dev/null +++ b/Samples/OpenGL/README.md @@ -0,0 +1,57 @@ +[English](README.md) / [日本語](README.ja.md) + +--- + +# Cubism Native MotionSync Samples for OpenGL + +This is a sample implementation of an application that handles motion-sync functionality implemented in OpenGL. + + +## Development environment + +| Third Party | Version | +| --- | --- | +| [GLEW] | 2.2.0 | +| [GLFW] | 3.3.8 | +| [stb_image.h] | 2.28 | + +For other development environments and operation environments, see [README.md](/README.md) in the top directory. + + +## Directory structure + +``` +. +└─ Demo + ├─ proj.mac.cmake # CMake project for macOS + └─ proj.win.cmake # CMake project for Windows +``` + + +## Demo + +This is a sample that supports motion-sync. + +The items contained in this directory are as follows. + +### proj.mac.cmake + +CMake project for macOS. + +Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. + +| Script name | Product | +| --- | --- | +| `make_xcode` | Executable application | +| `proj_xcode` | Xcode project | + +### proj.win.cmake + +CMake project for Windows. + +Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. + +| Script name | Product | +| --- | --- | +| `nmake_msvcXXXX.bat` | Executable application | +| `proj_msvcXXXX.bat` | Visual Studio project | diff --git a/Samples/Resources/Kei_basic/Kei_basic.2048/texture_00.png b/Samples/Resources/Kei_basic/Kei_basic.2048/texture_00.png new file mode 100644 index 0000000..0b50ccb Binary files /dev/null and b/Samples/Resources/Kei_basic/Kei_basic.2048/texture_00.png differ diff --git a/Samples/Resources/Kei_basic/Kei_basic.cdi3.json b/Samples/Resources/Kei_basic/Kei_basic.cdi3.json new file mode 100644 index 0000000..6626835 --- /dev/null +++ b/Samples/Resources/Kei_basic/Kei_basic.cdi3.json @@ -0,0 +1,277 @@ +{ + "Version": 3, + "Parameters": [ + { + "Id": "ParamAngleX", + "GroupId": "ParamGroup5", + "Name": "角度 X" + }, + { + "Id": "ParamAngleY", + "GroupId": "ParamGroup5", + "Name": "角度 Y" + }, + { + "Id": "ParamAngleZ", + "GroupId": "ParamGroup5", + "Name": "角度 Z" + }, + { + "Id": "ParamCheek", + "GroupId": "ParamGroup5", + "Name": "照れ" + }, + { + "Id": "ParamBodyAngleX", + "GroupId": "ParamGroup6", + "Name": "体の回転 X" + }, + { + "Id": "ParamBodyAngleY", + "GroupId": "ParamGroup6", + "Name": "体の回転 Y" + }, + { + "Id": "ParamBodyAngleZ", + "GroupId": "ParamGroup6", + "Name": "体の回転 Z" + }, + { + "Id": "ParamBreath", + "GroupId": "ParamGroup6", + "Name": "呼吸" + }, + { + "Id": "ParamBrowLY", + "GroupId": "ParamGroup4", + "Name": "左眉 上下" + }, + { + "Id": "ParamBrowRY", + "GroupId": "ParamGroup4", + "Name": "右眉 上下" + }, + { + "Id": "ParamBrowLForm", + "GroupId": "ParamGroup4", + "Name": "左眉 変形" + }, + { + "Id": "ParamBrowRForm", + "GroupId": "ParamGroup4", + "Name": "右眉 変形" + }, + { + "Id": "ParamEyeLOpen", + "GroupId": "ParamGroup2", + "Name": "左目 開閉" + }, + { + "Id": "ParamEyeLSmile", + "GroupId": "ParamGroup2", + "Name": "左目 笑顔" + }, + { + "Id": "ParamEyeROpen", + "GroupId": "ParamGroup2", + "Name": "右目 開閉" + }, + { + "Id": "ParamEyeRSmile", + "GroupId": "ParamGroup2", + "Name": "右目 笑顔" + }, + { + "Id": "ParamEyeBallX", + "GroupId": "ParamGroup3", + "Name": "目玉 X" + }, + { + "Id": "ParamEyeBallY", + "GroupId": "ParamGroup3", + "Name": "目玉 Y" + }, + { + "Id": "ParamMouthForm", + "GroupId": "ParamGroup8", + "Name": "口 変形" + }, + { + "Id": "ParamMouthOpenY", + "GroupId": "ParamGroup8", + "Name": "口 開閉" + }, + { + "Id": "ParamHairFront", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 前" + }, + { + "Id": "ParamHairSide", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 左横" + }, + { + "Id": "ParamHairSide2", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 右横" + }, + { + "Id": "ParamHairBack", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 後" + }, + { + "Id": "ParamHairFrontFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 前" + }, + { + "Id": "ParamHairSideFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 横" + }, + { + "Id": "ParamHairBackFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 後" + } + ], + "ParameterGroups": [ + { + "Id": "ParamGroup5", + "GroupId": "", + "Name": "顔" + }, + { + "Id": "ParamGroup6", + "GroupId": "", + "Name": "体" + }, + { + "Id": "ParamGroup4", + "GroupId": "", + "Name": "眉" + }, + { + "Id": "ParamGroup2", + "GroupId": "", + "Name": "目" + }, + { + "Id": "ParamGroup3", + "GroupId": "", + "Name": "目玉" + }, + { + "Id": "ParamGroup8", + "GroupId": "", + "Name": "口 基本" + }, + { + "Id": "ParamGroup7", + "GroupId": "", + "Name": "揺れ" + } + ], + "Parts": [ + { + "Id": "Part15", + "Name": "コア" + }, + { + "Id": "Part", + "Name": "左横髪" + }, + { + "Id": "Part2", + "Name": "右横髪" + }, + { + "Id": "Part3", + "Name": "前髪" + }, + { + "Id": "Part4", + "Name": "左まゆ毛" + }, + { + "Id": "Part5", + "Name": "右まゆ毛" + }, + { + "Id": "Part22", + "Name": "左目" + }, + { + "Id": "Part7", + "Name": "右目" + }, + { + "Id": "Part6", + "Name": "頬" + }, + { + "Id": "Part9", + "Name": "鼻" + }, + { + "Id": "Part13", + "Name": "口 基本" + }, + { + "Id": "Part10", + "Name": "顔" + }, + { + "Id": "Part11", + "Name": "左耳" + }, + { + "Id": "Part12", + "Name": "右耳" + }, + { + "Id": "Part14", + "Name": "首" + }, + { + "Id": "Part16", + "Name": "体" + }, + { + "Id": "Part17", + "Name": "後ろ髪" + }, + { + "Id": "Part8", + "Name": "SDK表示" + }, + { + "Id": "PartSketch0", + "Name": "[ 下絵 ]" + }, + { + "Id": "Part23", + "Name": "左目玉" + }, + { + "Id": "Part21", + "Name": "右目玉" + } + ], + "CombinedParameters": [ + [ + "ParamAngleX", + "ParamAngleY" + ], + [ + "ParamEyeBallX", + "ParamEyeBallY" + ], + [ + "ParamMouthForm", + "ParamMouthOpenY" + ] + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/Kei_basic.moc3 b/Samples/Resources/Kei_basic/Kei_basic.moc3 new file mode 100644 index 0000000..153fa78 Binary files /dev/null and b/Samples/Resources/Kei_basic/Kei_basic.moc3 differ diff --git a/Samples/Resources/Kei_basic/Kei_basic.model3.json b/Samples/Resources/Kei_basic/Kei_basic.model3.json new file mode 100644 index 0000000..9f71503 --- /dev/null +++ b/Samples/Resources/Kei_basic/Kei_basic.model3.json @@ -0,0 +1,59 @@ +{ + "Version": 3, + "FileReferences": { + "Moc": "Kei_basic.moc3", + "Textures": [ + "Kei_basic.2048/texture_00.png" + ], + "Physics": "Kei_basic.physics3.json", + "DisplayInfo": "Kei_basic.cdi3.json", + "MotionSync": "Kei_basic.motionsync3.json", + "Motions": { + "": [ + { + "File": "motions/01_kei_en.motion3.json", + "Sound": "sounds/01_kei_en.wav", + "MotionSync": "Basic_CRI" + }, + { + "File": "motions/01_kei_jp.motion3.json", + "Sound": "sounds/01_kei_jp.wav", + "MotionSync": "Basic_CRI" + }, + { + "File": "motions/01_kei_ko.motion3.json", + "Sound": "sounds/01_kei_ko.wav", + "MotionSync": "Basic_CRI" + }, + { + "File": "motions/01_kei_zh.motion3.json", + "Sound": "sounds/01_kei_zh.wav", + "MotionSync": "Basic_CRI" + } + ] + } + }, + "Groups": [ + { + "Target": "Parameter", + "Name": "LipSync", + "Ids": [ + "ParamMouthOpenY" + ] + }, + { + "Target": "Parameter", + "Name": "EyeBlink", + "Ids": [ + "ParamEyeLOpen", + "ParamEyeROpen" + ] + } + ], + "HitAreas": [ + { + "Id": "HitAreaHead", + "Name": "Head" + } + ] +} diff --git a/Samples/Resources/Kei_basic/Kei_basic.motionsync3.json b/Samples/Resources/Kei_basic/Kei_basic.motionsync3.json new file mode 100644 index 0000000..f70217c --- /dev/null +++ b/Samples/Resources/Kei_basic/Kei_basic.motionsync3.json @@ -0,0 +1,178 @@ +{ + "Version": 1, + "Meta": { + "SettingCount": 1, + "Dictionary": [ + { + "Id": "MotionSyncSetting", + "Name": "Basic_CRI" + } + ] + }, + "Settings": [ + { + "Id": "MotionSyncSetting", + "AnalysisType": "CRI", + "UseCase": "Mouth", + "CubismParameters": [ + { + "Name": "口 変形", + "Id": "ParamMouthForm", + "Min": -1.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "口 開閉", + "Id": "ParamMouthOpenY", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + } + ], + "AudioParameters": [ + { + "Name": "Silence", + "Id": "Silence", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.0, + "Enabled": true + }, + { + "Name": "A", + "Id": "A", + "Min": 0.0, + "Max": 1.0, + "Scale": 0.30000001192092896, + "Enabled": true + }, + { + "Name": "I", + "Id": "I", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.0, + "Enabled": true + }, + { + "Name": "U", + "Id": "U", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.5, + "Enabled": true + }, + { + "Name": "E", + "Id": "E", + "Min": 0.0, + "Max": 1.0, + "Scale": 6.0, + "Enabled": true + }, + { + "Name": "O", + "Id": "O", + "Min": 0.0, + "Max": 1.0, + "Scale": 8.0, + "Enabled": true + } + ], + "Mappings": [ + { + "Type": "Shape", + "Id": "Silence", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": 0.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "A", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": 1.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + } + ] + }, + { + "Type": "Shape", + "Id": "I", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": 1.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 0.4000000059604645 + } + ] + }, + { + "Type": "Shape", + "Id": "U", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": -1.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 0.4000000059604645 + } + ] + }, + { + "Type": "Shape", + "Id": "E", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": 1.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 0.699999988079071 + } + ] + }, + { + "Type": "Shape", + "Id": "O", + "Targets": [ + { + "Id": "ParamMouthForm", + "Value": -1.0 + }, + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + } + ] + } + ], + "PostProcessing": { + "BlendRatio": 0.5, + "Smoothing": 60, + "SampleRate": 60.0 + } + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/Kei_basic.physics3.json b/Samples/Resources/Kei_basic/Kei_basic.physics3.json new file mode 100644 index 0000000..531b219 --- /dev/null +++ b/Samples/Resources/Kei_basic/Kei_basic.physics3.json @@ -0,0 +1,533 @@ +{ + "Version": 3, + "Meta": { + "PhysicsSettingCount": 6, + "TotalInputCount": 18, + "TotalOutputCount": 7, + "VertexCount": 12, + "Fps": 60, + "EffectiveForces": { + "Gravity": { + "X": 0, + "Y": -1 + }, + "Wind": { + "X": 0, + "Y": 0 + } + }, + "PhysicsDictionary": [ + { + "Id": "PhysicsSetting1", + "Name": "髪揺れ 前" + }, + { + "Id": "PhysicsSetting2", + "Name": "髪揺れ 横" + }, + { + "Id": "PhysicsSetting3", + "Name": "髪揺れ 後" + }, + { + "Id": "PhysicsSetting4", + "Name": "髪ふわ 前" + }, + { + "Id": "PhysicsSetting5", + "Name": "髪ふわ 横" + }, + { + "Id": "PhysicsSetting6", + "Name": "髪ふわ 後" + } + ] + }, + "PhysicsSettings": [ + { + "Id": "PhysicsSetting1", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairFront" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 11.4 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.2, + "Radius": 11.4 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting2", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSide" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + }, + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSide2" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.3, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting3", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairBack" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.9, + "Acceleration": 1, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting4", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairFrontFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.2, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting5", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSideFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 9.7 + }, + "Mobility": 0.92, + "Delay": 0.8, + "Acceleration": 1.3, + "Radius": 9.7 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting6", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairBackFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 11.4 + }, + "Mobility": 0.88, + "Delay": 0.69, + "Acceleration": 1.36, + "Radius": 11.4 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/motions/01_kei_en.motion3.json b/Samples/Resources/Kei_basic/motions/01_kei_en.motion3.json new file mode 100644 index 0000000..ee4a1a0 --- /dev/null +++ b/Samples/Resources/Kei_basic/motions/01_kei_en.motion3.json @@ -0,0 +1,362 @@ +{ + "Version": 3, + "Meta": { + "Duration": 14.833, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 6, + "TotalSegmentCount": 46, + "TotalPointCount": 132, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 0, + 14.833, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 0, + 14.833, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/motions/01_kei_jp.motion3.json b/Samples/Resources/Kei_basic/motions/01_kei_jp.motion3.json new file mode 100644 index 0000000..68fd2f3 --- /dev/null +++ b/Samples/Resources/Kei_basic/motions/01_kei_jp.motion3.json @@ -0,0 +1,418 @@ +{ + "Version": 3, + "Meta": { + "Duration": 17.867, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 6, + "TotalSegmentCount": 54, + "TotalPointCount": 156, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.406, + 1, + 10.228, + 1, + 11.05, + 1, + 1, + 11.067, + 1, + 11.083, + 0, + 11.1, + 0, + 1, + 11.111, + 0, + 11.122, + 0, + 11.133, + 0, + 1, + 11.15, + 0, + 11.167, + 1, + 11.183, + 1, + 1, + 11.539, + 1, + 11.894, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.144, + 1, + 13.906, + 1, + 14.667, + 1, + 1, + 14.683, + 1, + 14.7, + 0, + 14.717, + 0, + 1, + 14.728, + 0, + 14.739, + 0, + 14.75, + 0, + 1, + 14.767, + 0, + 14.783, + 1, + 14.8, + 1, + 0, + 17.867, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.406, + 1, + 10.228, + 1, + 11.05, + 1, + 1, + 11.067, + 1, + 11.083, + 0, + 11.1, + 0, + 1, + 11.111, + 0, + 11.122, + 0, + 11.133, + 0, + 1, + 11.15, + 0, + 11.167, + 1, + 11.183, + 1, + 1, + 11.539, + 1, + 11.894, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.144, + 1, + 13.906, + 1, + 14.667, + 1, + 1, + 14.683, + 1, + 14.7, + 0, + 14.717, + 0, + 1, + 14.728, + 0, + 14.739, + 0, + 14.75, + 0, + 1, + 14.767, + 0, + 14.783, + 1, + 14.8, + 1, + 0, + 17.867, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/motions/01_kei_ko.motion3.json b/Samples/Resources/Kei_basic/motions/01_kei_ko.motion3.json new file mode 100644 index 0000000..7ade01e --- /dev/null +++ b/Samples/Resources/Kei_basic/motions/01_kei_ko.motion3.json @@ -0,0 +1,418 @@ +{ + "Version": 3, + "Meta": { + "Duration": 17.733, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 6, + "TotalSegmentCount": 54, + "TotalPointCount": 156, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.128, + 1, + 13.872, + 1, + 14.617, + 1, + 1, + 14.633, + 1, + 14.65, + 0, + 14.667, + 0, + 1, + 14.678, + 0, + 14.689, + 0, + 14.7, + 0, + 1, + 14.717, + 0, + 14.733, + 1, + 14.75, + 1, + 0, + 17.733, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.128, + 1, + 13.872, + 1, + 14.617, + 1, + 1, + 14.633, + 1, + 14.65, + 0, + 14.667, + 0, + 1, + 14.678, + 0, + 14.689, + 0, + 14.7, + 0, + 1, + 14.717, + 0, + 14.733, + 1, + 14.75, + 1, + 0, + 17.733, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/motions/01_kei_zh.motion3.json b/Samples/Resources/Kei_basic/motions/01_kei_zh.motion3.json new file mode 100644 index 0000000..8cbbaa2 --- /dev/null +++ b/Samples/Resources/Kei_basic/motions/01_kei_zh.motion3.json @@ -0,0 +1,362 @@ +{ + "Version": 3, + "Meta": { + "Duration": 14.4, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 6, + "TotalSegmentCount": 46, + "TotalPointCount": 132, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 8.911, + 1, + 9.239, + 1, + 9.567, + 1, + 1, + 9.583, + 1, + 9.6, + 0, + 9.617, + 0, + 1, + 9.628, + 0, + 9.639, + 0, + 9.65, + 0, + 1, + 9.667, + 0, + 9.683, + 1, + 9.7, + 1, + 1, + 10.533, + 1, + 11.367, + 1, + 12.2, + 1, + 1, + 12.217, + 1, + 12.233, + 0, + 12.25, + 0, + 1, + 12.261, + 0, + 12.272, + 0, + 12.283, + 0, + 1, + 12.3, + 0, + 12.317, + 1, + 12.333, + 1, + 0, + 14.4, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 8.911, + 1, + 9.239, + 1, + 9.567, + 1, + 1, + 9.583, + 1, + 9.6, + 0, + 9.617, + 0, + 1, + 9.628, + 0, + 9.639, + 0, + 9.65, + 0, + 1, + 9.667, + 0, + 9.683, + 1, + 9.7, + 1, + 1, + 10.533, + 1, + 11.367, + 1, + 12.2, + 1, + 1, + 12.217, + 1, + 12.233, + 0, + 12.25, + 0, + 1, + 12.261, + 0, + 12.272, + 0, + 12.283, + 0, + 1, + 12.3, + 0, + 12.317, + 1, + 12.333, + 1, + 0, + 14.4, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_basic/sounds/01_kei_en.wav b/Samples/Resources/Kei_basic/sounds/01_kei_en.wav new file mode 100644 index 0000000..4f10332 Binary files /dev/null and b/Samples/Resources/Kei_basic/sounds/01_kei_en.wav differ diff --git a/Samples/Resources/Kei_basic/sounds/01_kei_jp.wav b/Samples/Resources/Kei_basic/sounds/01_kei_jp.wav new file mode 100644 index 0000000..d1b3876 Binary files /dev/null and b/Samples/Resources/Kei_basic/sounds/01_kei_jp.wav differ diff --git a/Samples/Resources/Kei_basic/sounds/01_kei_ko.wav b/Samples/Resources/Kei_basic/sounds/01_kei_ko.wav new file mode 100644 index 0000000..150f3a6 Binary files /dev/null and b/Samples/Resources/Kei_basic/sounds/01_kei_ko.wav differ diff --git a/Samples/Resources/Kei_basic/sounds/01_kei_zh.wav b/Samples/Resources/Kei_basic/sounds/01_kei_zh.wav new file mode 100644 index 0000000..0cb16cc Binary files /dev/null and b/Samples/Resources/Kei_basic/sounds/01_kei_zh.wav differ diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.2048/texture_00.png b/Samples/Resources/Kei_vowels/Kei_vowels.2048/texture_00.png new file mode 100644 index 0000000..0a774b6 Binary files /dev/null and b/Samples/Resources/Kei_vowels/Kei_vowels.2048/texture_00.png differ diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.cdi3.json b/Samples/Resources/Kei_vowels/Kei_vowels.cdi3.json new file mode 100644 index 0000000..3922644 --- /dev/null +++ b/Samples/Resources/Kei_vowels/Kei_vowels.cdi3.json @@ -0,0 +1,293 @@ +{ + "Version": 3, + "Parameters": [ + { + "Id": "ParamAngleX", + "GroupId": "ParamGroup5", + "Name": "角度 X" + }, + { + "Id": "ParamAngleY", + "GroupId": "ParamGroup5", + "Name": "角度 Y" + }, + { + "Id": "ParamAngleZ", + "GroupId": "ParamGroup5", + "Name": "角度 Z" + }, + { + "Id": "ParamCheek", + "GroupId": "ParamGroup5", + "Name": "照れ" + }, + { + "Id": "ParamBodyAngleX", + "GroupId": "ParamGroup6", + "Name": "体の回転 X" + }, + { + "Id": "ParamBodyAngleY", + "GroupId": "ParamGroup6", + "Name": "体の回転 Y" + }, + { + "Id": "ParamBodyAngleZ", + "GroupId": "ParamGroup6", + "Name": "体の回転 Z" + }, + { + "Id": "ParamBreath", + "GroupId": "ParamGroup6", + "Name": "呼吸" + }, + { + "Id": "ParamBrowLY", + "GroupId": "ParamGroup4", + "Name": "左眉 上下" + }, + { + "Id": "ParamBrowRY", + "GroupId": "ParamGroup4", + "Name": "右眉 上下" + }, + { + "Id": "ParamBrowLForm", + "GroupId": "ParamGroup4", + "Name": "左眉 変形" + }, + { + "Id": "ParamBrowRForm", + "GroupId": "ParamGroup4", + "Name": "右眉 変形" + }, + { + "Id": "ParamEyeLOpen", + "GroupId": "ParamGroup2", + "Name": "左目 開閉" + }, + { + "Id": "ParamEyeLSmile", + "GroupId": "ParamGroup2", + "Name": "左目 笑顔" + }, + { + "Id": "ParamEyeROpen", + "GroupId": "ParamGroup2", + "Name": "右目 開閉" + }, + { + "Id": "ParamEyeRSmile", + "GroupId": "ParamGroup2", + "Name": "右目 笑顔" + }, + { + "Id": "ParamEyeBallX", + "GroupId": "ParamGroup3", + "Name": "目玉 X" + }, + { + "Id": "ParamEyeBallY", + "GroupId": "ParamGroup3", + "Name": "目玉 Y" + }, + { + "Id": "ParamMouthOpenY", + "GroupId": "ParamGroup10", + "Name": "口 開閉" + }, + { + "Id": "ParamA", + "GroupId": "ParamGroup10", + "Name": "A" + }, + { + "Id": "ParamI", + "GroupId": "ParamGroup10", + "Name": "I" + }, + { + "Id": "ParamU", + "GroupId": "ParamGroup10", + "Name": "U" + }, + { + "Id": "ParamE", + "GroupId": "ParamGroup10", + "Name": "E" + }, + { + "Id": "ParamO", + "GroupId": "ParamGroup10", + "Name": "O" + }, + { + "Id": "ParamHairFront", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 前" + }, + { + "Id": "ParamHairSide", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 左横" + }, + { + "Id": "ParamHairSide2", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 右横" + }, + { + "Id": "ParamHairBack", + "GroupId": "ParamGroup7", + "Name": "髪揺れ 後" + }, + { + "Id": "ParamHairFrontFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 前" + }, + { + "Id": "ParamHairSideFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 横" + }, + { + "Id": "ParamHairBackFuwa", + "GroupId": "ParamGroup7", + "Name": "髪ふわ 後" + } + ], + "ParameterGroups": [ + { + "Id": "ParamGroup5", + "GroupId": "", + "Name": "顔" + }, + { + "Id": "ParamGroup6", + "GroupId": "", + "Name": "体" + }, + { + "Id": "ParamGroup4", + "GroupId": "", + "Name": "眉" + }, + { + "Id": "ParamGroup2", + "GroupId": "", + "Name": "目" + }, + { + "Id": "ParamGroup3", + "GroupId": "", + "Name": "目玉" + }, + { + "Id": "ParamGroup10", + "GroupId": "", + "Name": "口 母音のみ" + }, + { + "Id": "ParamGroup7", + "GroupId": "", + "Name": "揺れ" + } + ], + "Parts": [ + { + "Id": "Part15", + "Name": "コア" + }, + { + "Id": "Part", + "Name": "左横髪" + }, + { + "Id": "Part2", + "Name": "右横髪" + }, + { + "Id": "Part3", + "Name": "前髪" + }, + { + "Id": "Part4", + "Name": "左まゆ毛" + }, + { + "Id": "Part5", + "Name": "右まゆ毛" + }, + { + "Id": "Part22", + "Name": "左目" + }, + { + "Id": "Part7", + "Name": "右目" + }, + { + "Id": "Part6", + "Name": "頬" + }, + { + "Id": "Part9", + "Name": "鼻" + }, + { + "Id": "Part18", + "Name": "口 母音のみ" + }, + { + "Id": "Part10", + "Name": "顔" + }, + { + "Id": "Part11", + "Name": "左耳" + }, + { + "Id": "Part12", + "Name": "右耳" + }, + { + "Id": "Part14", + "Name": "首" + }, + { + "Id": "Part16", + "Name": "体" + }, + { + "Id": "Part17", + "Name": "後ろ髪" + }, + { + "Id": "Part8", + "Name": "SDK表示" + }, + { + "Id": "PartSketch0", + "Name": "[ 下絵 ]" + }, + { + "Id": "Part23", + "Name": "左目玉" + }, + { + "Id": "Part21", + "Name": "右目玉" + } + ], + "CombinedParameters": [ + [ + "ParamAngleX", + "ParamAngleY" + ], + [ + "ParamEyeBallX", + "ParamEyeBallY" + ] + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.moc3 b/Samples/Resources/Kei_vowels/Kei_vowels.moc3 new file mode 100644 index 0000000..158fc5b Binary files /dev/null and b/Samples/Resources/Kei_vowels/Kei_vowels.moc3 differ diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.model3.json b/Samples/Resources/Kei_vowels/Kei_vowels.model3.json new file mode 100644 index 0000000..511e801 --- /dev/null +++ b/Samples/Resources/Kei_vowels/Kei_vowels.model3.json @@ -0,0 +1,57 @@ +{ + "Version": 3, + "FileReferences": { + "Moc": "Kei_vowels.moc3", + "Textures": [ + "Kei_vowels.2048/texture_00.png" + ], + "Physics": "Kei_vowels.physics3.json", + "DisplayInfo": "Kei_vowels.cdi3.json", + "MotionSync": "Kei_vowels.motionsync3.json", + "Motions": { + "": [ + { + "File": "motions/01_kei_en.motion3.json", + "Sound": "sounds/01_kei_en.wav", + "MotionSync": "Vowels_CRI" + }, + { + "File": "motions/01_kei_jp.motion3.json", + "Sound": "sounds/01_kei_jp.wav", + "MotionSync": "Vowels_CRI" + }, + { + "File": "motions/01_kei_ko.motion3.json", + "Sound": "sounds/01_kei_ko.wav", + "MotionSync": "Vowels_CRI" + }, + { + "File": "motions/01_kei_zh.motion3.json", + "Sound": "sounds/01_kei_zh.wav", + "MotionSync": "Vowels_CRI" + } + ] + } + }, + "Groups": [ + { + "Target": "Parameter", + "Name": "LipSync", + "Ids": [] + }, + { + "Target": "Parameter", + "Name": "EyeBlink", + "Ids": [ + "ParamEyeLOpen", + "ParamEyeROpen" + ] + } + ], + "HitAreas": [ + { + "Id": "HitAreaHead", + "Name": "Head" + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.motionsync3.json b/Samples/Resources/Kei_vowels/Kei_vowels.motionsync3.json new file mode 100644 index 0000000..29e03ce --- /dev/null +++ b/Samples/Resources/Kei_vowels/Kei_vowels.motionsync3.json @@ -0,0 +1,306 @@ +{ + "Version": 1, + "Meta": { + "SettingCount": 1, + "Dictionary": [ + { + "Id": "MotionSyncSetting3", + "Name": "Vowels_CRI" + } + ] + }, + "Settings": [ + { + "Id": "MotionSyncSetting3", + "AnalysisType": "CRI", + "UseCase": "Mouth", + "CubismParameters": [ + { + "Name": "口 開閉", + "Id": "ParamMouthOpenY", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "Aあ", + "Id": "ParamA", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "I", + "Id": "ParamI", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "U", + "Id": "ParamU", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "E", + "Id": "ParamE", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + }, + { + "Name": "O", + "Id": "ParamO", + "Min": 0.0, + "Max": 1.0, + "Damper": 0.0, + "Smooth": 25 + } + ], + "AudioParameters": [ + { + "Name": "Silence", + "Id": "Silence", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.0, + "Enabled": true + }, + { + "Name": "A", + "Id": "A", + "Min": 0.0, + "Max": 1.0, + "Scale": 0.30000001192092896, + "Enabled": true + }, + { + "Name": "I", + "Id": "I", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.0, + "Enabled": true + }, + { + "Name": "U", + "Id": "U", + "Min": 0.0, + "Max": 1.0, + "Scale": 1.5, + "Enabled": true + }, + { + "Name": "E", + "Id": "E", + "Min": 0.0, + "Max": 1.0, + "Scale": 6.0, + "Enabled": true + }, + { + "Name": "O", + "Id": "O", + "Min": 0.0, + "Max": 1.0, + "Scale": 8.0, + "Enabled": true + } + ], + "Mappings": [ + { + "Type": "Shape", + "Id": "Silence", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 0.0 + }, + { + "Id": "ParamA", + "Value": 0.0 + }, + { + "Id": "ParamI", + "Value": 0.0 + }, + { + "Id": "ParamU", + "Value": 0.0 + }, + { + "Id": "ParamE", + "Value": 0.0 + }, + { + "Id": "ParamO", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "A", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + }, + { + "Id": "ParamA", + "Value": 1.0 + }, + { + "Id": "ParamI", + "Value": 0.0 + }, + { + "Id": "ParamU", + "Value": 0.0 + }, + { + "Id": "ParamE", + "Value": 0.0 + }, + { + "Id": "ParamO", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "I", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + }, + { + "Id": "ParamA", + "Value": 0.0 + }, + { + "Id": "ParamI", + "Value": 1.0 + }, + { + "Id": "ParamU", + "Value": 0.0 + }, + { + "Id": "ParamE", + "Value": 0.0 + }, + { + "Id": "ParamO", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "U", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + }, + { + "Id": "ParamA", + "Value": 0.0 + }, + { + "Id": "ParamI", + "Value": 0.0 + }, + { + "Id": "ParamU", + "Value": 1.0 + }, + { + "Id": "ParamE", + "Value": 0.0 + }, + { + "Id": "ParamO", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "E", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + }, + { + "Id": "ParamA", + "Value": 0.0 + }, + { + "Id": "ParamI", + "Value": 0.0 + }, + { + "Id": "ParamU", + "Value": 0.0 + }, + { + "Id": "ParamE", + "Value": 1.0 + }, + { + "Id": "ParamO", + "Value": 0.0 + } + ] + }, + { + "Type": "Shape", + "Id": "O", + "Targets": [ + { + "Id": "ParamMouthOpenY", + "Value": 1.0 + }, + { + "Id": "ParamA", + "Value": 0.0 + }, + { + "Id": "ParamI", + "Value": 0.0 + }, + { + "Id": "ParamU", + "Value": 0.0 + }, + { + "Id": "ParamE", + "Value": 0.0 + }, + { + "Id": "ParamO", + "Value": 1.0 + } + ] + } + ], + "PostProcessing": { + "BlendRatio": 0.5, + "Smoothing": 60, + "SampleRate": 60.0 + } + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/Kei_vowels.physics3.json b/Samples/Resources/Kei_vowels/Kei_vowels.physics3.json new file mode 100644 index 0000000..531b219 --- /dev/null +++ b/Samples/Resources/Kei_vowels/Kei_vowels.physics3.json @@ -0,0 +1,533 @@ +{ + "Version": 3, + "Meta": { + "PhysicsSettingCount": 6, + "TotalInputCount": 18, + "TotalOutputCount": 7, + "VertexCount": 12, + "Fps": 60, + "EffectiveForces": { + "Gravity": { + "X": 0, + "Y": -1 + }, + "Wind": { + "X": 0, + "Y": 0 + } + }, + "PhysicsDictionary": [ + { + "Id": "PhysicsSetting1", + "Name": "髪揺れ 前" + }, + { + "Id": "PhysicsSetting2", + "Name": "髪揺れ 横" + }, + { + "Id": "PhysicsSetting3", + "Name": "髪揺れ 後" + }, + { + "Id": "PhysicsSetting4", + "Name": "髪ふわ 前" + }, + { + "Id": "PhysicsSetting5", + "Name": "髪ふわ 横" + }, + { + "Id": "PhysicsSetting6", + "Name": "髪ふわ 後" + } + ] + }, + "PhysicsSettings": [ + { + "Id": "PhysicsSetting1", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairFront" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 11.4 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.2, + "Radius": 11.4 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting2", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSide" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + }, + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSide2" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.3, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting3", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleX" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleZ" + }, + "Weight": 60, + "Type": "Angle", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleX" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleZ" + }, + "Weight": 40, + "Type": "Angle", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairBack" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.9, + "Acceleration": 1, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting4", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairFrontFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 10 + }, + "Mobility": 0.95, + "Delay": 0.8, + "Acceleration": 1.2, + "Radius": 10 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting5", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairSideFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 9.7 + }, + "Mobility": 0.92, + "Delay": 0.8, + "Acceleration": 1.3, + "Radius": 9.7 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + }, + { + "Id": "PhysicsSetting6", + "Input": [ + { + "Source": { + "Target": "Parameter", + "Id": "ParamAngleY" + }, + "Weight": 60, + "Type": "X", + "Reflect": false + }, + { + "Source": { + "Target": "Parameter", + "Id": "ParamBodyAngleY" + }, + "Weight": 40, + "Type": "X", + "Reflect": false + } + ], + "Output": [ + { + "Destination": { + "Target": "Parameter", + "Id": "ParamHairBackFuwa" + }, + "VertexIndex": 1, + "Scale": 1, + "Weight": 100, + "Type": "Angle", + "Reflect": false + } + ], + "Vertices": [ + { + "Position": { + "X": 0, + "Y": 0 + }, + "Mobility": 1, + "Delay": 1, + "Acceleration": 1, + "Radius": 0 + }, + { + "Position": { + "X": 0, + "Y": 11.4 + }, + "Mobility": 0.88, + "Delay": 0.69, + "Acceleration": 1.36, + "Radius": 11.4 + } + ], + "Normalization": { + "Position": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + }, + "Angle": { + "Minimum": -10, + "Default": 0, + "Maximum": 10 + } + } + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/motions/01_kei_en.motion3.json b/Samples/Resources/Kei_vowels/motions/01_kei_en.motion3.json new file mode 100644 index 0000000..801459b --- /dev/null +++ b/Samples/Resources/Kei_vowels/motions/01_kei_en.motion3.json @@ -0,0 +1,395 @@ +{ + "Version": 3, + "Meta": { + "Duration": 14.833, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 9, + "TotalSegmentCount": 49, + "TotalPointCount": 138, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 0, + 14.833, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLForm", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 0, + 14.833, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRForm", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallScale", + "Segments": [ + 0, + 0, + 0, + 14.833, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/motions/01_kei_jp.motion3.json b/Samples/Resources/Kei_vowels/motions/01_kei_jp.motion3.json new file mode 100644 index 0000000..4e25483 --- /dev/null +++ b/Samples/Resources/Kei_vowels/motions/01_kei_jp.motion3.json @@ -0,0 +1,451 @@ +{ + "Version": 3, + "Meta": { + "Duration": 17.867, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 9, + "TotalSegmentCount": 57, + "TotalPointCount": 162, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.406, + 1, + 10.228, + 1, + 11.05, + 1, + 1, + 11.067, + 1, + 11.083, + 0, + 11.1, + 0, + 1, + 11.111, + 0, + 11.122, + 0, + 11.133, + 0, + 1, + 11.15, + 0, + 11.167, + 1, + 11.183, + 1, + 1, + 11.539, + 1, + 11.894, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.144, + 1, + 13.906, + 1, + 14.667, + 1, + 1, + 14.683, + 1, + 14.7, + 0, + 14.717, + 0, + 1, + 14.728, + 0, + 14.739, + 0, + 14.75, + 0, + 1, + 14.767, + 0, + 14.783, + 1, + 14.8, + 1, + 0, + 17.867, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLForm", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.406, + 1, + 10.228, + 1, + 11.05, + 1, + 1, + 11.067, + 1, + 11.083, + 0, + 11.1, + 0, + 1, + 11.111, + 0, + 11.122, + 0, + 11.133, + 0, + 1, + 11.15, + 0, + 11.167, + 1, + 11.183, + 1, + 1, + 11.539, + 1, + 11.894, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.144, + 1, + 13.906, + 1, + 14.667, + 1, + 1, + 14.683, + 1, + 14.7, + 0, + 14.717, + 0, + 1, + 14.728, + 0, + 14.739, + 0, + 14.75, + 0, + 1, + 14.767, + 0, + 14.783, + 1, + 14.8, + 1, + 0, + 17.867, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRForm", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallScale", + "Segments": [ + 0, + 0, + 0, + 17.867, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/motions/01_kei_ko.motion3.json b/Samples/Resources/Kei_vowels/motions/01_kei_ko.motion3.json new file mode 100644 index 0000000..a34275b --- /dev/null +++ b/Samples/Resources/Kei_vowels/motions/01_kei_ko.motion3.json @@ -0,0 +1,451 @@ +{ + "Version": 3, + "Meta": { + "Duration": 17.733, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 9, + "TotalSegmentCount": 57, + "TotalPointCount": 162, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.128, + 1, + 13.872, + 1, + 14.617, + 1, + 1, + 14.633, + 1, + 14.65, + 0, + 14.667, + 0, + 1, + 14.678, + 0, + 14.689, + 0, + 14.7, + 0, + 1, + 14.717, + 0, + 14.733, + 1, + 14.75, + 1, + 0, + 17.733, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLForm", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 9.094, + 1, + 9.606, + 1, + 10.117, + 1, + 1, + 10.133, + 1, + 10.15, + 0, + 10.167, + 0, + 1, + 10.178, + 0, + 10.189, + 0, + 10.2, + 0, + 1, + 10.217, + 0, + 10.233, + 1, + 10.25, + 1, + 1, + 10.917, + 1, + 11.583, + 1, + 12.25, + 1, + 1, + 12.267, + 1, + 12.283, + 0, + 12.3, + 0, + 1, + 12.311, + 0, + 12.322, + 0, + 12.333, + 0, + 1, + 12.35, + 0, + 12.367, + 1, + 12.383, + 1, + 1, + 13.128, + 1, + 13.872, + 1, + 14.617, + 1, + 1, + 14.633, + 1, + 14.65, + 0, + 14.667, + 0, + 1, + 14.678, + 0, + 14.689, + 0, + 14.7, + 0, + 1, + 14.717, + 0, + 14.733, + 1, + 14.75, + 1, + 0, + 17.733, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRForm", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallScale", + "Segments": [ + 0, + 0, + 0, + 17.733, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/motions/01_kei_zh.motion3.json b/Samples/Resources/Kei_vowels/motions/01_kei_zh.motion3.json new file mode 100644 index 0000000..f844b0f --- /dev/null +++ b/Samples/Resources/Kei_vowels/motions/01_kei_zh.motion3.json @@ -0,0 +1,395 @@ +{ + "Version": 3, + "Meta": { + "Duration": 14.4, + "Fps": 60.0, + "Loop": true, + "AreBeziersRestricted": true, + "CurveCount": 9, + "TotalSegmentCount": 49, + "TotalPointCount": 138, + "UserDataCount": 0, + "TotalUserDataSize": 0 + }, + "Curves": [ + { + "Target": "Parameter", + "Id": "ParamEyeLOpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 8.911, + 1, + 9.239, + 1, + 9.567, + 1, + 1, + 9.583, + 1, + 9.6, + 0, + 9.617, + 0, + 1, + 9.628, + 0, + 9.639, + 0, + 9.65, + 0, + 1, + 9.667, + 0, + 9.683, + 1, + 9.7, + 1, + 1, + 10.533, + 1, + 11.367, + 1, + 12.2, + 1, + 1, + 12.217, + 1, + 12.233, + 0, + 12.25, + 0, + 1, + 12.261, + 0, + 12.272, + 0, + 12.283, + 0, + 1, + 12.3, + 0, + 12.317, + 1, + 12.333, + 1, + 0, + 14.4, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLSmile", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeLForm", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeROpen", + "Segments": [ + 0, + 1, + 1, + 0.878, + 1, + 1.756, + 1, + 2.633, + 1, + 1, + 2.65, + 1, + 2.667, + 0, + 2.683, + 0, + 1, + 2.694, + 0, + 2.706, + 0, + 2.717, + 0, + 1, + 2.733, + 0, + 2.75, + 1, + 2.767, + 1, + 1, + 3.561, + 1, + 4.356, + 1, + 5.15, + 1, + 1, + 5.167, + 1, + 5.183, + 0, + 5.2, + 0, + 1, + 5.211, + 0, + 5.222, + 0, + 5.233, + 0, + 1, + 5.25, + 0, + 5.267, + 1, + 5.283, + 1, + 1, + 6.339, + 1, + 7.394, + 1, + 8.45, + 1, + 1, + 8.467, + 1, + 8.483, + 0, + 8.5, + 0, + 1, + 8.511, + 0, + 8.522, + 0, + 8.533, + 0, + 1, + 8.55, + 0, + 8.567, + 1, + 8.583, + 1, + 1, + 8.911, + 1, + 9.239, + 1, + 9.567, + 1, + 1, + 9.583, + 1, + 9.6, + 0, + 9.617, + 0, + 1, + 9.628, + 0, + 9.639, + 0, + 9.65, + 0, + 1, + 9.667, + 0, + 9.683, + 1, + 9.7, + 1, + 1, + 10.533, + 1, + 11.367, + 1, + 12.2, + 1, + 1, + 12.217, + 1, + 12.233, + 0, + 12.25, + 0, + 1, + 12.261, + 0, + 12.272, + 0, + 12.283, + 0, + 1, + 12.3, + 0, + 12.317, + 1, + 12.333, + 1, + 0, + 14.4, + 1 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRSmile", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeRForm", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallX", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallY", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + }, + { + "Target": "Parameter", + "Id": "ParamEyeBallScale", + "Segments": [ + 0, + 0, + 0, + 14.4, + 0 + ] + } + ] +} \ No newline at end of file diff --git a/Samples/Resources/Kei_vowels/sounds/01_kei_en.wav b/Samples/Resources/Kei_vowels/sounds/01_kei_en.wav new file mode 100644 index 0000000..4f10332 Binary files /dev/null and b/Samples/Resources/Kei_vowels/sounds/01_kei_en.wav differ diff --git a/Samples/Resources/Kei_vowels/sounds/01_kei_jp.wav b/Samples/Resources/Kei_vowels/sounds/01_kei_jp.wav new file mode 100644 index 0000000..d1b3876 Binary files /dev/null and b/Samples/Resources/Kei_vowels/sounds/01_kei_jp.wav differ diff --git a/Samples/Resources/Kei_vowels/sounds/01_kei_ko.wav b/Samples/Resources/Kei_vowels/sounds/01_kei_ko.wav new file mode 100644 index 0000000..150f3a6 Binary files /dev/null and b/Samples/Resources/Kei_vowels/sounds/01_kei_ko.wav differ diff --git a/Samples/Resources/Kei_vowels/sounds/01_kei_zh.wav b/Samples/Resources/Kei_vowels/sounds/01_kei_zh.wav new file mode 100644 index 0000000..0cb16cc Binary files /dev/null and b/Samples/Resources/Kei_vowels/sounds/01_kei_zh.wav differ diff --git a/Samples/Resources/back_class_normal.png b/Samples/Resources/back_class_normal.png new file mode 100644 index 0000000..c7cea93 Binary files /dev/null and b/Samples/Resources/back_class_normal.png differ diff --git a/Samples/Resources/close.png b/Samples/Resources/close.png new file mode 100644 index 0000000..657db7f Binary files /dev/null and b/Samples/Resources/close.png differ diff --git a/Samples/Resources/icon_fastForward.png b/Samples/Resources/icon_fastForward.png new file mode 100644 index 0000000..fd1b571 Binary files /dev/null and b/Samples/Resources/icon_fastForward.png differ diff --git a/Samples/Resources/icon_gear.png b/Samples/Resources/icon_gear.png new file mode 100644 index 0000000..242ba34 Binary files /dev/null and b/Samples/Resources/icon_gear.png differ