This commit is contained in:
Misaki
2025-12-04 19:11:29 +08:00
commit bb600bbbc4
2741 changed files with 364700 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismCdiJson.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismCdiJson.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismDefaultParameterId.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismDefaultParameterId.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismFramework.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismFramework.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismFrameworkConfig.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelSettingJson.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelSettingJson.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismJsonHolder.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ICubismAllocator.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ICubismModelSetting.hpp
${CMAKE_CURRENT_SOURCE_DIR}/Live2DCubismCore.hpp
)
# Add sub directories.
add_subdirectory(Effect)
add_subdirectory(Id)
add_subdirectory(Math)
add_subdirectory(Model)
add_subdirectory(Motion)
add_subdirectory(Physics)
add_subdirectory(Rendering)
add_subdirectory(Type)
add_subdirectory(Utils)
+133
View File
@@ -0,0 +1,133 @@
/**
* 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 "CubismCdiJson.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
namespace {
// JSON keys
const csmChar* Version = "Version";
const csmChar* Parameters = "Parameters";
const csmChar* ParameterGroups = "ParameterGroups";
const csmChar* Parts = "Parts";
const csmChar* CombinedParameters = "CombinedParameters";
const csmChar* Id = "Id";
const csmChar* GroupId = "GroupId";
const csmChar* Name = "Name";
}
CubismCdiJson::CubismCdiJson(const csmByte* buffer, csmSizeInt size)
{
CreateCubismJson(buffer, size);
}
CubismCdiJson::~CubismCdiJson()
{
DeleteCubismJson();
}
// キーが存在するかどうかのチェック
csmBool CubismCdiJson::IsExistParameters() const
{
Utils::Value& node = (_json->GetRoot()[Parameters]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismCdiJson::IsExistParameterGroups() const
{
Utils::Value& node = (_json->GetRoot()[ParameterGroups]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismCdiJson::IsExistParts() const
{
Utils::Value& node = (_json->GetRoot()[Parts]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismCdiJson::IsExistCombinedParameters() const
{
Utils::Value& node = (_json->GetRoot()[CombinedParameters]);
return !node.IsNull() && !node.IsError();
}
// パラメータについて
csmInt32 CubismCdiJson::GetParametersCount()
{
if (!IsExistParameters()) return 0;
return _json->GetRoot()[Parameters].GetSize();
}
const csmChar* CubismCdiJson::GetParametersId(csmInt32 index)
{
return _json->GetRoot()[Parameters][index][Id].GetRawString();
}
const csmChar* CubismCdiJson::GetParametersGroupId(csmInt32 index)
{
return _json->GetRoot()[Parameters][index][GroupId].GetRawString();
}
const csmChar* CubismCdiJson::GetParametersName(csmInt32 index)
{
return _json->GetRoot()[Parameters][index][Name].GetRawString();
}
// パラメータグループについて
csmInt32 CubismCdiJson::GetParameterGroupsCount()
{
if (!IsExistParameterGroups()) return 0;
return _json->GetRoot()[ParameterGroups].GetSize();
}
const csmChar* CubismCdiJson::GetParameterGroupsId(csmInt32 index)
{
return _json->GetRoot()[ParameterGroups][index][Id].GetRawString();
}
const csmChar* CubismCdiJson::GetParameterGroupsGroupId(csmInt32 index)
{
return _json->GetRoot()[ParameterGroups][index][GroupId].GetRawString();
}
const csmChar* CubismCdiJson::GetParameterGroupsName(csmInt32 index)
{
return _json->GetRoot()[ParameterGroups][index][Name].GetRawString();
}
// パーツについて
csmInt32 CubismCdiJson::GetPartsCount()
{
if (!IsExistParts()) return 0;
return _json->GetRoot()[Parts].GetSize();
}
const csmChar* CubismCdiJson::GetPartsId(csmInt32 index)
{
return _json->GetRoot()[Parts][index][Id].GetRawString();
}
const csmChar* CubismCdiJson::GetPartsName(csmInt32 index)
{
return _json->GetRoot()[Parts][index][Name].GetRawString();
}
// 結合パラメータについて
csmInt32 CubismCdiJson::GetCombinedParametersCount()
{
if (!IsExistCombinedParameters()) return 0;
return _json->GetRoot()[CombinedParameters].GetSize();
}
const csmVector<Utils::Value*>* CubismCdiJson::GetCombinedParameters(csmInt32 index)
{
return _json->GetRoot()[CombinedParameters][index].GetVector();
}
}}}
+175
View File
@@ -0,0 +1,175 @@
/**
* 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 "Utils/CubismJson.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the Display Information File.
*/
class CubismCdiJson : public CubismJsonHolder
{
public:
/**
* Constructor<br>
* Loads the Display Information File.
*
* @param buffer Buffer that Display Settings File is loaded from.
* @param size Number of bytes in buffer
*/
CubismCdiJson(const csmByte* buffer, csmSizeInt size);
/**
 * Destructor
 */
virtual ~CubismCdiJson();
/**
* Returns the number of parameters.
*
* @return Number of parameters
*/
csmInt32 GetParametersCount();
/**
* Returns the ID of the parameter.
*
* @param index Index to the desired parameter
*
* @return ID of the parameter
*/
const csmChar* GetParametersId(csmInt32 index);
/**
* Returns the ID of the parameter group that the parameter belongs to.
*
* @param index Index to the desired parameter
*
* @return ID of the parameter group
*/
const csmChar* GetParametersGroupId(csmInt32 index);
/**
* Returns the name of the parameter.
*
* @param index Index to the desired parameter
*
* @return name of parameter
*/
const csmChar* GetParametersName(csmInt32 index);
/**
* Returns the number of parameter groups.
*
* @return Number of parameter groups
*/
csmInt32 GetParameterGroupsCount();
/**
* Returns the ID of the parameter group.
*
* @param index Index to the desired parameter group
*
* @return ID of parameter group
*/
const csmChar* GetParameterGroupsId(csmInt32 index);
/**
* Returns the ID of the parameter group that the parameter group belongs to.
*
* @param index Index to the desired parameter group
*
* @return ID of the parameter group
*/
const csmChar* GetParameterGroupsGroupId(csmInt32 index);
/**
* Returns the name of the parameter group.
*
* @param index Index to the desired parameter group
*
* @return Name of the parameter group
*/
const csmChar* GetParameterGroupsName(csmInt32 index);
/**
* Returns the number of parts.
*
* @return Number of parts
*/
csmInt32 GetPartsCount();
/**
* Returns the ID of the part.
*
* @param index Index to the desired part
*
* @return ID of the part
*/
const csmChar* GetPartsId(csmInt32 index);
/**
* Returns the name of the part.
*
* @param index Index to the desired part
*
* @return name of the part
*/
const csmChar* GetPartsName(csmInt32 index);
/**
* Returns the number of combined parameters.
*
* @return Number of combined parameters
*/
csmInt32 GetCombinedParametersCount();
/**
* Returns the pair list of the combined parameters.
*
* @param index Index to the desired combined parameter
*
* @return Pair list of the combined parameter
*/
const csmVector<Utils::Value*>* GetCombinedParameters(csmInt32 index);
private:
/**
* Returns whether the parameters exist in the Display Information File.
*
* @return true if parameters exists; otherwise false.
*/
csmBool IsExistParameters() const;
/**
* Returns whether parameter groups exist in the Display Information File.
*
* @return true if parameters on paramter groups exist; otherwise false.
*/
csmBool IsExistParameterGroups() const;
/**
* Returns whether the parts exist in the Display Information File.
*
* @return true if parts exist; otherwise false.
*/
csmBool IsExistParts() const;
/**
* Returns whether the combined parameters exist in the Display Information File.
*
* @return true if combined parameters exist; otherwise false.
*/
csmBool IsExistCombinedParameters() const;
};
}}}
@@ -0,0 +1,66 @@
/**
* 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 "CubismDefaultParameterId.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace DefaultParameterId {
// パーツID
const csmChar* HitAreaPrefix = "HitArea";
const csmChar* HitAreaHead = "Head";
const csmChar* HitAreaBody = "Body";
const csmChar* PartsIdCore = "Parts01Core";
const csmChar* PartsArmPrefix = "Parts01Arm_";
const csmChar* PartsArmLPrefix = "Parts01ArmL_";
const csmChar* PartsArmRPrefix = "Parts01ArmR_";
// パラメータID
const csmChar* ParamAngleX = "ParamAngleX";
const csmChar* ParamAngleY = "ParamAngleY";
const csmChar* ParamAngleZ = "ParamAngleZ";
const csmChar* ParamEyeLOpen = "ParamEyeLOpen";
const csmChar* ParamEyeLSmile = "ParamEyeLSmile";
const csmChar* ParamEyeROpen = "ParamEyeROpen";
const csmChar* ParamEyeRSmile = "ParamEyeRSmile";
const csmChar* ParamEyeBallX = "ParamEyeBallX";
const csmChar* ParamEyeBallY = "ParamEyeBallY";
const csmChar* ParamEyeBallForm = "ParamEyeBallForm";
const csmChar* ParamBrowLY = "ParamBrowLY";
const csmChar* ParamBrowRY = "ParamBrowRY";
const csmChar* ParamBrowLX = "ParamBrowLX";
const csmChar* ParamBrowRX = "ParamBrowRX";
const csmChar* ParamBrowLAngle = "ParamBrowLAngle";
const csmChar* ParamBrowRAngle = "ParamBrowRAngle";
const csmChar* ParamBrowLForm = "ParamBrowLForm";
const csmChar* ParamBrowRForm = "ParamBrowRForm";
const csmChar* ParamMouthForm = "ParamMouthForm";
const csmChar* ParamMouthOpenY = "ParamMouthOpenY";
const csmChar* ParamCheek = "ParamCheek";
const csmChar* ParamBodyAngleX = "ParamBodyAngleX";
const csmChar* ParamBodyAngleY = "ParamBodyAngleY";
const csmChar* ParamBodyAngleZ = "ParamBodyAngleZ";
const csmChar* ParamBreath = "ParamBreath";
const csmChar* ParamArmLA = "ParamArmLA";
const csmChar* ParamArmRA = "ParamArmRA";
const csmChar* ParamArmLB = "ParamArmLB";
const csmChar* ParamArmRB = "ParamArmRB";
const csmChar* ParamHandL = "ParamHandL";
const csmChar* ParamHandR = "ParamHandR";
const csmChar* ParamHairFront = "ParamHairFront";
const csmChar* ParamHairSide = "ParamHairSide";
const csmChar* ParamHairBack = "ParamHairBack";
const csmChar* ParamHairFluffy = "ParamHairFluffy";
const csmChar* ParamShoulderY = "ParamShoulderY";
const csmChar* ParamBustX = "ParamBustX";
const csmChar* ParamBustY = "ParamBustY";
const csmChar* ParamBaseX = "ParamBaseX";
const csmChar* ParamBaseY = "ParamBaseY";
const csmChar* ParamNONE = "NONE:";
}}}}
//--------- LIVE2D NAMESPACE ------------
@@ -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 "CubismFramework.hpp"
/**
* Constants that hold the default values of parameter IDs.<br>
* See manual for details on each ID.<br>
* https://docs.live2d.com/en/cubism-editor-manual/standard-parametor-list/
*/
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace DefaultParameterId {
/* ID of Part */
extern const csmChar* HitAreaPrefix;
extern const csmChar* HitAreaHead;
extern const csmChar* HitAreaBody;
extern const csmChar* PartsIdCore;
extern const csmChar* PartsArmPrefix;
extern const csmChar* PartsArmLPrefix;
extern const csmChar* PartsArmRPrefix;
/* ID of Parameter */
extern const csmChar* ParamAngleX;
extern const csmChar* ParamAngleY;
extern const csmChar* ParamAngleZ;
extern const csmChar* ParamEyeLOpen;
extern const csmChar* ParamEyeLSmile;
extern const csmChar* ParamEyeROpen;
extern const csmChar* ParamEyeRSmile;
extern const csmChar* ParamEyeBallX;
extern const csmChar* ParamEyeBallY;
extern const csmChar* ParamEyeBallForm;
extern const csmChar* ParamBrowLY;
extern const csmChar* ParamBrowRY;
extern const csmChar* ParamBrowLX;
extern const csmChar* ParamBrowRX;
extern const csmChar* ParamBrowLAngle;
extern const csmChar* ParamBrowRAngle;
extern const csmChar* ParamBrowLForm;
extern const csmChar* ParamBrowRForm;
extern const csmChar* ParamMouthForm;
extern const csmChar* ParamMouthOpenY;
extern const csmChar* ParamCheek;
extern const csmChar* ParamBodyAngleX;
extern const csmChar* ParamBodyAngleY;
extern const csmChar* ParamBodyAngleZ;
extern const csmChar* ParamBreath;
extern const csmChar* ParamArmLA;
extern const csmChar* ParamArmRA;
extern const csmChar* ParamArmLB;
extern const csmChar* ParamArmRB;
extern const csmChar* ParamHandL;
extern const csmChar* ParamHandR;
extern const csmChar* ParamHairFront;
extern const csmChar* ParamHairSide;
extern const csmChar* ParamHairBack;
extern const csmChar* ParamHairFluffy;
extern const csmChar* ParamShoulderY;
extern const csmChar* ParamBustX;
extern const csmChar* ParamBustY;
extern const csmChar* ParamBaseX;
extern const csmChar* ParamBaseY;
extern const csmChar* ParamNONE;
}}}}
//--------- LIVE2D NAMESPACE ------------
+394
View File
@@ -0,0 +1,394 @@
/**
* 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 "CubismFramework.hpp"
#include "Utils/CubismDebug.hpp"
#include "Utils/CubismJson.hpp"
#include "Id/CubismIdManager.hpp"
#include "Rendering/CubismRenderer.hpp"
#ifdef CSM_DEBUG_MEMORY_LEAKING
#include <vector>
#endif
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
// Framework内で使う定数の宣言
namespace Constant {
const csmInt32 VertexOffset = 0;
const csmInt32 VertexStep = 2;
}
// ファイルスコープの変数を初期化
namespace {
csmBool s_isStarted = false;
csmBool s_isInitialized = false;
ICubismAllocator* s_allocator = NULL;
const CubismFramework::Option* s_option = NULL;
CubismIdManager* s_cubismIdManager = NULL;
}
inline ICubismAllocator* GetAllocator()
{
return s_allocator;
}
#ifdef CSM_DEBUG_MEMORY_LEAKING
namespace {
std::vector<void*>* s_allocationList = NULL;
}
#endif
csmBool CubismFramework::StartUp(ICubismAllocator* allocator, const Option* option)
{
if(s_isStarted)
{
CubismLogInfo("CubismFramework::StartUp() is already done.");
return s_isStarted;
}
s_option = option;
if (s_option != NULL)
{
Core::csmSetLogFunction(s_option->LogFunction);
}
if (allocator == NULL)
{
CubismLogWarning("CubismFramework::StartUp() failed, need allocator instance.");
s_isStarted = false;
}
else
{
s_allocator = allocator;
s_isStarted = true;
}
// Live2D Cubism Coreバージョン情報を表示
if(s_isStarted)
{
const Core::csmVersion version = Core::csmGetVersion();
const csmUint32 major = static_cast<csmUint32>((version & 0xFF000000) >> 24);
const csmUint32 minor = static_cast<csmUint32>((version & 0x00FF0000) >> 16);
const csmUint32 patch = static_cast<csmUint32>((version & 0x0000FFFF));
const csmUint32 versionNumber = version;
CubismLogInfo("Live2D Cubism Core version: %02d.%02d.%04d (%d)", major, minor, patch, versionNumber);
}
CubismLogInfo("CubismFramework::StartUp() is complete.");
return s_isStarted;
}
void CubismFramework::CleanUp()
{
s_isStarted = false;
s_isInitialized = false;
s_allocator = NULL;
s_option = NULL;
s_cubismIdManager = NULL;
#ifdef CSM_DEBUG_MEMORY_LEAKING
s_allocationList = NULL;
#endif
}
csmBool CubismFramework::IsStarted()
{
return s_isStarted;
}
void CubismFramework::Initialize()
{
CSM_ASSERT(s_isStarted);
if(!s_isStarted)
{
CubismLogWarning("CubismFramework is not started.");
return;
}
// --- s_isInitializedによる連続初期化ガード ---
// 連続してリソース確保が行われないようにする。
// 再度Initialize()するには先にDispose()を実行する必要がある。
if (s_isInitialized)
{
CubismLogWarning("CubismFramework::Initialize() skipped, already initialized.");
return;
}
#ifdef CSM_DEBUG_MEMORY_LEAKING
s_allocationList = CSM_NEW std::vector<void*>();
#endif
//---- static 初期化 ----
Utils::Value::StaticInitializeNotForClientCall();
s_cubismIdManager = CSM_NEW CubismIdManager();
s_isInitialized = true;
CubismLogInfo("CubismFramework::Initialize() is complete.");
}
void CubismFramework::Dispose()
{
CSM_ASSERT(s_isStarted);
if (!s_isStarted)
{
CubismLogWarning("CubismFramework is not started.");
return;
}
// --- s_isInitializedによる未初期化解放ガード ---
// Dispose()するには先にInitialize()を実行する必要がある。
if (!s_isInitialized) // false...リソース未確保の場合
{
CubismLogWarning("CubismFramework::Dispose() skipped, not initialized.");
return;
}
//---- static 解放 ----
Utils::Value::StaticReleaseNotForClientCall();
CSM_DELETE(s_cubismIdManager);
//レンダラの静的リソース(シェーダプログラム他)を解放する
Rendering::CubismRenderer::StaticRelease();
#ifdef CSM_DEBUG_MEMORY_LEAKING
for (csmUint32 i = 0; i < s_allocationList->size(); ++i)
{
CubismLogInfo("Memory leaking: 0x%p", s_allocationList->at(i));
}
if (s_allocationList->size() == 0)
{
CubismLogInfo("No memory leaking");
}
CSM_DELETE(s_allocationList);
#endif
s_isInitialized = false;
CubismLogInfo("CubismFramework::Dispose() is complete.");
}
csmBool CubismFramework::IsInitialized()
{
return s_isInitialized;
}
void CubismFramework::CoreLogFunction(const csmChar* message)
{
// Return if logging not possible.
if (!Core::csmGetLogFunction())
{
return;
}
Core::csmGetLogFunction()(message);
}
CubismFramework::Option::LogLevel CubismFramework::GetLoggingLevel()
{
if (s_option != NULL)
{
return s_option->LoggingLevel;
}
return Option::LogLevel_Off;
}
csmLoadFileFunction CubismFramework::GetLoadFileFunction()
{
return s_option->LoadFileFunction;
}
csmReleaseBytesFunction CubismFramework::GetReleaseBytesFunction()
{
return s_option->ReleaseBytesFunction;
}
CubismIdManager* CubismFramework::GetIdManager()
{
return s_cubismIdManager;
}
#ifdef CSM_DEBUG_MEMORY_LEAKING
void* CubismFramework::Allocate(csmSizeType size, const csmChar* fileName, csmInt32 lineNumber)
{
void* address = GetAllocator()->Allocate(size);
CubismLogVerbose("CubismFramework::Allocate(0x%p, %dbytes) %s(%d)", address, size, fileName, lineNumber);
if (s_allocationList)
{
s_allocationList->push_back(address);
}
return address;
}
void* CubismFramework::AllocateAligned(csmSizeType size, csmUint32 alignment, const csmChar* fileName, csmInt32 lineNumber)
{
void* address = GetAllocator()->AllocateAligned(size, alignment);
CubismLogVerbose("CubismFramework::AllocateAligned(0x%p, a:%d, %dbytes) %s(%d)", address, alignment, size, fileName, lineNumber);
if (s_allocationList)
{
s_allocationList->push_back(address);
}
return address;
}
void CubismFramework::Deallocate(void* address, const csmChar* fileName, csmInt32 lineNumber)
{
if (!address)
{
return;
}
CubismLogVerbose("CubismFramework::Deallocate(0x%p) %s(%d)", address, fileName, lineNumber);
if (s_allocationList)
{
for (std::vector<void*>::iterator iter = s_allocationList->begin(); iter != s_allocationList->end(); ++iter)
{
if (*iter != address)
{
continue;
}
s_allocationList->erase(iter);
break;
}
}
GetAllocator()->Deallocate(address);
}
void CubismFramework::DeallocateAligned(void* address, const csmChar* fileName, csmInt32 lineNumber)
{
if (!address)
{
return;
}
CubismLogVerbose("CubismFramework::DeallocateAligned(0x%p) %s(%d)", address, fileName, lineNumber);
if (s_allocationList)
{
for (std::vector<void*>::iterator iter = s_allocationList->begin(); iter != s_allocationList->end(); ++iter)
{
if (*iter != address)
{
continue;
}
s_allocationList->erase(iter);
break;
}
}
GetAllocator()->DeallocateAligned(address);
}
#else
void* CubismFramework::Allocate(csmSizeType size)
{
return GetAllocator()->Allocate(size);
}
void* CubismFramework::AllocateAligned(csmSizeType size, csmUint32 alignment)
{
return GetAllocator()->AllocateAligned(size, alignment);
}
void CubismFramework::Deallocate(void* address)
{
if (!address)
{
return;
}
GetAllocator()->Deallocate(address);
}
void CubismFramework::DeallocateAligned(void* address)
{
if (!address)
{
return;
}
GetAllocator()->DeallocateAligned(address);
}
#endif
}}}
//--------- LIVE2D NAMESPACE ------------
#ifdef CSM_DEBUG_MEMORY_LEAKING
void* operator new(Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::CubismAllocationTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber)
{
return Live2D::Cubism::Framework::CubismFramework::Allocate(size, fileName, lineNumber);
}
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::csmUint32 alignment, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber)
{
return Live2D::Cubism::Framework::CubismFramework::AllocateAligned(size, alignment, fileName, lineNumber);
}
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber)
{
Live2D::Cubism::Framework::CubismFramework::Deallocate(address, fileName, lineNumber);
}
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber)
{
Live2D::Cubism::Framework::CubismFramework::DeallocateAligned(address, fileName, lineNumber);
}
#else
void* operator new(Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::CubismAllocationTag tag)
{
return Live2D::Cubism::Framework::CubismFramework::Allocate(size);
}
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::csmUint32 alignment, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag)
{
return Live2D::Cubism::Framework::CubismFramework::AllocateAligned(size, alignment);
}
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationTag tag)
{
Live2D::Cubism::Framework::CubismFramework::Deallocate(address);
}
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag)
{
Live2D::Cubism::Framework::CubismFramework::DeallocateAligned(address);
}
#endif
+436
View File
@@ -0,0 +1,436 @@
/**
* 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 the Live2D Cubism Core header.
//========================================================
#include "Live2DCubismCore.hpp"
//========================================================
// Include the Framework Configurations header.
//========================================================
#include "CubismFrameworkConfig.hpp"
//========================================================
// Include the Custom Allocator header.
//========================================================
#include <new>
#include "ICubismAllocator.hpp"
#ifdef __linux__
#include <cstdlib>
#endif
#include <string>
//========================================================
// Configurations of Memory Allocator.
//========================================================
namespace Live2D { namespace Cubism { namespace Framework {
class CubismAllocationTag
{ };
class CubismAllocationAlignedTag
{ };
static CubismAllocationTag GlobalTag;
static CubismAllocationAlignedTag GloabalAlignedTag;
}}}
// Macros for memory allocation.
#ifdef CSM_DEBUG_MEMORY_LEAKING
// For debugging.
// Tracks / Detects the memory leaking.
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::CubismAllocationTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber);
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::csmUint32 alignment, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber);
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber);
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber);
template<typename T>
void CsmDelete(T* address, const Live2D::Cubism::Framework::csmChar* fileName, Live2D::Cubism::Framework::csmInt32 lineNumber)
{
if (!address)
{
return;
}
address->~T();
operator delete(reinterpret_cast<void*>(address), Live2D::Cubism::Framework::GlobalTag, fileName, lineNumber);
}
#define CSM_NEW new(Live2D::Cubism::Framework::GlobalTag, __FILE__, __LINE__)
#define CSM_DELETE_SELF(type, obj) do { if (!obj){ break; } obj->~type(); operator delete(obj, Live2D::Cubism::Framework::GlobalTag, __FILE__, __LINE__); } while(0)
#define CSM_DELETE(obj) CsmDelete(obj, __FILE__, __LINE__)
#define CSM_MALLOC(size) Live2D::Cubism::Framework::CubismFramework::Allocate(size, __FILE__, __LINE__)
#define CSM_MALLOC_ALLIGNED(size, align) Live2D::Cubism::Framework::CubismFramework::AllocateAligned(size, align, __FILE__, __LINE__)
#define CSM_FREE(ptr) Live2D::Cubism::Framework::CubismFramework::Deallocate(ptr, __FILE__, __LINE__)
#define CSM_FREE_ALLIGNED(ptr) Live2D::Cubism::Framework::CubismFramework::DeallocateAligned(ptr, __FILE__, __LINE__)
#else
// For releasing.
// Without Tracking / Detecting.
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::CubismAllocationTag tag);
void* operator new (Live2D::Cubism::Framework::csmSizeType size, Live2D::Cubism::Framework::csmUint32 alignment, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag);
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationTag tag);
void operator delete(void* address, Live2D::Cubism::Framework::CubismAllocationAlignedTag tag);
template<typename T>
void CsmDelete(T* address)
{
if (!address)
{
return;
}
address->~T();
operator delete(reinterpret_cast<void*>(address), Live2D::Cubism::Framework::GlobalTag);
}
#define CSM_NEW new(Live2D::Cubism::Framework::GlobalTag)
#define CSM_DELETE_SELF(type, obj) do { if (!obj){ break; } obj->~type(); operator delete(obj, Live2D::Cubism::Framework::GlobalTag); } while(0)
#define CSM_DELETE(obj) CsmDelete(obj)
#define CSM_MALLOC(size) Live2D::Cubism::Framework::CubismFramework::Allocate(size)
#define CSM_MALLOC_ALLIGNED(size, align) Live2D::Cubism::Framework::CubismFramework::AllocateAligned(size, align)
#define CSM_FREE(ptr) Live2D::Cubism::Framework::CubismFramework::Deallocate(ptr)
#define CSM_FREE_ALLIGNED(ptr) Live2D::Cubism::Framework::CubismFramework::DeallocateAligned(ptr)
#endif
#define CSM_PLACEMENT_NEW(addrs) new((addrs))
//========================================================
// Include the definition of types for the each architectures.
//========================================================
#include "Type/CubismBasicType.hpp"
//========================================================
// Forward Declaration of CubismIdManager.
//========================================================
namespace Live2D { namespace Cubism { namespace Framework {
class CubismIdManager;
}}}
//========================================================
// Compiler Setttings for buiding the Framework.
//========================================================
#ifdef _MSC_VER
#pragma warning (disable : 4100)
#endif
#ifndef NULL
#define NULL 0
#endif
//========================================================
// Macros for validation.
//========================================================
/**
* Ensures that the expression is valid.
*
* @param expression Expression to be ensured
* @param message Message if the expression is invalid
* @param body Handler if the expression is invalid
*/
#define CubismEnsure(expression, message, body) \
do \
{ \
if (!(expression)) \
{ \
CubismFramework::CoreLogFunction("[Cubism Framework] " message); \
body; \
} \
} \
while (0);
//========================================================
// Ailias of the Framework.
//========================================================
namespace Csm = Live2D::Cubism::Framework;
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/** Typedef for file loader */
typedef csmByte* (*csmLoadFileFunction)(const std::string filePath, csmSizeInt* outSize);
typedef void (*csmReleaseBytesFunction)(Csm::csmByte* byteData);
/**
* Constants.
*/
namespace Constant {
/** Vertex offset of Drawable */
extern const csmInt32 VertexOffset;
/** Number of vertices in Drawable */
extern const csmInt32 VertexStep;
}
/**
* Entrypoint for the Live2D Cubism SDK
*
* @see #StartUp()
* @see #Initialize()
* @see #Dispose()
* @see #CleanUp()
*
* @note At the start of use, call CubismFramework::StartUp() before calling CubismFramework::Initialize(). <br>
* At the end, call CubismFramework::Dispose() before calling CubismFramework::CleanUp().
*/
class CubismFramework
{
public:
/**
* Framework configurations.
*/
class Option
{
public:
/**
* Enumerator for Logging level
*/
enum LogLevel
{
/** Indicates that the logging of all is enabled. */
LogLevel_Verbose = 0,
/** Indicates that up to the logging level of Debug. */
LogLevel_Debug,
/** Indicates that up to the logging level of Info. */
LogLevel_Info,
/** Indicates that up to the logging level of Warning. */
LogLevel_Warning,
/** Indicates that up to the logging level of Error. */
LogLevel_Error,
/** Indicates that the logging of all is disabled. */
LogLevel_Off
};
/** Logging function */
Core::csmLogFunction LogFunction;
/** Logging level */
LogLevel LoggingLevel;
/** File reading function */
csmLoadFileFunction LoadFileFunction;
/** Release bytes function */
csmReleaseBytesFunction ReleaseBytesFunction;
};
/**
*
* Enables the Cubism Framework API.
*
* @param allocator Instance of memory allocator
* @param option Instance of Framework configuration option.<br>
* If an empty instance is set, the Framework configuration option is not used.
*
* @return true if Cubism Framework is available; otherwise false.
*
* @note Make sure to execute this function before executing the API of the Framework, <br>
* and be sure to pass the memory allocator to the argument.<br>
* Once the preparation is complete, the process will be skipped if executed again afterwards.
*/
static csmBool StartUp(ICubismAllocator* allocator, const Option* option = NULL);
/**
* Enables the Cubism Framework API to reuse.
*
* @note Clear each parameter of CubismFramework initialized by StartUp().<br>
* Use this method when reusing Cubism Framework that has been Dispose().
*/
static void CleanUp();
/**
* Returns whether the API of Cubism Framework is available.
*
* @return true if the API is available; otherwise false.
*/
static csmBool IsStarted();
/**
* Initializes the resources in the Cubism Framework and makes the Model ready for display.
*/
static void Initialize();
/**
* Releases all resources in the Cubism Framework.
*
* @note Resources allocated externally will not be released.<br>
* Discard them externally as appropriate.
*/
static void Dispose();
/**
* Returns whether the Cubism Framework resources have been initialized.
*
* @return true if the resource has been initialized; otherwise false.
*/
static csmBool IsInitialized();
/**
* Executes the logging function of Cubism Core API.
*
* @param message Message for logging
*
* @note Logging using Option::logFunction.
*/
static void CoreLogFunction(const csmChar* message);
/**
* Returns the logging level setting.
*
* @return Logging level setting
*/
static Option::LogLevel GetLoggingLevel();
/**
* Returns the loading file function.
*
* @return Function to read the file as csmByte*.
*/
static csmLoadFileFunction GetLoadFileFunction();
/**
* Returns the memory release function.
*
* @return Function to free memory allocated by csmByte*.
*
* @note Memory allocated by GetLoadFileFunction() must be released with this function.
*/
static csmReleaseBytesFunction GetReleaseBytesFunction();
/**
* Returns the instance of CubismIdManager.
*
* @note Please use `GetId()` through this function to get `CubismId`.<br>
* ex) CubismFramework::GetIdManager()->GetId(id_str);
*
* @return Instance of CubismIdManager.
*/
static CubismIdManager* GetIdManager();
#ifdef CSM_DEBUG_MEMORY_LEAKING
/**
* (For debugging) Allocates the memory.
*
* @param size Desired amount of memory in bytes
* @param fileName Name of source code that called
* @param lineNumber Number of line of source code that called
*
* @return Pointer to the allocated memory if succeeded; otherwise `0`
*/
static void* Allocate(csmSizeType size, const csmChar* fileName, csmInt32 lineNumber);
/**
* (For debugging) Allocates the memory with specified alignment.
*
* @param size Desired amount of memory in bytes
* @param alignment Desired alignment of memory in bytes
* @param fileName Name of source code that called
* @param lineNumber Number of line of source code that called
*
* @return Pointer to the allocated memory if succeeded; otherwise `0`
*/
static void* AllocateAligned(csmSizeType size, csmUint32 alignment, const csmChar* fileName, csmInt32 lineNumber);
/**
* (For debugging) Deallocates the aligned memory.
*
* @param address Pointer to allocated memory to be deallocated
* @param fileName Name of source code that called
* @param lineNumber Number of line of source code that called
*/
static void Deallocate(void* address, const csmChar* fileName, csmInt32 lineNumber);
/**
* (For debugging) Deallocates the aligned memory.
*
* @param address Pointer to allocated memory to be deallocated
* @param fileName Name of source code that called
* @param lineNumber Number of line of source code that called
*/
static void DeallocateAligned(void* address, const csmChar* fileName, csmInt32 lineNumber);
#else
/**
* Allocates the memory with specified alignment.
*
* @param size Desired amount of memory in bytes
* @param alignment Desired alignment of memory in bytes
*
* @return PPointer to the allocated memory if succeeded; otherwise `0`
*/
static void* Allocate(csmSizeType size);
/**
* Allocates the memory with specified alignment.
*
* @param size Desired amount of memory in bytes
* @param alignment Desired alignment of memory in bytes
*
* @return Pointer to the allocated memory if succeeded; otherwise `0`
*/
static void* AllocateAligned(csmSizeType size, csmUint32 alignment);
/**
* Deallocates the memory.
*
* @param address Pointer to allocated memory to be deallocated
*/
static void Deallocate(void* address);
/**
* Deallocates the aligned memory.
*
* @param address Pointer to allocated memory to be deallocated
*/
static void DeallocateAligned(void* address);
#endif
private:
/**
* Constructor
*
* @note Prevent instantiating and be used as a static class.
*/
CubismFramework(){}
};
}}}
//--------- LIVE2D NAMESPACE ------------
@@ -0,0 +1,56 @@
/**
* 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
/**
* A set of macros to configure the Cubism Framework on build.
*/
/**
* A set of macros to use for debugging Cubism Framework.
*/
/** Runs Cubism Framework as debug mode. */
// #define CSM_DEBUG
/**
* Tracks memory leaking of Cubism Framework.
*
* @note Leakage is verified at the termination of Cubism Framework.
*/
// #define CSM_DEBUG_MEMORY_LEAKING
/**
* A set of macros to configure the logging level forcefully.
*
* @note The set logging level is applied by changing the definition of a group of macros that call logging in the CubismDebug class.
*/
/** Indicates that the logging of all is enabled. */
#define CSM_LOG_LEVEL_VERBOSE 0
/** Indicates that up to the logging level of Debug. */
#define CSM_LOG_LEVEL_DEBUG 1
/** Indicates that up to the logging level of Info. */
#define CSM_LOG_LEVEL_INFO 2
/** Indicates that up to the logging level of Warning. */
#define CSM_LOG_LEVEL_WARNING 3
/** Indicates that up to the logging level of Error. */
#define CSM_LOG_LEVEL_ERROR 4
/** Indicates that the logging of all is disabled. */
#define CSM_LOG_LEVEL_OFF 5
/**
* Logging level to set
*
* @note Set one of the logging levels from CSM_LOG_LEVEL_VERBOSE to CSM_LOG_LEVEL_OFF.
*/
#define CSM_LOG_LEVEL CSM_LOG_LEVEL_VERBOSE
+74
View File
@@ -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 "Utils/CubismJson.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* An interface that implements the CubismJson instantiation<br>
* and validity checks at each JSON parser.
*/
class CubismJsonHolder
{
public:
/**
* Constructor
*/
CubismJsonHolder()
: _json(NULL)
{ }
/**
* Destructor
*/
virtual ~CubismJsonHolder()
{ }
/**
* Returns whether the CubismJson is valid or not.
*
* @return true if valid; otherwise false
*/
csmBool IsValid() const
{
return _json;
}
protected:
/**
* Make the instance of CubismJson.
*
* @param buffer Buffer into which JSON is loaded
* @param size Number of bytes in buffer
*/
void CreateCubismJson(const csmByte* buffer, csmSizeInt size)
{
_json = Utils::CubismJson::Create(buffer, size);
if (!IsValid())
{
CubismLogError("[CubismJsonHolder] Invalid Json document.");
}
};
/**
* Destroy the instance of CubismJson.
*/
void DeleteCubismJson()
{
Utils::CubismJson::Delete(_json);
_json = NULL;
}
/** Instance of CubismJson */
Utils::CubismJson* _json;
};
}}}
@@ -0,0 +1,496 @@
/**
* 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 "CubismModelSettingJson.hpp"
#include "CubismFramework.hpp"
#include "Type/csmMap.hpp"
#include "Id/CubismId.hpp"
#include "Id/CubismIdManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* @brief Model3Jsonのキー文字列
*
*/
namespace {
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
#endif
// JSON keys
const csmChar* Version = "Version";
const csmChar* FileReferences = "FileReferences";
const csmChar* Groups = "Groups";
const csmChar* Layout = "Layout";
const csmChar* HitAreas = "HitAreas";
const csmChar* Moc = "Moc";
const csmChar* Textures = "Textures";
const csmChar* Physics = "Physics";
const csmChar* DisplayInfo = "DisplayInfo";
const csmChar* Pose = "Pose";
const csmChar* Expressions = "Expressions";
const csmChar* Motions = "Motions";
const csmChar* UserData = "UserData";
const csmChar* Name = "Name";
const csmChar* FilePath = "File";
const csmChar* Id = "Id";
const csmChar* Ids = "Ids";
const csmChar* Target = "Target";
// Motions
const csmChar* Idle = "Idle";
const csmChar* TapBody = "TapBody";
const csmChar* PinchIn = "PinchIn";
const csmChar* PinchOut = "PinchOut";
const csmChar* Shake = "Shake";
const csmChar* FlickHead = "FlickHead";
const csmChar* Parameter = "Parameter";
const csmChar* SoundPath = "Sound";
const csmChar* FadeInTime = "FadeInTime";
const csmChar* FadeOutTime = "FadeOutTime";
// Layout
const csmChar* CenterX = "CenterX";
const csmChar* CenterY = "CenterY";
const csmChar* X = "X";
const csmChar* Y = "Y";
const csmChar* Width = "Width";
const csmChar* Height = "Height";
const csmChar* LipSync = "LipSync";
const csmChar* EyeBlink = "EyeBlink";
const csmChar* InitParameter = "init_param";
const csmChar* InitPartsVisible = "init_parts_visible";
const csmChar* Val = "val";
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
// キーが存在するかどうかのチェック
csmBool CubismModelSettingJson::IsExistModelFile() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Moc]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistTextureFiles() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Textures]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistHitAreas() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_HitAreas]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistPhysicsFile() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Physics]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistPoseFile() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Pose]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistDisplayInfoFile() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_DisplayInfo]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistExpressionFile() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Expressions]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistMotionGroups() const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Motions]);
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistMotionGroupName(const csmChar* groupName) const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Motions])[groupName];
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistMotionSoundFile(const csmChar* groupName, csmInt32 index) const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Motions])[groupName][index][SoundPath];
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistMotionFadeIn(const csmChar* groupName, csmInt32 index) const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Motions])[groupName][index][FadeInTime];
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistMotionFadeOut(const csmChar* groupName, csmInt32 index) const
{
Utils::Value& node = (*_jsonValue[FrequentNode_Motions])[groupName][index][FadeOutTime];
return !node.IsNull() && !node.IsError();
}
csmBool CubismModelSettingJson::IsExistUserDataFile() const { return !_json->GetRoot()[FileReferences][UserData].IsNull(); }
csmBool CubismModelSettingJson::IsExistEyeBlinkParameters() const
{
if (_jsonValue[FrequentNode_Groups]->IsNull() || _jsonValue[FrequentNode_Groups]->IsError())
{
return false;
}
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); ++i)
{
if (strcmp((*_jsonValue[FrequentNode_Groups])[i][Name].GetRawString(), EyeBlink) == 0)
{
return true;
}
}
return false;
}
csmBool CubismModelSettingJson::IsExistLipSyncParameters() const
{
if (_jsonValue[FrequentNode_Groups]->IsNull() || _jsonValue[FrequentNode_Groups]->IsError())
{
return false;
}
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); ++i)
{
if (strcmp((*_jsonValue[FrequentNode_Groups])[i][Name].GetRawString(), LipSync) == 0)
{
return true;
}
}
return false;
}
CubismModelSettingJson::CubismModelSettingJson(const csmByte* buffer, csmSizeInt size)
{
CreateCubismJson(buffer, size);
if (_json)
{
_jsonValue.Clear();
// 順番はenum FrequentNodeと一致させる
_jsonValue.PushBack(&(_json->GetRoot()[Groups]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Moc]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Motions]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][DisplayInfo]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Expressions]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Textures]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Physics]));
_jsonValue.PushBack(&(_json->GetRoot()[FileReferences][Pose]));
_jsonValue.PushBack(&(_json->GetRoot()[HitAreas]));
}
}
CubismModelSettingJson::~CubismModelSettingJson()
{
DeleteCubismJson();
}
Utils::CubismJson* CubismModelSettingJson::GetJsonPointer() const
{
return _json;
}
const csmChar* CubismModelSettingJson::GetModelFileName()
{
if (!IsExistModelFile())return "";
return (*_jsonValue[FrequentNode_Moc]).GetRawString();
}
// テクスチャについて
csmInt32 CubismModelSettingJson::GetTextureCount()
{
if (!IsExistTextureFiles())return 0;
return (*_jsonValue[FrequentNode_Textures]).GetSize();
}
const csmChar* CubismModelSettingJson::GetTextureDirectory()
{
if (!IsExistTextureFiles())
{
return "";
}
csmVector<csmString> splitPathBuffer;
csmVector<csmChar> charBuffer;
const csmChar* rawString = (*_jsonValue[FrequentNode_Textures])[0].GetRawString();
csmInt32 rawStringSize = (*_jsonValue[FrequentNode_Textures])[0].GetString().GetLength();
for (csmInt32 i = 0; i < rawStringSize; i++)
{
// /を含んでいる場合splitする
if (rawString[i] == '/')
{
csmString str = csmString(charBuffer.GetPtr());
splitPathBuffer.PushBack(str);
charBuffer.Clear();
}
// 一文字ずつVector配列に格納する
else
{
charBuffer.PushBack(static_cast<csmChar>(rawString[i] & 0xFF));
}
}
csmInt32 arrayLength = splitPathBuffer.GetSize();
csmString textureDirectoryStr = csmString();
for(csmInt32 i = 0; i < arrayLength; i++)
{
textureDirectoryStr = textureDirectoryStr + splitPathBuffer[i];
if(i < arrayLength - 1)
{
textureDirectoryStr = textureDirectoryStr + "/";
}
}
return textureDirectoryStr.GetRawString();
}
const csmChar* CubismModelSettingJson::GetTextureFileName(csmInt32 index)
{
return (*_jsonValue[FrequentNode_Textures])[index].GetRawString();
}
// あたり判定について
csmInt32 CubismModelSettingJson::GetHitAreasCount()
{
if (!IsExistHitAreas())return 0;
return (*_jsonValue[FrequentNode_HitAreas]).GetSize();
}
CubismIdHandle CubismModelSettingJson::GetHitAreaId(csmInt32 index)
{
return CubismFramework::GetIdManager()->GetId((*_jsonValue[FrequentNode_HitAreas])[index][Id].GetRawString());
}
const csmChar* CubismModelSettingJson::GetHitAreaName(csmInt32 index)
{
return (*_jsonValue[FrequentNode_HitAreas])[index][Name].GetRawString();
}
// 物理演算、表示名称、パーツ切り替え、表情ファイルについて
const csmChar* CubismModelSettingJson::GetPhysicsFileName()
{
if (!IsExistPhysicsFile())return "";
return (*_jsonValue[FrequentNode_Physics]).GetRawString();
}
const csmChar* CubismModelSettingJson::GetPoseFileName()
{
if (!IsExistPoseFile())return "";
return (*_jsonValue[FrequentNode_Pose]).GetRawString();
}
const csmChar* CubismModelSettingJson::GetDisplayInfoFileName()
{
if (!IsExistDisplayInfoFile())return "";
return (*_jsonValue[FrequentNode_DisplayInfo]).GetRawString();
}
csmInt32 CubismModelSettingJson::GetExpressionCount()
{
if (!IsExistExpressionFile())return 0;
return (*_jsonValue[FrequentNode_Expressions]).GetSize();
}
const csmChar* CubismModelSettingJson::GetExpressionName(csmInt32 index)
{
return (*_jsonValue[FrequentNode_Expressions])[index][Name].GetRawString();
}
const csmChar* CubismModelSettingJson::GetExpressionFileName(csmInt32 index)
{
return (*_jsonValue[FrequentNode_Expressions])[index][FilePath].GetRawString();
}
// モーションについて
csmInt32 CubismModelSettingJson::GetMotionGroupCount()
{
if (!IsExistMotionGroups())
{
return 0;
}
return (*_jsonValue[FrequentNode_Motions]).GetKeys().GetSize();
}
const csmChar* CubismModelSettingJson::GetMotionGroupName(csmInt32 index)
{
if (!IsExistMotionGroups())
{
return NULL;
}
return (*_jsonValue[FrequentNode_Motions]).GetKeys()[index].GetRawString();
}
csmInt32 CubismModelSettingJson::GetMotionCount(const csmChar* groupName)
{
if (!IsExistMotionGroupName(groupName))return 0;
return (*_jsonValue[FrequentNode_Motions])[groupName].GetSize();
}
const csmChar* CubismModelSettingJson::GetMotionFileName(const csmChar* groupName, csmInt32 index)
{
if (!IsExistMotionGroupName(groupName))return "";
return (*_jsonValue[FrequentNode_Motions])[groupName][index][FilePath].GetRawString();
}
const csmChar* CubismModelSettingJson::GetMotionSoundFileName(const csmChar* groupName, csmInt32 index)
{
if (!IsExistMotionSoundFile(groupName, index))return "";
return (*_jsonValue[FrequentNode_Motions])[groupName][index][SoundPath].GetRawString();
}
csmFloat32 CubismModelSettingJson::GetMotionFadeInTimeValue(const csmChar* groupName, csmInt32 index)
{
if (!IsExistMotionFadeIn(groupName, index))return -1.0f;
return (*_jsonValue[FrequentNode_Motions])[groupName][index][FadeInTime].ToFloat();
}
csmFloat32 CubismModelSettingJson::GetMotionFadeOutTimeValue(const csmChar* groupName, csmInt32 index)
{
if (!IsExistMotionFadeOut(groupName, index))return -1.0f;
return (*_jsonValue[FrequentNode_Motions])[groupName][index][FadeOutTime].ToFloat();
}
const csmChar* CubismModelSettingJson::GetUserDataFile()
{
if (!IsExistUserDataFile())
{
return "";
}
return _json->GetRoot()[FileReferences][UserData].GetRawString();
}
csmBool CubismModelSettingJson::GetLayoutMap(csmMap<csmString, csmFloat32>& outLayoutMap)
{
csmMap<csmString, Utils::Value*>* map = _json->GetRoot()[Layout].GetMap();
if (map == NULL)
{
return false;
}
csmMap<csmString, Utils::Value*>::const_iterator map_ite;
csmBool ret = false;
for (map_ite = map->Begin(); map_ite != map->End(); ++map_ite)
{
outLayoutMap[map_ite->First] = map_ite->Second->ToFloat();
ret = true;
}
return ret;
}
csmInt32 CubismModelSettingJson::GetEyeBlinkParameterCount()
{
if (!IsExistEyeBlinkParameters())
{
return 0;
}
csmInt32 num = 0;
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); i++)
{
Utils::Value& refI = (*_jsonValue[FrequentNode_Groups])[i];
if(refI.IsNull() || refI.IsError())
{
continue;
}
if (strcmp(refI[Name].GetRawString(), EyeBlink) == 0)
{
num = refI[Ids].GetVector()->GetSize();
break;
}
}
return num;
}
CubismIdHandle CubismModelSettingJson::GetEyeBlinkParameterId(csmInt32 index)
{
if (!IsExistEyeBlinkParameters())
{
return NULL;
}
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); i++)
{
Utils::Value& refI = (*_jsonValue[FrequentNode_Groups])[i];
if (refI.IsNull() || refI.IsError())
{
continue;
}
if (strcmp(refI[Name].GetRawString(), EyeBlink) == 0)
{
return CubismFramework::GetIdManager()->GetId(refI[Ids][index].GetRawString());
}
}
return NULL;
}
csmInt32 CubismModelSettingJson::GetLipSyncParameterCount()
{
if (!IsExistLipSyncParameters())
{
return 0;
}
csmInt32 num = 0;
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); i++)
{
Utils::Value& refI = (*_jsonValue[FrequentNode_Groups])[i];
if (refI.IsNull() || refI.IsError())
{
continue;
}
if (strcmp(refI[Name].GetRawString(), LipSync) == 0)
{
num = refI[Ids].GetVector()->GetSize();
break;
}
}
return num;
}
CubismIdHandle CubismModelSettingJson::GetLipSyncParameterId(csmInt32 index)
{
if (!IsExistLipSyncParameters())
{
return NULL;
}
for (csmInt32 i = 0; i < _jsonValue[FrequentNode_Groups]->GetSize(); i++)
{
Utils::Value& refI = (*_jsonValue[FrequentNode_Groups])[i];
if (refI.IsNull() || refI.IsError())
{
continue;
}
if (strcmp(refI[Name].GetRawString(), LipSync) == 0)
{
return CubismFramework::GetIdManager()->GetId(refI[Ids][index].GetRawString());
}
}
return NULL;
}
}}}
@@ -0,0 +1,393 @@
/**
* 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 "ICubismModelSetting.hpp"
#include "CubismJsonHolder.hpp"
#include "Utils/CubismJson.hpp"
#include "Id/CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the Model Settings File
*/
class CubismModelSettingJson : public ICubismModelSetting, public CubismJsonHolder
{
public:
/**
* Constructor<br>
* Loads the Model Settings File.
*
* @param buffer Buffer into which the Model Settings File is loaded
* @param size Number of bytes in buffer
*/
CubismModelSettingJson(const csmByte* buffer, csmSizeInt size);
/**
* Destructor
*/
virtual ~CubismModelSettingJson();
/**
* Returns the instance of CubismJson that handles the JSON document.
*
* @return Instance of CubismJson
*/
Utils::CubismJson* GetJsonPointer() const;
/**
* Returns the file name of MOC3 File.
*
* @return Name of MOC3 File
*/
const csmChar* GetModelFileName();
/**
* Returns the number of textures in the Model.
*
* @return Number of textures
*/
csmInt32 GetTextureCount();
/**
* Returns the name of directory that texture is placed.
*
* @return Name of directory
*/
const csmChar* GetTextureDirectory();
/**
* Returns the name of texture in the Model.
*
* @param index Index to the desired texture name
*
* @return Name of texture
*/
const csmChar* GetTextureFileName(csmInt32 index);
/**
* Returns the number of Hit Area settings in the Model.
*
* @return Number of Hit Area settings
*/
csmInt32 GetHitAreasCount();
/**
* Returns whether ID of Drawable that is set for the Hit Area.
*
* @param groupName Name of the desired Motion Group
*
* @return true if Motion Group information exists; otherwise false
*/
CubismIdHandle GetHitAreaId(csmInt32 index);
/**
* Returns the name of Hit Area.
*
* @param index Index to the desired Hit Area
*
* @return Name of Hit Area
*/
const csmChar* GetHitAreaName(csmInt32 index);
/**
* Returns the name of Physics Settings File in the Model.
*
* @return Name of Physics Settings File
*/
const csmChar* GetPhysicsFileName();
/**
* Returns the name of Pose Settings File in the Model.
*
* @return Name of Pose Settings File
*/
const csmChar* GetPoseFileName();
/**
* Returns the name of Display Settings File in the Model.
*
* @return Name of Display Settings File
*/
const csmChar* GetDisplayInfoFileName();
/**
* Returns the number of expressions in the Model.
*
* @return Number of expressions
*/
csmInt32 GetExpressionCount();
/**
* Returns the name of expression.
*
* @param index Index to the desired expression
*
* @return Name of expression
*/
const csmChar* GetExpressionName(csmInt32 index);
/**
* Returns the name of Expression Settings File from the expression.
*
* @param index Index to the desired expression
*
* @return Name of Expression Settings File
*/
const csmChar* GetExpressionFileName(csmInt32 index);
/**
* Returns the number of Motion Groups in the Model.
*
* @return Number of Motion Groups
*/
csmInt32 GetMotionGroupCount();
/**
* Returns the name of Motion Group.
*
* @param index Index to the desired Motion Group
*
* @return Name of Motion Group
*/
const csmChar* GetMotionGroupName(csmInt32 index);
/**
* Returns the number of Motions in the Motion Group.
*
* @param groupName Name to the desired Motion Group
*
* @return Number of Motions
*/
csmInt32 GetMotionCount(const csmChar* groupName);
/**
* Returns the file name of Motion File in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired motion
*
* @return Name of Motion File
*/
const csmChar* GetMotionFileName(const csmChar* groupName, csmInt32 index);
/**
* Returns the name of Audio File attached to the Motion in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Name of Audio File
*/
const csmChar* GetMotionSoundFileName(const csmChar* groupName, csmInt32 index);
/**
* Returns the Fade-in time at the start of the Motion in the Motion Group
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Fade-in time [sec]
*/
csmFloat32 GetMotionFadeInTimeValue(const csmChar* groupName, csmInt32 index);
/**
* Returns the Fade-out time at the end of the Motion in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Fade-out time [sec]
*/
csmFloat32 GetMotionFadeOutTimeValue(const csmChar* groupName, csmInt32 index);
/**
* Returns the name of User Data File in the Model.
*
* @return Name of User Data File
*/
const csmChar* GetUserDataFile();
/**
* Returns the Layout Information set in the model.
*
* @param outLayoutMap Instance of a collection to store
*
* @return true if Layout Information exists; otherwise false
*/
csmBool GetLayoutMap(csmMap<csmString, csmFloat32>& outLayoutMap);
/**
* Returns the number of parameters attached to the Eye Blinking Settings.
*
* @return Number of parameters
*/
csmInt32 GetEyeBlinkParameterCount();
/**
* Returns the ID of parameter attached to the Eye Blinking Settings.
*
* @param index Index to the desired parameter
*
* @return ID of parameter
*/
CubismIdHandle GetEyeBlinkParameterId(csmInt32 index);
/**
* Returns the number of parameters attached to the Lip-sync Settings.
*
* @return Number of parameters
*/
csmInt32 GetLipSyncParameterCount();
/**
* Returns the ID of parameter attached to the Lip-sync Settings.
*
* @param index Index to the desired parameter
*
* @return ID of parameter
*/
CubismIdHandle GetLipSyncParameterId(csmInt32 index);
protected:
enum FrequentNode
{
FrequentNode_Groups,
FrequentNode_Moc,
FrequentNode_Motions,
FrequentNode_DisplayInfo,
FrequentNode_Expressions,
FrequentNode_Textures,
FrequentNode_Physics,
FrequentNode_Pose,
FrequentNode_HitAreas,
};
/**
* Returns whether the MOC3 File information exists in the Model Settings File.
*
* @return true if MOC3 File information exists; otherwise false
*/
csmBool IsExistModelFile() const;
/**
* Returns whether Texture File information exists in the Model Settings File.
*
* @return true if Texture File information exists; otherwise false
*/
csmBool IsExistTextureFiles() const;
/**
* Returns whether Hit Area information exists in the Model Settings File.
*
* @return true if Hit Area information exists; otherwise false
*/
csmBool IsExistHitAreas() const;
/**
* Returns whether Physics Settings File information exists in the Model Settings File.
*
* @return true if Physics Settings File information exists; otherwise false
*/
csmBool IsExistPhysicsFile() const;
/**
* Returns whether Pose Settings File information exists in the Model Settings File.
*
* @return true if Pose Settings File information exists; otherwise false
*/
csmBool IsExistPoseFile() const;
/**
* Returns whether Display Settings File information exists in the Model Settings File.
*
* @return true if Display Settings File information exists; otherwise false
*/
csmBool IsExistDisplayInfoFile() const;
/**
* Returns whether Expression File information exists in the Model Settings File.
*
* @return true if Expression File information exists; otherwise false
*/
csmBool IsExistExpressionFile() const;
/**
* Returns whether Motion Group information exists in the Model Settings File.
*
* @return true if Motion Group information exists; otherwise false
*/
csmBool IsExistMotionGroups() const;
/**
* Returns the Motion Group information with the specified name in the Model Settings File.
*
* @param groupName Name of the desired Motion Group
*
* @return true if Motion Group information exists; otherwise false
*/
csmBool IsExistMotionGroupName(const csmChar* groupName) const;
/**
* Returns whether the Audio File information in the Motion Group with the specified name in the Model Settings File.
*
* @param groupName Name of the desired Motion Group
* @param index Index to the desired Motion
*
* @return true if Audio File information exists; otherwise false
*/
csmBool IsExistMotionSoundFile(const csmChar* groupName, csmInt32 index) const;
/**
* Returns whether the Fade-in time at the start of Motion in Motion Group with the specified name exists in Model Setting File.
*
* @param groupName Name of the desired Motion Group
* @param index Index to the desired Motion
*
* @return true if Fade-in time exists; otherwise false
*/
csmBool IsExistMotionFadeIn(const csmChar* groupName, csmInt32 index) const;
/**
* Returns whether the Fade-out time at the end of the Motion in the Motion Group with the specified name in the Model Settings File.
*
* @param groupName Name of the desired Motion Group
* @param index Index to the desired Motion
*
* @return true if Fade-out time exists; otherwise false
*/
csmBool IsExistMotionFadeOut(const csmChar* groupName, csmInt32 index) const;
/**
* Returns whether the User Data File information exists in the Model Settings File.
*
* @return true if User Data File information exists; otherwise false
*/
csmBool IsExistUserDataFile() const;
/**
* Returns whether the parameter information attached to the Eye Blinking Settings exists in the Model Settings File.
*
* @return true if parameter information exists; otherwise false
*/
csmBool IsExistEyeBlinkParameters() const;
/**
* Returns whether the parameter information attached to the Lip-sync Settings exists in the Model Settings File.
*
* @return true if parameter information exists; otherwise false
*/
csmBool IsExistLipSyncParameters() const;
/** Cache of JSON nodes */
csmVector<Utils::Value*> _jsonValue;
};
}}}
@@ -0,0 +1,9 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismBreath.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismBreath.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismEyeBlink.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismEyeBlink.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPose.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPose.hpp
)
@@ -0,0 +1,55 @@
/**
* 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 "CubismBreath.hpp"
#include <math.h>
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismBreath* CubismBreath::Create()
{
return CSM_NEW CubismBreath();
}
void CubismBreath::Delete(CubismBreath* instance)
{
CSM_DELETE_SELF(CubismBreath, instance);
}
CubismBreath::CubismBreath()
: _currentTime(0.0f)
{ }
CubismBreath::~CubismBreath()
{ }
void CubismBreath::SetParameters(const csmVector<BreathParameterData>& breathParameters)
{
_breathParameters = breathParameters;
}
const csmVector<CubismBreath::BreathParameterData>& CubismBreath::GetParameters() const
{
return _breathParameters;
}
void CubismBreath::UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds)
{
_currentTime += deltaTimeSeconds;
const csmFloat32 t = _currentTime * 2.0f * CubismMath::Pi;
for (csmUint32 i = 0; i < _breathParameters.GetSize(); ++i)
{
BreathParameterData* data = &_breathParameters[i];
model->AddParameterValue(data->ParameterId, data->Offset + (data->Peak * sinf(t / data->Cycle)), data->Weight);
}
}
}}}
@@ -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 "Model/CubismModel.hpp"
#include "Id/CubismId.hpp"
#include "Type/csmVector.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the breathing effect
*/
class CubismBreath
{
public:
/**
* Data attached to the parameters of breathing
*/
struct BreathParameterData
{
/**
* Constructor
*/
BreathParameterData()
: ParameterId(NULL)
, Offset(0.0f)
, Peak(0.0f)
, Cycle(0.0f)
, Weight(0.0f)
{ }
/**
* Constructor<br>
* Sets the data.
*
* @param parameterId ID of the breath parameter to attach
* @param offset offset of the sine wave
* @param peak peak value of the sine wave
* @param cycle cycle of the sine wave
* @param weight weight of the parameter
*
* @note The cyclic motion of breathing is set entirely by sine waves.
*/
BreathParameterData(CubismIdHandle parameterId, csmFloat32 offset, csmFloat32 peak, csmFloat32 cycle, csmFloat32 weight)
: ParameterId(parameterId)
, Offset(offset)
, Peak(peak)
, Cycle(cycle)
, Weight(weight)
{ }
CubismIdHandle ParameterId; ///< ID of the breath parameter to attach
csmFloat32 Offset; ///< Offset of the sine wave
csmFloat32 Peak; ///< Peak value of the sine wave
csmFloat32 Cycle; ///< Cycle of the sine wave
csmFloat32 Weight; ///< Weight of the parameter
};
/**
* Makes an instance of CubismBreath.
*
* @return Maked instance of CubismBreath
*/
static CubismBreath* Create();
/**
* Destroys an instance of CubismBreath.
*
* @param instance Instance of CubismBreath to destroy
*/
static void Delete(CubismBreath* instance);
/**
* Attaches the parameters of breathing.
*
* @param breathParameters Collection of breathing parameters to attach
*/
void SetParameters(const csmVector<BreathParameterData>& breathParameters);
/**
* Returns parameters attached to breathing.
*
* @return Attached collection of breathing parameters
*/
const csmVector<BreathParameterData>& GetParameters() const;
/**
* Updates the parameters of the model.
*
* @param model Model to update
* @param deltaTimeSeconds Current time in seconds
*
* @note Execute after making an instance with #Create() and binding parameters with #setParameters().
*/
void UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds);
private:
CubismBreath();
virtual ~CubismBreath();
csmVector<BreathParameterData> _breathParameters;
csmFloat32 _currentTime;
};
}}}
@@ -0,0 +1,160 @@
/**
* 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 "CubismEyeBlink.hpp"
#include "Id/CubismId.hpp"
#include <stdlib.h>
namespace Live2D { namespace Cubism { namespace Framework {
/**
* IDで指定された目のパラメータが、0のときに閉じるなら true 、1の時に閉じるなら false 。
*/
const csmBool CloseIfZero = true;
CubismEyeBlink* CubismEyeBlink::Create(ICubismModelSetting* modelSetting)
{
return CSM_NEW CubismEyeBlink(modelSetting);
}
void CubismEyeBlink::Delete(CubismEyeBlink* eyeBlink)
{
CSM_DELETE_SELF(CubismEyeBlink, eyeBlink);
}
CubismEyeBlink::CubismEyeBlink(ICubismModelSetting* modelSetting)
: _blinkingState(EyeState_First)
, _nextBlinkingTime(0.0f)
, _stateStartTimeSeconds(0.0f)
, _blinkingIntervalSeconds(4.0f)
, _closingSeconds(0.1f)
, _closedSeconds(0.05f)
, _openingSeconds(0.15f)
, _userTimeSeconds(0.0f)
{
if (modelSetting == NULL)
{
return;
}
for (csmInt32 i = 0; i < modelSetting->GetEyeBlinkParameterCount(); ++i)
{
_parameterIds.PushBack(modelSetting->GetEyeBlinkParameterId(i));
}
}
CubismEyeBlink::~CubismEyeBlink()
{ }
csmFloat32 CubismEyeBlink::DetermineNextBlinkingTiming() const
{
const csmFloat32 r = static_cast<csmFloat32>(rand()) / RAND_MAX;
return _userTimeSeconds + (r * (2.0f * _blinkingIntervalSeconds - 1.0f));
}
void CubismEyeBlink::SetBlinkingInterval(csmFloat32 blinkingInterval)
{
_blinkingIntervalSeconds = blinkingInterval;
}
void CubismEyeBlink::SetBlinkingSettings(csmFloat32 closing, csmFloat32 closed, csmFloat32 opening)
{
_closingSeconds = closing;
_closedSeconds = closed;
_openingSeconds = opening;
}
void CubismEyeBlink::SetParameterIds(const csmVector<CubismIdHandle>& parameterIds)
{
_parameterIds = parameterIds;
}
const csmVector<CubismIdHandle>& CubismEyeBlink::GetParameterIds() const
{
return _parameterIds;
}
void CubismEyeBlink::UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds)
{
_userTimeSeconds += deltaTimeSeconds;
csmFloat32 parameterValue;
csmFloat32 t = 0.0f;
switch (_blinkingState)
{
case EyeState_Closing:
t = ((_userTimeSeconds - _stateStartTimeSeconds) / _closingSeconds);
if (t >= 1.0f)
{
t = 1.0f;
_blinkingState = EyeState_Closed;
_stateStartTimeSeconds = _userTimeSeconds;
}
parameterValue = 1.0f - t;
break;
case EyeState_Closed:
t = ((_userTimeSeconds - _stateStartTimeSeconds) / _closedSeconds);
if (t >= 1.0f)
{
_blinkingState = EyeState_Opening;
_stateStartTimeSeconds = _userTimeSeconds;
}
parameterValue = 0.0f;
break;
case EyeState_Opening:
t = ((_userTimeSeconds - _stateStartTimeSeconds) /_openingSeconds);
if (t >= 1.0f)
{
t = 1.0f;
_blinkingState = EyeState_Interval;
_nextBlinkingTime = DetermineNextBlinkingTiming();
}
parameterValue = t;
break;
case EyeState_Interval:
if (_nextBlinkingTime < _userTimeSeconds)
{
_blinkingState = EyeState_Closing;
_stateStartTimeSeconds = _userTimeSeconds;
}
parameterValue = 1.0f;
break;
case EyeState_First:
default:
_blinkingState = EyeState_Interval;
_nextBlinkingTime = DetermineNextBlinkingTiming();
parameterValue = 1.0f;
break;
}
if (!CloseIfZero)
{
parameterValue = -parameterValue;
}
for (csmUint32 i = 0; i < _parameterIds.GetSize(); ++i)
{
model->SetParameterValue(_parameterIds[i], parameterValue);
}
}
}}}
@@ -0,0 +1,114 @@
/**
* 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 "Type/csmVector.hpp"
#include "Id/CubismId.hpp"
#include "ICubismModelSetting.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles automatic blinking effects
*/
class CubismEyeBlink
{
public:
/**
* Enumeration representing the current state
*/
enum EyeState
{
EyeState_First = 0, ///< Initial state
EyeState_Interval, ///< State of not blinking
EyeState_Closing, ///< State of closing the eyelids
EyeState_Closed, ///< State where the eyelids are closed
EyeState_Opening ///< State of opening the eyelids
};
/**
* Makes an instance of CubismEyeBlink.
*
* @param modelSetting Model setting
*
* @return Maked instance of CubismEyeBlink
*
* @note If the model setting is empty, creates an empty instance with no parameter ID set.
*/
static CubismEyeBlink* Create(ICubismModelSetting* modelSetting = NULL);
/**
* Destroys an instance of CubismEyeBlink.
*
* @param eyeBlink Instance of CubismEyeBlink to destroy
*/
static void Delete(CubismEyeBlink* eyeBlink);
/**
* Sets the interval for blinking.
*
* @param blinkingInterval Time interval for blinking in seconds
*
* @note The time between blinks will be random from 0 seconds to twice the set interval.
*/
void SetBlinkingInterval(csmFloat32 blinkingInterval);
/**
* Sets the behavior for blinking.
*
* @param closing Time taken to close the eyelids in seconds
* @param closed Time taken to keep the eyelids closed in seconds
* @param opening Time taken to open the eyelids in seconds
*/
void SetBlinkingSettings(csmFloat32 closing, csmFloat32 closed, csmFloat32 opening);
/**
* Sets the collection of parameter IDs to apply blinking.
*
* @param parameterIds Collection of parameter IDs to apply
*/
void SetParameterIds(const csmVector<CubismIdHandle>& parameterIds);
/**
* Returns the collection of parameter IDs to apply blinking.
*
* @return Collection of parameter IDs
*/
const csmVector<CubismIdHandle>& GetParameterIds() const;
/**
* Updates the parameters of the model.
*
* @param model Model to update
* @param deltaTimeSeconds Current time in seconds
*/
void UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds);
private:
CubismEyeBlink(ICubismModelSetting* modelSetting);
virtual ~CubismEyeBlink();
csmFloat32 DetermineNextBlinkingTiming() const;
csmInt32 _blinkingState;
csmVector<CubismIdHandle> _parameterIds;
csmFloat32 _nextBlinkingTime;
csmFloat32 _stateStartTimeSeconds;
csmFloat32 _blinkingIntervalSeconds;
csmFloat32 _closingSeconds;
csmFloat32 _closedSeconds;
csmFloat32 _openingSeconds;
csmFloat32 _userTimeSeconds;
};
}}}
+330
View File
@@ -0,0 +1,330 @@
/**
* 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 "CubismPose.hpp"
#include "Id/CubismIdManager.hpp"
using namespace Live2D::Cubism::Framework;
namespace Live2D { namespace Cubism { namespace Framework {
namespace {
const csmFloat32 Epsilon= 0.001f;
const csmFloat32 DefaultFadeInSeconds = 0.5f;
// Pose.jsonのタグ
const csmChar* FadeIn = "FadeInTime";
const csmChar* Link = "Link";
const csmChar* Groups = "Groups";
const csmChar* Id = "Id";
}
CubismPose::PartData::PartData()
{ }
CubismPose::PartData::~PartData()
{ }
CubismPose::PartData::PartData(const PartData& v)
: ParameterIndex(0)
, PartIndex(0)
{
PartId = v.PartId;
for (csmVector<PartData>::const_iterator ite = v.Link.Begin(); ite != v.Link.End(); ++ite)
{
Link.PushBack(*ite);
}
}
CubismPose::PartData& CubismPose::PartData::operator=(const PartData& v)
{
PartId = v.PartId;
for (csmVector<PartData>::const_iterator ite = v.Link.Begin(); ite != v.Link.End(); ++ite)
{
Link.PushBack(*ite);
}
return (*this);
}
void CubismPose::PartData::Initialize(CubismModel* model)
{
ParameterIndex = model->GetParameterIndex(PartId);
PartIndex = model->GetPartIndex(PartId);
model->SetParameterValue(ParameterIndex, 1);
}
CubismPose::CubismPose() : _fadeTimeSeconds(DefaultFadeInSeconds)
, _lastModel(NULL)
{ }
CubismPose::~CubismPose()
{ }
CubismPose* CubismPose::Create(const csmByte* pose3json, csmSizeInt size)
{
Utils::CubismJson* json = Utils::CubismJson::Create(pose3json, size);
if (!json)
{
return NULL;
}
CubismPose* ret = CSM_NEW CubismPose();
Utils::Value& root = json->GetRoot();
// フェード時間の指定
if (!root[FadeIn].IsNull())
{
ret->_fadeTimeSeconds = root[FadeIn].ToFloat(DefaultFadeInSeconds);
if (ret->_fadeTimeSeconds < 0.0f)
{
ret->_fadeTimeSeconds = DefaultFadeInSeconds;
}
}
// パーツグループ
Utils::Value& poseListInfo = root[Groups];
const csmInt32 poseCount = poseListInfo.GetSize();
for (csmInt32 poseIndex = 0; poseIndex < poseCount; ++poseIndex)
{
Utils::Value& idListInfo = poseListInfo[poseIndex];
const csmInt32 idCount = idListInfo.GetSize();
csmInt32 groupCount = 0;
for (csmInt32 groupIndex = 0; groupIndex < idCount; ++groupIndex)
{
Utils::Value& partInfo = idListInfo[groupIndex];
PartData partData;
const CubismIdHandle parameterId = CubismFramework::GetIdManager()->GetId(partInfo[Id].GetRawString());
partData.PartId = parameterId;
// リンクするパーツの設定
if (!partInfo[Link].IsNull())
{
Utils::Value& linkListInfo = partInfo[Link];
const csmInt32 linkCount = linkListInfo.GetSize();
for (csmInt32 linkIndex = 0; linkIndex < linkCount; ++linkIndex)
{
PartData linkPart;
const CubismIdHandle linkId = CubismFramework::GetIdManager()->GetId(linkListInfo[linkIndex].GetString());
linkPart.PartId = linkId;
partData.Link.PushBack(linkPart);
}
}
ret->_partGroups.PushBack(partData);
++groupCount;
}
ret->_partGroupCounts.PushBack(groupCount);
}
Utils::CubismJson::Delete(json);
return ret;
}
void CubismPose::Delete(CubismPose* pose)
{
CSM_DELETE_SELF(CubismPose, pose);
}
void CubismPose::Reset(CubismModel* model)
{
csmInt32 beginIndex = 0;
for (csmUint32 i = 0; i < _partGroupCounts.GetSize(); ++i)
{
const csmInt32 groupCount = _partGroupCounts[i];
for (csmInt32 j = beginIndex; j < beginIndex + groupCount; ++j)
{
_partGroups[j].Initialize(model);
const csmInt32 partsIndex = _partGroups[j].PartIndex;
const csmInt32 paramIndex = _partGroups[j].ParameterIndex;
if (partsIndex < 0)
{
continue;
}
model->SetPartOpacity( partsIndex, (j == beginIndex ? 1.0f : 0.0f));
model->SetParameterValue( paramIndex, (j == beginIndex ? 1.0f : 0.0f));
for (csmUint32 k = 0; k < _partGroups[j].Link.GetSize(); ++k)
{
_partGroups[j].Link[k].Initialize(model);
}
}
beginIndex += groupCount;
}
}
void CubismPose::CopyPartOpacities(CubismModel* model)
{
for (csmUint32 groupIndex = 0; groupIndex < _partGroups.GetSize(); ++groupIndex)
{
PartData& partData = _partGroups[groupIndex];
if (partData.Link.GetSize() == 0)
{
continue; // 連動するパラメータはない
}
const csmInt32 partIndex = _partGroups[groupIndex].PartIndex;
const csmFloat32 opacity = model->GetPartOpacity(partIndex);
for (csmUint32 linkIndex = 0; linkIndex < partData.Link.GetSize(); ++linkIndex)
{
PartData& linkPart = partData.Link[linkIndex];
const csmInt32 linkPartIndex = linkPart.PartIndex;
if (linkPartIndex < 0)
{
continue;
}
model->SetPartOpacity(linkPartIndex, opacity);
}
}
}
void CubismPose::DoFade(CubismModel* model, csmFloat32 deltaTimeSeconds, csmInt32 beginIndex, csmInt32 partGroupCount)
{
csmInt32 visiblePartIndex = -1;
csmFloat32 newOpacity = 1.0f;
const csmFloat32 Phi = 0.5f;
const csmFloat32 BackOpacityThreshold = 0.15f;
// 現在、表示状態になっているパーツを取得
for (csmInt32 i = beginIndex; i < beginIndex + partGroupCount; ++i)
{
const csmInt32 partIndex = _partGroups[i].PartIndex;
const csmInt32 paramIndex = _partGroups[i].ParameterIndex;
if (model->GetParameterValue(paramIndex) > Epsilon)
{
if (visiblePartIndex >= 0)
{
break;
}
visiblePartIndex = i;
if (_fadeTimeSeconds == 0.0f)
{
newOpacity = 1.0f;
continue;
}
newOpacity = model->GetPartOpacity(partIndex);
// 新しい不透明度を計算
newOpacity += (deltaTimeSeconds / _fadeTimeSeconds);
if (newOpacity > 1.0f)
{
newOpacity = 1.0f;
}
}
}
if (visiblePartIndex < 0)
{
visiblePartIndex = 0;
newOpacity = 1.0f;
}
// 表示パーツ、非表示パーツの不透明度を設定する
for (csmInt32 i = beginIndex; i < beginIndex + partGroupCount; ++i)
{
const csmInt32 partsIndex = _partGroups[i].PartIndex;
// 表示パーツの設定
if (visiblePartIndex == i)
{
model->SetPartOpacity(partsIndex, newOpacity); // 先に設定
}
// 非表示パーツの設定
else
{
csmFloat32 opacity = model->GetPartOpacity(partsIndex);
csmFloat32 a1; // 計算によって求められる不透明度
if (newOpacity < Phi)
{
a1 = newOpacity * (Phi - 1) / Phi + 1.0f; // (0,1),(phi,phi)を通る直線式
}
else
{
a1 = (1 - newOpacity) * Phi / (1.0f - Phi); // (1,0),(phi,phi)を通る直線式
}
// 背景の見える割合を制限する場合
const csmFloat32 backOpacity = (1.0f - a1) * (1.0f - newOpacity);
if (backOpacity > BackOpacityThreshold)
{
a1 = 1.0f - BackOpacityThreshold / (1.0f - newOpacity);
}
if (opacity > a1)
{
opacity = a1; // 計算の不透明度よりも大きければ(濃ければ)不透明度を上げる
}
model->SetPartOpacity(partsIndex, opacity);
}
}
}
void CubismPose::UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds)
{
// 前回のモデルと同じではないときは初期化が必要
if (model != _lastModel)
{
// パラメータインデックスの初期化
Reset(model);
}
_lastModel = model;
// 設定から時間を変更すると、経過時間がマイナスになることがあるので、経過時間0として対応。
if (deltaTimeSeconds < 0.0f)
{
deltaTimeSeconds = 0.0f;
}
csmInt32 beginIndex = 0;
for (csmUint32 i = 0; i < _partGroupCounts.GetSize(); i++)
{
const csmInt32 partGroupCount = _partGroupCounts[i];
DoFade(model, deltaTimeSeconds, beginIndex, partGroupCount);
beginIndex += partGroupCount;
}
CopyPartOpacities(model);
}
}}}
+107
View File
@@ -0,0 +1,107 @@
/**
* 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 "Utils/CubismJson.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the management of model part opacities using pose settings
*/
class CubismPose
{
public:
/**
* Handles data related to parts
*/
struct PartData
{
/**
* Constructor
*/
PartData();
/**
* Copy constructor
*/
PartData(const PartData& v);
/**
* Destructor
*/
virtual ~PartData();
/**
* Overloads assignment
*/
PartData& operator=(const PartData& v);
/**
* Initializes.
*
* @param model Model used for initialization
*/
void Initialize(CubismModel* model);
CubismIdHandle PartId; ///< Part ID
csmInt32 ParameterIndex; ///< Parameter index
csmInt32 PartIndex; ///< Part index
csmVector<PartData> Link; ///< Attached parameter
};
/**
* Makes an instance of CubismPose.
*
* @param pose3json Buffer where the pose settings file is loaded
* @param size Size of the buffer in bytes
*
* @return Maked instance of CubismPose
*/
static CubismPose* Create(const csmByte* pose3json, csmSizeInt size);
/**
* Destroys an instance of CubismPose.
*
* @param pose Instance of CubismPose to destroy
*/
static void Delete(CubismPose* pose);
/**
* Updates the parameters of the model.
*
* @param model Model to update
* @param deltaTimeSeconds Current time in seconds
*/
void UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds);
/**
* Resets the state.
*
* @param model Model to reset
*
* @note Parameters with an initial opacity value other than 0 will have their opacity set to 1.
*/
void Reset(CubismModel* model);
private:
CubismPose();
virtual ~CubismPose();
void CopyPartOpacities(CubismModel* model);
void DoFade(CubismModel* model, csmFloat32 deltaTimeSeconds, csmInt32 beginIndex, csmInt32 partGroupCount);
csmVector<PartData> _partGroups;
csmVector<csmInt32> _partGroupCounts;
csmFloat32 _fadeTimeSeconds;
CubismModel* _lastModel;
};
}}}
+61
View File
@@ -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.
*/
#pragma once
#include "Type/CubismBasicType.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* An interface to implement memory allocation and deallocation processes<br>
* on the platform side and call from the Framework.
*/
class ICubismAllocator
{
public:
/**
* Destructor
*/
virtual ~ICubismAllocator() {}
/**
* Allocates the memory.
*
* @param size Desired amount of memory in bytes
*
* @return Pointer to the allocated memory if succeeded; otherwise `0`
*/
virtual void* Allocate(const csmSizeType size) = 0;
/**
* Deallocates the memory.
*
* @param memory Pointer to allocated memory to be deallocated
*/
virtual void Deallocate(void* memory) = 0;
/**
* Allocates the memory with specified alignment.
*
* @param size Desired amount of memory in bytes
* @param alignment Desired alignment of memory in bytes
*
* @return Pointer to the allocated memory if succeeded; otherwise `0`
*/
virtual void* AllocateAligned(const csmSizeType size, const csmUint32 alignment) = 0;
/**
* Deallocates the aligned memory.
*
* @param alignedMemory Pointer to allocated memory to be deallocated
*/
virtual void DeallocateAligned(void* alignedMemory) = 0;
};
}}}
@@ -0,0 +1,244 @@
/**
* 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 "CubismFramework.hpp"
#include "Type/csmMap.hpp"
#include "Id/CubismId.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* An interface that covers the settings defined in the Model Settings File.
*
* @note Inherit this interface if you need to extend model settings or implement a class that uses model settings.
*/
class ICubismModelSetting
{
public:
/**
* Destructor
*/
virtual ~ICubismModelSetting() {}
/**
* Returns the file name of MOC3 File.
*
* @return Name of MOC3 File
*/
virtual const csmChar* GetModelFileName() = 0;
/**
* Returns the number of textures in the Model.
*
* @return Number of textures
*/
virtual csmInt32 GetTextureCount() = 0;
/**
* Returns the name of directory that texture is placed.
*
* @return Name of directory
*/
virtual const csmChar* GetTextureDirectory() = 0;
/**
* Returns the name of texture in the Model.
*
* @param index Index to the desired texture name
*
* @return Name of texture
*/
virtual const csmChar* GetTextureFileName(csmInt32 index) = 0;
/**
* Returns the number of Hit Area settings in the Model.
*
* @return Number of Hit Area settings
*/
virtual csmInt32 GetHitAreasCount() = 0;
/**
* Returns whether ID of Drawable that is set for the Hit Area.
*
* @param groupName Name of the desired Motion Group
*
* @return true if Motion Group information exists; otherwise false
*/
virtual CubismIdHandle GetHitAreaId(csmInt32 index) = 0;
/**
* Returns the name of Hit Area.
*
* @param index Index to the desired Hit Area
*
* @return Name of Hit Area
*/
virtual const csmChar* GetHitAreaName(csmInt32 index) = 0;
/**
* Returns the name of Physics Settings File in the Model.
*
* @return Name of Physics Settings File
*/
virtual const csmChar* GetPhysicsFileName() = 0;
/**
* Returns the name of Pose Settings File in the Model.
*
* @return Name of Pose Settings File
*/
virtual const csmChar* GetPoseFileName() = 0;
/**
* Returns the name of Display Settings File in the Model.
*
* @return Name of Display Settings File
*/
virtual const csmChar* GetDisplayInfoFileName() = 0;
/**
* Returns the number of expressions in the Model.
*
* @return Number of expressions
*/
virtual csmInt32 GetExpressionCount() = 0;
/**
* Returns the name of expression.
*
* @param index Index to the desired expression
*
* @return Name of expression
*/
virtual const csmChar* GetExpressionName(csmInt32 index) = 0;
/**
* Returns the name of Expression Settings File from the expression.
*
* @param index Index to the desired expression
*
* @return Name of Expression Settings File
*/
virtual const csmChar* GetExpressionFileName(csmInt32 index) = 0;
/**
* Returns the number of Motion Groups in the Model.
*
* @return Number of Motion Groups
*/
virtual csmInt32 GetMotionGroupCount() = 0;
/**
* Returns the name of Motion Group.
*
* @param index Index to the desired Motion Group
*
* @return Name of Motion Group
*/
virtual const csmChar* GetMotionGroupName(csmInt32 index) = 0;
/**
* Returns the number of Motions in the Motion Group.
*
* @param groupName Name to the desired Motion Group
*
* @return Number of Motions
*/
virtual csmInt32 GetMotionCount(const csmChar* groupName) = 0;
/**
* Returns the file name of Motion File in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired motion
*
* @return Name of Motion File
*/
virtual const csmChar* GetMotionFileName(const csmChar* groupName, csmInt32 index) = 0;
/**
* Returns the name of Audio File attached to the Motion in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Name of Audio File
*/
virtual const csmChar* GetMotionSoundFileName(const csmChar* groupName, csmInt32 index) = 0;
/**
* Returns the Fade-in time at the start of the Motion in the Motion Group
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Fade-in time [sec]
*/
virtual csmFloat32 GetMotionFadeInTimeValue(const csmChar* groupName, csmInt32 index) = 0;
/**
* Returns the Fade-out time at the end of the Motion in the Motion Group.
*
* @param groupName Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Fade-out time [sec]
*/
virtual csmFloat32 GetMotionFadeOutTimeValue(const csmChar* groupName, csmInt32 index) = 0;
/**
* Returns the name of User Data File in the Model.
*
* @return Name of User Data File
*/
virtual const csmChar* GetUserDataFile() = 0;
/**
* Returns the Layout Information set in the model.
*
* @param outLayoutMap Instance of a collection to store
*
* @return true if Layout Information exists; otherwise false
*/
virtual csmBool GetLayoutMap(csmMap<csmString, csmFloat32>& outLayoutMap) = 0;
/**
* Returns the number of parameters attached to the Eye Blinking Settings.
*
* @return Number of parameters
*/
virtual csmInt32 GetEyeBlinkParameterCount() = 0;
/**
* Returns the ID of parameter attached to the Eye Blinking Settings.
*
* @param index Index to the desired parameter
*
* @return ID of parameter
*/
virtual CubismIdHandle GetEyeBlinkParameterId(csmInt32 index) = 0;
/**
* Returns the number of parameters attached to the Lip-sync Settings.
*
* @return Number of parameters
*/
virtual csmInt32 GetLipSyncParameterCount() = 0;
/**
* Returns the ID of parameter attached to the Lip-sync Settings.
*
* @param index Index to the desired parameter
*
* @return ID of parameter
*/
virtual CubismIdHandle GetLipSyncParameterId(csmInt32 index) = 0;
};
}}}
+7
View File
@@ -0,0 +1,7 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismId.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismId.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismIdManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismIdManager.hpp
)
+53
View File
@@ -0,0 +1,53 @@
/**
* 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 "CubismId.hpp"
#include "Type/CubismBasicType.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismId::CubismId()
{ }
CubismId::CubismId(const CubismId& c)
: _id(c._id)
{ }
CubismId::CubismId(const csmChar* id)
{
_id = id;
}
CubismId::~CubismId()
{ }
CubismId& CubismId::operator=(const CubismId& c)
{
if (this != &c)
{
_id = c._id;
}
return *this;
}
csmBool CubismId::operator==(const CubismId& c) const
{
return (_id == c._id);
}
csmBool CubismId::operator!=(const CubismId& c) const
{
return !(_id == c._id);
}
const csmString& CubismId::GetString() const
{
return _id;
}
}}}
+71
View File
@@ -0,0 +1,71 @@
/**
* 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"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismIdManager;
/**
* Handles the ID of parameters, parts, and drawing objects.
*/
struct CubismId
{
friend class CubismIdManager;
/**
* Returns the ID.
*
* @return ID
*/
const csmString& GetString() const;
/**
* Assigns the ID held by another CubismId to this ID.
*
* @param c CubismId object to assign
*
* @return Reference to this object after assignment
*/
CubismId& operator=(const CubismId& c);
/**
* Compares if the ID held by another CubismId is equal to the ID held by this object.
*
* @param c CubismId object to compare
*
* @return true if the IDs are equal; otherwise false.
*/
csmBool operator==(const CubismId& c) const;
/**
* Compares if the ID held by another CubismId is not equal to the ID held by this object.
*
* @param c CubismId object to compare
*
* @return true if the IDs are not equal; otherwise false.
*/
csmBool operator!=(const CubismId& c) const;
private:
CubismId();
CubismId(const csmChar* id);
~CubismId();
CubismId(const CubismId& c);
csmString _id;
};
typedef const CubismId* CubismIdHandle;
}}}
@@ -0,0 +1,92 @@
/**
* 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 "CubismIdManager.hpp"
#include "CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismIdManager::CubismIdManager()
{ }
CubismIdManager::~CubismIdManager()
{
for (csmUint32 i = 0; i < _ids.GetSize(); ++i)
{
CSM_DELETE_SELF(CubismId, _ids[i]);
}
}
void CubismIdManager::RegisterIds(const csmChar** ids, csmInt32 count)
{
for (csmInt32 i = 0; i < count; ++i)
{
RegisterId(ids[i]);
}
}
void CubismIdManager::RegisterIds(const csmVector<csmString>& ids)
{
for (csmUint32 i = 0; i < ids.GetSize(); ++i)
{
RegisterId(ids[i]);
}
}
const CubismId* CubismIdManager::GetId(const csmString& id)
{
return RegisterId(id.GetRawString());
}
const CubismId* CubismIdManager::GetId(const csmChar* id)
{
return RegisterId(id);
}
csmBool CubismIdManager::IsExist(const csmString& id) const
{
return IsExist(id.GetRawString());
}
csmBool CubismIdManager::IsExist(const csmChar* id) const
{
return (FindId(id) != NULL);
}
const CubismId* CubismIdManager::RegisterId(const csmChar* id)
{
CubismId* result = NULL;
if ((result = FindId(id)) != NULL)
{
return result;
}
result = CSM_NEW CubismId(id);
_ids.PushBack(result);
return result;
}
const CubismId* CubismIdManager::RegisterId(const csmString& id)
{
return RegisterId(id.GetRawString());
}
CubismId* CubismIdManager::FindId(const csmChar* id) const
{
for (csmUint32 i = 0; i < _ids.GetSize(); ++i)
{
if (_ids[i]->GetString() == id)
{
return _ids[i];
}
}
return NULL;
}
}}}
+117
View File
@@ -0,0 +1,117 @@
/**
* 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"
#include "Type/csmString.hpp"
#include "Type/csmVector.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
struct CubismId;
/**
* Handles ID names.
*/
class CubismIdManager
{
friend struct CubismId;
public:
/**
* Constructor
*/
CubismIdManager();
/**
* Destructor
*/
~CubismIdManager();
/**
* Registers IDs.
*
* @param ids Array of ID strings
* @param count Number of IDs
*/
void RegisterIds(const csmChar** ids, csmInt32 count);
/**
* Registers IDs.
*
* @param ids Collection of ID strings
*/
void RegisterIds(const csmVector<csmString>& ids);
/**
* Registers an ID.
*
* @param id ID string
*/
const CubismId* RegisterId(const csmChar* id);
/**
* Registers an ID.
*
* @param id ID string
*
* @return Registered ID<br>
* If the ID was already registered, the already registered ID
*/
const CubismId* RegisterId(const csmString& id);
/**
* Returns an ID.
*
* @param id ID string
*
* @return ID
*
* @note If the ID is not registered, it registers the ID.
*/
const CubismId* GetId(const csmString& id);
/**
* Returns an ID.
*
* @param id ID string
*
* @return ID
*
* @note If the requested ID is not registered, it registers the ID.
*/
const CubismId* GetId(const csmChar* id);
/**
* Checks if an ID is registered.
*
* @param id ID string to check
*
* @return true if the ID is registered; otherwise false.
*/
csmBool IsExist(const csmString& id) const;
/**
* Checks if an ID is registered.
*
* @param id ID string to check
*
* @return true if the ID is registered; otherwise false.
*/
csmBool IsExist(const csmChar* id) const;
private:
CubismIdManager(const CubismIdManager&);
CubismIdManager& operator=(const CubismIdManager&);
CubismId* FindId(const csmChar* id) const;
csmVector<CubismId*> _ids;
};
}}}
+17
View File
@@ -0,0 +1,17 @@
/**
* 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
/**
* Header to include the Live2D Cubism Core in the `Live2D::Cubism::Core` namespace
*
* @note Include this header instead of including the `Live2DCubismCore.h` directly.
*/
namespace Live2D { namespace Cubism { namespace Core {
#include "Live2DCubismCore.h"
}}}
+15
View File
@@ -0,0 +1,15 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismMath.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMath.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMatrix44.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMatrix44.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelMatrix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelMatrix.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismTargetPoint.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismTargetPoint.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismVector2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismVector2.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismViewMatrix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismViewMatrix.hpp
)
+216
View File
@@ -0,0 +1,216 @@
/**
* 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 "CubismMath.hpp"
#include "Utils/CubismDebug.hpp"
namespace Live2D {namespace Cubism {namespace Framework {
const csmFloat32 CubismMath::Pi = 3.1415926535897932384626433832795f;
const csmFloat32 CubismMath::Epsilon = 0.00001f;
csmInt32 CubismMath::Clamp(csmInt32 val, csmInt32 min, csmInt32 max)
{
if (val < min)
{
return min;
}
else if (max < val)
{
return max;
}
return val;
}
csmFloat32 CubismMath::ClampF(csmFloat32 val, csmFloat32 min, csmFloat32 max)
{
if (val < min)
{
return min;
}
else if (max < val)
{
return max;
}
return val;
}
csmFloat32 CubismMath::DegreesToRadian(csmFloat32 degrees)
{
return (degrees / 180.0f) * Pi;
}
csmFloat32 CubismMath::RadianToDegrees(csmFloat32 radian)
{
return (radian * 180.0f) / Pi;
}
csmFloat32 CubismMath::DirectionToRadian(CubismVector2 from, CubismVector2 to)
{
csmFloat32 q1;
csmFloat32 q2;
csmFloat32 ret;
q1 = atan2f(to.Y, to.X);
q2 = atan2f(from.Y, from.X);
ret = q1 - q2;
while (ret < -Pi)
{
ret += Pi * 2.0f;
}
while (ret > Pi)
{
ret -= Pi * 2.0f;
}
return ret;
}
csmFloat32 CubismMath::DirectionToDegrees(CubismVector2 from, CubismVector2 to)
{
csmFloat32 radian;
csmFloat32 degree;
radian = DirectionToRadian(from, to);
degree = RadianToDegrees(radian);
if ((to.X - from.X) > 0.0f)
{
degree = -degree;
}
return degree;
}
CubismVector2 CubismMath::RadianToDirection(csmFloat32 totalAngle)
{
CubismVector2 ret;
ret.X = CubismMath::SinF(totalAngle);
ret.Y = CubismMath::CosF(totalAngle);
return ret;
}
csmFloat32 CubismMath::QuadraticEquation(csmFloat32 a, csmFloat32 b, csmFloat32 c)
{
if (CubismMath::AbsF(a) < CubismMath::Epsilon)
{
if (CubismMath::AbsF(b) < CubismMath::Epsilon)
{
return -c;
}
return -c / b;
}
return -(b + CubismMath::SqrtF(b * b - 4.0f * a * c)) / (2.0f * a);
}
csmFloat32 CubismMath::CardanoAlgorithmForBezier(csmFloat32 a, csmFloat32 b, csmFloat32 c, csmFloat32 d)
{
if ( CubismMath::AbsF( a ) < CubismMath::Epsilon )
{
return CubismMath::RangeF( QuadraticEquation(b, c, d), 0.0f, 1.0f);
}
csmFloat32 ba = b / a;
csmFloat32 ca = c / a;
csmFloat32 da = d / a;
csmFloat32 p = (3.0f * ca - ba*ba) / 3.0f;
csmFloat32 p3 = p / 3.0f;
csmFloat32 q = (2.0f * ba*ba*ba - 9.0f * ba*ca + 27.0f * da) / 27.0f;
csmFloat32 q2 = q / 2.0f;
csmFloat32 discriminant = q2*q2 + p3*p3*p3;
const csmFloat32 center = 0.5f;
const csmFloat32 threshold = center + 0.01f;
if (discriminant < 0.0f) {
csmFloat32 mp3 = -p / 3.0f;
csmFloat32 mp33 = mp3*mp3*mp3;
csmFloat32 r = CubismMath::SqrtF(mp33);
csmFloat32 t = -q / (2.0f * r);
csmFloat32 cosphi = RangeF(t, -1.0f, 1.0f);
csmFloat32 phi = acos(cosphi);
csmFloat32 crtr = cbrt(r);
csmFloat32 t1 = 2.0f * crtr;
csmFloat32 root1 = t1 * CubismMath::CosF(phi / 3.0f) - ba / 3.0f;
if ( abs( root1 - center) < threshold)
{
return RangeF( root1, 0.0f, 1.0f);
}
csmFloat32 root2 = t1 * CubismMath::CosF((phi + 2.0f * CubismMath::Pi) / 3.0f) - ba / 3.0f;
if (abs(root2 - center) < threshold)
{
return RangeF(root2, 0.0f, 1.0f);
}
csmFloat32 root3 = t1 * CubismMath::CosF((phi + 4.0f * CubismMath::Pi) / 3.0f) - ba / 3.0f;
return RangeF(root3, 0.0f, 1.0f);
}
if (discriminant == 0.0f) {
csmFloat32 u1;
if (q2 < 0.0f)
{
u1 = cbrt(-q2);
}
else
{
u1 = -cbrt(q2);
}
csmFloat32 root1 = 2.0f * u1 - ba / 3.0f;
if (abs(root1 - center) < threshold)
{
return RangeF(root1, 0.0f, 1.0f);
}
csmFloat32 root2 = -u1 - ba / 3.0f;
return RangeF(root2, 0.0f, 1.0f);
}
csmFloat32 sd = CubismMath::SqrtF(discriminant);
csmFloat32 u1 = cbrt(sd - q2);
csmFloat32 v1 = cbrt(sd + q2);
csmFloat32 root1 = u1 - v1 - ba / 3.0f;
return RangeF(root1, 0.0f, 1.0f);
}
csmFloat32 CubismMath::ModF(csmFloat32 dividend, csmFloat32 divisor)
{
if (
!isfinite(dividend) ||
divisor == 0 ||
isnan(dividend) ||
isnan(divisor)
) {
CubismLogWarning("dividend: %f, divisor: %f ModF() returns 'NaN'.", dividend, divisor);
return NAN;
}
// 絶対値に変換する。
const csmFloat32 absDividend = CubismMath::AbsF(dividend);
const csmFloat32 absDivisor = CubismMath::AbsF(divisor);
// 絶対値で割り算する。
csmFloat32 result = absDividend - floorf(absDividend / absDivisor) * absDivisor;
// 符号を被除数のものに指定する。
return copysign(result, dividend);
}
}}}
+240
View File
@@ -0,0 +1,240 @@
/**
* 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 <cmath>
#include "Type/CubismBasicType.hpp"
#include "Math/CubismVector2.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles numerical calculations and other utility functions
*/
class CubismMath
{
public:
static const csmFloat32 Pi;
static const csmFloat32 Epsilon;
/**
* Returns the value of the first argument clamped within the range of the minimum and maximum values.
*
*@param value Value to be clamped
*@param min Minimum value of the range
*@param max Maximum value of the range
*
*@return Value clamped within the range of minimum and maximum values
*/
static csmFloat32 RangeF(csmFloat32 value, csmFloat32 min, csmFloat32 max)
{
if (value < min) value = min;
else if (value > max) value = max;
return value;
};
/**
* Returns the value of the sine function.
*
*@param x Angle value in radians [rad]
*
*@return Value of the sine function sin(x)
*/
static csmFloat32 SinF(csmFloat32 x)
{
return sinf(x);
};
/**
* Returns the value of the cosine function.
*
*@param x Angle value in radians [rad]
*
*@return Value of the cosine function cos(x)
*/
static csmFloat32 CosF(csmFloat32 x)
{
return cosf(x);
};
/**
* Returns the absolute value.
*
* @param x Value to calculate the absolute value
*
* @return Absolute value of the input
*/
static csmFloat32 AbsF(csmFloat32 x)
{
return std::fabs(x);
};
/**
* Returns the square root.
*
* @param x Value to calculate the square root
*
* @return Square root of the input
*/
static csmFloat32 SqrtF(csmFloat32 x)
{
return sqrtf(x);
};
/**
* Returns the value processed with sine wave easing.<br>
* Can be used for easing during fade-in and fade-out.
*
* @param value Value to be eased
*
* @return Value processed with sine wave easing
*/
static csmFloat32 GetEasingSine(csmFloat32 value)
{
if (value < 0.0f) return 0.0f;
else if (value > 1.0f) return 1.0f;
return static_cast<csmFloat32>(0.5f - 0.5f * CosF(value * Pi));
}
/**
* Returns the greater value.
*
* @param l Left-hand value
* @param r Right-hand value
*
* @return Greater value
*/
static csmFloat32 Max(csmFloat32 l, csmFloat32 r)
{
return (l > r) ? l : r;
}
/**
* Returns the smaller value.
*
* @param l Left-hand value
* @param r Right-hand value
*
* @return Smaller value
*/
static csmFloat32 Min(csmFloat32 l, csmFloat32 r)
{
return (l > r) ? r : l;
}
/**
* Returns the value clamped within the specified range.
*
* @param val Value to be clamped within the range
* @param min Minimum value
* @param max Maximum value
* @return Clamped value within the range
*/
static csmInt32 Clamp(csmInt32 val, csmInt32 min, csmInt32 max);
/**
* Returns the value clamped within the specified range.
*
* @param val Value to be checked within the range
* @param min Minimum value
* @param max Maximum value
* @return Clamped value within the range
*/
static csmFloat32 ClampF(csmFloat32 val, csmFloat32 min, csmFloat32 max);
/**
* Converts an angle from degrees to radians.
*
* @param degrees Angle in degrees [degree]
*
* @return Angle in radians [rad]
*/
static csmFloat32 DegreesToRadian(csmFloat32 degrees);
/**
* Converts an angle from radians to degrees.
*
* @param radian Angle in radians [rad]
*
* @return Angle in degrees [degree]
*/
static csmFloat32 RadianToDegrees(csmFloat32 radian);
/**
* Calculates the angle between two vectors.
*
* @param from Starting vector
* @param to Ending vector
*
* @return Angle in radians [rad]
*/
static csmFloat32 DirectionToRadian(CubismVector2 from, CubismVector2 to);
/**
* Calculates the angle between two vectors.
*
* @param from Starting vector
* @param to Ending vector
*
* @return Angle in radians [rad]
*/
static csmFloat32 DirectionToDegrees(CubismVector2 from, CubismVector2 to);
/**
* Calculates the direction vector from an angle.
*
* @param totalAngle Angle in radians [rad]
*
* @return Direction vector
*/
static CubismVector2 RadianToDirection(csmFloat32 totalAngle);
/**
* Finds the solution of a quadratic equation when the cubic coefficient of the cubic equation is zero.<br>
* a * x^2 + b * x + c = 0
*
* @param a Coefficient of the quadratic term
* @param b Coefficient of the linear term
* @param c Constant term
*
* @return Solution of the quadratic equation
*/
static csmFloat32 QuadraticEquation(csmFloat32 a, csmFloat32 b, csmFloat32 c);
/**
* Finds the solution of a cubic equation corresponding to the Bezier's t-value using Cardano's formula.<br>
* Returns the solution in the range 0.0-1.0 when it is a multiple root.<br>
* a * x^3 + b * x^2 + c * x + d = 0
*
* @param a Coefficient of the cubic term
* @param b Coefficient of the quadratic term
* @param c Coefficient of the linear term
* @param d Constant term
*
* @return Solution in the range 0.0-1.0
*/
static csmFloat32 CardanoAlgorithmForBezier(csmFloat32 a, csmFloat32 b, csmFloat32 c, csmFloat32 d);
/**
* Calculates the remainder of a floating-point division.
*
* @param dividend Dividend (value to be divided)
* @param divisor Divisor (value to divide by)
* @return Remainder
*/
static csmFloat32 ModF(csmFloat32 dividend, csmFloat32 divisor);
private:
CubismMath();
};
}}}
//--------- LIVE2D NAMESPACE ------------
@@ -0,0 +1,161 @@
/**
* 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 "CubismMatrix44.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismMatrix44::CubismMatrix44()
{
LoadIdentity();
}
CubismMatrix44::~CubismMatrix44()
{ }
void CubismMatrix44::LoadIdentity()
{
csmFloat32 c[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
SetMatrix(c);
}
csmFloat32* CubismMatrix44::GetArray()
{
return _tr;
}
void CubismMatrix44::Multiply(csmFloat32* a, csmFloat32* b, csmFloat32* dst)
{
csmFloat32 c[16] = {
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
csmInt32 n = 4;
for (csmInt32 i = 0; i < n; ++i)
{
for (csmInt32 j = 0; j < n; ++j)
{
for (csmInt32 k = 0; k < n; ++k)
{
c[j + i * 4] += a[k + i * 4] * b[j + k * 4];
}
}
}
for (csmInt32 i = 0; i < 16; ++i)
{
dst[i] = c[i];
}
}
void CubismMatrix44::TranslateRelative(csmFloat32 x, csmFloat32 y)
{
csmFloat32 tr1[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
x, y, 0.0f, 1.0f
};
Multiply(tr1, _tr, _tr);
}
void CubismMatrix44::Translate(csmFloat32 x, csmFloat32 y)
{
_tr[12] = x;
_tr[13] = y;
}
void CubismMatrix44::ScaleRelative(csmFloat32 x, csmFloat32 y)
{
csmFloat32 tr1[16] = {
x, 0.0f, 0.0f, 0.0f,
0.0f, y, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
Multiply(tr1, _tr, _tr);
}
void CubismMatrix44::Scale(csmFloat32 x, csmFloat32 y)
{
_tr[0] = x;
_tr[5] = y;
}
csmFloat32 CubismMatrix44::TransformX(csmFloat32 src)
{
return _tr[0] * src + _tr[12];
}
csmFloat32 CubismMatrix44::InvertTransformX(csmFloat32 src)
{
return (src - _tr[12]) / _tr[0];
}
csmFloat32 CubismMatrix44::TransformY(csmFloat32 src)
{
return _tr[5] * src + _tr[13];
}
csmFloat32 CubismMatrix44::InvertTransformY(csmFloat32 src)
{
return (src - _tr[13]) / _tr[5];
}
void CubismMatrix44::SetMatrix(csmFloat32* tr)
{
for (csmInt32 i = 0; i < 16; ++i)
{
_tr[i] = tr[i];
}
}
csmFloat32 CubismMatrix44::GetScaleX() const
{
return _tr[0];
}
csmFloat32 CubismMatrix44::GetScaleY() const
{
return _tr[5];
}
csmFloat32 CubismMatrix44::GetTranslateX() const
{
return _tr[12];
}
csmFloat32 CubismMatrix44::GetTranslateY() const
{
return _tr[13];
}
void CubismMatrix44::TranslateX(csmFloat32 x)
{
_tr[12] = x;
}
void CubismMatrix44::TranslateY(csmFloat32 y)
{
_tr[13] = y;
}
void CubismMatrix44::MultiplyByMatrix(CubismMatrix44* m)
{
Multiply(m->GetArray(), _tr, _tr);
}
}}}
@@ -0,0 +1,179 @@
/**
* 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"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles 4x4 matrices
*/
class CubismMatrix44
{
public:
/**
* Constructor
*/
CubismMatrix44();
/**
* Destructor
*/
virtual ~CubismMatrix44();
/**
* Multiplies the two given matrices and stores the result in the destination matrix.
*
* @param a Matrix a
* @param b Matrix b
* @param dst Destination matrix for storing the result
*/
static void Multiply(csmFloat32* a, csmFloat32* b, csmFloat32* dst);
/**
* Sets the identity matrix.
*/
void LoadIdentity();
/**
* Returns the matrix as an array of floating-point numbers.
*
* @return 4x4 matrix represented by 16 floating-point numbers
*/
csmFloat32* GetArray();
/**
* Sets the matrix.
*
* @param tr 4x4 matrix represented by 16 floating-point numbers
*/
void SetMatrix(csmFloat32* tr);
/**
* Returns the scaling factor along the X-axis.
*
* @return Scaling factor along the X-axis
*/
csmFloat32 GetScaleX() const;
/**
* Returns the scaling factor along the Y-axis.
*
* @return Scaling factor along the Y-axis
*/
csmFloat32 GetScaleY() const;
/**
* Returns the translation value along the X-axis.
*
* @return Translation value along the X-axis
*/
csmFloat32 GetTranslateX() const;
/**
* Returns the translation value along the Y-axis.
*
* @return Translation value along the Y-axis
*/
csmFloat32 GetTranslateY() const;
/**
* Calculates the value along the X-axis using the current matrix.
*
* @param src Value along the X-axis
*
* @return Calculated value along the X-axis using the current matrix
*/
csmFloat32 TransformX(csmFloat32 src);
/**
* Calculates the value along the Y-axis using the current matrix.
*
* @param src Value along the Y-axis
*
* @return Calculated value along the Y-axis using the current matrix
*/
csmFloat32 TransformY(csmFloat32 src);
/**
* Calculates the inverse value along the X-axis using the current matrix.
*
* @param src Value along the X-axis
*
* @return Calculated inverse value along the X-axis using the current matrix
*/
csmFloat32 InvertTransformX(csmFloat32 src);
/**
* Calculates the inverse value along the Y-axis using the current matrix.
*
* @param src Value along the Y-axis
*
* @return Calculated inverse value along the Y-axis using the current matrix
*/
csmFloat32 InvertTransformY(csmFloat32 src);
/**
* Moves relatively based on the current matrix position.
*
* @param x Translation amount along the X-axis
* @param y Translation amount along the Y-axis
*/
void TranslateRelative(csmFloat32 x, csmFloat32 y);
/**
* Moves the current matrix position to the specified location.
*
* @param x Translation value along the X-axis
* @param y Translation value along the Y-axis
*/
void Translate(csmFloat32 x, csmFloat32 y);
/**
* Moves the current matrix position along the X-axis to the specified location.
*
* @param x Translation value along the X-axis
*/
void TranslateX(csmFloat32 x);
/**
* Moves the current matrix position along the Y-axis to the specified location.
*
* @param x Translation value along the Y-axis
*/
void TranslateY(csmFloat32 y);
/**
* Sets the scaling factor relative to the current matrix.
*
* @param x Scaling factor along the X-axis
* @param y Scaling factor along the Y-axis
*/
void ScaleRelative(csmFloat32 x, csmFloat32 y);
/**
* Sets the scaling factor of the current matrix to the specified value.
*
* @param x Scaling factor along the X-axis
* @param y Scaling factor along the Y-axis
*/
void Scale(csmFloat32 x, csmFloat32 y);
/**
* Multiplies the current matrix by the given matrix.
*
* @param m Matrix to multiply with the current matrix
*/
void MultiplyByMatrix(CubismMatrix44* m);
protected:
csmFloat32 _tr[16];
};
}}}
@@ -0,0 +1,166 @@
/**
* 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 "CubismModelMatrix.hpp"
#include "Type/csmString.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismModelMatrix::CubismModelMatrix()
: _width(0.0f)
, _height(0.0f)
{ }
CubismModelMatrix::CubismModelMatrix(csmFloat32 w, csmFloat32 h)
{
_width = w;
_height = h;
SetHeight(2.0f);
}
CubismModelMatrix::~CubismModelMatrix()
{ }
void CubismModelMatrix::SetCenterPosition(csmFloat32 x, csmFloat32 y)
{
CenterX(x);
CenterY(y);
}
void CubismModelMatrix::Bottom(csmFloat32 y)
{
const csmFloat32 h = _height * GetScaleY();
TranslateY(y - h);
}
void CubismModelMatrix::CenterY(csmFloat32 y)
{
const csmFloat32 h = _height * GetScaleY();
TranslateY(y - (h / 2.0f));
}
void CubismModelMatrix::Right(csmFloat32 x)
{
const csmFloat32 w = _width * GetScaleX();
TranslateX(x - w);
}
void CubismModelMatrix::CenterX(csmFloat32 x)
{
const csmFloat32 w = _width * GetScaleX();
TranslateX(x - (w / 2.0f));
}
void CubismModelMatrix::SetWidth(csmFloat32 w)
{
const csmFloat32 scaleX = w / _width;
const csmFloat32 scaleY = scaleX;
Scale(scaleX, scaleY);
}
void CubismModelMatrix::SetHeight(csmFloat32 h)
{
const csmFloat32 scaleX = h / _height;
const csmFloat32 scaleY = scaleX;
Scale(scaleX, scaleY);
}
void CubismModelMatrix::SetupFromLayout(csmMap<csmString, csmFloat32>& layout)
{
const csmChar* KeyWidth = "width";
const csmChar* KeyHeight = "height";
const csmChar* KeyX = "x";
const csmChar* KeyY = "y";
const csmChar* KeyCenterX = "center_x";
const csmChar* KeyCenterY = "center_y";
const csmChar* KeyTop = "top";
const csmChar* KeyBottom = "bottom";
const csmChar* KeyLeft = "left";
const csmChar* KeyRight = "right";
for (csmMap<csmString, csmFloat32>::const_iterator ite = layout.Begin(); ite != layout.End(); ++ite)
{
const csmString key = ite->First;
const csmFloat32 value = ite->Second;
if (key == KeyWidth)
{
SetWidth(value);
}
else if (key == KeyHeight)
{
SetHeight(value);
}
}
for (csmMap<csmString, csmFloat32>::const_iterator ite = layout.Begin(); ite != layout.End(); ++ite)
{
const csmString key = ite->First;
const csmFloat32 value = ite->Second;
if (key == KeyX)
{
SetX(value);
}
else if (key == KeyY)
{
SetY(value);
}
else if (key == KeyCenterX)
{
CenterX(value);
}
else if (key == KeyCenterY)
{
CenterY(value);
}
else if (key == KeyTop)
{
Top(value);
}
else if (key == KeyBottom)
{
Bottom(value);
}
else if (key == KeyLeft)
{
Left(value);
}
else if (key == KeyRight)
{
Right(value);
}
}
}
void CubismModelMatrix::SetPosition(csmFloat32 x, csmFloat32 y)
{
Translate(x, y);
}
void CubismModelMatrix::Top(csmFloat32 y)
{
SetY(y);
}
void CubismModelMatrix::Left(csmFloat32 x)
{
SetX(x);
}
void CubismModelMatrix::SetX(csmFloat32 x)
{
TranslateX(x);
}
void CubismModelMatrix::SetY(csmFloat32 y)
{
TranslateY(y);
}
}}}
@@ -0,0 +1,139 @@
/**
* 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 "CubismMatrix44.hpp"
#include "Type/csmMap.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles 4x4 matrices for setting model coordinates
*/
class CubismModelMatrix : public CubismMatrix44
{
public:
/**
* Constructor
*/
CubismModelMatrix();
/**
* Constructor<br>
* Creates with specified width and height.
*
* @param w Width
* @param h Height
*/
CubismModelMatrix(csmFloat32 w, csmFloat32 h);
/**
* Destructor
*/
virtual ~CubismModelMatrix();
/**
* Sets the width.
*
* @param w Width
*/
void SetWidth(csmFloat32 w);
/**
* Sets the height.
*
* @param h Height
*/
void SetHeight(csmFloat32 h);
/**
* Sets the position.
*
* @param x Position along the X-axis
* @param y Position along the Y-axis
*/
void SetPosition(csmFloat32 x, csmFloat32 y);
/**
* Sets the center position.
*
* @param x Center position along the X-axis
* @param y Center position along the Y-axis
*
* @note Must be set after setting width or height to ensure correct scaling.
*/
void SetCenterPosition(csmFloat32 x, csmFloat32 y);
/**
* Sets the position of the top edge.
*
* @param y Y-axis position of the top edge
*/
void Top(csmFloat32 y);
/**
* Sets the position of the bottom edge.
*
* @param y Y-axis position of the bottom edge
*/
void Bottom(csmFloat32 y);
/**
* Sets the position of the left edge.
*
* @param x X-axis position of the left edge
*/
void Left(csmFloat32 x);
/**
* Sets the position of the right edge.
*
* @param x X-axis position of the right edge
*/
void Right(csmFloat32 x);
/**
* Sets the center position along the X-axis.
*
* @param x Center position along the X-axis
*/
void CenterX(csmFloat32 x);
/**
* Sets the position along the X-axis.
*
* @param x Position along the X-axis
*/
void SetX(csmFloat32 x);
/**
* Sets the center position along the Y-axis.
*
* @param y Center position along the Y-axis
*/
void CenterY(csmFloat32 y);
/**
* Sets the position along the Y-axis.
*
* @param y Position along the Y-axis
*/
void SetY(csmFloat32 y);
/**
* Sets the position based on layout information.
*
* @param layout Layout information
*/
void SetupFromLayout(csmMap<csmString, csmFloat32>& layout);
private:
csmFloat32 _width;
csmFloat32 _height;
};
}}}
@@ -0,0 +1,133 @@
/**
* 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 "CubismTargetPoint.hpp"
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
const csmInt32 FrameRate = 30;
const csmFloat32 Epsilon = 0.01f;
CubismTargetPoint::CubismTargetPoint()
: _faceTargetX(0.0f)
, _faceTargetY(0.0f)
, _faceX(0.0f)
, _faceY(0.0f)
, _faceVX(0.0f)
, _faceVY(0.0f)
, _lastTimeSeconds(0.0f)
, _userTimeSeconds(0.0f)
{ }
CubismTargetPoint::~CubismTargetPoint()
{ }
void CubismTargetPoint::Update(csmFloat32 deltaTimeSeconds)
{
// デルタ時間を加算する
_userTimeSeconds += deltaTimeSeconds;
// 首を中央から左右に振るときの平均的な早さは 秒程度。加速・減速を考慮して、その2倍を最高速度とする
// 顔のふり具合を、中央(0.0)から、左右は(+-1.0)とする
const csmFloat32 FaceParamMaxV = 40.0 / 10.0f; // 7.5秒間に40分移動(5.3/sc)
const csmFloat32 MaxV = FaceParamMaxV * 1.0f / static_cast<csmFloat32>(FrameRate); // 1frameあたりに変化できる速度の上限
if (_lastTimeSeconds == 0.0f)
{
_lastTimeSeconds = _userTimeSeconds;
return;
}
const csmFloat32 deltaTimeWeight = (_userTimeSeconds - _lastTimeSeconds) * static_cast<csmFloat32>(FrameRate);
_lastTimeSeconds = _userTimeSeconds;
// 最高速度になるまでの時間を
const csmFloat32 TimeToMaxSpeed = 0.15f;
const csmFloat32 FrameToMaxSpeed = TimeToMaxSpeed * static_cast<csmFloat32>(FrameRate); // sec * frame/sec
const csmFloat32 MaxA = deltaTimeWeight * MaxV / FrameToMaxSpeed; // 1frameあたりの加速度
// 目指す向きは、(dx, dy)方向のベクトルとなる
const csmFloat32 dx = _faceTargetX - _faceX;
const csmFloat32 dy = _faceTargetY - _faceY;
if (CubismMath::AbsF(dx) <= Epsilon && CubismMath::AbsF(dy) <= Epsilon)
{
return; // 変化なし
}
// 速度の最大よりも大きい場合は、速度を落とす
const csmFloat32 d = CubismMath::SqrtF((dx * dx) + (dy * dy));
// 進行方向の最大速度ベクトル
const csmFloat32 vx = MaxV * dx / d;
const csmFloat32 vy = MaxV * dy / d;
// 現在の速度から、新規速度への変化(加速度)を求める
csmFloat32 ax = vx - _faceVX;
csmFloat32 ay = vy - _faceVY;
const csmFloat32 a = CubismMath::SqrtF((ax * ax) + (ay * ay));
// 加速のとき
if (a < -MaxA || a > MaxA)
{
ax *= MaxA / a;
ay *= MaxA / a;
}
// 加速度を元の速度に足して、新速度とする
_faceVX += ax;
_faceVY += ay;
// 目的の方向に近づいたとき、滑らかに減速するための処理
// 設定された加速度で止まることのできる距離と速度の関係から
// 現在とりうる最高速度を計算し、それ以上のときは速度を落とす
// ※本来、人間は筋力で力(加速度)を調整できるため、より自由度が高いが、簡単な処理ですませている
{
// 加速度、速度、距離の関係式。
// 2 6 2 3
// sqrt(a t + 16 a h t - 8 a h) - a t
// v = --------------------------------------
// 2
// 4 t - 2
// (t=1)
// 時刻tは、あらかじめ加速度、速度を1/60(フレームレート、単位なし)で
// 考えているので、t=1として消してよい(※未検証)
const csmFloat32 maxV = 0.5f * (CubismMath::SqrtF((MaxA * MaxA) + 16.0f * MaxA * d - 8.0f * MaxA * d) - MaxA);
const csmFloat32 curV = CubismMath::SqrtF((_faceVX * _faceVX) + (_faceVY * _faceVY));
if (curV > maxV)
{
// 現在の速度 > 最高速度のとき、最高速度まで減速
_faceVX *= maxV / curV;
_faceVY *= maxV / curV;
}
}
_faceX += _faceVX;
_faceY += _faceVY;
}
void CubismTargetPoint::Set(csmFloat32 x, csmFloat32 y)
{
this->_faceTargetX = x;
this->_faceTargetY = y;
}
csmFloat32 CubismTargetPoint::GetX() const
{
return this->_faceX;
}
csmFloat32 CubismTargetPoint::GetY() const
{
return this->_faceY;
}
}}}
@@ -0,0 +1,71 @@
/**
* 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 "CubismFramework.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the direction the model is facing
*/
class CubismTargetPoint
{
public:
/**
* Constructor
*/
CubismTargetPoint();
/**
* Destructor
*/
virtual ~CubismTargetPoint();
/**
* Updates the state.
*
* @param deltaTimeSeconds Time step in seconds [seconds]
*/
void Update(csmFloat32 deltaTimeSeconds);
/**
* Returns the direction value along the X-axis.
*
* @return Direction value of the face along the X-axis (-1.0 to 1.0)
*/
csmFloat32 GetX() const;
/**
* Returns the direction value along the Y-axis.
*
* @return Direction value of the face along the Y-axis (-1.0 to 1.0)
*/
csmFloat32 GetY() const;
/**
* Sets the target direction values.
*
* @param x Direction value along the X-axis (-1.0 to 1.0)
* @param y Direction value along the Y-axis (-1.0 to 1.0)
*/
void Set(csmFloat32 x, csmFloat32 y);
private:
csmFloat32 _faceTargetX;
csmFloat32 _faceTargetY;
csmFloat32 _faceX;
csmFloat32 _faceY;
csmFloat32 _faceVX;
csmFloat32 _faceVY;
csmFloat32 _lastTimeSeconds;
csmFloat32 _userTimeSeconds;
};
}}}
+118
View File
@@ -0,0 +1,118 @@
/**
* 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 "CubismVector2.hpp"
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismVector2 operator+(const CubismVector2& a, const CubismVector2& b)
{
return CubismVector2(a.X + b.X, a.Y + b.Y);
}
CubismVector2 operator-(const CubismVector2& a, const CubismVector2& b)
{
return CubismVector2(a.X - b.X, a.Y - b.Y);
}
CubismVector2 operator*(const CubismVector2& vector, const csmFloat32 scalar)
{
return CubismVector2(vector.X * scalar, vector.Y * scalar);
}
CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2& vector)
{
return CubismVector2(vector.X * scalar, vector.Y * scalar);
}
CubismVector2 operator/(const CubismVector2& vector, const csmFloat32 scalar)
{
return CubismVector2(vector.X / scalar, vector.Y / scalar);
}
const CubismVector2& CubismVector2::operator+=(const CubismVector2& rhs)
{
X += rhs.X;
Y += rhs.Y;
return *this;
}
const CubismVector2& CubismVector2::operator-=(const CubismVector2& rhs)
{
X -= rhs.X;
Y -= rhs.Y;
return *this;
}
const CubismVector2& CubismVector2::operator*=(const CubismVector2& rhs)
{
X *= rhs.X;
Y *= rhs.Y;
return *this;
}
const CubismVector2& CubismVector2::operator/=(const CubismVector2& rhs)
{
X /= rhs.X;
Y /= rhs.Y;
return *this;
}
const CubismVector2& CubismVector2::operator*=(const csmFloat32 scalar)
{
X *= scalar;
Y *= scalar;
return *this;
}
const CubismVector2& CubismVector2::operator/=(const csmFloat32 scalar)
{
X /= scalar;
Y /= scalar;
return *this;
}
csmBool CubismVector2::operator==(const CubismVector2& rhs) const
{
return (X == rhs.X) && (Y == rhs.Y);
}
csmBool CubismVector2::operator!=(const CubismVector2& rhs) const
{
return !(*this == rhs);
}
csmFloat32 CubismVector2::GetLength() const
{
return CubismMath::SqrtF(X * X + Y * Y);
}
csmFloat32 CubismVector2::GetDistanceWith(CubismVector2 a) const
{
return CubismMath::SqrtF(((X - a.X) * (X - a.X)) + ((Y - a.Y) * (Y - a.Y)));
}
csmFloat32 CubismVector2::Dot(const CubismVector2& a) const
{
return (X * a.X) + (Y * a.Y);
}
void CubismVector2::Normalize()
{
const csmFloat32 length = powf((X * X) + (Y * Y), 0.5f);
X = X / length;
Y = Y / length;
}
}}}
+209
View File
@@ -0,0 +1,209 @@
/**
* 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 "CubismFramework.hpp"
#include "math.h"
#ifndef NULL
# define NULL 0
#endif
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles 2D vectors
*/
struct CubismVector2
{
csmFloat32 X; ///< X-axis value
csmFloat32 Y; ///< Y-axis value
/**
* Constructor
*/
CubismVector2(): X(0.0f), Y(0.0f)
{}
/**
* Constructor<br>
* Initializes with specified values.
*
* @param x Value along the X-axis
* @param y Value along the Y-axis
*/
CubismVector2(csmFloat32 x, csmFloat32 y) : X(x), Y(y)
{}
/**
* Adds two vectors.<br>
* a + b = result
*
* @param a Value a
* @param b Value b
*
* @return Result of a + b
*/
friend CubismVector2 operator+(const CubismVector2& a, const CubismVector2& b);
/**
* Subtracts one vector from another.<br>
* a - b = result
*
* @param a Value a
* @param b Value b
*
* @return Result of a - b
*/
friend CubismVector2 operator-(const CubismVector2& a, const CubismVector2& b);
/**
* Multiplies a vector by a scalar.<br>
* vector * scalar = result
*
* @param vector Value vector (vector quantity)
* @param scalar Value scalar (scalar quantity)
*
* @return Result of vector * scalar (vector quantity)
*/
friend CubismVector2 operator*(const CubismVector2& vector, const csmFloat32 scalar);
/**
* Multiplies a scalar by a vector.<br>
* scalar * vector = result
*
* @param scalar Value scalar (scalar quantity)
* @param vector Value vector (vector quantity)
*
* @return Result of scalar * vector (vector quantity)
*/
friend CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2& vector);
/**
* Divides a vector by a scalar.<br>
* vector / scalar = result
*
* @param vector Value vector (vector quantity)
* @param scalar Value scalar (scalar quantity)
*
* @return Result of vector / scalar (vector quantity)
*/
friend CubismVector2 operator/(const CubismVector2& vector, const csmFloat32 scalar);
/**
* Adds a vector to this vector.
*
* @param rhs Value to add
*
* @return Result of addition
*/
const CubismVector2& operator+=(const CubismVector2& rhs);
/**
* Subtracts a vector from this vector.
*
* @param rhs Value to subtract
*
* @return Result of subtraction
*/
const CubismVector2& operator-=(const CubismVector2& rhs);
/**
* Multiplies this vector by another vector.
*
* @param rhs Value to multiply by
*
* @return Result of multiplication
*/
const CubismVector2& operator*=(const CubismVector2& rhs);
/**
* Divides this vector by another vector.
*
* @param rhs Value to divide by
*
* @return Result of division
*/
const CubismVector2& operator/=(const CubismVector2& rhs);
/**
* Multiplies this vector by a scalar.
*
* @param scalar Value to multiply by
*
* @return Result of multiplication
*/
const CubismVector2& operator*=(const csmFloat32 scalar);
/**
* Divides this vector by a scalar.
*
* @param scalar Value to divide by
*
* @return Result of division
*/
const CubismVector2& operator/=(const csmFloat32 scalar);
/**
* Checks if the value is equal.
*
* @param rhs Value to check
*
* @return true if the value is equal; otherwise false.
*/
csmBool operator==(const CubismVector2& rhs) const;
/**
* Checks if the value is not equal.
*
* @param rhs Value to check
*
* @return true if the value is not equal; otherwise false.
*/
csmBool operator!=(const CubismVector2& rhs) const;
/**
* Normalizes the vector.
*/
void Normalize();
/**
* Returns the length of the vector.
*
* @return Length of the vector
*/
csmFloat32 GetLength() const;
/**
* Returns the distance between this vector and the given position vector.
*
* @param a Position vector
*
* @return Distance between the vectors
*/
csmFloat32 GetDistanceWith(CubismVector2 a) const;
/**
* Calculates the dot product of this vector and the given vector.
*
* @param a Vector to be multiplied
*
* @return Result of the dot product
*/
csmFloat32 Dot(const CubismVector2& a) const;
};
CubismVector2 operator+(const CubismVector2& a, const CubismVector2& b);
CubismVector2 operator-(const CubismVector2& a, const CubismVector2& b);
CubismVector2 operator*(const CubismVector2& vector, const csmFloat32 scalar);
CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2& vector);
CubismVector2 operator/(const CubismVector2& vector, const csmFloat32 scalar);
}}}
//------------------------- LIVE2D NAMESPACE ------------
@@ -0,0 +1,193 @@
/**
* 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 "CubismViewMatrix.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismViewMatrix::CubismViewMatrix()
: _screenLeft(0.0f)
, _screenRight(0.0f)
, _screenTop(0.0f)
, _screenBottom(0.0f)
, _maxLeft(0.0f)
, _maxRight(0.0f)
, _maxTop(0.0f)
, _maxBottom(0.0f)
, _maxScale(0.0f)
, _minScale(0.0f)
{ }
CubismViewMatrix::~CubismViewMatrix()
{ }
csmFloat32 CubismViewMatrix::GetMaxScale() const
{
return _maxScale;
}
csmFloat32 CubismViewMatrix::GetMinScale() const
{
return _minScale;
}
csmFloat32 CubismViewMatrix::GetScreenLeft() const
{
return _screenLeft;
}
csmFloat32 CubismViewMatrix::GetScreenRight() const
{
return _screenRight;
}
csmFloat32 CubismViewMatrix::GetScreenBottom() const
{
return _screenBottom;
}
csmFloat32 CubismViewMatrix::GetScreenTop() const
{
return _screenTop;
}
csmFloat32 CubismViewMatrix::GetMaxLeft() const
{
return _maxLeft;
}
csmFloat32 CubismViewMatrix::GetMaxRight() const
{
return _maxRight;
}
csmFloat32 CubismViewMatrix::GetMaxBottom() const
{
return _maxBottom;
}
csmFloat32 CubismViewMatrix::GetMaxTop() const
{
return _maxTop;
}
csmBool CubismViewMatrix::IsMaxScale() const
{
return GetScaleX() >= _maxScale;
}
csmBool CubismViewMatrix::IsMinScale() const
{
return GetScaleX() <= _minScale;
}
void CubismViewMatrix::AdjustTranslate(csmFloat32 x, csmFloat32 y)
{
if (_tr[0] * _maxLeft + (_tr[12] + x) > _screenLeft)
{
x = _screenLeft - _tr[0] * _maxLeft - _tr[12];
}
if (_tr[0] * _maxRight + (_tr[12] + x) < _screenRight)
{
x = _screenRight - _tr[0] * _maxRight - _tr[12];
}
if (_tr[5] * _maxTop + (_tr[13] + y) < _screenTop)
{
y = _screenTop - _tr[5] * _maxTop - _tr[13];
}
if (_tr[5] * _maxBottom + (_tr[13] + y) > _screenBottom)
{
y = _screenBottom - _tr[5] * _maxBottom - _tr[13];
}
csmFloat32 tr1[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
x, y, 0.0f, 1.0f
};
Multiply(tr1, _tr, _tr);
}
void CubismViewMatrix::AdjustScale(csmFloat32 cx, csmFloat32 cy, csmFloat32 scale)
{
csmFloat32 MaxScale = GetMaxScale();
csmFloat32 MinScale = GetMinScale();
csmFloat32 targetScale = scale * _tr[0]; //
if (targetScale < MinScale)
{
if (_tr[0] > 0.0f)
{
scale = MinScale / _tr[0];
}
}
else if (targetScale > MaxScale)
{
if (_tr[0] > 0.0f)
{
scale = MaxScale / _tr[0];
}
}
csmFloat32 tr1[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
cx, cy, 0.0f, 1.0f
};
csmFloat32 tr2[16] = {
scale, 0.0f, 0.0f, 0.0f,
0.0f, scale, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
csmFloat32 tr3[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-cx, -cy, 0.0f, 1.0f
};
Multiply(tr3, _tr, _tr);
Multiply(tr2, _tr, _tr);
Multiply(tr1, _tr, _tr);
}
void CubismViewMatrix::SetScreenRect(csmFloat32 left, csmFloat32 right, csmFloat32 bottom, csmFloat32 top)
{
_screenLeft = left;
_screenRight = right;
_screenTop = top;
_screenBottom = bottom;
}
void CubismViewMatrix::SetMaxScreenRect(csmFloat32 left, csmFloat32 right, csmFloat32 bottom, csmFloat32 top)
{
_maxLeft = left;
_maxRight = right;
_maxTop = top;
_maxBottom = bottom;
}
void CubismViewMatrix::SetMaxScale(csmFloat32 maxScale)
{
_maxScale = maxScale;
}
void CubismViewMatrix::SetMinScale(csmFloat32 minScale)
{
_minScale = minScale;
}
}}}
@@ -0,0 +1,179 @@
/**
* 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 "CubismMatrix44.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles 4x4 matrix utilities for changing camera position
*/
class CubismViewMatrix : public CubismMatrix44
{
public:
/**
* Constructor
*/
CubismViewMatrix();
/**
* Destructor
*/
virtual ~CubismViewMatrix();
/**
* Moves by the given values.<br>
* The movement amount is adjusted with respect to the screen size and its maximum value.
*
* @param x Translation amount along the X-axis
* @param y Translation amount along the Y-axis
*/
void AdjustTranslate(csmFloat32 x, csmFloat32 y);
/**
* Scales by the given values.<br>
* The scaling factor is adjusted considering the maximum and minimum scaling rates.
*
* @param cx Center position along the X-axis for scaling
* @param cy Center position along the Y-axis for scaling
* @param scale Scaling factor
*/
void AdjustScale(csmFloat32 cx, csmFloat32 cy, csmFloat32 scale);
/**
* Sets the range on the logical coordinates corresponding to the device.
*
* @param left X-axis position of the left edge
* @param right X-axis position of the right edge
* @param bottom Y-axis position of the bottom edge
* @param top Y-axis position of the top edge
*/
void SetScreenRect(csmFloat32 left, csmFloat32 right, csmFloat32 bottom, csmFloat32 top);
/**
* Sets the movable range on the logical coordinates corresponding to the device.
*
* @param left X-axis position of the left edge
* @param right X-axis position of the right edge
* @param bottom Y-axis position of the bottom edge
* @param top Y-axis position of the top edge
*/
void SetMaxScreenRect(csmFloat32 left, csmFloat32 right, csmFloat32 bottom, csmFloat32 top);
/**
* Sets the maximum scaling factor.
*
* @param maxScale Maximum scaling factor
*/
void SetMaxScale(csmFloat32 maxScale);
/**
* Sets the minimum scaling factor.
*
* @param minScale Minimum scaling factor
*/
void SetMinScale(csmFloat32 minScale);
/**
* Returns the maximum scaling factor.
*
* @return Maximum scaling factor
*/
csmFloat32 GetMaxScale() const;
/**
* Returns the minimum scaling factor.
*
* @return Minimum scaling factor
*/
csmFloat32 GetMinScale() const;
/**
* Checks if the scaling factor is at its maximum.
*
* @return true if the scaling factor is at its maximum; otherwise false.
*/
csmBool IsMaxScale() const;
/**
* Checks if the scaling factor is at its minimum.
*
* @return true if the scaling factor is at its minimum; otherwise false.
*/
csmBool IsMinScale() const;
/**
* Returns the X-axis position of the left edge on the logical coordinates corresponding to the device.
*
* @return X-axis position of the left edge on the logical coordinates corresponding to the device
*/
csmFloat32 GetScreenLeft() const;
/**
* Returns the X-axis position of the right edge on the logical coordinates corresponding to the device.
*
* @return X-axis position of the right edge on the logical coordinates corresponding to the device
*/
csmFloat32 GetScreenRight() const;
/**
* Returns the Y-axis position of the bottom edge on the logical coordinates corresponding to the device.
*
* @return Y-axis position of the bottom edge on the logical coordinates corresponding to the device
*/
csmFloat32 GetScreenBottom() const;
/**
* Returns the Y-axis position of the top edge on the logical coordinates corresponding to the device.
*
* @return Y-axis position of the top edge on the logical coordinates corresponding to the device
*/
csmFloat32 GetScreenTop() const;
/**
* Returns the maximum X-axis position of the left edge.
*
* @return Maximum X-axis position of the left edge
*/
csmFloat32 GetMaxLeft() const;
/**
* Returns the maximum X-axis position of the right edge.
*
* @return Maximum X-axis position of the right edge
*/
csmFloat32 GetMaxRight() const;
/**
* Returns the maximum Y-axis position of the bottom edge.
*
* @return Maximum Y-axis position of the bottom edge
*/
csmFloat32 GetMaxBottom() const;
/**
* Returns the maximum Y-axis position of the top edge.
*
* @return Maximum Y-axis position of the top edge
*/
csmFloat32 GetMaxTop() const;
private:
csmFloat32 _screenLeft;
csmFloat32 _screenRight;
csmFloat32 _screenTop;
csmFloat32 _screenBottom;
csmFloat32 _maxLeft;
csmFloat32 _maxRight;
csmFloat32 _maxTop;
csmFloat32 _maxBottom;
csmFloat32 _maxScale;
csmFloat32 _minScale;
};
}}}
+13
View File
@@ -0,0 +1,13 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismMoc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMoc.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModel.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelUserData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelUserData.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelUserDataJson.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismModelUserDataJson.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModel.hpp
)
+117
View File
@@ -0,0 +1,117 @@
/**
* 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 "CubismMoc.hpp"
#include "CubismModel.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismMoc* CubismMoc::Create(const csmByte* mocBytes, csmSizeInt size, csmBool shouldCheckMocConsistency)
{
CubismMoc* cubismMoc = NULL;
void* alignedBuffer = CSM_MALLOC_ALLIGNED(size, Core::csmAlignofMoc);
memcpy(alignedBuffer, mocBytes, size);
if (shouldCheckMocConsistency)
{
// .moc3の整合性を確認
csmBool consistency = HasMocConsistency(alignedBuffer, size);
if (!consistency)
{
CSM_FREE_ALLIGNED(alignedBuffer);
// 整合性が確認できなければ処理しない
CubismLogError("Inconsistent MOC3.");
return cubismMoc;
}
}
Core::csmMoc* moc = Core::csmReviveMocInPlace(alignedBuffer, size);
const Core::csmMocVersion version = Core::csmGetMocVersion(alignedBuffer, size);
if (moc)
{
cubismMoc = CSM_NEW CubismMoc(moc);
cubismMoc->_mocVersion = version;
}
return cubismMoc;
}
void CubismMoc::Delete(CubismMoc* moc)
{
CSM_DELETE_SELF(CubismMoc, moc);
}
CubismMoc::CubismMoc(Core::csmMoc* moc)
: _moc(moc)
, _modelCount(0)
, _mocVersion(0)
{ }
CubismMoc::~CubismMoc()
{
CSM_ASSERT(_modelCount == 0);
CSM_FREE_ALLIGNED(_moc);
}
CubismModel* CubismMoc::CreateModel()
{
CubismModel* cubismModel = NULL;
const csmUint32 modelSize = Core::csmGetSizeofModel(_moc);
void* modelMemory = CSM_MALLOC_ALLIGNED(modelSize, Core::csmAlignofModel);
Core::csmModel* model = Core::csmInitializeModelInPlace(_moc, modelMemory, modelSize);
if (model)
{
cubismModel = CSM_NEW CubismModel(model);
cubismModel->Initialize();
++_modelCount;
}
return cubismModel;
}
void CubismMoc::DeleteModel(CubismModel* model)
{
CSM_DELETE_SELF(CubismModel, model);
--_modelCount;
}
Core::csmMocVersion CubismMoc::GetLatestMocVersion()
{
return Core::csmGetLatestMocVersion();
}
Core::csmMocVersion CubismMoc::GetMocVersion()
{
return _mocVersion;
}
csmBool CubismMoc::HasMocConsistency(void* address, const csmUint32 size)
{
csmInt32 isConsistent = Core::csmHasMocConsistency(address, size);
return isConsistent != 0 ? true : false;
}
csmBool CubismMoc::HasMocConsistencyFromUnrevivedMoc(const csmByte* mocBytes, csmSizeInt size)
{
void* alignedBuffer = CSM_MALLOC_ALLIGNED(size, Core::csmAlignofMoc);
memcpy(alignedBuffer, mocBytes, size);
csmBool consistency = CubismMoc::HasMocConsistency(alignedBuffer, size);
CSM_FREE_ALLIGNED(alignedBuffer);
return consistency;
}
}}}
+98
View File
@@ -0,0 +1,98 @@
/**
* 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 "CubismFramework.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismModel;
/**
* Handles management of MOC data
*/
class CubismMoc
{
friend class CubismModel;
public:
/**
* Makes an instance.
*
* @param mocBytes Buffer containing the loaded MOC file
* @param size Size of the buffer in bytes
*
* @return Created instance
*/
static CubismMoc* Create(const csmByte* mocBytes, csmSizeInt size, csmBool shouldCheckMocConsistency = false);
/**
* Destroys an instance.
*
* @param moc `CubismMoc` instance to be destroyed
*/
static void Delete(CubismMoc* moc);
/**
* Makes a model instance.
*
* @return Created model instance
*/
CubismModel* CreateModel();
/**
* Destroys a model instance.
*
* @param model `CubismModel` instance to be destroyed
*/
void DeleteModel(CubismModel* model);
/**
* Returns the latest MOC file version.
*
* @return Version
*/
static Core::csmMocVersion GetLatestMocVersion();
/**
* Returns the version of the loaded MOC file.
*
* @return Version
*/
Core::csmMocVersion GetMocVersion();
/**
* Checks the consistency of the MOC file.
*
* @param address Address of the un-restored MOC file. The address must be aligned to 'csmAlignofMoc'.
* @param size Size of the MOC file in bytes
*
* @return true if the file is consistent; otherwise false
*/
static csmBool HasMocConsistency(void* address, const csmUint32 size);
/**
* Checks the consistency of the MOC file.
*
* @param mocBytes Buffer of the MOC file
* @param size Size of the buffer
*
* @return true if the file is consistent; otherwise false
*/
static csmBool HasMocConsistencyFromUnrevivedMoc(const csmByte* mocBytes, csmSizeInt size);
private:
CubismMoc(Core::csmMoc* moc);
virtual ~CubismMoc();
Core::csmMoc* _moc;
csmInt32 _modelCount;
csmUint32 _mocVersion;
};
}}}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,76 @@
/**
* 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 "CubismModelUserData.hpp"
#include "CubismModelUserDataJson.hpp"
#include "Utils/CubismString.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
namespace
{
const Live2D::Cubism::Framework::csmChar* ArtMesh = "ArtMesh";
}
CubismModelUserData::~CubismModelUserData()
{
for (csmUint32 i = 0;i < _userDataNodes.GetSize(); ++i)
{
CSM_DELETE(const_cast<CubismModelUserDataNode*>(_userDataNodes[i]));
}
}
const csmVector<const CubismModelUserData::CubismModelUserDataNode*>& CubismModelUserData::GetArtMeshUserDatas() const
{
return _artMeshUserDataNodes;
}
CubismModelUserData* CubismModelUserData::Create(const csmByte* buffer, const csmSizeInt size)
{
CubismModelUserData* ret = CSM_NEW CubismModelUserData();
ret->ParseUserData(buffer, size);
return ret;
}
void CubismModelUserData::Delete(CubismModelUserData* modelUserData)
{
CSM_DELETE_SELF(CubismModelUserData, modelUserData);
}
void CubismModelUserData::ParseUserData(const csmByte* buffer, const csmSizeInt size)
{
CubismModelUserDataJson* json = CSM_NEW CubismModelUserDataJson(buffer, size);
if (!json->IsValid())
{
CSM_DELETE(json);
return;
}
const ModelUserDataType typeOfArtMesh = CubismFramework::GetIdManager()->GetId(ArtMesh);
const csmUint32 nodeCount = json->GetUserDataCount();
for (csmUint32 i = 0; i < nodeCount; i++)
{
CubismModelUserDataNode* addNode = CSM_NEW CubismModelUserDataNode();
addNode->TargetId = json->GetUserDataId(i);
addNode->TargetType = CubismFramework::GetIdManager()->GetId(json->GetUserDataTargetType(i));
addNode->Value = json->GetUserDataValue(i);
_userDataNodes.PushBack(addNode);
if (addNode->TargetType == typeOfArtMesh)
{
_artMeshUserDataNodes.PushBack(addNode);
}
}
CSM_DELETE(json);
}
}}}
@@ -0,0 +1,68 @@
/**
* 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 "CubismModel.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
typedef CubismIdHandle ModelUserDataType;
/**
* Handles management of user data.
*/
class CubismModelUserData
{
public:
/**
* Structure for user data information
*/
struct CubismModelUserDataNode
{
ModelUserDataType TargetType; ///< User data type
CubismIdHandle TargetId; ///< ID of the object attached to the user data
csmString Value; ///< User data value
};
/**
* Makes an instance.
*
* @param buffer Buffer where the user data file is loaded
* @param size Byte size of the buffer
*
* @return Instance
*/
static CubismModelUserData* Create(const csmByte* buffer, csmSizeInt size);
/**
* Destroys the instance.
*
* @param modelUserData Instance of `CubismModelUserData` to destroy
*/
static void Delete(CubismModelUserData* modelUserData);
/**
* Destructor
*/
virtual ~CubismModelUserData();
/**
* Returns the list of user data for ArtMesh.
*
* @return List of user data
*/
const csmVector<const CubismModelUserDataNode*>& GetArtMeshUserDatas() const;
private:
void ParseUserData(const csmByte* buffer, csmSizeInt size);
csmVector<const CubismModelUserDataNode*> _userDataNodes;
csmVector<const CubismModelUserDataNode*> _artMeshUserDataNodes;
};
}}} //--------- LIVE2D NAMESPACE ------------
@@ -0,0 +1,58 @@
/**
* 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 "CubismModelUserDataJson.hpp"
#include "CubismModelUserData.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
namespace {
const csmChar* Meta = "Meta";
const csmChar* UserDataCount = "UserDataCount";
const csmChar* TotalUserDataSize = "TotalUserDataSize";
const csmChar* UserData = "UserData";
const csmChar* Target = "Target";
const csmChar* Id = "Id";
const csmChar* Value = "Value";
}
CubismModelUserDataJson::CubismModelUserDataJson(const csmByte* buffer, csmSizeInt size)
{
CreateCubismJson(buffer, size);
}
CubismModelUserDataJson::~CubismModelUserDataJson()
{
DeleteCubismJson();
}
csmInt32 CubismModelUserDataJson::GetUserDataCount() const
{
return _json->GetRoot()[Meta][UserDataCount].ToInt();
}
csmInt32 CubismModelUserDataJson::GetTotalUserDataSize() const
{
return _json->GetRoot()[Meta][TotalUserDataSize].ToInt();
}
csmString CubismModelUserDataJson::GetUserDataTargetType(const csmInt32 i) const
{
return _json->GetRoot()[UserData][i][Target].GetRawString();
}
CubismIdHandle CubismModelUserDataJson::GetUserDataId(const csmInt32 i) const
{
return CubismFramework::GetIdManager()->GetId(_json->GetRoot()[UserData][i][Id].GetRawString());
}
const csmChar* CubismModelUserDataJson::GetUserDataValue(const csmInt32 i) const
{
return _json->GetRoot()[UserData][i][Value].GetRawString();
}
}}}
@@ -0,0 +1,79 @@
/**
* 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 "Utils/CubismJson.hpp"
#include "Model/CubismModel.hpp"
#include "Id/CubismIdManager.hpp"
//--------- LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles user data.
*/
class CubismModelUserDataJson : public CubismJsonHolder
{
public:
/**
* Constructor
*
* @param buffer Buffer where the user data file is loaded
* @param size Number of bytes in the buffer
*/
CubismModelUserDataJson(const csmByte* buffer, csmSizeInt size);
/**
* Destructor
*/
virtual ~CubismModelUserDataJson();
/**
* Returns the number of user data entries in the user data file.
*
* @return Number of user data entries
*/
csmInt32 GetUserDataCount() const;
/**
* Returns the number of bytes in the user data file.
*
* @return Number of bytes
*/
csmInt32 GetTotalUserDataSize() const;
/**
* Returns the type of user data at the specified index.
*
* @param i Index of the user data
*
* @return Type of user data
*/
csmString GetUserDataTargetType(csmInt32 i) const;
/**
* Returns the ID of the target attached to the user data at the specified index.
*
* @param i Index of the user data
*
* @return ID of the target attached to the user data
*/
CubismIdHandle GetUserDataId(csmInt32 i) const;
/**
* Returns the value of the user data at the specified index.
*
* @param i Index of the user data
*
* @return Value of the user data
*/
const csmChar* GetUserDataValue(csmInt32 i) const;
};
}}}
@@ -0,0 +1,309 @@
/**
* 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 "CubismUserModel.hpp"
#include "Motion/CubismMotion.hpp"
#include "Physics/CubismPhysics.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismUserModel::CubismUserModel()
: _moc(NULL)
, _model(NULL)
, _motionManager(NULL)
, _expressionManager(NULL)
, _eyeBlink(NULL)
, _breath(NULL)
, _modelMatrix(NULL)
, _pose(NULL)
, _dragManager(NULL)
, _physics(NULL)
, _modelUserData(NULL)
, _initialized(false)
, _updating(false)
, _opacity(1.0f)
, _lipSync(true)
, _lastLipSyncValue(0.0f)
, _dragX(0.0f)
, _dragY(0.0f)
, _accelerationX(0.0f)
, _accelerationY(0.0f)
, _accelerationZ(0.0f)
, _mocConsistency(false)
, _motionConsistency(false)
, _debugMode(false)
, _renderer(NULL)
{
// モーションマネージャーを作成
// MotionQueueManagerクラスからの継承なので使い方は同じ
_motionManager = CSM_NEW CubismMotionManager();
_motionManager->SetEventCallback(CubismDefaultMotionEventCallback, this);
// 表情モーションマネージャを作成
_expressionManager = CSM_NEW CubismExpressionMotionManager();
// ドラッグによるアニメーション
_dragManager = CSM_NEW CubismTargetPoint();
}
CubismUserModel::~CubismUserModel()
{
CSM_DELETE(_motionManager);
CSM_DELETE(_expressionManager);
if (_moc)
{
_moc->DeleteModel(_model);
}
CubismMoc::Delete(_moc);
CSM_DELETE(_modelMatrix);
CubismPose::Delete(_pose);
CubismEyeBlink::Delete(_eyeBlink);
CubismBreath::Delete(_breath);
CSM_DELETE(_dragManager);
CubismPhysics::Delete(_physics);
CubismModelUserData::Delete(_modelUserData);
DeleteRenderer();
}
void CubismUserModel::SetAcceleration(csmFloat32 x, csmFloat32 y, csmFloat32 z)
{
_accelerationX = x;
_accelerationY = y;
_accelerationZ = z;
}
void CubismUserModel::LoadModel(const csmByte* buffer, csmSizeInt size, csmBool shouldCheckMocConsistency)
{
_moc = CubismMoc::Create(buffer, size, shouldCheckMocConsistency);
if (_moc == NULL)
{
CubismLogError("Failed to CubismMoc::Create().");
return;
}
_model = _moc->CreateModel();
if (_model == NULL)
{
CubismLogError("Failed to CreateModel().");
return;
}
_model->SaveParameters();
_modelMatrix = CSM_NEW CubismModelMatrix(_model->GetCanvasWidth(), _model->GetCanvasHeight());
}
ACubismMotion* CubismUserModel::LoadExpression(const csmByte* buffer, csmSizeInt size, const csmChar* name)
{
if (!buffer)
{
CubismLogError("Failed to LoadExpression().");
return NULL;
}
return CubismExpressionMotion::Create(buffer, size);
}
void CubismUserModel::LoadPose(const csmByte* buffer, csmSizeInt size)
{
_pose = CubismPose::Create(buffer, size);
if (!_pose)
{
CubismLogError("Failed to LoadPose().");
}
}
void CubismUserModel::LoadPhysics(const csmByte* buffer, csmSizeInt size)
{
_physics = CubismPhysics::Create(buffer, size);
if (!_physics)
{
CubismLogError("Failed to LoadPhysics().");
}
}
void CubismUserModel::LoadUserData(const csmByte* buffer, csmSizeInt size)
{
if (!buffer)
{
CubismLogError("Failed to LoadUserData().");
return;
}
_modelUserData = CubismModelUserData::Create(buffer, size);
}
csmBool CubismUserModel::IsHit(CubismIdHandle drawableId, csmFloat32 pointX, csmFloat32 pointY)
{
const csmInt32 drawIndex = _model->GetDrawableIndex(drawableId);
if (drawIndex < 0)
{
return false; // 存在しない場合はfalse
}
const csmInt32 count = _model->GetDrawableVertexCount(drawIndex);
const csmFloat32* vertices = _model->GetDrawableVertices(drawIndex);
csmFloat32 left = vertices[0];
csmFloat32 right = vertices[0];
csmFloat32 top = vertices[1];
csmFloat32 bottom = vertices[1];
for (csmInt32 j = 1; j < count; ++j)
{
csmFloat32 x = vertices[Constant::VertexOffset + j * Constant::VertexStep];
csmFloat32 y = vertices[Constant::VertexOffset + j * Constant::VertexStep + 1];
if (x < left)
{
left = x; // Min x
}
if (x > right)
{
right = x; // Max x
}
if (y < top)
{
top = y; // Min y
}
if (y > bottom)
{
bottom = y; // Max y
}
}
const csmFloat32 tx = _modelMatrix->InvertTransformX(pointX);
const csmFloat32 ty = _modelMatrix->InvertTransformY(pointY);
return ((left <= tx) && (tx <= right) && (top <= ty) && (ty <= bottom));
}
ACubismMotion* CubismUserModel::LoadMotion(const csmByte* buffer, csmSizeInt size, const csmChar* name,
ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler,
ICubismModelSetting* modelSetting, const csmChar* group, const csmInt32 index, csmBool shouldCheckMotionConsistency)
{
if (!buffer)
{
CubismLogError("Failed to LoadMotion(). Buffer is NULL.");
return NULL;
}
ACubismMotion* motion = CubismMotion::Create(buffer, size, onFinishedMotionHandler, onBeganMotionHandler, shouldCheckMotionConsistency);
if (!motion)
{
CubismLogError("Failed to create motion from buffer in LoadMotion().");
return NULL;
}
// 必要であればモーションフェード値を上書き
if (modelSetting)
{
const csmFloat32 fadeInTime = modelSetting->GetMotionFadeInTimeValue(group, index);
if (fadeInTime >= 0.0f)
{
motion->SetFadeInTime(fadeInTime);
}
const csmFloat32 fadeOutTime = modelSetting->GetMotionFadeOutTimeValue(group, index);
if (fadeOutTime >= 0.0f)
{
motion->SetFadeOutTime(fadeOutTime);
}
}
return motion;
}
void CubismUserModel::SetDragging(csmFloat32 x, csmFloat32 y)
{
_dragManager->Set(x, y);
}
CubismModelMatrix* CubismUserModel::GetModelMatrix() const
{
return _modelMatrix;
}
csmBool CubismUserModel::IsInitialized()
{
return _initialized;
}
void CubismUserModel::IsInitialized(csmBool v)
{
_initialized = v;
}
csmBool CubismUserModel::IsUpdating()
{
return _updating;
}
void CubismUserModel::IsUpdating(csmBool v)
{
_updating = v;
}
void CubismUserModel::SetOpacity(csmFloat32 a)
{
_opacity = a;
}
csmFloat32 CubismUserModel::GetOpacity()
{
return _opacity;
}
CubismModel* CubismUserModel::GetModel() const
{
return _model;
}
void CubismUserModel::CreateRenderer(csmInt32 maskBufferCount)
{
if (_renderer)
{
DeleteRenderer();
}
_renderer = Rendering::CubismRenderer::Create();
_renderer->Initialize(_model, maskBufferCount);
}
void CubismUserModel::DeleteRenderer()
{
if (_renderer)
{
Rendering::CubismRenderer::Delete(_renderer);
_renderer = NULL;
}
}
void CubismUserModel::CubismDefaultMotionEventCallback(const CubismMotionQueueManager* caller, const csmString& eventValue, void* customData)
{
CubismUserModel* model = reinterpret_cast<CubismUserModel*>(customData);
if (model != NULL)
{
model->MotionEventFired(eventValue);
}
}
void CubismUserModel::MotionEventFired(const csmString& eventValue)
{
CubismLogInfo("%s",eventValue.GetRawString());
}
}}}
@@ -0,0 +1,256 @@
/**
* 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 "Effect/CubismPose.hpp"
#include "Effect/CubismEyeBlink.hpp"
#include "Effect/CubismBreath.hpp"
#include "Math/CubismModelMatrix.hpp"
#include "Math/CubismTargetPoint.hpp"
#include "Model/CubismMoc.hpp"
#include "Model/CubismModel.hpp"
#include "Motion/CubismMotionManager.hpp"
#include "Motion/CubismExpressionMotion.hpp"
#include "Physics/CubismPhysics.hpp"
#include "Rendering/CubismRenderer.hpp"
#include "Model/CubismModelUserData.hpp"
#include "Motion/CubismExpressionMotionManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Base for models actually used by thegit a user.
*/
class CubismUserModel
{
public:
/**
* Constructor
*/
CubismUserModel();
/**
* Destructor
*/
virtual ~CubismUserModel();
/**
* Checks if it is initialized.
*
* @return true if initialized; otherwise false.
*/
virtual csmBool IsInitialized();
/**
* Sets the initialization state.
*
* @param v Initialization state. true if initialized.
*/
virtual void IsInitialized(csmBool v);
/**
* Checks if it is updated.
*
* @return true if updated; otherwise false.
*/
virtual csmBool IsUpdating();
/**
* Sets the update state.
*
* @param v Update state. true if updated.
*/
virtual void IsUpdating(csmBool v);
/**
* Sets the information during mouse dragging.
*
* @param x X position of the mouse cursor during dragging
* @param y Y position of the mouse cursor during dragging
*/
virtual void SetDragging(csmFloat32 x, csmFloat32 y);
/**
* Sets the acceleration information.
*
* @param x Acceleration in the X-axis direction
* @param y Acceleration in the Y-axis direction
* @param z Acceleration in the Z-axis direction
*/
virtual void SetAcceleration(csmFloat32 x, csmFloat32 y, csmFloat32 z);
/**
* Returns the matrix applied to the model.
*
* @return Matrix
*/
CubismModelMatrix* GetModelMatrix() const;
/**
* Sets the opacity.
*
* @param a Opacity
*/
virtual void SetOpacity(csmFloat32 a);
/**
* Returns the opacity.
*
* @return Opacity
*/
virtual csmFloat32 GetOpacity();
/**
* Loads the model from a MOC3 file.
*
* @param buffer Buffer where the MOC3 file is loaded
* @param size Number of bytes in the buffer
*/
virtual void LoadModel(const csmByte* buffer, csmSizeInt size, csmBool shouldCheckMocConsistency = false);
/**
* Loads motion from a motion file.
* If a fade value is defined in model3.json, the fade value defined in motion3.json will be overwritten.
*
* @param buffer Buffer where the motion file is loaded
* @param size Number of bytes in the buffer
* @param name Name of the motion
* @param onFinishedMotionHandler Callback function when motion playback finishes
* @param modelSetting Model setting information
* @param group Name to the desired Motion Group
* @param index Index to the desired Motion
*
* @return Instance of the motion class
*/
virtual ACubismMotion* LoadMotion(const csmByte* buffer, csmSizeInt size, const csmChar* name,
ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL,
ICubismModelSetting* modelSetting = NULL, const csmChar* group = NULL, const csmInt32 index = -1, csmBool shouldCheckMotionConsistency = false);
/**
* Loads expression from an expression configuration file.
*
* @param buffer Buffer where the expression configuration file is loaded
* @param size Number of bytes in the buffer
* @param name Name of the expression
*
* @return Instance of the expression motion class
*/
virtual ACubismMotion* LoadExpression(const csmByte* buffer, csmSizeInt size, const csmChar* name);
/**
* Loads pose from a pose configuration file.
*
* @param buffer Buffer where the pose configuration file is loaded
* @param size Number of bytes in the buffer
*/
virtual void LoadPose(const csmByte* buffer, csmSizeInt size);
/**
* Loads physics from a physics configuration file.
*
* @param buffer Buffer where the physics configuration file is loaded
* @param size Number of bytes in the buffer
*/
virtual void LoadPhysics(const csmByte* buffer, csmSizeInt size);
/**
* Loads user data from a user data file.
*
* @param buffer Buffer where the user data file is loaded
* @param size Number of bytes in the buffer
*/
virtual void LoadUserData(const csmByte* buffer, csmSizeInt size);
/**
* Returns whether the hit test of a drawable object hits at the specified position.
*
* @param drawableId ID of the drawable object to test
* @param pointX X position
* @param pointY Y position
*
* @return true if the hit test of the drawable object hits at the specified position; otherwise false.
*/
virtual csmBool IsHit(CubismIdHandle drawableId, csmFloat32 pointX, csmFloat32 pointY);
/**
* Returns the model.
*
* @return Instance of the model
*/
CubismModel* GetModel() const;
/**
* Returns the renderer.
*
* @return Instance of the renderer
*/
template<class T> T* GetRenderer() { return dynamic_cast<T*>(_renderer); }
/**
* Makes the renderer.
*/
void CreateRenderer(csmInt32 maskBufferCount = 1);
/**
* Destroys the renderer.
*/
void DeleteRenderer();
/**
* Handles the event when user data fires during motion playback.
*
* @param eventValue Event value of the user data that fired
*
* @note This function is intended to be overridden.<br>
* If not overridden, it outputs to the log.
*/
virtual void MotionEventFired(const csmString& eventValue);
/**
* Callback function to receive user data events registered in the motion management class.
*
* @param caller Motion management class that handled the fired user data event
* @param eventValue Event value of the fired user data
* @param customData Arbitrary data
*
* @note Calls the `MotionEventFired` of the CubismUserModel subclass.
*/
static void CubismDefaultMotionEventCallback(const CubismMotionQueueManager* caller, const csmString& eventValue, void* customData);
protected:
CubismMoc* _moc;
CubismModel* _model;
CubismMotionManager* _motionManager;
CubismExpressionMotionManager* _expressionManager;
CubismEyeBlink* _eyeBlink;
CubismBreath* _breath;
CubismModelMatrix* _modelMatrix;
CubismPose* _pose;
CubismTargetPoint* _dragManager;
CubismPhysics* _physics;
CubismModelUserData* _modelUserData;
csmBool _initialized;
csmBool _updating;
csmFloat32 _opacity;
csmBool _lipSync;
csmFloat32 _lastLipSyncValue;
csmFloat32 _dragX;
csmFloat32 _dragY;
csmFloat32 _accelerationX;
csmFloat32 _accelerationY;
csmFloat32 _accelerationZ;
csmBool _mocConsistency;
csmBool _motionConsistency;
csmBool _debugMode;
private:
Rendering::CubismRenderer* _renderer;
};
}}}
@@ -0,0 +1,274 @@
/**
* 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 "ACubismMotion.hpp"
#include "Model/CubismModel.hpp"
#include "CubismMotionQueueEntry.hpp"
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
void ACubismMotion::Delete(ACubismMotion* motion)
{
CSM_DELETE_SELF(ACubismMotion, motion);
}
ACubismMotion::ACubismMotion()
: _fadeInSeconds(-1.0f)
, _fadeOutSeconds(-1.0f)
, _weight(1.0f)
, _offsetSeconds(0.0f) // 再生の開始時刻
, _isLoop(false) // trueから false へデフォルトを変更
, _isLoopFadeIn(true) // ループ時にフェードインが有効かどうかのフラグ
, _previousLoopState(_isLoop)
, _onBeganMotion(NULL)
, _onBeganMotionCustomData(NULL)
, _onFinishedMotion(NULL)
, _onFinishedMotionCustomData(NULL)
{ }
ACubismMotion::~ACubismMotion()
{
this->_weight = 0.0f;
}
void ACubismMotion::UpdateParameters(CubismModel* model, CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds)
{
if (!motionQueueEntry->IsAvailable() || motionQueueEntry->IsFinished())
{
return;
}
SetupMotionQueueEntry(motionQueueEntry, userTimeSeconds);
csmFloat32 fadeWeight = UpdateFadeWeight(motionQueueEntry, userTimeSeconds);
//---- 全てのパラメータIDをループする ----
DoUpdateParameters(model, userTimeSeconds, fadeWeight, motionQueueEntry);
//後処理
//終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager
if ((motionQueueEntry->GetEndTime() > 0.0f) && (motionQueueEntry->GetEndTime() < userTimeSeconds))
{
motionQueueEntry->IsFinished(true); //終了
}
}
void ACubismMotion::SetupMotionQueueEntry(CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds)
{
if (!motionQueueEntry->IsAvailable() || motionQueueEntry->IsFinished()) {
return;
}
if (motionQueueEntry->IsStarted()) {
return;
}
motionQueueEntry->IsStarted(true);
motionQueueEntry->SetStartTime(userTimeSeconds - _offsetSeconds); //モーションの開始時刻を記録
motionQueueEntry->SetFadeInStartTime(userTimeSeconds); //フェードインの開始時刻
if (motionQueueEntry->GetEndTime() < 0)
{
//開始していないうちに終了設定している場合がある。
AdjustEndTime(motionQueueEntry);
}
if (this->_onBeganMotion != NULL)
{
this->_onBeganMotion(this);
}
}
csmFloat32 ACubismMotion::UpdateFadeWeight(CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds)
{
if (motionQueueEntry == NULL)
{
CubismLogError("motionQueueEntry is null.");
return -1;
}
csmFloat32 fadeWeight = _weight; //現在の値と掛け合わせる割合
//---- フェードイン・アウトの処理 ----
//単純なサイン関数でイージングする
const csmFloat32 fadeIn = _fadeInSeconds == 0.0f
? 1.0f
: CubismMath::GetEasingSine((userTimeSeconds - motionQueueEntry->GetFadeInStartTime()) / _fadeInSeconds);
const csmFloat32 fadeOut = (_fadeOutSeconds == 0.0f || motionQueueEntry->GetEndTime() < 0.0f)
? 1.0f
: CubismMath::GetEasingSine((motionQueueEntry->GetEndTime() - userTimeSeconds) / _fadeOutSeconds);
fadeWeight = fadeWeight * fadeIn * fadeOut;
motionQueueEntry->SetState(userTimeSeconds, fadeWeight);
CSM_ASSERT(0.0f <= fadeWeight && fadeWeight <= 1.0f);
return fadeWeight;
}
void ACubismMotion::SetFadeInTime(csmFloat32 fadeInSeconds)
{
this->_fadeInSeconds = fadeInSeconds;
}
void ACubismMotion::SetFadeOutTime(csmFloat32 fadeOutSeconds)
{
this->_fadeOutSeconds = fadeOutSeconds;
}
csmFloat32 ACubismMotion::GetFadeOutTime() const
{
return this->_fadeOutSeconds;
}
csmFloat32 ACubismMotion::GetFadeInTime() const
{
return this->_fadeInSeconds;
}
void ACubismMotion::SetWeight(csmFloat32 weight)
{
this->_weight = weight;
}
csmFloat32 ACubismMotion::GetWeight() const
{
return this->_weight;
}
csmFloat32 ACubismMotion::GetDuration()
{
return -1.0f;
}
csmFloat32 ACubismMotion::GetLoopDuration()
{
return -1.0f;
}
void ACubismMotion::SetOffsetTime(csmFloat32 offsetSeconds)
{
this->_offsetSeconds = offsetSeconds;
}
void ACubismMotion::SetLoop(csmBool loop)
{
this->_isLoop = loop;
}
csmBool ACubismMotion::GetLoop() const
{
return this->_isLoop;
}
void ACubismMotion::SetLoopFadeIn(csmBool loopFadeIn)
{
this->_isLoopFadeIn = loopFadeIn;
}
csmBool ACubismMotion::GetLoopFadeIn() const
{
return this->_isLoopFadeIn;
}
const csmVector<const csmString*>& ACubismMotion::GetFiredEvent(csmFloat32 beforeCheckTimeSeconds, csmFloat32 motionTimeSeconds)
{
return _firedEventValues;
}
void ACubismMotion::SetBeganMotionHandler(BeganMotionCallback onBeganMotionHandler)
{
this->_onBeganMotion = onBeganMotionHandler;
}
ACubismMotion::BeganMotionCallback ACubismMotion::GetBeganMotionHandler() const
{
return this->_onBeganMotion;
}
void ACubismMotion::SetBeganMotionCustomData(void* onBeganMotionCustomData)
{
this->_onBeganMotionCustomData = onBeganMotionCustomData;
}
void* ACubismMotion::GetBeganMotionCustomData() const
{
return this->_onBeganMotionCustomData;
}
void ACubismMotion::SetBeganMotionHandlerAndMotionCustomData(BeganMotionCallback onBeganMotionHandler,
void* onBeganMotionCustomData)
{
this->_onBeganMotion = onBeganMotionHandler;
this->_onBeganMotionCustomData = onBeganMotionCustomData;
}
void ACubismMotion::SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler)
{
this->_onFinishedMotion = onFinishedMotionHandler;
}
ACubismMotion::FinishedMotionCallback ACubismMotion::GetFinishedMotionHandler()
{
return this->_onFinishedMotion;
}
void ACubismMotion::SetFinishedMotionCustomData(void* onFinishedMotionCustomData)
{
this->_onFinishedMotionCustomData = onFinishedMotionCustomData;
}
void* ACubismMotion::GetFinishedMotionCustomData()
{
return this->_onFinishedMotionCustomData;
}
void ACubismMotion::SetFinishedMotionHandlerAndMotionCustomData(FinishedMotionCallback onFinishedMotionHandler, void* onFinishedMotionCustomData)
{
this->_onFinishedMotion = onFinishedMotionHandler;
this->_onFinishedMotionCustomData = onFinishedMotionCustomData;
}
csmBool ACubismMotion::IsExistModelOpacity() const
{
return false;
}
csmInt32 ACubismMotion::GetModelOpacityIndex() const
{
return -1;
}
CubismIdHandle ACubismMotion::GetModelOpacityId(csmInt32 index)
{
return NULL;
}
csmFloat32 ACubismMotion::GetModelOpacityValue() const
{
return 1.0f;
}
void ACubismMotion::AdjustEndTime(CubismMotionQueueEntry* motionQueueEntry)
{
const csmFloat32 duration = GetDuration();
// duration == -1 の場合はループする
const csmFloat32 endTime = (duration <= 0) ?
-1 :
motionQueueEntry->GetStartTime() + duration;
motionQueueEntry->SetEndTime(endTime);
}
}}}
@@ -0,0 +1,321 @@
/**
* 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 "CubismFramework.hpp"
#include "Id/CubismId.hpp"
#include "Type/csmVector.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismMotionQueueManager;
class CubismMotionQueueEntry;
class CubismModel;
/**
* Abstract base class for motions.<br>
* Handles the management of motion playback through the MotionQueueManager.
*/
class ACubismMotion
{
public:
typedef void (*BeganMotionCallback)(ACubismMotion* self);
typedef void (*FinishedMotionCallback)(ACubismMotion* self);
/**
* Destroys the instance.
*
* @param motion instance to destroy
*/
static void Delete(ACubismMotion* motion);
/**
* Constructor
*/
ACubismMotion();
/**
* Updates the model parameters.
*
* @param model model to update
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
* @param userTimeSeconds current time in seconds
*/
void UpdateParameters(CubismModel* model, CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds);
/**
* Sets up to start the playback of the motion.
*
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
* @param userTimeSeconds total playback time in seconds
*/
void SetupMotionQueueEntry(CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds);
/**
* Sets the number of seconds for the motion to complete fading in.
*
* @param fadeInSeconds number of seconds for the fade-in to complete
*/
void SetFadeInTime(csmFloat32 fadeInSeconds);
/**
* Sets the number of seconds for the motion to complete fading out.
*
* @param fadeOutSeconds number of seconds for the fade-out to complete
*/
void SetFadeOutTime(csmFloat32 fadeOutSeconds);
/**
* Returns the number of seconds for the motion to complete fading out.
*
* @return number of seconds for the fade-out to complete
*/
csmFloat32 GetFadeOutTime() const;
/**
* Returns the number of seconds for the motion to complete fading in.
*
* @return number of seconds for the fade-in to complete
*/
csmFloat32 GetFadeInTime() const;
/**
* Sets the weight during the application of the motion.
*
* @param weight weight during the application of the motion (0.0-1.0)
*/
void SetWeight(csmFloat32 weight);
/**
* Returns the weight during the application of the motion.
*
* @return weight during the application of the motion (0.0-1.0)
*/
csmFloat32 GetWeight() const;
/**
* Returns the length of the motion.
*
* @return length of the motion in seconds<br>
* -1 if the motion is looping.
*
* @note When a positive value is returned, the motion ends at the obtained time.<br>
* When -1 is returned, the motion is looping and does not end.
*/
virtual csmFloat32 GetDuration();
/**
* Returns the length of one loop of the looping motion.
*
* @return length of one loop of the looping motion in seconds<br>
* Same value as GetDuration() if the motion is not looping.
*
* @note Returns -1 if the length of one loop of the looping motion cannot be determined.
*/
virtual csmFloat32 GetLoopDuration();
/**
* Sets the number of seconds to start the motion playback.
*
* @param offsetSeconds number of seconds to start the motion playback
*/
void SetOffsetTime(csmFloat32 offsetSeconds);
/**
* Sets whether the motion should loop.
*
* @param loop true to set the motion to loop
*/
void SetLoop(csmBool loop);
/**
* Checks whether the motion is set to loop.
*
* @return true if the motion is set to loop; otherwise false.
*/
csmBool GetLoop() const;
/**
* Sets whether to perform fade-in for looping motion.
*
* @param loopFadeIn true to perform fade-in for looping motion
*/
void SetLoopFadeIn(csmBool loopFadeIn);
/**
* Checks the setting for fade-in of looping motion.
*
* @return true if fade-in for looping motion is set; otherwise false.
*/
csmBool GetLoopFadeIn() const;
/**
* Returns the triggered user data events.
*
* @param beforeCheckTimeSeconds previous playback time in seconds
* @param motionTimeSeconds current playback time in seconds
*
* @return instance of the collection of triggered user data events
*
* @note The input times should be in seconds, with the motion timing set to zero.
*/
virtual const csmVector<const csmString*>& GetFiredEvent(csmFloat32 beforeCheckTimeSeconds,
csmFloat32 motionTimeSeconds);
/**
* Sets the motion playback completion callback.
*
* Not called in the following cases:
* 1. When the motion being played is set as "loop"
* 2. When NULL is set as the callback
*
* @param onBeganMotionHandler Motion playback start callback function
*/
void SetBeganMotionHandler(BeganMotionCallback onBeganMotionHandler);
/**
* Sets the motion playback start callback.
*
* @return Set motion playback start callback function. NULL if no function is set.
*/
BeganMotionCallback GetBeganMotionHandler() const;
/**
* Sets the user-defined data.
*
* @param onBeganMotionCustomData User-defined data
*/
void SetBeganMotionCustomData(void* onBeganMotionCustomData);
/**
* Returns the user-defined data.
*
* @return Set user-defined data.
*/
void* GetBeganMotionCustomData() const;
/**
* Sets the motion playback start callback.
*
* Not called in the following cases:
* 1. When the motion being played is set as "loop"
* 2. When NULL is set as the callback
*
* @param onBeganMotionHandler Motion playback start callback function
* @param onBeganMotionCustomData User-defined data
*/
void SetBeganMotionHandlerAndMotionCustomData(BeganMotionCallback onBeganMotionHandler, void* onBeganMotionCustomData);
/**
* Sets the callback function for when motion playback ends.
*
* @param onFinishedMotionHandler callback function for when motion playback ends
*
* @note The callback function is called at the timing of setting the IsFinished flag.<br>
* Not called in the following states:
* 1. When the playing motion is a loop motion
* 2. When the callback function is not set
*/
void SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler);
/**
* Returns the callback function for when motion playback ends.
*
* @return set callback function for when motion playback ends
*/
FinishedMotionCallback GetFinishedMotionHandler();
/**
* Sets the user-defined data.
*
* @param onFinishedMotionCustomData User-defined data
*/
void SetFinishedMotionCustomData(void* onFinishedMotionCustomData);
/**
* Returns the user-defined data.
*
* @return Set user-defined data.
*/
void* GetFinishedMotionCustomData();
/**
* Sets the motion playback completion callback.
*
* Called when the IsFinished flag is set.
* Not called in the following cases:
* 1. When the motion being played is set as "loop"
* 2. When NULL is set as the callback
*
* @param onFinishedMotionHandler Motion playback completion callback function
* @param onFinishedMotionCustomData User-defined data
*/
void SetFinishedMotionHandlerAndMotionCustomData(FinishedMotionCallback onFinishedMotionHandler, void* onFinishedMotionCustomData);
/**
* Checks whether there is an opacity curve.
*
* @return true if the key exists; otherwise false.
*/
virtual csmBool IsExistModelOpacity() const;
/**
* Returns the index of the opacity curve.
*
* @return index of the opacity curve on success
*/
virtual csmInt32 GetModelOpacityIndex() const;
/**
* Returns the ID of the opacity.
*
* @return ID of the opacity on success
*/
virtual CubismIdHandle GetModelOpacityId(csmInt32 index);
/**
* Updates the fade weight of the motion.
*
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
* @param userTimeSeconds cumulative delta time in seconds
*
* @return true if the fade weight of the motion is updated; otherwise false.
*/
csmFloat32 UpdateFadeWeight(CubismMotionQueueEntry* motionQueueEntry, csmFloat32 userTimeSeconds);
private:
// Prevention of copy Constructor
ACubismMotion(const ACubismMotion&);
ACubismMotion& operator=(const ACubismMotion&);
protected:
virtual ~ACubismMotion();
virtual csmFloat32 GetModelOpacityValue() const;
virtual void DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSeconds, csmFloat32 weight, CubismMotionQueueEntry* motionQueueEntry) = 0;
void AdjustEndTime(CubismMotionQueueEntry* motionQueueEntry);
csmFloat32 _fadeInSeconds;
csmFloat32 _fadeOutSeconds;
csmFloat32 _weight;
csmFloat32 _offsetSeconds;
csmBool _isLoop;
csmBool _isLoopFadeIn;
csmBool _previousLoopState;
csmVector<const csmString*> _firedEventValues;
BeganMotionCallback _onBeganMotion;
void* _onBeganMotionCustomData;
FinishedMotionCallback _onFinishedMotion;
void* _onFinishedMotionCustomData;
};
}}}
+20
View File
@@ -0,0 +1,20 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/ACubismMotion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ACubismMotion.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismExpressionMotion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismExpressionMotion.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismExpressionMotionManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismExpressionMotionManager.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotion.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionInternal.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionJson.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionJson.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionManager.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionQueueEntry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionQueueEntry.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionQueueManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismMotionQueueManager.hpp
)
@@ -0,0 +1,253 @@
/**
* 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 "CubismExpressionMotion.hpp"
#include "CubismMotionQueueEntry.hpp"
#include "Id/CubismIdManager.hpp"
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
const csmFloat32 CubismExpressionMotion::DefaultAdditiveValue = 0.0f; ///< 加算適用の初期値
const csmFloat32 CubismExpressionMotion::DefaultMultiplyValue = 1.0f; ///< 乗算適用の初期値
namespace {
// exp3.jsonのキーとデフォルト値
const csmChar* ExpressionKeyFadeIn = "FadeInTime";
const csmChar* ExpressionKeyFadeOut = "FadeOutTime";
const csmChar* ExpressionKeyParameters = "Parameters";
const csmChar* ExpressionKeyId = "Id";
const csmChar* ExpressionKeyValue = "Value";
const csmChar* ExpressionKeyBlend = "Blend";
const csmChar* BlendValueAdd = "Add";
const csmChar* BlendValueMultiply = "Multiply";
const csmChar* BlendValueOverwrite = "Overwrite";
const csmFloat32 DefaultFadeTime = 1.0f;
}
CubismExpressionMotion::CubismExpressionMotion()
{ }
CubismExpressionMotion::~CubismExpressionMotion()
{ }
CubismExpressionMotion* CubismExpressionMotion::Create(const csmByte* buffer, csmSizeInt size)
{
CubismExpressionMotion* expression = CSM_NEW CubismExpressionMotion();
expression->Parse(buffer, size);
return expression;
}
void CubismExpressionMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSeconds, csmFloat32 weight, CubismMotionQueueEntry* motionQueueEntry)
{
for (csmUint32 i = 0; i < _parameters.GetSize(); ++i)
{
ExpressionParameter& parameter = _parameters[i];
switch (parameter.BlendType)
{
case Additive: {
model->AddParameterValue(parameter.ParameterId, parameter.Value, weight); // 相対変化 加算
break;
}
case Multiply: {
model->MultiplyParameterValue(parameter.ParameterId, parameter.Value, weight); // 相対変化 乗算
break;
}
case Overwrite: {
model->SetParameterValue(parameter.ParameterId, parameter.Value, weight); // 絶対変化 上書き
break;
}
default:
// 仕様にない値を設定したときは既に加算モードになっている
break;
}
}
}
void CubismExpressionMotion::CalculateExpressionParameters(CubismModel* model, csmFloat32 userTimeSeconds, CubismMotionQueueEntry* motionQueueEntry,
csmVector<CubismExpressionMotionManager::ExpressionParameterValue>* expressionParameterValues, csmInt32 expressionIndex, csmFloat32 fadeWeight)
{
if (motionQueueEntry == NULL || expressionParameterValues == NULL)
{
return;
}
if (!motionQueueEntry->IsAvailable())
{
return;
}
// CubismExpressionMotion._fadeWeight は廃止予定です。
// 互換性のために処理は残りますが、実際には使用しておりません。
_fadeWeight = UpdateFadeWeight(motionQueueEntry, userTimeSeconds);
// モデルに適用する値を計算
for (csmInt32 i = 0; i < expressionParameterValues->GetSize(); ++i)
{
CubismExpressionMotionManager::ExpressionParameterValue expressionParameterValue = expressionParameterValues->At(i);
if (expressionParameterValue.ParameterId == NULL)
{
continue;
}
const csmFloat32 currentParameterValue = expressionParameterValue.OverwriteValue =
model->GetParameterValue(expressionParameterValue.ParameterId);
csmVector<ExpressionParameter> expressionParameters = GetExpressionParameters();
csmInt32 parameterIndex = -1;
for (csmInt32 j = 0; j < expressionParameters.GetSize(); ++j)
{
if (expressionParameterValue.ParameterId != expressionParameters[j].ParameterId)
{
continue;
}
parameterIndex = j;
break;
}
// 再生中のExpressionが参照していないパラメータは初期値を適用
if (parameterIndex < 0)
{
if (expressionIndex == 0)
{
expressionParameterValues->At(i).AdditiveValue = DefaultAdditiveValue;
expressionParameterValues->At(i).MultiplyValue = DefaultMultiplyValue;
expressionParameterValues->At(i).OverwriteValue = currentParameterValue;
}
else
{
expressionParameterValues->At(i).AdditiveValue =
CalculateValue(expressionParameterValue.AdditiveValue, DefaultAdditiveValue, fadeWeight);
expressionParameterValues->At(i).MultiplyValue =
CalculateValue(expressionParameterValue.MultiplyValue, DefaultMultiplyValue, fadeWeight);
expressionParameterValues->At(i).OverwriteValue =
CalculateValue(expressionParameterValue.OverwriteValue, currentParameterValue, fadeWeight);
}
continue;
}
// 値を計算
csmFloat32 value = expressionParameters.At(parameterIndex).Value;
csmFloat32 newAdditiveValue, newMultiplyValue, newSetValue;
switch (expressionParameters.At(parameterIndex).BlendType) {
case Additive:
newAdditiveValue = value;
newMultiplyValue = DefaultMultiplyValue;
newSetValue = currentParameterValue;
break;
case Multiply:
newAdditiveValue = DefaultAdditiveValue;
newMultiplyValue = value;
newSetValue = currentParameterValue;
break;
case Overwrite:
newAdditiveValue = DefaultAdditiveValue;
newMultiplyValue = DefaultMultiplyValue;
newSetValue = value;
break;
default:
return;
}
if (expressionIndex == 0) {
expressionParameterValues->At(i).AdditiveValue = newAdditiveValue;
expressionParameterValues->At(i).MultiplyValue = newMultiplyValue;
expressionParameterValues->At(i).OverwriteValue = newSetValue;
}
else {
expressionParameterValues->At(i).AdditiveValue = (expressionParameterValue.AdditiveValue * (1.0f - fadeWeight)) + newAdditiveValue * fadeWeight;
expressionParameterValues->At(i).MultiplyValue = (expressionParameterValue.MultiplyValue * (1.0f - fadeWeight)) + newMultiplyValue * fadeWeight;
expressionParameterValues->At(i).OverwriteValue = (expressionParameterValue.OverwriteValue * (1.0f - fadeWeight)) + newSetValue * fadeWeight;
}
}
}
csmVector<CubismExpressionMotion::ExpressionParameter> CubismExpressionMotion::GetExpressionParameters()
{
return _parameters;
}
csmFloat32 CubismExpressionMotion::GetFadeWeight()
{
CubismLogWarning("GetFadeWeight() is a deprecated function. Please use CubismExpressionMotionManager.GetFadeWeight(int index).");
return _fadeWeight;
}
void CubismExpressionMotion::Parse(const csmByte* buffer, csmSizeInt size)
{
Utils::CubismJson* json = Utils::CubismJson::Create(buffer, size);
if (!json)
{
return;
}
Utils::Value& root = json->GetRoot();
SetFadeInTime(root[ExpressionKeyFadeIn].ToFloat(DefaultFadeTime)); // フェードイン
SetFadeOutTime(root[ExpressionKeyFadeOut].ToFloat(DefaultFadeTime)); // フェードアウト
// 各パラメータについて
const csmInt32 parameterCount = root[ExpressionKeyParameters].GetSize();
_parameters.PrepareCapacity(parameterCount);
for (csmInt32 i = 0; i < parameterCount; ++i)
{
Utils::Value& param = root[ExpressionKeyParameters][i];
const CubismIdHandle parameterId = CubismFramework::GetIdManager()->GetId(param[ExpressionKeyId].GetRawString()); // パラメータID
const csmFloat32 value = static_cast<csmFloat32>(param[ExpressionKeyValue].ToFloat()); // 値
// 計算方法の設定
ExpressionBlendType blendType;
if (param[ExpressionKeyBlend].IsNull() || param[ExpressionKeyBlend].GetString() == BlendValueAdd)
{
blendType = Additive;
}
else if (param[ExpressionKeyBlend].GetString() == BlendValueMultiply)
{
blendType = Multiply;
}
else if (param[ExpressionKeyBlend].GetString() == BlendValueOverwrite)
{
blendType = Overwrite;
}
else
{
// その他 仕様にない値を設定したときは加算モードにすることで復旧
blendType = Additive;
}
// 設定オブジェクトを作成してリストに追加する
ExpressionParameter item;
item.ParameterId = parameterId;
item.BlendType = blendType;
item.Value = value;
_parameters.PushBack(item);
}
Utils::CubismJson::Delete(json);// JSONデータは不要になったら削除する
}
csmFloat32 CubismExpressionMotion::CalculateValue(csmFloat32 source, csmFloat32 destination, csmFloat32 fadeWeight)
{
return (source * (1.0f - fadeWeight)) + (destination * fadeWeight);
}
}}}
@@ -0,0 +1,112 @@
/**
* 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 "ACubismMotion.hpp"
#include "Utils/CubismJson.hpp"
#include "Model/CubismModel.hpp"
#include "CubismExpressionMotionManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles facial expression motions.
*/
class CubismExpressionMotion : public ACubismMotion
{
public:
/**
* Blending calculation method for facial expression parameters
*/
enum ExpressionBlendType
{
Additive = 0, ///< Addition
Multiply = 1, ///< Multiplication
Overwrite = 2 ///< Overwrite
};
/**
* Data for facial expression parameter information
*/
struct ExpressionParameter
{
CubismIdHandle ParameterId; ///< Attached parameter ID
ExpressionBlendType BlendType; ///< Blending calculation method for facial expression parameters attached to the parameter
csmFloat32 Value; ///< Parameter value
};
/**
* Makes an instance.
*
* @param buf buffer containing the loaded facial expression settings file
* @param size size of the buffer in bytes
*
* @return created instance
*/
static CubismExpressionMotion* Create(const csmByte* buf, csmSizeInt size);
/**
* Updates the model parameters.
*
* @param model model to update
* @param userTimeSeconds current time in seconds
* @param weight weight during the application of the motion (0.0-1.0)
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
*/
virtual void DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSeconds, csmFloat32 weight, CubismMotionQueueEntry* motionQueueEntry);
/**
* Computes the parameters related to the model's facial expressions.
*
* @param model model to update
* @param userTimeSeconds cumulative delta time in seconds
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
* @param expressionParameterValues values of each parameter to be applied to the model
* @param expressionIndex index of the facial expression
*/
void CalculateExpressionParameters(CubismModel* model, csmFloat32 userTimeSeconds, CubismMotionQueueEntry* motionQueueEntry,
csmVector<CubismExpressionMotionManager::ExpressionParameterValue>* expressionParameterValues, csmInt32 expressionIndex, csmFloat32 fadeWeight);
/**
* Returns the parameters referenced by the facial expression.
*/
csmVector<ExpressionParameter> GetExpressionParameters();
/**
* Returns the current fade weight value of the facial expression.
*
* @return fade weight value of the facial expression
*
* @deprecated Not recommended due to the planned removal of CubismExpressionMotion._fadeWeight.
* Use CubismExpressionMotionManager.getFadeWeight(int index) instead.
*
* @see CubismExpressionMotionManager#getFadeWeight(int index)
*/
csmFloat32 GetFadeWeight();
static const csmFloat32 DefaultAdditiveValue;
static const csmFloat32 DefaultMultiplyValue;
protected:
CubismExpressionMotion();
virtual ~CubismExpressionMotion();
void Parse(const csmByte* exp3Json, csmSizeInt size);
csmVector<ExpressionParameter> _parameters;
private:
csmFloat32 CalculateValue(csmFloat32 source, csmFloat32 destination, csmFloat32 fadeWeight);
csmFloat32 _fadeWeight;
};
}}}
@@ -0,0 +1,227 @@
/**
* 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 "CubismExpressionMotionManager.hpp"
#include "CubismExpressionMotion.hpp"
#include "CubismMotionQueueEntry.hpp"
#include "CubismFramework.hpp"
#include "Math/CubismMath.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismExpressionMotionManager::CubismExpressionMotionManager()
: _currentPriority(0)
, _reservePriority(0)
, _expressionParameterValues(CSM_NEW csmVector<ExpressionParameterValue>())
, _fadeWeights(CSM_NEW csmVector<csmFloat32>())
{ }
CubismExpressionMotionManager::~CubismExpressionMotionManager()
{
if(_expressionParameterValues)
{
CSM_DELETE(_expressionParameterValues);
_expressionParameterValues = NULL;
}
if (_fadeWeights)
{
CSM_DELETE(_fadeWeights);
_fadeWeights = NULL;
}
}
csmInt32 CubismExpressionMotionManager::GetCurrentPriority() const
{
CubismLogWarning("CubismExpressionMotionManager::GetCurrentPriority() is deprecated because a priority value is not actually used during expression motion playback.");
return _currentPriority;
}
csmInt32 CubismExpressionMotionManager::GetReservePriority() const
{
CubismLogWarning("CubismExpressionMotionManager::GetReservePriority() is deprecated because a priority value is not actually used during expression motion playback.");
return _reservePriority;
}
void CubismExpressionMotionManager::SetReservePriority(csmInt32 priority)
{
CubismLogWarning("CubismExpressionMotionManager::SetReservePriority() is deprecated because a priority value is not actually used during expression motion playback.");
_reservePriority = priority;
}
CubismMotionQueueEntryHandle CubismExpressionMotionManager::StartMotionPriority(ACubismMotion* motion, csmBool autoDelete, csmInt32 priority)
{
CubismLogWarning("CubismExpressionMotionManager::StartMotionPriority() is deprecated because a priority value is not actually used during expression motion playback.");
if (priority == _reservePriority)
{
_reservePriority = 0; // 予約を解除
}
_currentPriority = priority; // 再生中モーションの優先度を設定
return CubismMotionQueueManager::StartMotion(motion, autoDelete);
}
csmBool CubismExpressionMotionManager::UpdateMotion(CubismModel* model, csmFloat32 deltaTimeSeconds)
{
_userTimeSeconds += deltaTimeSeconds;
csmBool updated = false;
csmVector<CubismMotionQueueEntry*>* motions = GetCubismMotionQueueEntries();
csmFloat32 expressionWeight = 0.0f;
csmInt32 expressionIndex = 0;
while (_fadeWeights->GetSize() < motions->GetSize())
{
_fadeWeights->PushBack(0.0f);
}
// ------- 処理を行う --------
// 既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = motions->Begin(); ite != motions->End();)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
ite = motions->Erase(ite); // 削除
continue;
}
CubismExpressionMotion* expressionMotion = (CubismExpressionMotion*)motionQueueEntry->GetCubismMotion();
if (expressionMotion == NULL)
{
CSM_DELETE(motionQueueEntry);
ite = motions->Erase(ite); // 削除
continue;
}
csmVector<CubismExpressionMotion::ExpressionParameter> expressionParameters = expressionMotion->GetExpressionParameters();
if (motionQueueEntry->IsAvailable())
{
// 再生中のExpressionが参照しているパラメータをすべてリストアップ
for (csmInt32 i = 0; i < expressionParameters.GetSize(); ++i)
{
if (expressionParameters[i].ParameterId == NULL)
{
continue;
}
csmInt32 index = -1;
// リストにパラメータIDが存在するか検索
for (csmInt32 j = 0; j < _expressionParameterValues->GetSize(); ++j)
{
if (_expressionParameterValues->At(j).ParameterId != expressionParameters[i].ParameterId)
{
continue;
}
index = j;
break;
}
if (index >= 0)
{
continue;
}
// パラメータがリストに存在しないなら新規追加
ExpressionParameterValue item;
item.ParameterId = expressionParameters[i].ParameterId;
item.AdditiveValue = CubismExpressionMotion::DefaultAdditiveValue;
item.MultiplyValue = CubismExpressionMotion::DefaultMultiplyValue;
item.OverwriteValue = model->GetParameterValue(item.ParameterId);
_expressionParameterValues->PushBack(item);
}
}
// ------ 値を計算する ------
expressionMotion->SetupMotionQueueEntry(motionQueueEntry, _userTimeSeconds);
SetFadeWeight(expressionIndex, expressionMotion->UpdateFadeWeight(motionQueueEntry, _userTimeSeconds));
expressionMotion->CalculateExpressionParameters(model, _userTimeSeconds, motionQueueEntry,
_expressionParameterValues, expressionIndex, GetFadeWeight(expressionIndex));
expressionWeight += expressionMotion->GetFadeInTime() == 0.0f
? 1.0f
: CubismMath::GetEasingSine((_userTimeSeconds - motionQueueEntry->GetFadeInStartTime()) / expressionMotion->GetFadeInTime());
updated = true;
if (motionQueueEntry->IsTriggeredFadeOut())
{
// フェードアウト開始
motionQueueEntry->StartFadeout(motionQueueEntry->GetFadeOutSeconds(), _userTimeSeconds);
}
++ite;
++expressionIndex;
}
// ----- 最新のExpressionのフェードが完了していればそれ以前を削除する ------
if (motions->GetSize() > 1)
{
csmFloat32 latestFadeWeight = GetFadeWeight(_fadeWeights->GetSize() - 1);
if (latestFadeWeight >= 1.0f)
{
// 配列の最後の要素は削除しない
for (csmInt32 i = motions->GetSize()-2; i >= 0; i--)
{
CubismMotionQueueEntry* motionQueueEntry = motions->At(i);
CSM_DELETE(motionQueueEntry);
motions->Remove(i);
_fadeWeights->Remove(i);
}
}
}
if (expressionWeight > 1.0f)
{
expressionWeight = 1.0f;
}
// モデルに各値を適用
for (csmInt32 i = 0; i < _expressionParameterValues->GetSize(); ++i)
{
model->SetParameterValue(_expressionParameterValues->At(i).ParameterId,
(_expressionParameterValues->At(i).OverwriteValue + _expressionParameterValues->At(i).AdditiveValue) * _expressionParameterValues->At(i).MultiplyValue,
expressionWeight);
_expressionParameterValues->At(i).AdditiveValue = CubismExpressionMotion::DefaultAdditiveValue;
_expressionParameterValues->At(i).MultiplyValue = CubismExpressionMotion::DefaultMultiplyValue;
}
return updated;
}
csmFloat32 CubismExpressionMotionManager::GetFadeWeight(csmInt32 index)
{
if (index < 0 || _fadeWeights->GetSize() < 1 || _fadeWeights->GetSize() <= index)
{
CubismLogWarning("Failed to get the fade weight value. The element at that index does not exist.");
return -1;
}
return _fadeWeights->At(index);
}
void CubismExpressionMotionManager::SetFadeWeight(csmInt32 index, csmFloat32 expressionFadeWeight)
{
if (index < 0 || _fadeWeights->GetSize() < 1 || _fadeWeights->GetSize() <= index)
{
CubismLogWarning("Failed to set the fade weight value. The element at that index does not exist.");
return;
}
_fadeWeights->At(index) = expressionFadeWeight;
}
}}}
@@ -0,0 +1,121 @@
/**
* 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 "ACubismMotion.hpp"
#include "CubismMotionQueueManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the management of facial expression motions.
*/
class CubismExpressionMotionManager : public CubismMotionQueueManager
{
public:
/**
* Structure that holds facial expression values to apply to parameters
*/
struct ExpressionParameterValue
{
CubismIdHandle ParameterId; ///< Parameter ID
csmFloat32 AdditiveValue; ///< Added value
csmFloat32 MultiplyValue; ///< Multiplied value
csmFloat32 OverwriteValue; ///< Overwritten value
};
/**
* Constructor
*/
CubismExpressionMotionManager();
/**
* Destructor
*/
virtual ~CubismExpressionMotionManager();
/**
* Returns the priority of the playing facial expression motion.
*
* @deprecated This function is deprecated because a priority value is not actually used during expression motion playback.
*
* @return priority of the facial expression motion
*/
csmInt32 GetCurrentPriority() const;
/**
* Returns the priority of the reserved facial expression motion.
*
* @deprecated This function is deprecated because a priority value is not actually used during expression motion playback.
*
* @return priority of the facial expression motion
*/
csmInt32 GetReservePriority() const;
/**
* Sets the priority of the reserved facial expression motion.
*
* @deprecated This function is deprecated because a priority value is not actually used during expression motion playback.
*
* @param[in] priority priority to set
*/
void SetReservePriority(csmInt32 priority);
/**
* Starts the facial expression motion with the specified priority.
*
* @deprecated This function is deprecated because a priority value is not actually used during expression motion playback.
* Use CubismMotionQueueManager::StartMotion(ACubismMotion* motion, csmBool autoDelete) instead.
*
* @param[in] motion motion
* @param[in] autoDelete true to delete the instance of the motion when playback ends
* @param[in] priority priority
* @return identifier of the started motion. Use this as an argument to IsFinished() to determine if the individual motion has finished. Returns -1 if the motion could not be started.
*/
CubismMotionQueueEntryHandle StartMotionPriority(ACubismMotion* motion, csmBool autoDelete, csmInt32 priority);
/**
* Updates the facial expression motion and reflects the parameter values on the model.
*
* @param[in] model target model
* @param[in] deltaTimeSeconds delta time in seconds
* @return true if updated; otherwise false.
*/
csmBool UpdateMotion(CubismModel* model, csmFloat32 deltaTimeSeconds);
/**
* @param index index of the facial expression motion to retrieve
*
* @return fade weight value of the facial expression
*/
csmFloat32 GetFadeWeight(csmInt32 index);
private:
/**
* @brief Set the weight of expression fade
*
* Set the weight of expression fade.
*
* @param[in] index Index of the expression motion to be set
* @param[in] expressionFadeWeight Weight value of expression fade
*/
void SetFadeWeight(csmInt32 index, csmFloat32 expressionFadeWeight);
// Values of each parameter to be applied to the model
csmVector<ExpressionParameterValue>* _expressionParameterValues;
// Weights of the currently playing expression
csmVector<csmFloat32>* _fadeWeights;
csmInt32 _currentPriority; ///< @deprecated This variable is deprecated because a priority value is not actually used during expression motion playback.
csmInt32 _reservePriority; ///< @deprecated This variable is deprecated because a priority value is not actually used during expression motion playback.
};
}}}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,241 @@
/**
* 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 "ACubismMotion.hpp"
#include "Type/CubismBasicType.hpp"
#include "Type/csmVector.hpp"
#include "Id/CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismMotionQueueEntry;
struct CubismMotionData;
/**
* Handles motions.
*/
class CubismMotion : public ACubismMotion
{
public:
/**
* Enumerator for version control of Motion Behavior
For details, see the SDK Manual.
*/
enum MotionBehavior
{
MotionBehavior_V1,
MotionBehavior_V2,
};
/**
* Makes an instance.
*
* @param buf buffer containing the loaded motion file
* @param size size of the buffer in bytes
* @param onFinishedMotionHandler callback function for when motion playback ends
* @param onBeganMotionHandler callback function for when motion playback starts
* @param shouldCheckMotionConsistency flag to validate the consistency of motion3.json
*
* @return created instance
*/
static CubismMotion* Create(const csmByte* buffer, csmSizeInt size, FinishedMotionCallback onFinishedMotionHandler = NULL, BeganMotionCallback onBeganMotionHandler = NULL, csmBool shouldCheckMotionConsistency = false);
/**
* Updates the model parameters.
*
* @param model model to update
* @param userTimeSeconds current time in seconds
* @param weight weight during the application of the motion (0.0-1.0)
* @param motionQueueEntry motion managed by the CubismMotionQueueManager
*/
virtual void DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSeconds, csmFloat32 fadeWeight, CubismMotionQueueEntry* motionQueueEntry);
/**
* @deprecated Not recommended due to the relocation of _isLoop to the base class.
* Use ACubismMotion.SetLoop(csmBool loop) instead.
*
* Sets whether the motion should loop.
*
* @param loop true to set the motion to loop
*/
void IsLoop(csmBool loop);
/**
* @deprecated Not recommended due to the relocation of _isLoop to the base class.
* Use ACubismMotion.GetLoop() instead.
*
* Checks whether the motion is set to loop.
*
* @return true if the motion is set to loop; otherwise false.
*/
csmBool IsLoop() const;
/**
* @deprecated Not recommended due to the relocation of _isLoopFadeIn to the base class.
* Use ACubismMotion.SetLoopFadeIn(csmBool loopFadeIn) instead.
*
* Sets whether to perform fade-in for looping motion.
*
* @param loopFadeIn true to perform fade-in for looping motion
*/
void IsLoopFadeIn(csmBool loopFadeIn);
/**
* @deprecated Not recommended due to the relocation of _isLoopFadeIn to the base class.
* Use ACubismMotion.GetLoopFadeIn() instead.
*
* Checks the setting for fade-in of looping motion.
*
* @return true if fade-in for looping motion is set; otherwise false.
*/
csmBool IsLoopFadeIn() const;
/**
* Sets the version of the Motion Behavior.
*
* @param Specifies the version of the Motion Behavior.
*/
void SetMotionBehavior(MotionBehavior motionBehavior);
/**
* Gets the version of the Motion Behavior.
*
* @return Returns the version of the Motion Behavior.
*/
MotionBehavior GetMotionBehavior() const;
/**
* Returns the length of the motion.
*
* @return length of the motion in seconds<br>
* -1 if the motion is looping.
*
* @note When a positive value is returned, the motion ends at the obtained time.<br>
* When -1 is returned, the motion is looping and does not end.
*/
virtual csmFloat32 GetDuration();
/**
* Returns the length of one loop of the looping motion.
*
* @return length of one loop of the looping motion in seconds<br>
* Same value as GetDuration() if the motion is not looping.
*
* @note Returns -1 if the length of one loop of the looping motion cannot be determined.
*/
virtual csmFloat32 GetLoopDuration();
/**
* Sets the number of seconds for the motion parameter to complete fading in.
*
* @param parameterId parameter ID
* @param value number of seconds for the fade-in to complete
*/
void SetParameterFadeInTime(CubismIdHandle parameterId, csmFloat32 value);
/**
* Sets the number of seconds for the motion parameter to complete fading out.
*
* @param parameterId parameter ID
* @param value number of seconds for the fade-out to complete
*/
void SetParameterFadeOutTime(CubismIdHandle parameterId, csmFloat32 value);
/**
* Sets the number of seconds for the motion parameter to complete fading in.
*
* @param parameterId parameter ID
* @param value number of seconds for the fade-in to complete
*/
csmFloat32 GetParameterFadeInTime(CubismIdHandle parameterId) const;
/**
* Sets the number of seconds for the motion parameter to complete fading out.
*
* @param parameterId parameter ID
* @param value number of seconds for the fade-out to complete
*/
csmFloat32 GetParameterFadeOutTime(CubismIdHandle parameterId) const;
/**
* Sets the collections of parameter IDs associated with the eye blink and lip sync settings.
*
* @param eyeBlinkParameterIds collection of parameter IDs associated with the eye blink settings
* @param lipSyncParameterIds collection of parameter IDs associated with the lip sync settings
*/
void SetEffectIds(const csmVector<CubismIdHandle>& eyeBlinkParameterIds, const csmVector<CubismIdHandle>& lipSyncParameterIds);
/**
* Returns the triggered user data events.
*
* @param beforeCheckTimeSeconds previous playback time in seconds
* @param motionTimeSeconds current playback time in seconds
*
* @return instance of the collection of triggered user data events
*
* @note The input times should be in seconds, with the motion timing set to zero.
*/
virtual const csmVector<const csmString*>& GetFiredEvent(csmFloat32 beforeCheckTimeSeconds, csmFloat32 motionTimeSeconds);
/**
* Checks whether there is an opacity curve.
*
* @return true if the key exists; otherwise false.
*/
csmBool IsExistModelOpacity() const;
/**
* Returns the index of the opacity curve.
*
* @return index of the opacity curve on success
*/
csmInt32 GetModelOpacityIndex() const;
/**
* Returns the ID of the opacity.
*
* @return ID of the opacity on success
*/
CubismIdHandle GetModelOpacityId(csmInt32 index);
protected:
csmFloat32 GetModelOpacityValue() const;
private:
CubismMotion();
virtual ~CubismMotion();
CubismMotion(const CubismMotion&);
CubismMotion& operator=(const CubismMotion&);
void UpdateForNextLoop(CubismMotionQueueEntry* motionQueueEntry, const csmFloat32 userTimeSeconds, const csmFloat32 time);
void Parse(const csmByte* motionJson, const csmSizeInt size, csmBool shouldCheckMotionConsistency);
csmFloat32 _sourceFrameRate;
csmFloat32 _loopDurationSeconds;
MotionBehavior _motionBehavior;
csmFloat32 _lastWeight;
CubismMotionData* _motionData;
csmVector<CubismIdHandle> _eyeBlinkParameterIds;
csmVector<CubismIdHandle> _lipSyncParameterIds;
CubismIdHandle _modelCurveIdEyeBlink;
CubismIdHandle _modelCurveIdLipSync;
CubismIdHandle _modelCurveIdOpacity;
csmFloat32 _modelOpacity;
};
}}}
//--------- LIVE2D NAMESPACE ------------
@@ -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
#include "CubismFramework.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Types of motion curve application targets
*/
enum CubismMotionCurveTarget
{
CubismMotionCurveTarget_Model, ///< Applied to model
CubismMotionCurveTarget_Parameter, ///< Applied to parameter
CubismMotionCurveTarget_PartOpacity ///< Applied to part opacity
};
/**
* Types of motion curve segments
*/
enum CubismMotionSegmentType
{
CubismMotionSegmentType_Linear = 0, ///< Linear
CubismMotionSegmentType_Bezier = 1, ///< Bezier curve
CubismMotionSegmentType_Stepped = 2, ///< Step
CubismMotionSegmentType_InverseStepped = 3 ///< Inverse step
};
/**
* Data for control points of motion curve
*/
struct CubismMotionPoint
{
/**
* Constructor
*/
CubismMotionPoint()
: Time(0.0f)
, Value(0.0f)
{ }
csmFloat32 Time; ///< Time [seconds]
csmFloat32 Value; ///< Value
};
/**
* Function declaration for evaluating motion curve segments
*
* @param points Collection of control points for the motion curve
* @param time Time to evaluate [seconds]
*/
typedef csmFloat32 (*csmMotionSegmentEvaluationFunction)(const CubismMotionPoint* points, const csmFloat32 time);
/**
* Data for motion curve segments
*/
struct CubismMotionSegment
{
/**
* Constructor
*/
CubismMotionSegment()
: Evaluate(NULL)
, BasePointIndex(0)
, SegmentType(0)
{ }
csmMotionSegmentEvaluationFunction Evaluate; ///< Function to evaluate segment
csmInt32 BasePointIndex; ///< Index of the first control point
csmInt32 SegmentType; ///< Segment type
};
/**
* Data for motion curve
*/
struct CubismMotionCurve
{
/**
* Constructor
*/
CubismMotionCurve()
: Type(CubismMotionCurveTarget_Model)
, SegmentCount(0)
, BaseSegmentIndex(0)
, FadeInTime(0.0f)
, FadeOutTime(0.0f)
{ }
CubismMotionCurveTarget Type; ///< Curve type
CubismIdHandle Id; ///< ID of the parameter attached to the curve
csmInt32 SegmentCount; ///< Number of segments
csmInt32 BaseSegmentIndex; ///< Index of the first segment
csmFloat32 FadeInTime; ///< Seconds to complete fade-in from start to finish [seconds]
csmFloat32 FadeOutTime; ///< Seconds to complete fade-out from start to finish [seconds]
};
/**
* Data for user data events
*/
struct CubismMotionEvent
{
/**
* Constructor
*/
CubismMotionEvent()
: FireTime(0.0f)
{ }
csmFloat32 FireTime; ///< Seconds in motion when the event fires [seconds]
csmString Value; ///< Value
};
/**
* Data for motion
*/
struct CubismMotionData
{
/**
* Constructor
*/
CubismMotionData()
: Duration(0.0f)
, Loop(0)
, CurveCount(0)
, EventCount(0)
, Fps(0.0f)
{ }
csmFloat32 Duration; ///< Motion length [seconds]
csmInt16 Loop; ///< Whether to loop
csmInt16 CurveCount; ///< Number of curves
csmInt32 EventCount; ///< Number of user data events
csmFloat32 Fps; ///< Motion frame rate
csmVector<CubismMotionCurve> Curves; ///< Curve collection
csmVector<CubismMotionSegment> Segments; ///< Segment collection
csmVector<CubismMotionPoint> Points; ///< Control point collection
csmVector<CubismMotionEvent> Events; ///< User data event collection
};
}}}
@@ -0,0 +1,241 @@
/**
* 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 "CubismMotionJson.hpp"
#include "CubismMotionInternal.hpp"
#include "Id/CubismId.hpp"
#include "Id/CubismIdManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
namespace {
// JSON keys
const csmChar* Meta = "Meta";
const csmChar* Duration = "Duration";
const csmChar* Loop = "Loop";
const csmChar* AreBeziersRestricted = "AreBeziersRestricted";
const csmChar* CurveCount = "CurveCount";
const csmChar* Fps = "Fps";
const csmChar* TotalSegmentCount = "TotalSegmentCount";
const csmChar* TotalPointCount = "TotalPointCount";
const csmChar* Curves = "Curves";
const csmChar* Target = "Target";
const csmChar* Id = "Id";
const csmChar* FadeInTime = "FadeInTime";
const csmChar* FadeOutTime = "FadeOutTime";
const csmChar* Segments = "Segments";
const csmChar* UserData = "UserData";
const csmChar* UserDataCount = "UserDataCount";
const csmChar* TotalUserDataSize = "TotalUserDataSize";
const csmChar* Time = "Time";
const csmChar* Value = "Value";
}
CubismMotionJson::CubismMotionJson(const csmByte* buffer, csmSizeInt size)
{
CreateCubismJson(buffer, size);
}
CubismMotionJson::~CubismMotionJson()
{
DeleteCubismJson();
}
csmFloat32 CubismMotionJson::GetMotionDuration() const
{
return _json->GetRoot()[Meta][Duration].ToFloat();
}
csmBool CubismMotionJson::IsMotionLoop() const
{
return _json->GetRoot()[Meta][Loop].ToBoolean();
}
csmBool CubismMotionJson::HasConsistency() const
{
csmBool result = true;
if (!IsValid())
{
return false;
}
const csmInt32 actualCurveListSize = static_cast<csmInt32>(_json->GetRoot()[Curves].GetVector()->GetSize());
csmInt32 actualTotalSegmentCount = 0;
csmInt32 actualTotalPointCount = 0;
// カウント処理
for (csmInt32 curvePosition = 0; curvePosition < actualCurveListSize; ++curvePosition)
{
for (csmInt32 segmentPosition = 0; segmentPosition < GetMotionCurveSegmentCount(curvePosition);)
{
if (segmentPosition == 0)
{
actualTotalPointCount += 1;
segmentPosition += 2;
}
const csmInt32 segment = static_cast<csmInt32>(GetMotionCurveSegment(curvePosition, segmentPosition));
switch (segment)
{
case CubismMotionSegmentType_Linear:
actualTotalPointCount += 1;
segmentPosition += 3;
break;
case CubismMotionSegmentType_Bezier:
actualTotalPointCount += 3;
segmentPosition += 7;
break;
case CubismMotionSegmentType_Stepped:
actualTotalPointCount += 1;
segmentPosition += 3;
break;
case CubismMotionSegmentType_InverseStepped:
actualTotalPointCount += 1;
segmentPosition += 3;
break;
default:
CSM_ASSERT(0);
break;
}
++actualTotalSegmentCount;
}
}
// 個数チェック
if (actualCurveListSize != GetMotionCurveCount())
{
CubismLogWarning("The number of curves does not match the metadata.");
result = false;
}
if (actualTotalSegmentCount != GetMotionTotalSegmentCount())
{
CubismLogWarning("The number of segment does not match the metadata.");
result = false;
}
if (actualTotalPointCount != GetMotionTotalPointCount())
{
CubismLogWarning("The number of point does not match the metadata.");
result = false;
}
return result;
}
csmBool CubismMotionJson::GetEvaluationOptionFlag(const csmInt32 flagType) const
{
if (EvaluationOptionFlag_AreBeziersRestricted == flagType)
{
return _json->GetRoot()[Meta][AreBeziersRestricted].ToBoolean();
}
return false;
}
csmInt32 CubismMotionJson::GetMotionCurveCount() const
{
return _json->GetRoot()[Meta][CurveCount].ToInt();
}
csmFloat32 CubismMotionJson::GetMotionFps() const
{
return _json->GetRoot()[Meta][Fps].ToFloat();
}
csmInt32 CubismMotionJson::GetMotionTotalSegmentCount() const
{
return _json->GetRoot()[Meta][TotalSegmentCount].ToInt();
}
csmInt32 CubismMotionJson::GetMotionTotalPointCount() const
{
return _json->GetRoot()[Meta][TotalPointCount].ToInt();
}
csmBool CubismMotionJson::IsExistMotionFadeInTime() const
{
return !_json->GetRoot()[Meta][FadeInTime].IsNull();
}
csmBool CubismMotionJson::IsExistMotionFadeOutTime() const
{
return !_json->GetRoot()[Meta][FadeOutTime].IsNull();
}
csmFloat32 CubismMotionJson::GetMotionFadeInTime() const
{
return _json->GetRoot()[Meta][FadeInTime].ToFloat();
}
csmFloat32 CubismMotionJson::GetMotionFadeOutTime() const
{
return _json->GetRoot()[Meta][FadeOutTime].ToFloat();
}
const csmChar* CubismMotionJson::GetMotionCurveTarget(csmInt32 curveIndex) const
{
return _json->GetRoot()[Curves][curveIndex][Target].GetRawString();
}
CubismIdHandle CubismMotionJson::GetMotionCurveId(csmInt32 curveIndex) const
{
return CubismFramework::GetIdManager()->GetId(_json->GetRoot()[Curves][curveIndex][Id].GetRawString());
}
csmBool CubismMotionJson::IsExistMotionCurveFadeInTime(csmInt32 curveIndex) const
{
return !_json->GetRoot()[Curves][curveIndex][FadeInTime].IsNull();
}
csmBool CubismMotionJson::IsExistMotionCurveFadeOutTime(csmInt32 curveIndex) const
{
return !_json->GetRoot()[Curves][curveIndex][FadeOutTime].IsNull();
}
csmFloat32 CubismMotionJson::GetMotionCurveFadeInTime(csmInt32 curveIndex) const
{
return _json->GetRoot()[Curves][curveIndex][FadeInTime].ToFloat();
}
csmFloat32 CubismMotionJson::GetMotionCurveFadeOutTime(csmInt32 curveIndex) const
{
return _json->GetRoot()[Curves][curveIndex][FadeOutTime].ToFloat();
}
csmInt32 CubismMotionJson::GetMotionCurveSegmentCount(csmInt32 curveIndex) const
{
return static_cast<csmInt32>(_json->GetRoot()[Curves][curveIndex][Segments].GetVector()->GetSize());
}
csmFloat32 CubismMotionJson::GetMotionCurveSegment(csmInt32 curveIndex, csmInt32 segmentIndex) const
{
return _json->GetRoot()[Curves][curveIndex][Segments][segmentIndex].ToFloat();
}
csmInt32 CubismMotionJson::GetEventCount() const
{
return _json->GetRoot()[Meta][UserDataCount].ToInt();
}
csmInt32 CubismMotionJson::GetTotalEventValueSize() const
{
return _json->GetRoot()[Meta][TotalUserDataSize].ToInt();
}
csmFloat32 CubismMotionJson::GetEventTime(csmInt32 userDataIndex) const
{
return _json->GetRoot()[UserData][userDataIndex][Time].ToFloat();
}
const csmChar* CubismMotionJson::GetEventValue(csmInt32 userDataIndex) const
{
return _json->GetRoot()[UserData][userDataIndex][Value].GetRawString();
}
}}}
@@ -0,0 +1,233 @@
/**
* 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 "Utils/CubismJson.hpp"
#include "Id/CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
enum EvaluationOptionFlag
{
EvaluationOptionFlag_AreBeziersRestricted = 0,
};
/**
* Handles motion files.
*/
class CubismMotionJson : public CubismJsonHolder
{
public:
/**
* Constructor<br>
* Loads the motion file.
*
* @param buffer buffer containing the loaded motion file
* @param size size of the buffer in bytes
*/
CubismMotionJson(const csmByte* buffer, csmSizeInt size);
/**
* Destructor
*/
virtual ~CubismMotionJson();
/**
* Returns the length of the motion.
*
* @return length of the motion in seconds
*/
csmFloat32 GetMotionDuration() const;
/**
* Checks whether the motion is set to loop.
*
* @return true if the motion is set to loop; otherwise false.
*/
csmBool IsMotionLoop() const;
/**
* Returns the consistency of the motion3.json file.
*
* @return true if the file is consistent; otherwise returns false.
*/
csmBool HasConsistency() const;
/**
* Returns the option settings used during the motion curve evaluation.
*
* @param Type option to retrieve
*
* @return option setting; true if enabled
*
* @note Use EvaluationOptionFlag to specify the option to retrieve.
*/
csmBool GetEvaluationOptionFlag(csmInt32 flagType) const;
/**
* Returns the number of curves in the motion.
*
* @return number of curves in the motion
*/
csmInt32 GetMotionCurveCount() const;
/**
* Returns the frame rate of the motion.
*
* @return frame rate of the motion in FPS
*/
csmFloat32 GetMotionFps() const;
/**
* Returns the total number of segments in the motion.
*
* @return total number of segments in the motion
*/
csmInt32 GetMotionTotalSegmentCount() const;
/**
* Returns the total number of control points in the motion curves.
*
* @return total number of control points in the motion curves
*/
csmInt32 GetMotionTotalPointCount() const;
/**
* Checks whether the setting for the number of seconds to complete fading in exists.
*
* @return true if the setting exists; otherwise false.
*/
csmBool IsExistMotionFadeInTime() const;
/**
* Checks whether the setting for the number of seconds to complete fading out exists.
*
* @return true if the setting exists; otherwise false.
*/
csmBool IsExistMotionFadeOutTime() const;
/**
* Returns the number of seconds for the motion to complete fading in.
*
* @return number of seconds for the fade-in to complete
*/
csmFloat32 GetMotionFadeInTime() const;
/**
* Returns the number of seconds for the motion to complete fading out.
*
* @return number of seconds for the fade-out to complete
*/
csmFloat32 GetMotionFadeOutTime() const;
/**
* Returns the destination type of the motion curve.
*
* @param curveIndex index of the curve to retrieve
*
* @return destination type of the curve
*/
const csmChar* GetMotionCurveTarget(csmInt32 curveIndex) const;
/**
* Returns the ID of the parameter attached to the motion curve.
*
* @param curveIndex index of the curve to retrieve
*
* @return ID of the attached parameter
*/
CubismIdHandle GetMotionCurveId(csmInt32 curveIndex) const;
/**
* Checks whether the setting for the number of seconds to complete fading in for the motion curve exists.
*
* @param curveIndex index of the curve to check
*
* @return true if the setting exists; otherwise false.
*/
csmBool IsExistMotionCurveFadeInTime(csmInt32 curveIndex) const;
/**
* Checks whether the setting for the number of seconds to complete fading out for the motion curve exists.
*
* @param curveIndex index of the curve to check
*
* @return true if the setting exists; otherwise false.
*/
csmBool IsExistMotionCurveFadeOutTime(csmInt32 curveIndex) const;
/**
* Returns the number of seconds for the motion curve to complete fading in.
*
* @return number of seconds for the fade-in to complete
*/
csmFloat32 GetMotionCurveFadeInTime(csmInt32 curveIndex) const;
/**
* Returns the number of seconds for the motion to complete fading out.
*
* @return number of seconds for the fade-out to complete
*/
csmFloat32 GetMotionCurveFadeOutTime(csmInt32 curveIndex) const;
/**
* Returns the number of segments in the motion curve.
*
* @param curveIndex index of the curve to retrieve
*
* @return number of segments in the curve
*/
csmInt32 GetMotionCurveSegmentCount(csmInt32 curveIndex) const;
/**
* Returns the value of the segment in the motion curve.
*
* @param curveIndex index of the curve to retrieve
* @param segmentIndex index of the segment to retrieve
*
* @return value of the segment in the curve
*/
csmFloat32 GetMotionCurveSegment(csmInt32 curveIndex, csmInt32 segmentIndex) const;
/**
* Returns the number of user data events in the motion.
*
* @return number of user data events
*/
csmInt32 GetEventCount() const;
/**
* Returns the number of user data events in the motion.
*
* @return number of user data events
*/
csmInt32 GetTotalEventValueSize() const;
/**
* Returns the motion time in seconds when the user data event fires.
*
* @param userDataIndex index of the user data event to retrieve
*
* @return motion time in seconds when the user data event fires
*/
csmFloat32 GetEventTime(csmInt32 userDataIndex) const;
/**
* Returns the value of the user data event in the motion.
*
* @param userDataIndex index of the user data event to retrieve
*
* @return value of the user data event
*/
const csmChar* GetEventValue(csmInt32 userDataIndex) const;
};
}}}
@@ -0,0 +1,73 @@
/**
* 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 "CubismMotionManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismMotionManager::CubismMotionManager()
: _currentPriority(0)
, _reservePriority(0)
{ }
CubismMotionManager::~CubismMotionManager()
{ }
csmInt32 CubismMotionManager::GetCurrentPriority() const
{
return _currentPriority;
}
csmInt32 CubismMotionManager::GetReservePriority() const
{
return _reservePriority;
}
void CubismMotionManager::SetReservePriority(csmInt32 val)
{
_reservePriority = val;
}
CubismMotionQueueEntryHandle CubismMotionManager::StartMotionPriority(ACubismMotion* motion, csmBool autoDelete, csmInt32 priority)
{
if (priority == _reservePriority)
{
_reservePriority = 0; // 予約を解除
}
_currentPriority = priority; // 再生中モーションの優先度を設定
return CubismMotionQueueManager::StartMotion(motion, autoDelete);
}
csmBool CubismMotionManager::UpdateMotion(CubismModel* model, csmFloat32 deltaTimeSeconds)
{
_userTimeSeconds += deltaTimeSeconds;
const csmBool updated = CubismMotionQueueManager::DoUpdateMotion(model, _userTimeSeconds);
if (IsFinished())
{
_currentPriority = 0; // 再生中モーションの優先度を解除
}
return updated;
}
csmBool CubismMotionManager::ReserveMotion(csmInt32 priority)
{
if ((priority <= _reservePriority) || (priority <= _currentPriority))
{
return false;
}
_reservePriority = priority;
return true;
}
}}}
@@ -0,0 +1,93 @@
/**
* 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 "ACubismMotion.hpp"
#include "CubismMotionQueueManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* Handles the management of motions.
*/
class CubismMotionManager : public CubismMotionQueueManager
{
public:
/**
* Constructor.
*/
CubismMotionManager();
/**
* Destructor
*/
virtual ~CubismMotionManager();
/**
* Returns the priority of the playing motion.
*
* @return priority of the motion
*/
csmInt32 GetCurrentPriority() const;
/**
* Returns the priority of the reserved motion.
*
* @return priority of the motion
*/
csmInt32 GetReservePriority() const;
/**
* Sets the priority of the reserved motion.
*
* @param val priority to set
*/
void SetReservePriority(csmInt32 val);
/**
* Plays the motion with the specified priority.
*
* @param motion motion to play
* @param autoDelete true to delete the instance of the motion when playback ends
* @param priority priority of the motion
*
* @return ID of the played motion.<br>
* -1 if the motion could not be started.
*
* @note The return value can be used as an argument to IsFinished() to determine if the motion has finished playing.
*/
CubismMotionQueueEntryHandle StartMotionPriority(ACubismMotion* motion, csmBool autoDelete, csmInt32 priority);
/**
* Updates the motion.<br>
* Evaluates the current motion and sets the parameter values on the model.
*
* @param model model to update
* @param deltaTimeSeconds current time in seconds
* @param opacity opacity to set or get
*
* @return true if the motion was updated; otherwise false.
*/
csmBool UpdateMotion(CubismModel* model, csmFloat32 deltaTimeSeconds);
/**
* Reserves the motion for playback.
*
* @param priority priority of the motion
*
* @return true if the motion was reserved for playback; otherwise false.
*/
csmBool ReserveMotion(csmInt32 priority);
private:
csmInt32 _currentPriority;
csmInt32 _reservePriority;
};
}}}
@@ -0,0 +1,159 @@
/**
* 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 "CubismMotionQueueEntry.hpp"
#include "CubismFramework.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
CubismMotionQueueEntry::CubismMotionQueueEntry()
: _autoDelete(false)
, _motion(NULL)
, _available(true)
, _finished(false)
, _started(false)
, _startTimeSeconds(-1.0f)
, _fadeInStartTimeSeconds(0.0f)
, _endTimeSeconds(-1.0f)
, _stateTimeSeconds(0.0f)
, _stateWeight(0.0f)
, _lastEventCheckSeconds(0.0f)
, _motionQueueEntryHandle(NULL)
, _fadeOutSeconds(0.0f)
, _IsTriggeredFadeOut(false)
{
this->_motionQueueEntryHandle = this;
}
CubismMotionQueueEntry::~CubismMotionQueueEntry()
{
if (_autoDelete && _motion)
{
ACubismMotion::Delete(_motion); //
}
}
void CubismMotionQueueEntry::SetFadeout(csmFloat32 fadeOutSeconds)
{
_fadeOutSeconds = fadeOutSeconds;
_IsTriggeredFadeOut = true;
}
void CubismMotionQueueEntry::StartFadeout(csmFloat32 fadeOutSeconds, csmFloat32 userTimeSeconds)
{
const csmFloat32 newEndTimeSeconds = userTimeSeconds + fadeOutSeconds;
_IsTriggeredFadeOut = true;
if (_endTimeSeconds < 0.0f || newEndTimeSeconds < _endTimeSeconds)
{
_endTimeSeconds = newEndTimeSeconds;
}
}
csmBool CubismMotionQueueEntry::IsFinished() const
{
return _finished;
}
csmBool CubismMotionQueueEntry::IsStarted() const
{
return _started;
}
csmFloat32 CubismMotionQueueEntry::GetStartTime() const
{
return _startTimeSeconds;
}
csmFloat32 CubismMotionQueueEntry::GetFadeInStartTime() const
{
return _fadeInStartTimeSeconds;
}
csmFloat32 CubismMotionQueueEntry::GetEndTime() const
{
return _endTimeSeconds;
}
void CubismMotionQueueEntry::SetStartTime(csmFloat32 startTime)
{
this->_startTimeSeconds = startTime;
}
void CubismMotionQueueEntry::SetFadeInStartTime(csmFloat32 startTime)
{
this->_fadeInStartTimeSeconds = startTime;
}
void CubismMotionQueueEntry::SetEndTime(csmFloat32 endTime)
{
this->_endTimeSeconds = endTime;
}
void CubismMotionQueueEntry::IsFinished(csmBool f)
{
this->_finished = f;
}
void CubismMotionQueueEntry::IsStarted(csmBool f)
{
this->_started = f;
}
csmBool CubismMotionQueueEntry::IsAvailable() const
{
return _available;
}
void CubismMotionQueueEntry::IsAvailable(csmBool v)
{
this->_available = v;
}
void CubismMotionQueueEntry::SetState(csmFloat32 timeSeconds, csmFloat32 weight)
{
this->_stateTimeSeconds = timeSeconds;
this->_stateWeight = weight;
}
csmFloat32 CubismMotionQueueEntry::GetStateTime() const
{
return this->_stateTimeSeconds;
}
csmFloat32 CubismMotionQueueEntry::GetStateWeight() const
{
return this->_stateWeight;
}
csmFloat32 CubismMotionQueueEntry::GetLastCheckEventTime() const
{
return this->_lastEventCheckSeconds;
}
void CubismMotionQueueEntry::SetLastCheckEventTime(csmFloat32 checkTime)
{
this->_lastEventCheckSeconds = checkTime;
}
csmBool CubismMotionQueueEntry::IsTriggeredFadeOut()
{
return this->_IsTriggeredFadeOut;
}
csmFloat32 CubismMotionQueueEntry::GetFadeOutSeconds()
{
return this->_fadeOutSeconds;
}
ACubismMotion* CubismMotionQueueEntry::GetCubismMotion()
{
return _motion;
}
}}}
@@ -0,0 +1,208 @@
/**
* 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 "ACubismMotion.hpp"
#include "Type/csmVector.hpp"
#include "Model/CubismUserModel.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismMotion;
/**
* Handles adding information to the motion data for use by the CubismMotionQueueManager.
*/
class CubismMotionQueueEntry
{
friend class CubismMotionQueueManager;
friend class ACubismMotion;
friend class CubismMotion;
public:
/**
* Constructor
*/
CubismMotionQueueEntry();
/**
* Destructor
*/
virtual ~CubismMotionQueueEntry();
/**
* Sets the number of seconds for the motion to complete fading out.
*
* @param fadeOutSeconds number of seconds for the fade-out to complete
*/
void SetFadeout(csmFloat32 fadeOutSeconds);
/**
* Sets the number of seconds for the motion to complete fading out and starts the fade out.
*
* @param fadeOutSeconds number of seconds for the fade-out to complete
* @param userTimeSeconds current time in seconds
*/
void StartFadeout(csmFloat32 fadeOutSeconds, csmFloat32 userTimeSeconds);
/**
* Checks whether the motion playback has finished.
*
* @return true if the motion playback has finished; otherwise false.
*/
csmBool IsFinished() const;
/**
* Checks whether the motion playback has started.
*
* @return true if the motion playback has started; otherwise false.
*/
csmBool IsStarted() const;
/**
* Returns the time at which the motion playback started.
*
* @return time at which the motion playback started in seconds
*/
csmFloat32 GetStartTime() const;
/**
* Returns the time at which the fade-in of the motion starts.
*
* @return time at which the fade-in starts in seconds
*/
csmFloat32 GetFadeInStartTime() const;
/**
* Returns the time at which the fade-in of the motion ends.
*
* @return time at which the fade-in ends in seconds
*/
csmFloat32 GetEndTime() const;
/**
* Sets the time to start playing the motion.
*
* @param startTime time to start playing the motion in seconds
*/
void SetStartTime(csmFloat32 startTime);
/**
* Sets the time to start the fade-in of the motion.
*
* @param startTime time to start the fade-in in seconds
*/
void SetFadeInStartTime(csmFloat32 startTime);
/**
* Sets the time to end the fade-in of the motion.
*
* @param endTime time to end the fade-in in seconds
*/
void SetEndTime(csmFloat32 endTime);
/**
* Sets whether to end the motion playback.
*
* @param f true to end the motion playback
*/
void IsFinished(csmBool f);
/**
* Sets whether to play the motion.
*
* @param f true to play the motion
*/
void IsStarted(csmBool f);
/**
* Checks whether the motion is active.
*
* @return true if the motion is active; otherwise false.
*/
csmBool IsAvailable() const;
/**
* Sets whether the motion is active.
*
* @param v true to activate the motion
*/
void IsAvailable(csmBool v);
/**
* Sets the state of the motion.
*
* @param timeSeconds current time to set in seconds
* @param weight weight of the motion to set
*/
void SetState(csmFloat32 timeSeconds, csmFloat32 weight);
/**
* Returns the current time from the state of the motion.
*
* @return current time in seconds
*/
csmFloat32 GetStateTime() const;
/**
* Returns the weight of the motion from its state.
*
* @return weight of the motion
*/
csmFloat32 GetStateWeight() const;
/**
* Returns the last time the user data event was confirmed to fire.
*
* @return last time the user data event was confirmed to fire in seconds
*/
csmFloat32 GetLastCheckEventTime() const;
/**
* Sets the time when the user data event was last confirmed to fire.
*
* @param checkTime last confirmed time in seconds
*/
void SetLastCheckEventTime(csmFloat32 checkTime);
/**
* Checks whether the motion is currently fading out.
*
* @return true if the motion is currently fading out; otherwise false.
*/
csmBool IsTriggeredFadeOut();
/**
* Returns the number of seconds for the motion to complete fading out.
*
* @return number of seconds for the fade-out to complete
*/
csmFloat32 GetFadeOutSeconds();
ACubismMotion* GetCubismMotion();
private:
csmBool _autoDelete;
ACubismMotion* _motion;
csmBool _available;
csmBool _finished;
csmBool _started;
csmFloat32 _startTimeSeconds;
csmFloat32 _fadeInStartTimeSeconds;
csmFloat32 _endTimeSeconds;
csmFloat32 _stateTimeSeconds;
csmFloat32 _stateWeight;
csmFloat32 _lastEventCheckSeconds;
csmFloat32 _fadeOutSeconds;
csmBool _IsTriggeredFadeOut;
CubismMotionQueueEntryHandle _motionQueueEntryHandle;
};
}}}
@@ -0,0 +1,276 @@
/**
* 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 "CubismMotionQueueManager.hpp"
#include "CubismMotionQueueEntry.hpp"
#include "CubismFramework.hpp"
#include "CubismMotion.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
const CubismMotionQueueEntryHandle InvalidMotionQueueEntryHandleValue = reinterpret_cast<CubismMotionQueueEntryHandle*>(-1);
CubismMotionQueueManager::CubismMotionQueueManager()
: _userTimeSeconds(0.0f)
, _eventCallback(NULL)
, _eventCustomData(NULL)
{}
CubismMotionQueueManager::~CubismMotionQueueManager()
{
for (csmUint32 i = 0; i < _motions.GetSize(); ++i)
{
if (_motions[i])
{
CSM_DELETE(_motions[i]);
}
}
}
CubismMotionQueueEntryHandle CubismMotionQueueManager::StartMotion(ACubismMotion* motion, csmBool autoDelete)
{
if (motion == NULL)
{
return InvalidMotionQueueEntryHandleValue;
}
CubismMotionQueueEntry* motionQueueEntry = NULL;
// 既にモーションがあれば終了フラグを立てる
for (csmUint32 i = 0; i < _motions.GetSize(); ++i)
{
motionQueueEntry = _motions.At(i);
if (motionQueueEntry == NULL)
{
continue;
}
motionQueueEntry->SetFadeout(motionQueueEntry->_motion->GetFadeOutTime());
}
motionQueueEntry = CSM_NEW CubismMotionQueueEntry(); // 終了時に破棄する
motionQueueEntry->_autoDelete = autoDelete;
motionQueueEntry->_motion = motion;
_motions.PushBack(motionQueueEntry, false);
return motionQueueEntry->_motionQueueEntryHandle;
}
CubismMotionQueueEntryHandle CubismMotionQueueManager::StartMotion(ACubismMotion* motion, csmBool autoDelete, csmFloat32 userTimeSeconds)
{
CubismLogWarning("StartMotion(ACubismMotion* motion, csmBool autoDelete, csmFloat32 userTimeSeconds) is a deprecated function. Please use StartMotion(ACubismMotion* motion, csmBool autoDelete).");
if (motion == NULL)
{
return InvalidMotionQueueEntryHandleValue;
}
CubismMotionQueueEntry* motionQueueEntry = NULL;
// 既にモーションがあれば終了フラグを立てる
for (csmUint32 i = 0; i < _motions.GetSize(); ++i)
{
motionQueueEntry = _motions.At(i);
if (motionQueueEntry == NULL)
{
continue;
}
motionQueueEntry->SetFadeout(motionQueueEntry->_motion->GetFadeOutTime());
}
motionQueueEntry = CSM_NEW CubismMotionQueueEntry(); // 終了時に破棄する
motionQueueEntry->_autoDelete = autoDelete;
motionQueueEntry->_motion = motion;
_motions.PushBack(motionQueueEntry, false);
return motionQueueEntry->_motionQueueEntryHandle;
}
csmBool CubismMotionQueueManager::DoUpdateMotion(CubismModel* model, csmFloat32 userTimeSeconds)
{
csmBool updated = false;
// ------- 処理を行う --------
// 既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = _motions.Begin(); ite != _motions.End();)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
ite = _motions.Erase(ite); // 削除
continue;
}
ACubismMotion* motion = motionQueueEntry->_motion;
if (motion == NULL)
{
CSM_DELETE(motionQueueEntry);
ite = _motions.Erase(ite); // 削除
continue;
}
// ------ 値を反映する ------
motion->UpdateParameters(model, motionQueueEntry, userTimeSeconds);
updated = true;
// ------ ユーザトリガーイベントを検査する ----
const csmVector<const csmString*>& firedList = motion->GetFiredEvent(
motionQueueEntry->GetLastCheckEventTime() - motionQueueEntry->GetStartTime()
, userTimeSeconds - motionQueueEntry->GetStartTime()
);
for (csmUint32 i = 0; i < firedList.GetSize(); ++i)
{
_eventCallback(this, *(firedList[i]), _eventCustomData);
}
motionQueueEntry->SetLastCheckEventTime(userTimeSeconds);
// ----- 終了済みの処理があれば削除する ------
if (motionQueueEntry->IsFinished())
{
CSM_DELETE(motionQueueEntry);
ite = _motions.Erase(ite); // 削除
}
else
{
if (motionQueueEntry->IsTriggeredFadeOut())
{
motionQueueEntry->StartFadeout(motionQueueEntry->GetFadeOutSeconds(), userTimeSeconds);
}
++ite;
}
}
return updated;
}
csmVector<CubismMotionQueueEntry*>* CubismMotionQueueManager::GetCubismMotionQueueEntries()
{
return &_motions;
}
CubismMotionQueueEntry* CubismMotionQueueManager::GetCubismMotionQueueEntry(CubismMotionQueueEntryHandle motionQueueEntryNumber)
{
//------- 処理を行う --------
//既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = _motions.Begin(); ite != _motions.End(); ++ite)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
continue;
}
if (motionQueueEntry->_motionQueueEntryHandle == motionQueueEntryNumber)
{
return motionQueueEntry;
}
}
return NULL;
}
csmBool CubismMotionQueueManager::IsFinished()
{
// ------- 処理を行う --------
// 既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = _motions.Begin(); ite != _motions.End();)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
ite = _motions.Erase(ite); // 削除
continue;
}
ACubismMotion* motion = motionQueueEntry->_motion;
if (motion == NULL)
{
CSM_DELETE(motionQueueEntry);
ite = _motions.Erase(ite); // 削除
continue;
}
// ----- 終了済みの処理があれば削除する ------
if (!motionQueueEntry->IsFinished())
{
return false;
}
else
{
++ite;
}
}
return true;
}
csmBool CubismMotionQueueManager::IsFinished(CubismMotionQueueEntryHandle motionQueueEntryNumber)
{
// 既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = _motions.Begin(); ite != _motions.End(); ite++)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
continue;
}
if (motionQueueEntry->_motionQueueEntryHandle == motionQueueEntryNumber && !motionQueueEntry->IsFinished())
{
return false;
}
}
return true;
}
void CubismMotionQueueManager::StopAllMotions()
{
// ------- 処理を行う --------
// 既にモーションがあれば終了フラグを立てる
for (csmVector<CubismMotionQueueEntry*>::iterator ite = _motions.Begin(); ite != _motions.End();)
{
CubismMotionQueueEntry* motionQueueEntry = *ite;
if (motionQueueEntry == NULL)
{
ite = _motions.Erase(ite);
continue;
}
// ----- 終了済みの処理があれば削除する ------
CSM_DELETE(motionQueueEntry);
ite = _motions.Erase(ite); //削除
}
}
void CubismMotionQueueManager::SetEventCallback(CubismMotionEventFunction callback, void* customData)
{
_eventCallback = callback;
_eventCustomData = customData;
}
}}}
@@ -0,0 +1,138 @@
/**
* 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 "ACubismMotion.hpp"
#include "Model/CubismModel.hpp"
#include "Type/csmVector.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismMotionQueueEntry;
class CubismMotionQueueManager;
typedef void(*CubismMotionEventFunction)(const CubismMotionQueueManager* caller, const csmString& eventValue, void* customData);
typedef void* CubismMotionQueueEntryHandle;
extern const CubismMotionQueueEntryHandle InvalidMotionQueueEntryHandleValue;
/**
* Handles the management of motion playback.<br>
* Used for playing subclasses of ACubismMotion such as CubismMotion.
*
* @note If a different motion is started with StartMotion() during playback,
* it transitions smoothly to the new motion, interrupting the old one.<br>
* When different motions such as facial expressions and body motions are played together,<br>
* use multiple instances of CubismMotionQueueManager.
*/
class CubismMotionQueueManager
{
public:
/**
* Constructor
*/
CubismMotionQueueManager();
/**
* Destructor
*/
virtual ~CubismMotionQueueManager();
/**
* Plays the motion.<br>
* If a motion of the same type is already playing, it ends the currently playing motion and starts fading it out.
*
* @param motion motion to play
* @param autoDelete true to delete the instance of the motion when playback ends
* @param userTimeSeconds current time in seconds
*
* @return ID of the played motion.<br>
* -1 if the motion could not be started.
*
* @note The return value can be used as an argument to IsFinished() to determine if the motion has finished playing.
*/
CubismMotionQueueEntryHandle StartMotion(ACubismMotion* motion, csmBool autoDelete);
/**
* @deprecated Not recommended as the third parameter userTimeSeconds is not used within the function.
* Use StartMotion(ACubismMotion* motion, csmBool autoDelete) instead.
*
* Plays the motion.<br>
* If a motion of the same type is already playing, it ends the currently playing motion and starts fading it out.
*
* @param motion motion to play
* @param autoDelete true to delete the instance of the motion when playback ends
* @param userTimeSeconds current time in seconds
*
* @return ID of the played motion.<br>
* -1 if the motion could not be started.
*
* @note The return value can be used as an argument to IsFinished() to determine if the motion has finished playing.
*/
CubismMotionQueueEntryHandle StartMotion(ACubismMotion* motion, csmBool autoDelete, csmFloat32 userTimeSeconds);
/**
* Checks whether all motions have finished playing.
*
* @return true if all motions have finished playing; otherwise false.
*/
csmBool IsFinished();
/**
* Checks whether the motion has finished playing.
*
* @param motionQueueEntryNumber identifier of the motion to check
*
* @return true if the motion has finished playing; otherwise false.
*/
csmBool IsFinished(CubismMotionQueueEntryHandle motionQueueEntryNumber);
/**
* Ends the playback of all motions.
*/
void StopAllMotions();
/**
* Returns a reference to the CubismMotionQueueEntry.
*
* @param motionQueueEntryNumber identifier of the motion to retrieve
*
* @return reference to the CubismMotionQueueEntry
*/
CubismMotionQueueEntry* GetCubismMotionQueueEntry(CubismMotionQueueEntryHandle motionQueueEntryNumber);
/**
* Returns a pointer to the array of CubismMotionQueueEntry.
*
* @return pointer to the array of CubismMotionQueueEntry
*/
csmVector<CubismMotionQueueEntry*>* GetCubismMotionQueueEntries();
/**
* Sets the callback function to receive user data events.
*
* @param callback Callback function to receive user data events
* @param customData User-defined data passed to the callback
*/
void SetEventCallback(CubismMotionEventFunction callback, void* customData = NULL);
protected:
virtual csmBool DoUpdateMotion(CubismModel* model, csmFloat32 userTimeSeconds);
csmFloat32 _userTimeSeconds;
private:
csmVector<CubismMotionQueueEntry*> _motions;
CubismMotionEventFunction _eventCallback;
void* _eventCustomData;
};
}}}
@@ -0,0 +1,8 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismPhysics.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPhysics.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPhysicsInternal.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPhysicsJson.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismPhysicsJson.hpp
)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,168 @@
/**
* 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 "Math/CubismVector2.hpp"
#include "CubismPhysicsInternal.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
class CubismModel;
struct CubismPhysicsRig;
/**
* @brief 物理演算クラス
*
* 物理演算のクラス。
*/
class CubismPhysics
{
public:
/**
* @brief オプション
*
* 物理演算のオプション。
*/
struct Options
{
CubismVector2 Gravity; ///< 重力方向
CubismVector2 Wind; ///< 風の方向
};
/**
* @brief 物理演算出力結果
*
* パラメータに適用する前の物理演算の出力結果
*/
struct PhysicsOutput
{
csmVector<csmFloat32> outputs;
};
/**
* @brief インスタンスの作成
*
* インスタンスを作成する。
*
* @param[in] buffer physics3.jsonが読み込まれいるバッファ
* @param[in] size バッファのサイズ
* @return 作成されたインスタンス
*/
static CubismPhysics* Create(const csmByte* buffer, csmSizeInt size);
/**
* @brief インスタンスの破棄
*
* インスタンスを破棄する。
*
* @param[in] physics 破棄するインスタンス
*/
static void Delete(CubismPhysics* physics);
/**
* @brief パラメータのリセット
*
* パラメータをリセットする。
*/
void Reset();
/**
* @brief 現在のパラメータ値で物理演算が安定化する状態を演算する。
* @param[in] model 物理演算の結果を適用するモデル
*/
void Stabilization(CubismModel* model);
/**
* @brief 物理演算の評価
*
* 物理演算を評価する。
*
* @param[in] model 物理演算の結果を適用するモデル
* @param[in] deltaTimeSeconds デルタ時間[秒]
*/
void Evaluate(CubismModel* model, csmFloat32 deltaTimeSeconds);
/**
* @brief オプションの設定
*
* オプションを設定する。
*
* @param[in] options オプション
*/
void SetOptions(const Options& options);
/**
* @brief オプションの取得
*
* オプションを取得する。
*
* @return オプション
*/
const Options& GetOptions() const;
private:
/**
* @brief コンストラクタ
*
* コンストラクタ。
*/
CubismPhysics();
/**
* @brief デストラクタ
*
* デストラクタ。
*/
virtual ~CubismPhysics();
// Prevention of copy Constructor
CubismPhysics(const CubismPhysics&);
CubismPhysics& operator=(const CubismPhysics&);
/**
* @brief physics3.jsonのパース
*
* physics3.jsonをパースする。
*
* @param[in] physicsJson physics3.jsonが読み込まれているバッファ
* @param[in] size バッファのサイズ
*/
void Parse(const csmByte* physicsJson, csmSizeInt size);
/**
* @brief 初期化
*
* 初期化する。
*/
void Initialize();
/**
* @brief 物理演算結果の適用
*
* 振り子演算の最新の結果と一つ前の結果から指定した重みで適用する。
*
* @param model 物理演算の結果を適用するモデル
* @param weight 最新結果の重み
*/
void Interpolate(CubismModel* model, csmFloat32 weight);
CubismPhysicsRig* _physicsRig; ///< 物理演算のデータ
Options _options; ///< オプション
csmVector<PhysicsOutput> _currentRigOutputs; ///< 最新の振り子計算の結果
csmVector<PhysicsOutput> _previousRigOutputs; ///< 一つ前の振り子計算の結果
csmFloat32 _currentRemainTime; ///< 物理演算が処理していない時間
csmVector<csmFloat32> _parameterCaches; ///< Evaluateで利用するパラメータのキャッシュ
csmVector<csmFloat32> _parameterInputCaches; ///< UpdateParticlesが動くときの入力をキャッシュ
csmBool _isJsonValid; ///< 正しくJsonデータが取得出来たか
};
}}}
@@ -0,0 +1,221 @@
/**
* 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 "Math/CubismVector2.hpp"
#include "Id/CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* @brief 物理演算の適用先の種類
*
* 物理演算の適用先の種類。
*/
enum CubismPhysicsTargetType
{
CubismPhysicsTargetType_Parameter, ///< パラメータに対して適用
};
/**
* @brief 物理演算の入力の種類
*
* 物理演算の入力の種類。
*/
enum CubismPhysicsSource
{
CubismPhysicsSource_X, ///< X軸の位置から
CubismPhysicsSource_Y, ///< Y軸の位置から
CubismPhysicsSource_Angle, ///< 角度から
};
/**
* @brief 物理演算で使用する外部の力
*
* 物理演算で使用する外部の力。
*/
struct PhysicsJsonEffectiveForces
{
CubismVector2 Gravity; ///< 重力
CubismVector2 Wind; ///< 風
};
/**
* @brief 物理演算のパラメータ情報
*
* 物理演算のパラメータ情報。
*/
struct CubismPhysicsParameter
{
CubismIdHandle Id; ///< パラメータID
CubismPhysicsTargetType TargetType; ///< 適用先の種類
};
/**
* @brief 物理演算の正規化情報
*
* 物理演算の正規化情報。
*/
struct CubismPhysicsNormalization
{
csmFloat32 Minimum; ///< 最大値
csmFloat32 Maximum; ///< 最小値
csmFloat32 Default; ///< デフォルト値
};
/**
* @brief 物理演算の演算に使用する物理点の情報
*
* 物理演算の演算に使用する物理点の情報。
*/
struct CubismPhysicsParticle
{
CubismVector2 InitialPosition; ///< 初期位置
csmFloat32 Mobility; ///< 動きやすさ
csmFloat32 Delay; ///< 遅れ
csmFloat32 Acceleration; ///< 加速度
csmFloat32 Radius; ///< 距離
CubismVector2 Position; ///< 現在の位置
CubismVector2 LastPosition; ///< 最後の位置
CubismVector2 LastGravity; ///< 最後の重力
CubismVector2 Force; ///< 現在かかっている力
CubismVector2 Velocity; ///< 現在の速度
};
/**
* @brief 物理演算の物理点の管理
*
* 物理演算の物理点の管理。
*/
struct CubismPhysicsSubRig
{
csmInt32 InputCount; ///< 入力の個数
csmInt32 OutputCount; ///< 出力の個数
csmInt32 ParticleCount; ///< 物理点の個数
csmInt32 BaseInputIndex; ///< 入力の最初のインデックス
csmInt32 BaseOutputIndex; ///< 出力の最初のインデックス
csmInt32 BaseParticleIndex; ///< 物理点の最初のインデックス
CubismPhysicsNormalization NormalizationPosition; ///< 正規化された位置
CubismPhysicsNormalization NormalizationAngle; ///< 正規化された角度
};
/**
* @brief 正規化されたパラメータの取得関数の宣言
*
* 正規化されたパラメータの取得関数の宣言。
*
* @param[out] targetTranslation 演算結果の移動値
* @param[out] targetAngle 演算結果の角度
* @param[in] value パラメータの値
* @param[in] parameterMinimumValue パラメータの最小値
* @param[in] parameterMaximumValue パラメータの最大値
* @param[in] parameterDefaultValue パラメータのデフォルト値
* @param[in] normalizationPosition 正規化された位置
* @param[in] normalizationAngle 正規化された角度
* @param[in] isInverted 値が反転されているか?
* @param[in] weight 重み
*/
typedef void (*NormalizedPhysicsParameterValueGetter)(
CubismVector2* targetTranslation,
csmFloat32* targetAngle,
csmFloat32 value,
csmFloat32 parameterMinimumValue,
csmFloat32 parameterMaximumValue,
csmFloat32 parameterDefaultValue,
CubismPhysicsNormalization* normalizationPosition,
CubismPhysicsNormalization* normalizationAngle,
csmInt32 isInverted,
csmFloat32 weight
);
/**
* @brief 物理演算の値の取得関数の宣言
*
* 物理演算の値の取得関数の宣言。
*
* @param[in] translation 移動値
* @param[in] particles 物理点のリスト
* @param[in] isInverted 値が反転されているか?
* @param[in] parentGravity 重力
* @return 値
*/
typedef csmFloat32 (*PhysicsValueGetter)(
CubismVector2 translation,
CubismPhysicsParticle* particles,
csmInt32 particleIndex,
csmInt32 isInverted,
CubismVector2 parentGravity
);
/**
* @brief 物理演算のスケールの取得関数の宣言
*
* 物理演算のスケールの取得関数の宣言。
*
* @param[in] translationScale 移動値のスケール
* @param[in] angleScale 角度のスケール
* @return スケール値
*/
typedef csmFloat32 (*PhysicsScaleGetter)(CubismVector2 translationScale, csmFloat32 angleScale);
/**
* @brief 物理演算の入力情報
*
* 物理演算の入力情報。
*/
struct CubismPhysicsInput
{
CubismPhysicsParameter Source; ///< 入力元のパラメータ
csmInt32 SourceParameterIndex; ///< 入力元のパラメータのインデックス
csmFloat32 Weight; ///< 重み
csmInt16 Type; ///< 入力の種類
csmInt16 Reflect; ///< 値が反転されているかどうか
NormalizedPhysicsParameterValueGetter GetNormalizedParameterValue; ///< 正規化されたパラメータ値の取得関数
};
/**
* @brief 物理演算の出力情報
*
* 物理演算の出力情報。
*/
struct CubismPhysicsOutput
{
CubismPhysicsParameter Destination; ///< 出力先のパラメータ
csmInt32 DestinationParameterIndex; ///< 出力先のパラメータのインデックス
csmInt32 VertexIndex; ///< 振り子のインデックス
CubismVector2 TranslationScale; ///< 移動値のスケール
csmFloat32 AngleScale; ///< 角度のスケール
csmFloat32 Weight; /// 重み
CubismPhysicsSource Type; ///< 出力の種類
csmInt16 Reflect; ///< 値が反転されているかどうか
csmFloat32 ValueBelowMinimum; ///< 最小値を下回った時の値
csmFloat32 ValueExceededMaximum; ///< 最大値をこえた時の値
PhysicsValueGetter GetValue; ///< 物理演算の値の取得関数
PhysicsScaleGetter GetScale; ///< 物理演算のスケール値の取得関数
};
/**
* @brief 物理演算のデータ
*
* 物理演算のデータ。
*/
struct CubismPhysicsRig
{
csmInt32 SubRigCount; ///< 物理演算の物理点の個数
csmVector<CubismPhysicsSubRig> Settings; ///< 物理演算の物理点の管理のリスト
csmVector<CubismPhysicsInput> Inputs; ///< 物理演算の入力のリスト
csmVector<CubismPhysicsOutput> Outputs; ///< 物理演算の出力のリスト
csmVector<CubismPhysicsParticle> Particles; ///< 物理演算の物理点のリスト
CubismVector2 Gravity; ///< 重力
CubismVector2 Wind; ///< 風
csmFloat32 Fps; ///< 物理演算動作FPS
};
}}}
@@ -0,0 +1,236 @@
/**
* 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 "CubismPhysicsJson.hpp"
#include "Id/CubismIdManager.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/// Physics Json Constants
namespace {
// JSON keys
const csmChar* Position = "Position";
const csmChar* X = "X";
const csmChar* Y = "Y";
const csmChar* Angle = "Angle";
const csmChar* Type = "Type";
const csmChar* Id = "Id";
// Meta
const csmChar* Meta = "Meta";
const csmChar* EffectiveForces = "EffectiveForces";
const csmChar* TotalInputCount = "TotalInputCount";
const csmChar* TotalOutputCount = "TotalOutputCount";
const csmChar* PhysicsSettingCount = "PhysicsSettingCount";
const csmChar* Gravity = "Gravity";
const csmChar* Wind = "Wind";
const csmChar* VertexCount = "VertexCount";
const csmChar* Fps = "Fps";
// PhysicsSettings
const csmChar* PhysicsSettings = "PhysicsSettings";
const csmChar* Normalization = "Normalization";
const csmChar* Minimum = "Minimum";
const csmChar* Maximum = "Maximum";
const csmChar* Default = "Default";
const csmChar* Reflect = "Reflect";
const csmChar* Weight = "Weight";
// Input
const csmChar* Input = "Input";
const csmChar* Source = "Source";
// Output
const csmChar* Output = "Output";
const csmChar* Scale = "Scale";
const csmChar* VertexIndex = "VertexIndex";
const csmChar* Destination = "Destination";
// Particle
const csmChar* Vertices = "Vertices";
const csmChar* Mobility = "Mobility";
const csmChar* Delay = "Delay";
const csmChar* Radius = "Radius";
const csmChar* Acceleration = "Acceleration";
}
CubismPhysicsJson::CubismPhysicsJson(const csmByte* buffer, csmSizeInt size)
{
CreateCubismJson(buffer, size);
}
CubismPhysicsJson::~CubismPhysicsJson()
{
DeleteCubismJson();
}
CubismVector2 CubismPhysicsJson::GetGravity() const
{
CubismVector2 ret;
ret.X = _json->GetRoot()[Meta][EffectiveForces][Gravity][X].ToFloat();
ret.Y = _json->GetRoot()[Meta][EffectiveForces][Gravity][Y].ToFloat();
return ret;
}
CubismVector2 CubismPhysicsJson::GetWind() const
{
CubismVector2 ret;
ret.X = _json->GetRoot()[Meta][EffectiveForces][Wind][X].ToFloat();
ret.Y = _json->GetRoot()[Meta][EffectiveForces][Wind][Y].ToFloat();
return ret;
}
csmFloat32 CubismPhysicsJson::GetFps() const
{
// if FPS information does not exist in physics3.json, 0.0f is returned.
return _json->GetRoot()[Meta][Fps].ToFloat(0.0f);
}
csmInt32 CubismPhysicsJson::GetSubRigCount() const
{
return _json->GetRoot()[Meta][PhysicsSettingCount].ToInt();
}
csmInt32 CubismPhysicsJson::GetTotalInputCount() const
{
return _json->GetRoot()[Meta][TotalInputCount].ToInt();
}
csmInt32 CubismPhysicsJson::GetTotalOutputCount() const
{
return _json->GetRoot()[Meta][TotalOutputCount].ToInt();
}
csmInt32 CubismPhysicsJson::GetVertexCount() const
{
return _json->GetRoot()[Meta][VertexCount].ToInt();
}
// Input
csmFloat32 CubismPhysicsJson::GetNormalizationPositionMinimumValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Position][Minimum].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetNormalizationPositionMaximumValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Position][Maximum].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetNormalizationPositionDefaultValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Position][Default].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetNormalizationAngleMinimumValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Angle][Minimum].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetNormalizationAngleMaximumValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Angle][Maximum].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetNormalizationAngleDefaultValue(csmInt32 physicsSettingIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Normalization][Angle][Default].ToFloat();
}
csmInt32 CubismPhysicsJson::GetInputCount(csmInt32 physicsSettingIndex) const
{
return static_cast<csmInt32>(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Input].GetVector()->GetSize());
}
csmFloat32 CubismPhysicsJson::GetInputWeight(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Input][inputIndex][Weight].ToFloat();
}
csmBool CubismPhysicsJson::GetInputReflect(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Input][inputIndex][Reflect].ToBoolean();
}
const csmChar* CubismPhysicsJson::GetInputType(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Input][inputIndex][Type].GetRawString();
}
CubismIdHandle CubismPhysicsJson::GetInputSourceId(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const
{
return CubismFramework::GetIdManager()->GetId(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Input][inputIndex][Source][Id].GetRawString());
}
// Output
csmInt32 CubismPhysicsJson::GetOutputCount(csmInt32 physicsSettingIndex) const
{
return static_cast<csmInt32>(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output].GetVector()->GetSize());
}
csmInt32 CubismPhysicsJson::GetOutputVertexIndex(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][VertexIndex].ToInt();
}
csmFloat32 CubismPhysicsJson::GetOutputAngleScale(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][Scale].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetOutputWeight(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][Weight].ToFloat();
}
CubismIdHandle CubismPhysicsJson::GetOutputsDestinationId(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return CubismFramework::GetIdManager()->GetId(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][Destination][Id].GetRawString());
}
const csmChar* CubismPhysicsJson::GetOutputType(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][Type].GetRawString();
}
csmBool CubismPhysicsJson::GetOutputReflect(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Output][outputIndex][Reflect].ToBoolean();
}
// Particle
csmInt32 CubismPhysicsJson::GetParticleCount(csmInt32 physicsSettingIndex) const
{
return static_cast<csmInt32>(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices].GetVector()->GetSize());
}
csmFloat32 CubismPhysicsJson::GetParticleMobility(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Mobility].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetParticleDelay(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Delay].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetParticleAcceleration(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Acceleration].ToFloat();
}
csmFloat32 CubismPhysicsJson::GetParticleRadius(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const
{
return _json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Radius].ToFloat();
}
CubismVector2 CubismPhysicsJson::GetParticlePosition(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const
{
return CubismVector2(_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Position][X].ToFloat(),
_json->GetRoot()[PhysicsSettings][physicsSettingIndex][Vertices][vertexIndex][Position][Y].ToFloat() );
}
}}}
@@ -0,0 +1,362 @@
/**
* 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 "Utils/CubismJson.hpp"
#include "Math/CubismVector2.hpp"
#include "Id/CubismId.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
/**
* @brief physics3.jsonのコンテナ
*
* physics3.jsonのコンテナ。
*/
class CubismPhysicsJson : public CubismJsonHolder
{
public:
/**
* @brief コンストラクタ
*
* コンストラクタ。
*
* @param[in] buffer physics3.jsonが読み込まれているバッファ
* @param[in] size バッファのサイズ
*/
CubismPhysicsJson(const csmByte* buffer, csmSizeInt size);
/**
* @brief デストラクタ
*
* デストラクタ。
*/
virtual ~CubismPhysicsJson();
/**
* @brief 重力の取得
*
* 重力を取得する。
*
* @return 重力
*/
CubismVector2 GetGravity() const;
/**
* @brief 風の取得
*
* 風を取得する。
*
* @return 風
*/
CubismVector2 GetWind() const;
/**
* @brief 物理演算設定FPSの取得
*
* 物理演算の想定FPSを取得する。
* physics3.jsonにFPS情報が存在しない場合、0.0fを返す。
*
* @return 物理演算設定FPS
*/
csmFloat32 GetFps() const;
/**
* @brief 物理点の管理の個数の取得
*
* 物理点の管理の個数を取得する。
*
* @return 物理点の管理の個数
*/
csmInt32 GetSubRigCount() const;
/**
* @brief 入力の総合計の取得
*
* 入力の総合計を取得する。
*
* @return 入力の総合計
*/
csmInt32 GetTotalInputCount() const;
/**
* @brief 出力の総合計の取得
*
* 出力の総合計を取得する。
*
* @return 出力の総合計
*/
csmInt32 GetTotalOutputCount() const;
/**
* @brief 物理点の個数の取得
*
* 物理点の個数を取得する。
*
* @return 物理点の個数
*/
csmInt32 GetVertexCount() const;
/**
* @brief 正規化された位置の最小値の取得
*
* 正規化された位置の最小値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された位置の最小値
*/
csmFloat32 GetNormalizationPositionMinimumValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 正規化された位置の最大値の取得
*
* 正規化された位置の最大値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された位置の最大値
*/
csmFloat32 GetNormalizationPositionMaximumValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 正規化された位置のデフォルト値の取得
*
* 正規化された位置のデフォルト値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された位置のデフォルト値
*/
csmFloat32 GetNormalizationPositionDefaultValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 正規化された角度の最小値の取得
*
* 正規化された角度の最小値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された角度の最小値
*/
csmFloat32 GetNormalizationAngleMinimumValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 正規化された角度の最大値の取得
*
* 正規化された角度の最大値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された角度の最大値
*/
csmFloat32 GetNormalizationAngleMaximumValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 正規化された角度のデフォルト値の取得
*
* 正規化された角度のデフォルト値を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 正規化された角度のデフォルト値
*/
csmFloat32 GetNormalizationAngleDefaultValue(csmInt32 physicsSettingIndex) const;
/**
* @brief 入力の個数の取得
*
* 入力の個数を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 入力の個数
*/
csmInt32 GetInputCount(csmInt32 physicsSettingIndex) const;
/**
* @brief 入力の重みの取得
*
* 入力の重みを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] inputIndex 入力のインデックス
* @return 入力の重み
*/
csmFloat32 GetInputWeight(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const;
/**
* @brief 入力の反転の取得
*
* 入力の反転を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] inputIndex 入力のインデックス
* @return 入力の反転
*/
csmBool GetInputReflect(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const;
/**
* @brief 入力の種類の取得
*
* 入力の種類を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] inputIndex 入力のインデックス
* @return 入力の種類
*/
const csmChar* GetInputType(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const;
/**
* @brief 入力元のIDの取得
*
* 入力元のIDを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] inputIndex 入力のインデックス
* @return 入力元のID
*/
CubismIdHandle GetInputSourceId(csmInt32 physicsSettingIndex, csmInt32 inputIndex) const;
/**
* @brief 出力の個数の取得
*
* 出力の個数を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 出力の個数
*/
csmInt32 GetOutputCount(csmInt32 physicsSettingIndex) const;
/**
* @brief 出力の物理点のインデックスの取得
*
* 出力の物理点のインデックスを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力の物理点のインデックス
*/
csmInt32 GetOutputVertexIndex(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 出力の角度のスケールの取得
*
* 出力の角度のスケールを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力の角度のスケール
*/
csmFloat32 GetOutputAngleScale(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 出力の重みの取得
*
* 出力の重みを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力の重み
*/
csmFloat32 GetOutputWeight(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 出力先のIDの取得
*
* 出力先のIDを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力先のID
*/
CubismIdHandle GetOutputsDestinationId(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 出力の種類の取得
*
* 出力の種類を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力の種類
*/
const csmChar* GetOutputType(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 出力の反転の取得
*
* 出力の反転を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] outputIndex 出力のインデックス
* @return 出力の反転
*/
csmBool GetOutputReflect(csmInt32 physicsSettingIndex, csmInt32 outputIndex) const;
/**
* @brief 物理点の個数の取得
*
* 物理点の個数を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @return 物理点の個数
*/
csmInt32 GetParticleCount(csmInt32 physicsSettingIndex) const;
/**
* @brief 物理点の動きやすさの取得
*
* 物理点の動きやすさを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] vertexIndex 物理点のインデックス
* @return 物理点の動きやすさ
*/
csmFloat32 GetParticleMobility(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const;
/**
* @brief 物理点の遅れの取得
*
* 物理点の遅れを取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] vertexIndex 物理点のインデックス
* @return 物理点の遅れ
*/
csmFloat32 GetParticleDelay(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const;
/**
* @brief 物理点の加速度の取得
*
* 物理点の加速度を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] vertexIndex 物理点のインデックス
* @return 物理点の加速度
*/
csmFloat32 GetParticleAcceleration(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const;
/**
* @brief 物理点の距離の取得
*
* 物理点の距離を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] vertexIndex 物理点のインデックス
* @return 物理点の距離
*/
csmFloat32 GetParticleRadius(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const;
/**
* @brief 物理点の位置の取得
*
* 物理点の位置を取得する。
*
* @param[in] physicsSettingIndex 物理演算の設定のインデックス
* @param[in] vertexIndex 物理点のインデックス
* @return 物理点の位置
*/
CubismVector2 GetParticlePosition(csmInt32 physicsSettingIndex, csmInt32 vertexIndex) const;
};
}}}
@@ -0,0 +1,19 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismClippingManager.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismClippingManager.tpp
)
# Add specified rendering directory.
add_subdirectory(${FRAMEWORK_SOURCE})
# Add include path set in application (Deprecated).
set(RENDER_INCLUDE_PATH
${FRAMEWORK_DX9_INCLUDE_PATH}
${FRAMEWORK_DX11_INCLUDE_PATH}
${FRAMEWORK_GLEW_PATH}
${FRAMEWORK_GLFW_PATH}
PARENT_SCOPE
)
@@ -0,0 +1,155 @@
/**
* 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 <float.h>
#include "CubismFramework.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmRectF.hpp"
#include "Math/CubismVector2.hpp"
#include "Math/CubismMatrix44.hpp"
#include "Model/CubismModel.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
///< ファイルスコープの変数宣言
#ifndef CSM_MASK_FILESCOPE
#define CSM_MASK_FILESCOPE
namespace {
const csmInt32 ColorChannelCount = 4; // 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4
const csmInt32 ClippingMaskMaxCountOnDefault = 36; // 通常のフレームバッファ1枚あたりのマスク最大数
const csmInt32 ClippingMaskMaxCountOnMultiRenderTexture = 32; // フレームバッファが2枚以上ある場合のフレームバッファ1枚あたりのマスク最大数
}
#endif
template <class T_ClippingContext, class T_OffscreenSurface>
class CubismClippingManager
{
public:
/**
* @brief コンストラクタ
*/
CubismClippingManager();
/**
* @brief デストラクタ
*/
virtual ~CubismClippingManager();
/**
* @brief マネージャの初期化処理<br>
* クリッピングマスクを使う描画オブジェクトの登録を行う
*
* @param[in] model -> モデルのインスタンス
* @param[in] maskBufferCount -> バッファの生成数
*/
void Initialize(CubismModel& model, const csmInt32 maskBufferCount);
/**
* @brief 既にマスクを作っているかを確認。<br>
* 作っているようであれば該当するクリッピングマスクのインスタンスを返す。<br>
* 作っていなければNULLを返す
*
* @param[in] drawableMasks -> 描画オブジェクトをマスクする描画オブジェクトのリスト
* @param[in] drawableMaskCounts -> 描画オブジェクトをマスクする描画オブジェクトの数
* @return 該当するクリッピングマスクが存在すればインスタンスを返し、なければNULLを返す。
*/
T_ClippingContext* FindSameClip(const csmInt32* drawableMasks, csmInt32 drawableMaskCounts) const;
/**
* @brief 高精細マスク処理用の行列を計算する
*
* @param[in] model -> モデルのインスタンス
* @param[in] isRightHanded -> 処理が右手系であるか
*/
void SetupMatrixForHighPrecision(CubismModel& model, csmBool isRightHanded);
/**
* @brief マスク作成・描画用の行列を作成する。
*
* @param[in] isRightHanded -> 座標を右手系として扱うかを指定
* @param[in] layoutBoundsOnTex01 -> マスクを収める領域
* @param[in] scaleX -> 描画オブジェクトの伸縮率
* @param[in] scaleY -> 描画オブジェクトの伸縮率
*/
void createMatrixForMask(csmBool isRightHanded, csmRectF* layoutBoundsOnTex01, csmFloat32 scaleX, csmFloat32 scaleY);
/**
* @brief クリッピングコンテキストを配置するレイアウト。<br>
* ひとつのレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする。<br>
* マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する。
*
* @param[in] usingClipCount -> 配置するクリッピングコンテキストの数
*/
void SetupLayoutBounds(csmInt32 usingClipCount) const;
/**
* @brief マスクされる描画オブジェクト群全体を囲む矩形(モデル座標系)を計算する
*
* @param[in] model -> モデルのインスタンス
* @param[in] clippingContext -> クリッピングマスクのコンテキスト
*/
void CalcClippedDrawTotalBounds(CubismModel& model, T_ClippingContext* clippingContext);
/**
* @brief 画面描画に使用するクリッピングマスクのリストを取得する
*
* @return 画面描画に使用するクリッピングマスクのリスト
*/
csmVector<T_ClippingContext*>* GetClippingContextListForDraw();
/**
*@brief クリッピングマスクバッファのサイズを取得する
*
*@return クリッピングマスクバッファのサイズ
*/
CubismVector2 GetClippingMaskBufferSize() const;
/**
* このバッファのレンダーテクスチャの枚数を取得する。
*
* @return このバッファのレンダーテクスチャの枚数
*/
csmInt32 GetRenderTextureCount();
/**
* @brief カラーチャンネル(RGBA)のフラグを取得する
*
* @param[in] channelIndex -> カラーチャンネル(RGBA)の番号(0:R , 1:G , 2:B, 3:A)
*/
CubismRenderer::CubismTextureColor* GetChannelFlagAsColor(csmInt32 channelIndex);
/**
*@brief クリッピングマスクバッファのサイズを設定する
*
*@param size -> クリッピングマスクバッファのサイズ
*
*/
void SetClippingMaskBufferSize(csmFloat32 width, csmFloat32 height);
protected:
T_OffscreenSurface* _currentMaskBuffer; /// オフスクリーンサーフェイスのアドレス
csmVector<csmBool> _clearedMaskBufferFlags; /// マスクのクリアフラグの配列
csmVector<CubismRenderer::CubismTextureColor*> _channelColors;
csmVector<T_ClippingContext*> _clippingContextListForMask; ///< マスク用クリッピングコンテキストのリスト
csmVector<T_ClippingContext*> _clippingContextListForDraw; ///< 描画用クリッピングコンテキストのリスト
CubismVector2 _clippingMaskBufferSize; ///< クリッピングマスクのバッファサイズ(初期値:256)
csmInt32 _renderTextureCount; ///< 生成するレンダーテクスチャの枚数
CubismMatrix44 _tmpMatrix; ///< マスク計算用の行列
CubismMatrix44 _tmpMatrixForMask; ///< マスク計算用の行列
CubismMatrix44 _tmpMatrixForDraw; ///< マスク計算用の行列
csmRectF _tmpBoundsOnModel; ///< マスク配置計算用の矩形
};
#include "CubismClippingManager.tpp"
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,512 @@
/**
* 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
// template で宣言下 CubismClippingManager の実装を記述
template <class T_ClippingContext, class T_OffscreenSurface>
CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::CubismClippingManager() :
_clippingMaskBufferSize(256, 256)
{
CubismRenderer::CubismTextureColor* tmp = NULL;
tmp = CSM_NEW CubismRenderer::CubismTextureColor();
tmp->R = 1.0f;
tmp->G = 0.0f;
tmp->B = 0.0f;
tmp->A = 0.0f;
_channelColors.PushBack(tmp);
tmp = CSM_NEW CubismRenderer::CubismTextureColor();
tmp->R = 0.0f;
tmp->G = 1.0f;
tmp->B = 0.0f;
tmp->A = 0.0f;
_channelColors.PushBack(tmp);
tmp = CSM_NEW CubismRenderer::CubismTextureColor();
tmp->R = 0.0f;
tmp->G = 0.0f;
tmp->B = 1.0f;
tmp->A = 0.0f;
_channelColors.PushBack(tmp);
tmp = CSM_NEW CubismRenderer::CubismTextureColor();
tmp->R = 0.0f;
tmp->G = 0.0f;
tmp->B = 0.0f;
tmp->A = 1.0f;
_channelColors.PushBack(tmp);
}
template <class T_ClippingContext, class T_OffscreenSurface>
CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::~CubismClippingManager()
{
for (csmUint32 i = 0; i < _clippingContextListForMask.GetSize(); i++)
{
if (_clippingContextListForMask[i]) CSM_DELETE_SELF(T_ClippingContext, _clippingContextListForMask[i]);
_clippingContextListForMask[i] = NULL;
}
// _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEは不要。
for (csmUint32 i = 0; i < _clippingContextListForDraw.GetSize(); i++)
{
_clippingContextListForDraw[i] = NULL;
}
for (csmUint32 i = 0; i < _channelColors.GetSize(); i++)
{
if (_channelColors[i]) CSM_DELETE(_channelColors[i]);
_channelColors[i] = NULL;
}
if (_clearedMaskBufferFlags.GetSize() != 0)
{
_clearedMaskBufferFlags.Clear();
_clearedMaskBufferFlags = NULL;
}
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::Initialize(CubismModel& model, const csmInt32 maskBufferCount)
{
_renderTextureCount = maskBufferCount;
// レンダーテクスチャのクリアフラグの設定
for (csmInt32 i = 0; i < _renderTextureCount; ++i)
{
_clearedMaskBufferFlags.PushBack(false);
}
//クリッピングマスクを使う描画オブジェクトを全て登録する
//クリッピングマスクは、通常数個程度に限定して使うものとする
for (csmInt32 i = 0; i < model.GetDrawableCount(); i++)
{
if (model.GetDrawableMaskCounts()[i] <= 0)
{
//クリッピングマスクが使用されていないアートメッシュ(多くの場合使用しない)
_clippingContextListForDraw.PushBack(NULL);
continue;
}
// 既にあるClipContextと同じかチェックする
T_ClippingContext* cc = FindSameClip(model.GetDrawableMasks()[i], model.GetDrawableMaskCounts()[i]);
if (cc == NULL)
{
// 同一のマスクが存在していない場合は生成する
cc = CSM_NEW T_ClippingContext(this, model, model.GetDrawableMasks()[i], model.GetDrawableMaskCounts()[i]);
_clippingContextListForMask.PushBack(cc);
}
cc->AddClippedDrawable(i);
_clippingContextListForDraw.PushBack(cc);
}
}
template <class T_ClippingContext, class T_OffscreenSurface>
T_ClippingContext* CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::FindSameClip(const csmInt32* drawableMasks, csmInt32 drawableMaskCounts) const
{
// 作成済みClippingContextと一致するか確認
for (csmUint32 i = 0; i < _clippingContextListForMask.GetSize(); i++)
{
T_ClippingContext* cc = _clippingContextListForMask[i];
const csmInt32 count = cc->_clippingIdCount;
if (count != drawableMaskCounts) continue; //個数が違う場合は別物
csmInt32 samecount = 0;
// 同じIDを持つか確認。配列の数が同じなので、一致した個数が同じなら同じ物を持つとする。
for (csmInt32 j = 0; j < count; j++)
{
const csmInt32 clipId = cc->_clippingIdList[j];
for (csmInt32 k = 0; k < count; k++)
{
if (drawableMasks[k] == clipId)
{
samecount++;
break;
}
}
}
if (samecount == count)
{
return cc;
}
}
return NULL; //見つからなかった
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::SetupMatrixForHighPrecision(CubismModel& model, csmBool isRightHanded)
{
// 全てのクリッピングを用意する
// 同じクリップ(複数の場合はまとめて1つのクリップ)を使う場合は1度だけ設定する
csmInt32 usingClipCount = 0;
for (csmUint32 clipIndex = 0; clipIndex < _clippingContextListForMask.GetSize(); clipIndex++)
{
// 1つのクリッピングマスクに関して
T_ClippingContext* cc = _clippingContextListForMask[clipIndex];
// このクリップを利用する描画オブジェクト群全体を囲む矩形を計算
CalcClippedDrawTotalBounds(model, cc);
if (cc->_isUsing)
{
usingClipCount++; //使用中としてカウント
}
}
if (usingClipCount <= 0) {
return;
}
// マスク行列作成処理
SetupLayoutBounds(0);
// サイズがレンダーテクスチャの枚数と合わない場合は合わせる
if (_clearedMaskBufferFlags.GetSize() != _renderTextureCount)
{
_clearedMaskBufferFlags.Clear();
for (csmInt32 i = 0; i < _renderTextureCount; ++i)
{
_clearedMaskBufferFlags.PushBack(false);
}
}
else
{
// マスクのクリアフラグを毎フレーム開始時に初期化
for (csmInt32 i = 0; i < _renderTextureCount; ++i)
{
_clearedMaskBufferFlags[i] = false;
}
}
// 実際にマスクを生成する
// 全てのマスクをどの様にレイアウトして描くかを決定し、ClipContext , ClippedDrawContext に記憶する
for (csmUint32 clipIndex = 0; clipIndex < _clippingContextListForMask.GetSize(); clipIndex++)
{
// --- 実際に1つのマスクを描く ---
T_ClippingContext* clipContext = _clippingContextListForMask[clipIndex];
csmRectF* allClippedDrawRect = clipContext->_allClippedDrawRect; //このマスクを使う、全ての描画オブジェクトの論理座標上の囲み矩形
csmRectF* layoutBoundsOnTex01 = clipContext->_layoutBounds; //この中にマスクを収める
const csmFloat32 MARGIN = 0.05f;
csmFloat32 scaleX = 0.0f;
csmFloat32 scaleY = 0.0f;
const csmFloat32 ppu = model.GetPixelsPerUnit();
const csmFloat32 maskPixelWidth = clipContext->GetClippingManager()->_clippingMaskBufferSize.X;
const csmFloat32 maskPixelHeight = clipContext->GetClippingManager()->_clippingMaskBufferSize.Y;
const csmFloat32 physicalMaskWidth = layoutBoundsOnTex01->Width * maskPixelWidth;
const csmFloat32 physicalMaskHeight = layoutBoundsOnTex01->Height * maskPixelHeight;
_tmpBoundsOnModel.SetRect(allClippedDrawRect);
if (_tmpBoundsOnModel.Width * ppu > physicalMaskWidth)
{
_tmpBoundsOnModel.Expand(allClippedDrawRect->Width * MARGIN, 0.0f);
scaleX = layoutBoundsOnTex01->Width / _tmpBoundsOnModel.Width;
}
else
{
scaleX = ppu / physicalMaskWidth;
}
if (_tmpBoundsOnModel.Height * ppu > physicalMaskHeight)
{
_tmpBoundsOnModel.Expand(0.0f, allClippedDrawRect->Height * MARGIN);
scaleY = layoutBoundsOnTex01->Height / _tmpBoundsOnModel.Height;
}
else
{
scaleY = ppu / physicalMaskHeight;
}
// マスク生成時に使う行列を求める
createMatrixForMask(isRightHanded, layoutBoundsOnTex01, scaleX, scaleY);
clipContext->_matrixForMask.SetMatrix(_tmpMatrixForMask.GetArray());
clipContext->_matrixForDraw.SetMatrix(_tmpMatrixForDraw.GetArray());
}
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::createMatrixForMask(csmBool isRightHanded, csmRectF* layoutBoundsOnTex01, csmFloat32 scaleX, csmFloat32 scaleY)
{
_tmpMatrix.LoadIdentity();
{
// Layout0..1 を -1..1に変換
_tmpMatrix.TranslateRelative(-1.0f, -1.0f);
_tmpMatrix.ScaleRelative(2.0f, 2.0f);
}
{
// view to Layout0..1
_tmpMatrix.TranslateRelative(layoutBoundsOnTex01->X, layoutBoundsOnTex01->Y); //new = [translate]
_tmpMatrix.ScaleRelative(scaleX, scaleY); //new = [translate][scale]
_tmpMatrix.TranslateRelative(-_tmpBoundsOnModel.X, -_tmpBoundsOnModel.Y); //new = [translate][scale][translate]
}
// tmpMatrixForMask が計算結果
_tmpMatrixForMask.SetMatrix(_tmpMatrix.GetArray());
_tmpMatrix.LoadIdentity();
{
_tmpMatrix.TranslateRelative(layoutBoundsOnTex01->X, layoutBoundsOnTex01->Y * ((isRightHanded) ? -1.0f : 1.0f)); //new = [translate]
_tmpMatrix.ScaleRelative(scaleX, scaleY * ((isRightHanded) ? -1.0f : 1.0f)); //new = [translate][scale]
_tmpMatrix.TranslateRelative(-_tmpBoundsOnModel.X, -_tmpBoundsOnModel.Y); //new = [translate][scale][translate]
}
_tmpMatrixForDraw.SetMatrix(_tmpMatrix.GetArray());
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::SetupLayoutBounds(csmInt32 usingClipCount) const
{
const csmInt32 useClippingMaskMaxCount = _renderTextureCount <= 1
? ClippingMaskMaxCountOnDefault
: ClippingMaskMaxCountOnMultiRenderTexture * _renderTextureCount;
if (usingClipCount <= 0 || usingClipCount > useClippingMaskMaxCount)
{
if (usingClipCount > useClippingMaskMaxCount)
{
// マスクの制限数の警告を出す
csmInt32 count = usingClipCount - useClippingMaskMaxCount;
CubismLogError("not supported mask count : %d\n[Details] render texture count: %d\n, mask count : %d"
, count, _renderTextureCount, usingClipCount);
}
// この場合は一つのマスクターゲットを毎回クリアして使用する
for (csmUint32 index = 0; index < _clippingContextListForMask.GetSize(); index++)
{
T_ClippingContext* cc = _clippingContextListForMask[index];
cc->_layoutChannelIndex = 0; // どうせ毎回消すので固定で良い
cc->_layoutBounds->X = 0.0f;
cc->_layoutBounds->Y = 0.0f;
cc->_layoutBounds->Width = 1.0f;
cc->_layoutBounds->Height = 1.0f;
cc->_bufferIndex = 0;
}
return;
}
// レンダーテクスチャが1枚なら9分割する(最大36枚)
const csmInt32 layoutCountMaxValue = _renderTextureCount <= 1 ? 9 : 8;
// ひとつのRenderTextureを極力いっぱいに使ってマスクをレイアウトする
// マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する
const csmInt32 countPerSheetDiv = (usingClipCount + _renderTextureCount - 1) / _renderTextureCount; // レンダーテクスチャ1枚あたり何枚割り当てるか(切り上げ)
const csmInt32 reduceLayoutTextureCount = usingClipCount % _renderTextureCount; // レイアウトの数を1枚減らすレンダーテクスチャの数(この数だけのレンダーテクスチャが対象)
// RGBAを順番に使っていく
const csmInt32 divCount = countPerSheetDiv / ColorChannelCount; //1チャンネルに配置する基本のマスク個数
const csmInt32 modCount = countPerSheetDiv % ColorChannelCount; //余り、この番号のチャンネルまでに1つずつ配分する
// RGBAそれぞれのチャンネルを用意していく(0:R , 1:G , 2:B, 3:A, )
csmInt32 curClipIndex = 0; //順番に設定していく
for (csmInt32 renderTextureIndex = 0; renderTextureIndex < _renderTextureCount; renderTextureIndex++)
{
for (csmInt32 channelIndex = 0; channelIndex < ColorChannelCount; channelIndex++)
{
// このチャンネルにレイアウトする数
// NOTE: レイアウト数 = 1チャンネルに配置する基本のマスク + 余りのマスクを置くチャンネルなら1つ追加
csmInt32 layoutCount = divCount + (channelIndex < modCount ? 1 : 0);
// レイアウトの数を1枚減らす場合にそれを行うチャンネルを決定
// divが0の時は正常なインデックスの範囲内になるように調整
const csmInt32 checkChannelIndex = modCount + (divCount < 1 ? -1 : 0);
// 今回が対象のチャンネルかつ、レイアウトの数を1枚減らすレンダーテクスチャが存在する場合
if (channelIndex == checkChannelIndex && reduceLayoutTextureCount > 0)
{
// 現在のレンダーテクスチャが、対象のレンダーテクスチャであればレイアウトの数を1枚減らす
layoutCount -= !(renderTextureIndex < reduceLayoutTextureCount) ? 1 : 0;
}
// 分割方法を決定する
if (layoutCount == 0)
{
// 何もしない
}
else if (layoutCount == 1)
{
//全てをそのまま使う
T_ClippingContext* cc = _clippingContextListForMask[curClipIndex++];
cc->_layoutChannelIndex = channelIndex;
cc->_layoutBounds->X = 0.0f;
cc->_layoutBounds->Y = 0.0f;
cc->_layoutBounds->Width = 1.0f;
cc->_layoutBounds->Height = 1.0f;
cc->_bufferIndex = renderTextureIndex;
}
else if (layoutCount == 2)
{
for (csmInt32 i = 0; i < layoutCount; i++)
{
const csmInt32 xpos = i % 2;
T_ClippingContext* cc = _clippingContextListForMask[curClipIndex++];
cc->_layoutChannelIndex = channelIndex;
cc->_layoutBounds->X = xpos * 0.5f;
cc->_layoutBounds->Y = 0.0f;
cc->_layoutBounds->Width = 0.5f;
cc->_layoutBounds->Height = 1.0f;
cc->_bufferIndex = renderTextureIndex;
//UVを2つに分解して使う
}
}
else if (layoutCount <= 4)
{
//4分割して使う
for (csmInt32 i = 0; i < layoutCount; i++)
{
const csmInt32 xpos = i % 2;
const csmInt32 ypos = i / 2;
T_ClippingContext* cc = _clippingContextListForMask[curClipIndex++];
cc->_layoutChannelIndex = channelIndex;
cc->_layoutBounds->X = xpos * 0.5f;
cc->_layoutBounds->Y = ypos * 0.5f;
cc->_layoutBounds->Width = 0.5f;
cc->_layoutBounds->Height = 0.5f;
cc->_bufferIndex = renderTextureIndex;
}
}
else if (layoutCount <= layoutCountMaxValue)
{
//9分割して使う
for (csmInt32 i = 0; i < layoutCount; i++)
{
const csmInt32 xpos = i % 3;
const csmInt32 ypos = i / 3;
T_ClippingContext* cc = _clippingContextListForMask[curClipIndex++];
cc->_layoutChannelIndex = channelIndex;
cc->_layoutBounds->X = xpos / 3.0f;
cc->_layoutBounds->Y = ypos / 3.0f;
cc->_layoutBounds->Width = 1.0f / 3.0f;
cc->_layoutBounds->Height = 1.0f / 3.0f;
cc->_bufferIndex = renderTextureIndex;
}
}
// マスクの制限枚数を超えた場合の処理
else
{
csmInt32 count = usingClipCount - useClippingMaskMaxCount;
CubismLogError("not supported mask count : %d\n[Details] render texture count: %d\n, mask count : %d"
, count, _renderTextureCount, usingClipCount);
// 開発モードの場合は停止させる
CSM_ASSERT(0);
// 引き続き実行する場合、 SetupShaderProgramでオーバーアクセスが発生するので仕方なく適当に入れておく
// もちろん描画結果はろくなことにならない
for (csmInt32 i = 0; i < layoutCount; i++)
{
T_ClippingContext* cc = _clippingContextListForMask[curClipIndex++];
cc->_layoutChannelIndex = 0;
cc->_layoutBounds->X = 0.0f;
cc->_layoutBounds->Y = 0.0f;
cc->_layoutBounds->Width = 1.0f;
cc->_layoutBounds->Height = 1.0f;
cc->_bufferIndex = 0;
}
}
}
}
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::CalcClippedDrawTotalBounds(CubismModel& model, T_ClippingContext* clippingContext)
{
// 被クリッピングマスク(マスクされる描画オブジェクト)の全体の矩形
csmFloat32 clippedDrawTotalMinX = FLT_MAX, clippedDrawTotalMinY = FLT_MAX;
csmFloat32 clippedDrawTotalMaxX = -FLT_MAX, clippedDrawTotalMaxY = -FLT_MAX;
// このマスクが実際に必要か判定する
// このクリッピングを利用する「描画オブジェクト」がひとつでも使用可能であればマスクを生成する必要がある
const csmInt32 clippedDrawCount = clippingContext->_clippedDrawableIndexList->GetSize();
for (csmInt32 clippedDrawableIndex = 0; clippedDrawableIndex < clippedDrawCount; clippedDrawableIndex++)
{
// マスクを使用する描画オブジェクトの描画される矩形を求める
const csmInt32 drawableIndex = (*clippingContext->_clippedDrawableIndexList)[clippedDrawableIndex];
csmInt32 drawableVertexCount = model.GetDrawableVertexCount(drawableIndex);
csmFloat32* drawableVertexes = const_cast<csmFloat32*>(model.GetDrawableVertices(drawableIndex));
csmFloat32 minX = FLT_MAX, minY = FLT_MAX;
csmFloat32 maxX = -FLT_MAX, maxY = -FLT_MAX;
csmInt32 loop = drawableVertexCount * Constant::VertexStep;
for (csmInt32 pi = Constant::VertexOffset; pi < loop; pi += Constant::VertexStep)
{
csmFloat32 x = drawableVertexes[pi];
csmFloat32 y = drawableVertexes[pi + 1];
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
//
if (minX == FLT_MAX) continue; //有効な点がひとつも取れなかったのでスキップする
// 全体の矩形に反映
if (minX < clippedDrawTotalMinX) clippedDrawTotalMinX = minX;
if (minY < clippedDrawTotalMinY) clippedDrawTotalMinY = minY;
if (maxX > clippedDrawTotalMaxX) clippedDrawTotalMaxX = maxX;
if (maxY > clippedDrawTotalMaxY) clippedDrawTotalMaxY = maxY;
}
if (clippedDrawTotalMinX == FLT_MAX)
{
clippingContext->_allClippedDrawRect->X = 0.0f;
clippingContext->_allClippedDrawRect->Y = 0.0f;
clippingContext->_allClippedDrawRect->Width = 0.0f;
clippingContext->_allClippedDrawRect->Height = 0.0f;
clippingContext->_isUsing = false;
}
else
{
clippingContext->_isUsing = true;
csmFloat32 w = clippedDrawTotalMaxX - clippedDrawTotalMinX;
csmFloat32 h = clippedDrawTotalMaxY - clippedDrawTotalMinY;
clippingContext->_allClippedDrawRect->X = clippedDrawTotalMinX;
clippingContext->_allClippedDrawRect->Y = clippedDrawTotalMinY;
clippingContext->_allClippedDrawRect->Width = w;
clippingContext->_allClippedDrawRect->Height = h;
}
}
template <class T_ClippingContext, class T_OffscreenSurface>
csmVector<T_ClippingContext*>* CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::GetClippingContextListForDraw()
{
return &_clippingContextListForDraw;
}
template <class T_ClippingContext, class T_OffscreenSurface>
CubismVector2 CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::GetClippingMaskBufferSize() const
{
return _clippingMaskBufferSize;
}
template <class T_ClippingContext, class T_OffscreenSurface>
csmInt32 CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::GetRenderTextureCount()
{
return _renderTextureCount;
}
template <class T_ClippingContext, class T_OffscreenSurface>
CubismRenderer::CubismTextureColor* CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::GetChannelFlagAsColor(csmInt32 channelIndex)
{
return _channelColors[channelIndex];
}
template <class T_ClippingContext, class T_OffscreenSurface>
void CubismClippingManager<T_ClippingContext, T_OffscreenSurface>::SetClippingMaskBufferSize(csmFloat32 width, csmFloat32 height)
{
_clippingMaskBufferSize = CubismVector2(width, height);
}
@@ -0,0 +1,203 @@
/**
* 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 "CubismRenderer.hpp"
#include "CubismFramework.hpp"
#include "Model/CubismModel.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
void CubismRenderer::Delete(CubismRenderer* renderer)
{
CSM_DELETE_SELF(CubismRenderer, renderer);
}
CubismRenderer::CubismRenderer()
: _isCulling(false)
, _isPremultipliedAlpha(false)
, _anisotropy(0.0f)
, _model(NULL)
, _useHighPrecisionMask(false)
{
//単位行列に初期化
_mvpMatrix4x4.LoadIdentity();
}
CubismRenderer::~CubismRenderer()
{}
void CubismRenderer::Initialize(Framework::CubismModel* model)
{
Initialize(model, 1);
}
void CubismRenderer::Initialize(Framework::CubismModel* model, csmInt32 maskBufferCount)
{
_model = model;
}
void CubismRenderer::DrawModel()
{
if (GetModel() == NULL) return;
/**
* DoDrawModelの描画前と描画後に以下の関数を呼んでください。
* ・SaveProfile();
* ・RestoreProfile();
* これはレンダラの描画設定を保存・復帰させることで、
* モデル描画直前の状態に戻すための処理です。
*/
SaveProfile();
DoDrawModel();
RestoreProfile();
}
void CubismRenderer::SetMvpMatrix(CubismMatrix44* matrix4x4)
{
_mvpMatrix4x4.SetMatrix(matrix4x4->GetArray());
}
CubismMatrix44 CubismRenderer::GetMvpMatrix() const
{
return _mvpMatrix4x4;
}
void CubismRenderer::SetModelColor(csmFloat32 red, csmFloat32 green, csmFloat32 blue, csmFloat32 alpha)
{
if (red < 0.0f) red = 0.0f;
else if (red > 1.0f) red = 1.0f;
if (green < 0.0f) green = 0.0f;
else if (green > 1.0f) green = 1.0f;
if (blue < 0.0f) blue = 0.0f;
else if (blue > 1.0f) blue = 1.0f;
if (alpha < 0.0f) alpha = 0.0f;
else if (alpha > 1.0f) alpha = 1.0f;
_modelColor.R = red;
_modelColor.G = green;
_modelColor.B = blue;
_modelColor.A = alpha;
}
CubismRenderer::CubismTextureColor CubismRenderer::GetModelColor() const
{
return _modelColor;
}
CubismRenderer::CubismTextureColor CubismRenderer::GetModelColorWithOpacity(const csmFloat32 opacity) const
{
CubismTextureColor modelColorRGBA = GetModelColor();
modelColorRGBA.A *= opacity;
if (IsPremultipliedAlpha())
{
modelColorRGBA.R *= modelColorRGBA.A;
modelColorRGBA.G *= modelColorRGBA.A;
modelColorRGBA.B *= modelColorRGBA.A;
}
return modelColorRGBA;
}
void CubismRenderer::IsPremultipliedAlpha(csmBool enable)
{
_isPremultipliedAlpha = enable;
}
csmBool CubismRenderer::IsPremultipliedAlpha() const
{
return _isPremultipliedAlpha;
}
void CubismRenderer::IsCulling(csmBool culling)
{
_isCulling = culling;
}
csmBool CubismRenderer::IsCulling() const
{
return _isCulling;
}
void CubismRenderer::SetAnisotropy(csmFloat32 n)
{
_anisotropy = n;
}
csmFloat32 CubismRenderer::GetAnisotropy() const
{
return _anisotropy;
}
CubismModel* CubismRenderer::GetModel() const
{
return _model;
}
void CubismRenderer::UseHighPrecisionMask(csmBool high)
{
_useHighPrecisionMask = high;
}
csmBool CubismRenderer::IsUsingHighPrecisionMask()
{
return _useHighPrecisionMask;
}
/*********************************************************************************************************************
* CubismClippingContext
********************************************************************************************************************/
CubismClippingContext::CubismClippingContext(const csmInt32* clippingDrawableIndices, csmInt32 clipCount)
{
// クリップしている(=マスク用の)Drawableのインデックスリスト
_clippingIdList = clippingDrawableIndices;
// マスクの数
_clippingIdCount = clipCount;
_layoutChannelIndex = 0;
_allClippedDrawRect = CSM_NEW csmRectF();
_layoutBounds = CSM_NEW csmRectF();
_clippedDrawableIndexList = CSM_NEW csmVector<csmInt32>();
}
CubismClippingContext::~CubismClippingContext()
{
if (_layoutBounds != NULL)
{
CSM_DELETE(_layoutBounds);
_layoutBounds = NULL;
}
if (_allClippedDrawRect != NULL)
{
CSM_DELETE(_allClippedDrawRect);
_allClippedDrawRect = NULL;
}
if (_clippedDrawableIndexList != NULL)
{
CSM_DELETE(_clippedDrawableIndexList);
_clippedDrawableIndexList = NULL;
}
}
void CubismClippingContext::AddClippedDrawable(csmInt32 drawableIndex)
{
_clippedDrawableIndexList->PushBack(drawableIndex);
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,310 @@
/**
* 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 "CubismFramework.hpp"
#include "Math/CubismMatrix44.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmRectF.hpp"
namespace Live2D {namespace Cubism {namespace Framework {
class CubismModel;
}}}
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
/**
* @brief モデル描画を処理するレンダラ<br>
* サブクラスに環境依存の描画命令を記述する
*/
class CubismRenderer
{
public:
/**
* @brief カラーブレンディングのモード
*/
enum CubismBlendMode
{
CubismBlendMode_Normal = 0, ///< 通常
CubismBlendMode_Additive = 1, ///< 加算
CubismBlendMode_Multiplicative = 2, ///< 乗算
CubismBlendMode_Mask = 3, ///< マスク
}; // CubismBlendMode
/**
* @brief テクスチャの色をRGBAで扱うための構造体
*/
struct CubismTextureColor
{
/**
* @brief コンストラクタ
*/
CubismTextureColor()
: R(1.0f)
, G(1.0f)
, B(1.0f)
, A(1.0f) {};
/**
* @brief コンストラクタ
*/
CubismTextureColor(csmFloat32 r, csmFloat32 g, csmFloat32 b, csmFloat32 a)
: R(r)
, G(g)
, B(b)
, A(a) {};
/**
* @brief デストラクタ
*/
virtual ~CubismTextureColor() {};
csmFloat32 R; ///< 赤チャンネル
csmFloat32 G; ///< 緑チャンネル
csmFloat32 B; ///< 青チャンネル
csmFloat32 A; ///< αチャンネル
}; // CubismTextureColor
/**
* @brief レンダラのインスタンスを生成して取得する
*
* @retrun レンダラのインスタンス
*/
static CubismRenderer* Create();
/**
* @brief レンダラのインスタンスを解放する
*/
static void Delete(CubismRenderer* renderer);
/**
* @brief レンダラが保持する静的なリソースを解放する
*/
static void StaticRelease();
/**
* @brief レンダラの初期化処理を実行する<br>
* 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる
*
* @param[in] model -> モデルのインスタンス
*/
virtual void Initialize(Framework::CubismModel* model);
/**
* @brief レンダラの初期化処理を実行する<br>
* 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる
*
* @param[in] model -> モデルのインスタンス
* @param[in] maskBufferCount -> バッファの生成数
*/
virtual void Initialize(Framework::CubismModel* model, csmInt32 maskBufferCount);
/**
* @brief モデルを描画する
*
*/
void DrawModel();
/**
* @brief Model-View-Projection 行列をセットする<br>
* 配列は複製されるので元の配列は外で破棄して良い
*
* @param[in] matrix4x4 -> Model-View-Projection 行列
*/
void SetMvpMatrix(CubismMatrix44* matrix4x4);
/**
* @brief Model-View-Projection 行列を取得する
*
* @return Model-View-Projection 行列
*/
CubismMatrix44 GetMvpMatrix() const;
/**
* @brief モデルの色をセットする。<br>
* 各色0.0f~1.0fの間で指定する(1.0fが標準の状態)。
*
* @param[in] red -> 赤チャンネルの値
* @param[in] green -> 緑チャンネルの値
* @param[in] blue -> 青チャンネルの値
* @param[in] alpha -> αチャンネルの値
*
*/
void SetModelColor(csmFloat32 red, csmFloat32 green, csmFloat32 blue, csmFloat32 alpha);
/**
* @brief モデルの色を取得する。<br>
* 各色0.0f~1.0fの間で指定する(1.0fが標準の状態)。
*
* @return RGBAのカラー情報
*/
CubismTextureColor GetModelColor() const;
/**
* @brief 透明度を考慮したモデルの色を計算する。
*
* @param[in] opacity -> 透明度
*
* @return RGBAのカラー情報
*/
CubismTextureColor GetModelColorWithOpacity(const csmFloat32 opacity) const;
/**
* @brief 乗算済みαの有効・無効をセットする。<br>
* 有効にするならtrue, 無効にするならfalseをセットする。
*/
void IsPremultipliedAlpha(csmBool enable);
/**
* @brief 乗算済みαの有効・無効を取得する。
*
* @retval true -> 乗算済みα有効
* @retval false -> 乗算済みα無効
*/
csmBool IsPremultipliedAlpha() const;
/**
* @brief カリング(片面描画)の有効・無効をセットする。<br>
* 有効にするならtrue, 無効にするならfalseをセットする。
*/
void IsCulling(csmBool culling);
/**
* @brief カリング(片面描画)の有効・無効を取得する。
*
* @retval true -> カリング有効
* @retval false -> カリング無効
*/
csmBool IsCulling() const;
/**
* @brief テクスチャの異方性フィルタリングのパラメータをセットする<br>
* パラメータ値の影響度はレンダラの実装に依存する
*
* @param[in] anisotropy -> パラメータの値
*/
void SetAnisotropy(csmFloat32 anisotropy);
/**
* @brief テクスチャの異方性フィルタリングのパラメータをセットする
*
* @return 異方性フィルタリングのパラメータ
*/
csmFloat32 GetAnisotropy() const;
/**
* @brief レンダリングするモデルを取得する。
*
* @return レンダリングするモデルのポインタ
*/
CubismModel* GetModel() const;
/**
* @brief マスク描画の方式を変更する。
* falseの場合、マスクを1枚のテクスチャに分割してレンダリングする(デフォルトはこちら)。
* 高速だが、マスク個数の上限が36に限定され、質も荒くなる。
* trueの場合、パーツ描画の前にその都度必要なマスクを描き直す。
* レンダリング品質は高いが描画処理負荷は増す。
*/
void UseHighPrecisionMask(csmBool high);
/**
* @brief マスク描画の方式を取得する。
*/
csmBool IsUsingHighPrecisionMask();
protected:
/**
* @brief コンストラクタ
*/
CubismRenderer();
/**
* @brief デストラクタ
*/
virtual ~CubismRenderer();
/**
* @brief モデル描画の実装
*
*/
virtual void DoDrawModel() = 0;
/**
* @brief モデル描画直前のレンダラのステートを保持する
*/
virtual void SaveProfile() = 0;
/**
* @brief モデル描画直前のレンダラのステートを復帰させる
*/
virtual void RestoreProfile() = 0;
private:
// コピーコンストラクタを隠す
CubismRenderer(const CubismRenderer&);
CubismRenderer& operator=(const CubismRenderer&);
CubismMatrix44 _mvpMatrix4x4; ///< Model-View-Projection 行列
CubismTextureColor _modelColor; ///< モデル自体のカラー(RGBA)
csmBool _isCulling; ///< カリングが有効ならtrue
csmBool _isPremultipliedAlpha; ///< 乗算済みαならtrue
csmFloat32 _anisotropy; ///< テクスチャの異方性フィルタリングのパラメータ
CubismModel* _model; ///< レンダリング対象のモデル
csmBool _useHighPrecisionMask; ///< falseの場合、マスクを纏めて描画する trueの場合、マスクはパーツ描画ごとに書き直す
};
/**
* @brief クリッピングについての設定を保持するクラス<br>
* サブクラスに環境依存のフィールドを保持する
*/
class CubismClippingContext
{
public:
/**
* @brief 引数付きコンストラクタ
*
*/
CubismClippingContext(const csmInt32* clippingDrawableIndices, csmInt32 clipCount);
/**
* @brief デストラクタ
*/
~CubismClippingContext();
/**
* @brief このマスクにクリップされる描画オブジェクトを追加する
*
* @param[in] drawableIndex -> クリッピング対象に追加する描画オブジェクトのインデックス
*/
void AddClippedDrawable(csmInt32 drawableIndex);
csmBool _isUsing; ///< 現在の描画状態でマスクの準備が必要ならtrue
const csmInt32* _clippingIdList; ///< クリッピングマスクのIDリスト
csmInt32 _clippingIdCount; ///< クリッピングマスクの数
csmInt32 _layoutChannelIndex; ///< RGBAのいずれのチャンネルにこのクリップを配置するか(0:R , 1:G , 2:B , 3:A)
csmRectF* _layoutBounds; ///< マスク用チャンネルのどの領域にマスクを入れるか(View座標-1..1, UVは0..1に直す)
csmRectF* _allClippedDrawRect; ///< このクリッピングで、クリッピングされる全ての描画オブジェクトの囲み矩形(毎回更新)
CubismMatrix44 _matrixForMask; ///< マスクの位置計算結果を保持する行列
CubismMatrix44 _matrixForDraw; ///< 描画オブジェクトの位置計算結果を保持する行列
csmVector<csmInt32>* _clippedDrawableIndexList; ///< このマスクにクリップされる描画オブジェクトのリスト
csmInt32 _bufferIndex; ///< このマスクが割り当てられるレンダーテクスチャ(フレームバッファ)やカラーバッファのインデックス
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,13 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismNativeInclude_D3D11.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismOffscreenSurface_D3D11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismOffscreenSurface_D3D11.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer_D3D11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer_D3D11.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderState_D3D11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderState_D3D11.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismShader_D3D11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismShader_D3D11.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismType_D3D11.hpp
)
@@ -0,0 +1,11 @@
/**
* 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 <d3d11.h>
#include <DirectXMath.h>
@@ -0,0 +1,253 @@
/**
* 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 "CubismOffscreenSurface_D3D11.hpp"
#include "CubismRenderer_D3D11.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
CubismOffscreenSurface_D3D11::CubismOffscreenSurface_D3D11()
: _texture(NULL)
, _textureView(NULL)
, _renderTargetView(NULL)
, _depthTexture(NULL)
, _depthView(NULL)
, _backupRender(NULL)
, _backupDepth(NULL)
, _bufferWidth(0)
, _bufferHeight(0)
{
}
void CubismOffscreenSurface_D3D11::BeginDraw(ID3D11DeviceContext* renderContext)
{
if(_textureView==NULL || _renderTargetView==NULL || _depthView==NULL)
{
return;
}
_backupRender = NULL;
_backupDepth = NULL;
// バックバッファのサーフェイスを記憶しておく
renderContext->OMGetRenderTargets(1, &_backupRender, &_backupDepth);
// NULLを設定しないとこのような警告が出る
// OMSetRenderTargets: Resource being set to OM RenderTarget slot 0 is still bound on input! [ STATE_SETTING WARNING #9: DEVICE_OMSETRENDERTARGETS_HAZARD ]
{
ID3D11ShaderResourceView* const viewArray[2] = { NULL, NULL };
renderContext->PSSetShaderResources(0, 2, viewArray);
}
// マスクをクリアする
// 自前のレンダーターゲットビューに切り替え
renderContext->OMSetRenderTargets( 1, &_renderTargetView, _depthView);
}
void CubismOffscreenSurface_D3D11::EndDraw(ID3D11DeviceContext* renderContext)
{
if (_textureView == NULL || _renderTargetView == NULL || _depthView == NULL)
{
return;
}
// ターゲットを元に戻す
renderContext->OMSetRenderTargets(1, &_backupRender, _backupDepth);
// BeginでGetした分のRelease
if(_backupDepth)
{
_backupDepth->Release();
_backupDepth = NULL;
}
if (_backupRender)
{
_backupRender->Release();
_backupRender = NULL;
}
}
void CubismOffscreenSurface_D3D11::Clear(ID3D11DeviceContext* renderContext, float r, float g, float b, float a)
{
float clearColor[4] = {r,g,b,a};
renderContext->ClearRenderTargetView(_renderTargetView, clearColor);
renderContext->ClearDepthStencilView(_depthView, D3D11_CLEAR_DEPTH, 1.0f, 0);
}
csmBool CubismOffscreenSurface_D3D11::CreateOffscreenSurface(ID3D11Device* device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight)
{
// 一旦削除
DestroyOffscreenSurface();
do
{
HRESULT result;
D3D11_TEXTURE2D_DESC textureDesc;
memset(&textureDesc, 0, sizeof(textureDesc));
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; // レンダーターゲットを指定
textureDesc.Width = displayBufferWidth;
textureDesc.Height = displayBufferHeight;
textureDesc.CPUAccessFlags = 0;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
result = device->CreateTexture2D(&textureDesc, NULL, &_texture);
if (FAILED(result))
{// テクスチャ作成失敗
CubismLogError("Error : create offscreen texture");
break;
}
// レンダーターゲットビューの生成
D3D11_RENDER_TARGET_VIEW_DESC renderTargetDesc;
memset( &renderTargetDesc, 0, sizeof(renderTargetDesc) );
renderTargetDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
renderTargetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
result = device->CreateRenderTargetView( _texture, &renderTargetDesc, &_renderTargetView );
if ( FAILED(result) )
{
CubismLogError("Error : create offscreen rendertarget view");
break;
}
// シェーダリソースビューの生成
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
memset(&resourceViewDesc, 0, sizeof(resourceViewDesc));
resourceViewDesc.Format = renderTargetDesc.Format;
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MipLevels = 1;
result = device->CreateShaderResourceView(_texture, &resourceViewDesc, &_textureView);
if (FAILED(result))
{
CubismLogError("Error : create offscreen resource view");
break;
}
// Depth/Stencil
D3D11_TEXTURE2D_DESC depthDesc;
memset(&depthDesc, 0, sizeof(depthDesc));
depthDesc.Width = displayBufferWidth;
depthDesc.Height = displayBufferHeight;
depthDesc.MipLevels = 1;
depthDesc.ArraySize = 1;
depthDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthDesc.SampleDesc.Count = 1;
depthDesc.SampleDesc.Quality = 0;
depthDesc.Usage = D3D11_USAGE_DEFAULT;
depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthDesc.CPUAccessFlags = 0;
depthDesc.MiscFlags = 0;
result = device->CreateTexture2D(&depthDesc, NULL, &_depthTexture);
if (FAILED(result))
{
CubismLogError("Error : create offscreen depth texture");
break;
}
D3D11_DEPTH_STENCIL_VIEW_DESC depthViewDesc;
memset(&depthViewDesc, 0, sizeof(depthViewDesc));
depthViewDesc.Format = depthDesc.Format;
depthViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthViewDesc.Texture2D.MipSlice = 0;
result = device->CreateDepthStencilView(_depthTexture, &depthViewDesc, &_depthView);
if (FAILED(result))
{
CubismLogError("Error : create offscreen depth view");
break;
}
_bufferWidth = displayBufferWidth;
_bufferHeight = displayBufferHeight;
// 成功
return true;
} while (0);
// 失敗したので削除
DestroyOffscreenSurface();
return false;
}
void CubismOffscreenSurface_D3D11::DestroyOffscreenSurface()
{
// これらがあるのはEndDrawが来なかった場合
if (_backupDepth)
{
_backupDepth->Release();
_backupDepth = NULL;
}
if (_backupRender)
{
_backupRender->Release();
_backupRender = NULL;
}
if (_depthView)
{
_depthView->Release();
_depthView = NULL;
}
if (_depthTexture)
{
_depthTexture->Release();
_depthTexture = NULL;
}
if (_textureView)
{
_textureView->Release();
_textureView = NULL;
}
if (_renderTargetView)
{
_renderTargetView->Release();
_renderTargetView = NULL;
}
if (_texture)
{
_texture->Release();
_texture = NULL;
}
}
ID3D11ShaderResourceView* CubismOffscreenSurface_D3D11::GetTextureView() const
{
return _textureView;
}
csmUint32 CubismOffscreenSurface_D3D11::GetBufferWidth() const
{
return _bufferWidth;
}
csmUint32 CubismOffscreenSurface_D3D11::GetBufferHeight() const
{
return _bufferHeight;
}
csmBool CubismOffscreenSurface_D3D11::IsValid() const
{
if (_textureView == NULL || _renderTargetView == NULL || _depthView == NULL)
{
return false;
}
return true;
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,108 @@
/**
* 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 "CubismNativeInclude_D3D11.hpp"
#include "Math/CubismMatrix44.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
/**
* @brief オフスクリーン描画用構造体
*/
class CubismOffscreenSurface_D3D11
{
public:
CubismOffscreenSurface_D3D11();
/**
* @brief 指定の描画ターゲットに向けて描画開始
*
* @param renderContext[in] 描画コンテキスト
*/
void BeginDraw(ID3D11DeviceContext* renderContext);
/**
* @brief 描画終了
*
* @param renderContext[in] 描画コンテキスト
*/
void EndDraw(ID3D11DeviceContext* renderContext);
/**
* @brief レンダリングターゲットのクリア
* 呼ぶ場合はBeginDrawの後で呼ぶこと
* @param r 赤(0.0~1.0)
* @param g 緑(0.0~1.0)
* @param b 青(0.0~1.0)
* @param a α(0.0~1.0)
*/
void Clear(ID3D11DeviceContext* renderContext, float r, float g, float b, float a);
/**
* @brief CubismOffscreenSurface作成
* @param device[in] D3dデバイス
* @param displayBufferWidth[in] 作成するバッファ幅
* @param displayBufferHeight[in] 作成するバッファ高さ
*/
csmBool CreateOffscreenSurface(ID3D11Device* device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight);
/**
* @brief CubismOffscreenSurfaceの削除
*/
void DestroyOffscreenSurface();
/**
* @brief クリアカラーの上書き
*/
void SetClearColor(float r, float g, float b, float a);
/**
* @brief テクスチャビューへのアクセッサ
*/
ID3D11ShaderResourceView* GetTextureView() const;
/**
* @brief バッファ幅取得
*/
csmUint32 GetBufferWidth() const;
/**
* @brief バッファ高さ取得
*/
csmUint32 GetBufferHeight() const;
/**
* @brief 現在有効かどうか
*/
csmBool IsValid() const;
private:
ID3D11Texture2D* _texture; ///< 生成テクスチャ
ID3D11ShaderResourceView* _textureView; ///< テクスチャのシェーダーリソースとしてのビュー
ID3D11RenderTargetView* _renderTargetView; ///< テクスチャのレンダーターゲットとしてのビュー
ID3D11Texture2D* _depthTexture; ///< Zテクスチャ
ID3D11DepthStencilView* _depthView; ///< Zビュー
ID3D11RenderTargetView* _backupRender; ///< 元々のターゲットを退避
ID3D11DepthStencilView* _backupDepth; ///< 元々のZを退避
csmUint32 _bufferWidth; ///< Create時に指定されたサイズ
csmUint32 _bufferHeight; ///< Create時に指定されたサイズ
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,471 @@
/**
* 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 "CubismRenderState_D3D11.hpp"
#include "CubismShader_D3D11.hpp"
#include "CubismRenderer_D3D11.hpp"
#include "Type/csmVector.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
CubismRenderState_D3D11::CubismRenderState_D3D11()
{
//
memset(_stored._valid, 0, sizeof(_stored._valid));
Create(CubismRenderer_D3D11::GetCurrentDevice());
}
CubismRenderState_D3D11::~CubismRenderState_D3D11()
{
_pushed.Clear();
// サンプラーステート解放
for (csmUint32 i = 0; i<_samplerState.GetSize(); i++)
{
ID3D11SamplerState* sampl = _samplerState[i];
if (sampl)
{
sampl->Release();
}
}
_samplerState.Clear();
// Z解放
for (csmUint32 i = 0; i<_depthStencilState.GetSize(); i++)
{
ID3D11DepthStencilState* depth = _depthStencilState[i];
if (depth)
{
depth->Release();
}
}
_depthStencilState.Clear();
// ラスタライザ解放
for (csmUint32 i = 0; i<_rasterizeStateObjects.GetSize(); i++)
{
ID3D11RasterizerState* raster = _rasterizeStateObjects[i];
if (raster)
{
raster->Release();
}
}
_rasterizeStateObjects.Clear();
// ブレンドステート解放
for( csmUint32 i=0; i<_blendStateObjects.GetSize(); i++ )
{
ID3D11BlendState* state = _blendStateObjects[i];
if(state)
{
state->Release();
}
}
_blendStateObjects.Clear();
}
void CubismRenderState_D3D11::Create(ID3D11Device* device)
{
if(!device)
{
return;
}
// Blend
ID3D11BlendState* state = NULL;
D3D11_BLEND_DESC blendDesc;
memset(&blendDesc, 0, sizeof(blendDesc));
// origin
_blendStateObjects.PushBack(NULL);
// ゼロ
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE; // falseの場合はRenderTarget[0]しか使用しなくなる
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
device->CreateBlendState(&blendDesc, &state);
_blendStateObjects.PushBack(state);
// 通常
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
device->CreateBlendState(&blendDesc, &state);
_blendStateObjects.PushBack(state);
// 加算
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
device->CreateBlendState(&blendDesc, &state);
_blendStateObjects.PushBack(state);
// 乗算
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_DEST_COLOR;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
device->CreateBlendState(&blendDesc, &state);
_blendStateObjects.PushBack(state);
// マスク
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
device->CreateBlendState(&blendDesc, &state);
_blendStateObjects.PushBack(state);
// ラスタライザ
ID3D11RasterizerState* rasterizer = NULL;
D3D11_RASTERIZER_DESC rasterDesc;
memset(&rasterDesc, 0, sizeof(rasterDesc));
// origin
_rasterizeStateObjects.PushBack(NULL);
// None
rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE; // カリング無し
rasterDesc.FrontCounterClockwise = TRUE; // CCWを表面にする
rasterDesc.DepthClipEnable = FALSE;
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.DepthBiasClamp = 0;
rasterDesc.SlopeScaledDepthBias = 0;
device->CreateRasterizerState(&rasterDesc, &rasterizer);
_rasterizeStateObjects.PushBack(rasterizer);
// CCW
rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK; // 裏面を切る
device->CreateRasterizerState(&rasterDesc, &rasterizer);
_rasterizeStateObjects.PushBack(rasterizer);
// Depth
ID3D11DepthStencilState* depth = NULL;
D3D11_DEPTH_STENCIL_DESC depthDesc;
memset(&depthDesc, 0, sizeof(depthDesc));
// origin
_depthStencilState.PushBack(NULL);
// 無効
depthDesc.DepthEnable = false;
depthDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthDesc.StencilEnable = false;
device->CreateDepthStencilState(&depthDesc, &depth);
_depthStencilState.PushBack(depth);
// 有効
depthDesc.DepthEnable = true;
depthDesc.StencilEnable = false;
device->CreateDepthStencilState(&depthDesc, &depth);
_depthStencilState.PushBack(depth);
// Sampler
ID3D11SamplerState* sampler = NULL;
D3D11_SAMPLER_DESC samplerDesc;
memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC));
// origin
_samplerState.PushBack(NULL);
// normal
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MaxAnisotropy = 0;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.MinLOD = -D3D11_FLOAT32_MAX;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.BorderColor[0] = samplerDesc.BorderColor[1] = samplerDesc.BorderColor[2] = samplerDesc.BorderColor[3] = 1.0f;
device->CreateSamplerState(&samplerDesc, &sampler);
_samplerState.PushBack(sampler);
}
void CubismRenderState_D3D11::StartFrame()
{
memset(_stored._valid, 0, sizeof(_stored._valid));
_pushed.Clear();
}
void CubismRenderState_D3D11::Save()
{
// 現時点のステートをPush
_pushed.PushBack(_stored);
}
void CubismRenderState_D3D11::Restore(ID3D11DeviceContext* renderContext)
{
const csmUint32 size = _pushed.GetSize();
if (size == 0)
{
return;
}
//forで辿って最後に設定した個所までチェック
csmBool isSet[State_Max];
memset(isSet, 0, sizeof(isSet));
for (csmInt32 i = static_cast<csmInt32>(_pushed.GetSize())-1; i>=0; i--)
{
Stored &current = _pushed[i];
if (_pushed[i]._valid[State_Blend] && !isSet[State_Blend])
{
SetBlend(renderContext, current._blendState, current._blendFactor, current._blendMask, true);
isSet[State_Blend] = true;
}
if (_pushed[i]._valid[State_CullMode] && !isSet[State_CullMode])
{
SetCullMode(renderContext, current._cullMode, true);
isSet[State_CullMode] = true;
}
if (_pushed[i]._valid[State_Viewport] && !isSet[State_Viewport])
{
SetViewport(renderContext, current._viewportX, current._viewportY, current._viewportWidth, current._viewportHeight, current._viewportMinZ, current._viewportMaxZ, true);
isSet[State_Viewport] = true;
}
if (_pushed[i]._valid[State_ZEnable] && !isSet[State_ZEnable])
{
SetZEnable(renderContext, current._depthEnable, current._depthRef, true);
isSet[State_ZEnable] = true;
}
if (_pushed[i]._valid[State_Sampler] && !isSet[State_Sampler])
{
SetSampler(renderContext, current._sampler, true);
isSet[State_Sampler] = true;
}
}
Stored store = _pushed[size - 1];
_pushed.Remove(size - 1);
if(_pushed.GetSize()==0)
{
_pushed.Clear();
}
_stored = store;
}
void CubismRenderState_D3D11::SetBlend(ID3D11DeviceContext* renderContext, Blend blendState, DirectX::XMFLOAT4 blendFactor, UINT mask,
csmBool force)
{
if(!renderContext || blendState<0 || Blend_Max<= blendState)
{// パラメータ異常チェック
return;
}
if (!_stored._valid[State_Blend] || force ||
_stored._blendFactor.x != blendFactor.x || _stored._blendFactor.y != blendFactor.y || _stored._blendFactor.z != blendFactor.z || _stored._blendFactor.w != blendFactor.w ||
_stored._blendMask != mask ||
_stored._blendState != blendState)
{
const float factor[4] = { blendFactor.x, blendFactor.y, blendFactor.z, blendFactor.w };
renderContext->OMSetBlendState(_blendStateObjects[blendState], factor, mask);
}
_stored._blendState = blendState;
_stored._blendFactor = blendFactor;
_stored._blendMask = mask;
_stored._valid[State_Blend] = true;
}
void CubismRenderState_D3D11::SetCullMode(ID3D11DeviceContext* renderContext, Cull cullFace, csmBool force)
{
if (!renderContext || cullFace<0 || Cull_Max <= cullFace)
{// パラメータ異常チェック
return;
}
if (!_stored._valid[State_CullMode] || force ||
_stored._cullMode != cullFace)
{
renderContext->RSSetState(_rasterizeStateObjects[cullFace]);
}
_stored._cullMode = cullFace;
_stored._valid[State_CullMode] = true;
}
void CubismRenderState_D3D11::SetViewport(ID3D11DeviceContext* renderContext, FLOAT left, FLOAT top, FLOAT width, FLOAT height, FLOAT zMin, FLOAT zMax, csmBool force)
{
if (!_stored._valid[State_Blend] || force ||
_stored._viewportX != left || _stored._viewportY != top || _stored._viewportWidth != width || _stored._viewportHeight != height ||
_stored._viewportMinZ != zMin || _stored._viewportMaxZ != zMax)
{
// コンテキストにセット
D3D11_VIEWPORT setViewport;
setViewport.TopLeftX = left;
setViewport.TopLeftY = top;
setViewport.Width = width;
setViewport.Height = height;
setViewport.MinDepth = zMin;
setViewport.MaxDepth = zMax;
renderContext->RSSetViewports(1, &setViewport);
}
_stored._viewportX = left;
_stored._viewportY = top;
_stored._viewportWidth = width;
_stored._viewportHeight = height;
_stored._viewportMinZ = zMin;
_stored._viewportMaxZ = zMax;
_stored._valid[State_Viewport] = true;
}
void CubismRenderState_D3D11::SetZEnable(ID3D11DeviceContext* renderContext, Depth enable, UINT stelcilRef, csmBool force)
{
if (!renderContext || enable<0 || Depth_Max <= enable)
{// パラメータ異常チェック
return;
}
if (!_stored._valid[State_ZEnable] || force ||
_stored._depthEnable != enable)
{
renderContext->OMSetDepthStencilState(_depthStencilState[enable], stelcilRef);
}
_stored._depthEnable = enable;
_stored._depthRef = stelcilRef;
_stored._valid[State_ZEnable] = true;
}
void CubismRenderState_D3D11::SetSampler(ID3D11DeviceContext* renderContext, Sampler sample, csmFloat32 anisotropy, ID3D11Device* device, csmBool force)
{
if (!renderContext || sample<0 || Sampler_Max <= sample)
{// パラメータ異常チェック
return;
}
if (!_stored._valid[State_ZEnable] || force ||
_stored._sampler != sample)
{
if (anisotropy > 0.0f && sample == Sampler_Anisotropy && device != NULL)
{
// Sampler
ID3D11SamplerState* sampler;
D3D11_SAMPLER_DESC samplerDesc;
memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC));
renderContext->PSGetSamplers(0, 1, &sampler);
sampler->GetDesc(&samplerDesc);
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
samplerDesc.MaxAnisotropy = anisotropy;
device->CreateSamplerState(&samplerDesc, &sampler);
_samplerState.PushBack(sampler);
}
// 0番だけ使用している
renderContext->PSSetSamplers(0, 1, &_samplerState[sample]);
}
_stored._sampler = sample;
_stored._valid[State_Sampler] = true;
}
void CubismRenderState_D3D11::SaveCurrentNativeState(ID3D11Device* device, ID3D11DeviceContext* renderContext)
{
// まずは全破棄
_pushed.Clear();
// 未設定扱いに
memset(_stored._valid, 0, sizeof(_stored._valid));
// ここで取得したオブジェクトはRestoreNativeStateでリリース
// Blend
ID3D11BlendState* originBlend;
FLOAT originFactor[4];
UINT originMask;
renderContext->OMGetBlendState(&originBlend, originFactor, &originMask);
_blendStateObjects[Blend_Origin] = originBlend; // と入れた上で
SetBlend(renderContext, Blend_Origin, DirectX::XMFLOAT4(originFactor), originMask, true); // コールする
// Cull
ID3D11RasterizerState* originRaster;
renderContext->RSGetState(&originRaster);
_rasterizeStateObjects[Cull_Origin] = originRaster; // と入れた上で
SetCullMode(renderContext, Cull_Origin, true); // コールする
// Depth
ID3D11DepthStencilState* originDepth;
UINT stelcilRef;
renderContext->OMGetDepthStencilState(&originDepth, &stelcilRef);
_depthStencilState[Depth_Origin] = originDepth; // と入れた上で
SetZEnable(renderContext, Depth_Origin, stelcilRef, true); // コールする
// Sampler
ID3D11SamplerState* originSampler;
renderContext->PSGetSamplers(0, 1, &originSampler);
_samplerState[Sampler_Origin] = originSampler; // と入れた上で
SetSampler(renderContext, Sampler_Origin, true); // コールする
// ViewPortはオブジェクトではない
UINT numViewport = 1; // 取得は一つでOK
D3D11_VIEWPORT viewPort;
renderContext->RSGetViewports(&numViewport, &viewPort);
SetViewport(renderContext, viewPort.TopLeftX, viewPort.TopLeftY, viewPort.Width, viewPort.Height, viewPort.MinDepth, viewPort.MaxDepth, true);
// 最後に上記の値を保存
Save();
}
void CubismRenderState_D3D11::RestoreNativeState(ID3D11Device* device, ID3D11DeviceContext* renderContext)
{
// 全て再現
for (csmInt32 i = static_cast<csmInt32>(_pushed.GetSize()) - 1; i >= 0; i--)
{
Restore(renderContext);
}
// 各オリジナルオブジェクトはここで関わりをなくする
if (_samplerState[Sampler_Origin])
{
_samplerState[Sampler_Origin]->Release();
_samplerState[Sampler_Origin] = NULL;
}
if(_depthStencilState[Depth_Origin])
{
_depthStencilState[Depth_Origin]->Release();
_depthStencilState[Depth_Origin] = NULL;
}
if (_rasterizeStateObjects[Cull_Origin])
{
_rasterizeStateObjects[Cull_Origin]->Release();
_rasterizeStateObjects[Cull_Origin] = NULL;
}
if (_blendStateObjects[Blend_Origin])
{
_blendStateObjects[Blend_Origin]->Release();
_blendStateObjects[Blend_Origin] = NULL;
}
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,235 @@
/**
* 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 "CubismNativeInclude_D3D11.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmMap.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
class CubismRenderer_D3D11;
/**
* @brief CubismDX11内部で設定するステートのうち、途中で変更する可能性のあるものを管理。
* CubismRenderer_D3D11がシングルトンとして管理。
*/
class CubismRenderState_D3D11
{
friend class CubismRenderer_D3D11;
public:
enum
{
State_None,
State_Blend, ///< ブレンドモード
State_Viewport, ///< ビューポート
State_ZEnable, ///< Z有効無効
State_CullMode, ///< カリングモード
State_Sampler, ///< テクスチャフィルター
State_Max,
};
// ブレンドステート D3D11ではオブジェクト単位での管理
enum Blend
{
Blend_Origin,
Blend_Zero,
Blend_Normal,
Blend_Add,
Blend_Mult,
Blend_Mask,
Blend_Max,
};
// カリング D3D11ではオブジェクト単位での管理
enum Cull
{
Cull_Origin,///< 元々の設定
Cull_None, ///< カリング無し
Cull_Ccw, ///< CCW表示
Cull_Max,
};
// Z D3D11ではオブジェクト単位での管理
enum Depth
{
Depth_Origin, ///< 元々の設定
Depth_Disable, ///< Zoff
Depth_Enable, ///< Zon
Depth_Max,
};
// サンプラーステート D3D11ではオブジェクト単位での管理
enum Sampler
{
Sampler_Origin, ///< 元々の設定
Sampler_Normal, ///< 使用ステート
Sampler_Anisotropy, ///< 異方性フィルタリング使用
Sampler_Max,
};
/**
* @notice デフォルトの=でコピーします
*/
struct Stored
{
Stored()
{
_blendState = Blend_Zero;
_blendFactor.x = _blendFactor.y = _blendFactor.z = _blendFactor.w = 0.0f;
_blendMask = 0xffffffff;
_cullMode = Cull_None;
_depthEnable = Depth_Disable;
_depthRef = 0;
_viewportX = 0;
_viewportY = 0;
_viewportWidth = 0;
_viewportHeight = 0;
_viewportMinZ = 0.0f;
_viewportMaxZ = 0.0f;
_sampler = Sampler_Normal;
_anisotropy = 0.0f;
memset(_valid, 0, sizeof(_valid));
}
// State_Blend
Blend _blendState;
DirectX::XMFLOAT4 _blendFactor;
UINT _blendMask;
// State_CullMode
Cull _cullMode;
// State_Viewport
FLOAT _viewportX;
FLOAT _viewportY;
FLOAT _viewportWidth;
FLOAT _viewportHeight;
FLOAT _viewportMinZ;
FLOAT _viewportMaxZ;
// State_ZEnable
Depth _depthEnable;
UINT _depthRef;
// State_Sampler
Sampler _sampler;
FLOAT _anisotropy;
csmBool _valid[State_Max]; ///< 設定したかどうか。現在はStartFrameで一通りは呼んでいる
};
/**
* @brief フレーム先頭で呼び出す処理
*/
void StartFrame();
/**
* @brief 管理中のステートをPush
*/
void Save();
/**
* @brief Push下ステートをPop
* @notice Saveの際にCubismRenderState_D3D11で設定していなかった項目は戻せないことに注意
*/
void Restore(ID3D11DeviceContext* renderContext);
/**
* @brief ブレンドモードセット
*
* @param renderContext[in] 描画コンテキスト
* @param blendState[in] 予め用意したブレンドオブジェクトの番号(enum CubismRenderState_D3D11::Blend)
* @param blendFactor[in] D3D11_BLEND_BLEND_FACTOR指定時の係数
* @param mask[in] ピクセルマスク
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetBlend(ID3D11DeviceContext* renderContext, Blend blendState, DirectX::XMFLOAT4 blendFactor, UINT mask,
csmBool force=false);
/**
* @brief カリングモードセット
*
* @param device[in] 描画コンテキスト
* @param cullFace[in] 切除するべき面 指定された面を切る Cwだと時計回りを切除
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetCullMode(ID3D11DeviceContext* renderContext, Cull cullFace, csmBool force = false);
/**
* @brief ビューポートセット
*
* @param renderContext[in] 描画コンテキスト
* @param left[in] ビューポート左座標
* @param top[in] ビューポート上座標
* @param width[in] ビューポート右座標
* @param height[in] ビューポート下座標
* @param zMin[in] Z最小値
* @param zMax[in] Z最大値
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetViewport(ID3D11DeviceContext* renderContext, FLOAT left, FLOAT top, FLOAT width, FLOAT height, FLOAT zMin, FLOAT zMax, csmBool force = false);
/**
* @brief Z有効無効セット
*
* @param renderContext[in] 描画コンテキスト
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetZEnable(ID3D11DeviceContext* renderContext, Depth enable, UINT stelcilRef, csmBool force = false);
/**
* @brief サンプラーステートセット
*
* @param renderContext[in] 描画コンテキスト
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetSampler(ID3D11DeviceContext* renderContext, Sampler sample, csmFloat32 anisotropy = 0.0f, ID3D11Device* device = NULL, csmBool force = false);
private:
CubismRenderState_D3D11();
~CubismRenderState_D3D11();
/**
* @brief 各種オブジェクトを作成する
*/
void Create(ID3D11Device* device);
/**
* @brief D3DDeviceから、Cubismに関係する値を取得したうえでCubismRenderState_D3D11に反映しSaveを呼び出し、_pushedは破棄
* Cubismフレーム処理の最初、StartFrameの後で呼んでいる
*/
void SaveCurrentNativeState(ID3D11Device* device, ID3D11DeviceContext* renderContext);
/**
* @brief 最初にPushしたステートまで戻す
*/
void RestoreNativeState(ID3D11Device* device, ID3D11DeviceContext* renderContext);
Stored _stored; ///< ストアされた各種設定
csmVector<Stored> _pushed;
csmVector<ID3D11BlendState*> _blendStateObjects;
csmVector<ID3D11RasterizerState*> _rasterizeStateObjects;
csmVector<ID3D11DepthStencilState*> _depthStencilState;
csmVector<ID3D11SamplerState*> _samplerState;
};
}}}}
//------------ LIVE2D NAMESPACE ------------
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,443 @@
/**
* 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 "CubismNativeInclude_D3D11.hpp"
#include "../CubismRenderer.hpp"
#include "../CubismClippingManager.hpp"
#include "CubismFramework.hpp"
#include "CubismType_D3D11.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmRectF.hpp"
#include "Math/CubismVector2.hpp"
#include "Type/csmMap.hpp"
#include "Rendering/D3D11/CubismOffscreenSurface_D3D11.hpp"
#include "CubismRenderState_D3D11.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
// 前方宣言
class CubismRenderer_D3D11;
class CubismShader_D3D11;
class CubismClippingContext_D3D11;
/**
* @brief DirectX::XMMATRIXに変換
*/
DirectX::XMMATRIX ConvertToD3DX(CubismMatrix44& mtx);
/**
* @brief クリッピングマスクの処理を実行するクラス
*
*/
class CubismClippingManager_D3D11 : public CubismClippingManager<CubismClippingContext_D3D11, CubismOffscreenSurface_D3D11>
{
public:
/**
* @brief クリッピングコンテキストを作成する。モデル描画時に実行する。
*
* @param[in] model -> モデルのインスタンス
* @param[in] renderer -> レンダラのインスタンス
*/
void SetupClippingContext(ID3D11Device* device, ID3D11DeviceContext* renderContext, CubismModel& model, CubismRenderer_D3D11* renderer, csmInt32 offscreenCurrent);
};
/**
* @brief クリッピングマスクのコンテキスト
*/
class CubismClippingContext_D3D11 : public CubismClippingContext
{
friend class CubismClippingManager_D3D11;
friend class CubismShader_D3D11;
friend class CubismRenderer_D3D11;
public:
/**
* @brief 引数付きコンストラクタ
*
*/
CubismClippingContext_D3D11(CubismClippingManager<CubismClippingContext_D3D11, CubismOffscreenSurface_D3D11>* manager, CubismModel& model, const csmInt32* clippingDrawableIndices, csmInt32 clipCount);
/**
* @brief デストラクタ
*/
virtual ~CubismClippingContext_D3D11();
/**
* @brief このマスクを管理するマネージャのインスタンスを取得する。
*
* @return クリッピングマネージャのインスタンス
*/
CubismClippingManager<CubismClippingContext_D3D11, CubismOffscreenSurface_D3D11>* GetClippingManager();
CubismClippingManager<CubismClippingContext_D3D11, CubismOffscreenSurface_D3D11>* _owner; ///< このマスクを管理しているマネージャのインスタンス
};
/**
* @brief DirectX11用の描画命令を実装したクラス
*
*/
class CubismRenderer_D3D11 : public CubismRenderer
{
friend class CubismRenderer;
friend class CubismClippingManager_D3D11;
friend class CubismShader_D3D11;
public:
/**
* @brief レンダラを作成するための各種設定
* モデルロードの前に一度だけ呼び出す
*
* @param[in] bufferSetNum -> 描画コマンドバッファ数
* @param[in] device -> 使用デバイス
*/
static void InitializeConstantSettings(csmUint32 bufferSetNum, ID3D11Device* device);
/**
* @brief CubismRenderStateにデフォルトの設定をセットする
*/
static void SetDefaultRenderState();
/**
* @brief Cubism描画関連の先頭で行う処理。
* 各フレームでのCubism処理前にこれを呼んでもらう
*
* @param[in] device -> 使用デバイス
*/
static void StartFrame(ID3D11Device* device, ID3D11DeviceContext* renderContext, csmUint32 viewportWidth, csmUint32 viewportHeight);
/**
* @brief Cubism描画関連の終了時行う処理。
* 各フレームでのCubism処理前にこれを呼んでもらう
*
* @param[in] device -> 使用デバイス
*/
static void EndFrame(ID3D11Device* device);
/**
* @brief CubismRenderer_D3D11で使用するレンダーステート管理マネージャ取得
*/
static CubismRenderState_D3D11* GetRenderStateManager();
/**
* @brief レンダーステート管理マネージャ削除
*/
static void DeleteRenderStateManager();
/**
* @brief シェーダ管理機構の取得
*/
static CubismShader_D3D11* GetShaderManager();
/**
* @brief シェーダ管理機構の削除
*/
static void DeleteShaderManager();
/**
* @brief デバイスロスト・デバイス再作成時コールする
*/
static void OnDeviceLost();
/**
* @brief 使用シェーダー作成
*/
static void GenerateShader(ID3D11Device* device);
/**
* @brief 使用中デバイス取得
*/
static ID3D11Device* GetCurrentDevice();
/**
* @brief レンダラの初期化処理を実行する<br>
* 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる
*
* @param[in] model -> モデルのインスタンス
*/
virtual void Initialize(Framework::CubismModel* model);
/**
* @brief レンダラの初期化処理を実行する<br>
* 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる
*
* @param[in] model -> モデルのインスタンス
*/
virtual void Initialize(Framework::CubismModel* model, csmInt32 maskBufferCount);
/**
* @brief OpenGLテクスチャのバインド処理<br>
* CubismRendererにテクスチャを設定し、CubismRenderer中でその画像を参照するためのIndex値を戻り値とする
*
* @param[in] modelTextureAssign -> セットするモデルテクスチャのアサイン番号
* @param[in] textureView -> 描画に使用するテクスチャ
*
*/
void BindTexture(csmUint32 modelTextureAssign, ID3D11ShaderResourceView* textureView);
/**
* @brief OpenGLにバインドされたテクスチャのリストを取得する
*
* @return テクスチャのアドレスのリスト
*/
const csmMap<csmInt32, ID3D11ShaderResourceView*>& GetBindedTextures() const;
/**
* @brief クリッピングマスクバッファのサイズを設定する<br>
* マスク用のOffscreenSurfaceを破棄・再作成するため処理コストは高い。
*
* @param[in] size -> クリッピングマスクバッファのサイズ
*
*/
void SetClippingMaskBufferSize(csmFloat32 width, csmFloat32 height);
/**
* @brief レンダーテクスチャの枚数を取得する。
*
* @return レンダーテクスチャの枚数
*
*/
csmInt32 GetRenderTextureCount() const;
/**
* @brief クリッピングマスクバッファのサイズを取得する
*
* @return クリッピングマスクバッファのサイズ
*
*/
CubismVector2 GetClippingMaskBufferSize() const;
/**
* @brief クリッピングマスクのバッファを取得する
*
* @return クリッピングマスクのバッファへの参照
*
*/
CubismOffscreenSurface_D3D11* GetMaskBuffer(csmUint32 backbufferNum, csmInt32 offscreenIndex);
protected:
/**
* @brief コンストラクタ
*/
CubismRenderer_D3D11();
/**
* @brief デストラクタ
*/
virtual ~CubismRenderer_D3D11();
/**
* @brief モデルを描画する実際の処理
*
*/
virtual void DoDrawModel() override;
/**
* @brief 描画オブジェクト(アートメッシュ)を描画する。
*
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
void DrawMeshDX11(const CubismModel& model, const csmInt32 index);
private:
/**
* @brief 描画用に使用するシェーダの設定・コンスタントバッファの設定などを行い、マスク描画を実行
*
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
void ExecuteDrawForMask(const CubismModel& model, const csmInt32 index);
/**
* @brief マスク作成用に使用するシェーダの設定・コンスタントバッファの設定などを行い、描画を実行
*
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
void ExecuteDrawForDraw(const CubismModel& model, const csmInt32 index);
/**
* @brief 指定されたメッシュインデックスに対して描画命令を実行する
*
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
void DrawDrawableIndexed(const CubismModel& model, const csmInt32 index);
/**
* @brief レンダラが保持する静的なリソースを解放する
*/
static void DoStaticRelease();
/**
* @brief 使用シェーダーと頂点定義の削除
*/
static void ReleaseShader();
// Prevention of copy Constructor
CubismRenderer_D3D11(const CubismRenderer_D3D11&);
CubismRenderer_D3D11& operator=(const CubismRenderer_D3D11&);
/**
* @brief 描画開始時の追加処理。<br>
* モデルを描画する前にクリッピングマスクに必要な処理を実装している。
*/
void PreDraw();
/**
* @brief 描画完了後の追加処理。<br>
* ダブル・トリプルバッファリングに必要な処理を実装している。
*/
void PostDraw();
/**
* @brief モデル描画直前のステートを保持する
*/
virtual void SaveProfile() override;
/**
* @brief モデル描画直前のステートを保持する
*/
virtual void RestoreProfile() override;
/**
* @brief マスクテクスチャに描画するクリッピングコンテキストをセットする。
*/
void SetClippingContextBufferForMask(CubismClippingContext_D3D11* clip);
/**
* @brief マスクテクスチャに描画するクリッピングコンテキストを取得する。
*
* @return マスクテクスチャに描画するクリッピングコンテキスト
*/
CubismClippingContext_D3D11* GetClippingContextBufferForMask() const;
/**
* @brief 画面上に描画するクリッピングコンテキストをセットする。
*/
void SetClippingContextBufferForDraw(CubismClippingContext_D3D11* clip);
/**
* @brief 画面上に描画するクリッピングコンテキストを取得する。
*
* @return 画面上に描画するクリッピングコンテキスト
*/
CubismClippingContext_D3D11* GetClippingContextBufferForDraw() const;
/**
* @brief GetDrawableVertices,GetDrawableVertexUvsの内容をバッファへコピー
*/
void CopyToBuffer(ID3D11DeviceContext* renderContext, csmInt32 drawAssign, const csmInt32 vcount, const csmFloat32* varray, const csmFloat32* uvarray);
/**
* @brief modelのindexにバインドされているテクスチャを返す。<br>
* もしバインドしていないindexを指定した場合NULLが返る。
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
ID3D11ShaderResourceView* GetTextureViewWithIndex(const CubismModel& model, const csmInt32 index);
/**
* @brief ブレンドステートをセットする。
*/
void SetBlendState(const CubismBlendMode blendMode);
/**
* @brief シェーダをコンテキストにセットする<br>
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
Csm::csmBool SetShader(const CubismModel& model, const csmInt32 index);
/**
* @brief 描画に使用するテクスチャを設定する。
*
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
*/
void SetTextureView(const CubismModel& model, const csmInt32 index);
/**
* @brief 色関連の定数バッファを設定する
*
* @param[in] cb -> 設定する定数バッファ
* @param[in] model -> 描画対象のモデル
* @param[in] index -> 描画対象のインデックス
* @param[in] baseColor -> ベースカラー
* @param[in] multiplyColor -> 乗算カラー
* @param[in] screenColor -> スクリーンカラー
*/
void SetColorConstantBuffer(CubismConstantBufferD3D11& cb, const CubismModel& model, const csmInt32 index,
CubismTextureColor& baseColor, CubismTextureColor& multiplyColor, CubismTextureColor& screenColor);
/**
* @brief 描画に使用するカラーチャンネルを設定
*
* @param[in] cb -> 設定する定数バッファ
* @param[in] contextBuffer -> 描画コンテキスト
*/
void SetColorChannel(CubismConstantBufferD3D11& cb, CubismClippingContext_D3D11* contextBuffer);
/**
* @brief 描画に使用するプロジェクション行列を更新する
*
* @param[in] cb -> 設定する定数バッファ
* @param[in] matrix -> 設定するプロジェクション行列
*/
void SetProjectionMatrix(CubismConstantBufferD3D11& cb, CubismMatrix44 matrix);
/**
* @brief 定数バッファを更新する
*
* @param[in] cb -> 書き込む定数バッファ情報
* @param[in] index -> 描画対象のインデックス
*/
void UpdateConstantBuffer(CubismConstantBufferD3D11& cb, csmInt32 index);
/**
* @brief 異方向フィルタリングの値によってサンプラーを設定する。
*/
void SetSamplerAccordingToAnisotropy();
/**
* @brief マスク生成時かを判定する
*
* @return 判定値
*/
const csmBool inline IsGeneratingMask() const;
ID3D11Buffer*** _vertexBuffers; ///< 描画バッファ カラー無し、位置+UV
ID3D11Buffer*** _indexBuffers; ///< インデックスのバッファ
ID3D11Buffer*** _constantBuffers; ///< 定数のバッファ
csmUint32 _drawableNum; ///< _vertexBuffers, _indexBuffersの確保数
csmInt32 _commandBufferNum;
csmInt32 _commandBufferCurrent;
csmVector<csmInt32> _sortedDrawableIndexList; ///< 描画オブジェクトのインデックスを描画順に並べたリスト
csmMap<csmInt32, ID3D11ShaderResourceView*> _textures; ///< モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ
csmVector<csmVector<CubismOffscreenSurface_D3D11> > _offscreenSurfaces; ///< マスク描画用のフレームバッファ
CubismClippingManager_D3D11* _clippingManager; ///< クリッピングマスク管理オブジェクト
CubismClippingContext_D3D11* _clippingContextBufferForMask; ///< マスクテクスチャに描画するためのクリッピングコンテキスト
CubismClippingContext_D3D11* _clippingContextBufferForDraw; ///< 画面上描画するためのクリッピングコンテキスト
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,329 @@
/**
* 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 "CubismShader_D3D11.hpp"
#include "CubismRenderer_D3D11.hpp"
#include <d3dcompiler.h>
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
void CubismShader_D3D11::ReleaseShaderProgram()
{
// シェーダーソースコード開放
_shaderSrc.Clear();
// 頂点レイアウト開放
if (_vertexFormat)
{
_vertexFormat->Release();
_vertexFormat = NULL;
}
// 器はそのまま
for (csmInt32 i = 0; i < ShaderNames_Max; i++)
{
if(_shaderSetsVS[i])
{
_shaderSetsVS[i]->Release();
_shaderSetsVS[i] = NULL;
}
if (_shaderSetsPS[i])
{
_shaderSetsPS[i]->Release();
_shaderSetsPS[i] = NULL;
}
}
}
CubismShader_D3D11::CubismShader_D3D11()
: _vertexFormat(NULL)
{
// 器作成
for (csmInt32 i = 0; i < ShaderNames_Max; i++)
{
_shaderSetsVS.PushBack(NULL);
_shaderSetsPS.PushBack(NULL);
}
}
CubismShader_D3D11::~CubismShader_D3D11()
{
ReleaseShaderProgram();
// 器の削除
_shaderSetsVS.Clear();
_shaderSetsPS.Clear();
}
void CubismShader_D3D11::GenerateShaders(ID3D11Device* device)
{
// 既に有るかどうかをこれで判断している
if(_vertexFormat!=NULL)
{
return;
}
// 一旦開放
ReleaseShaderProgram();
csmBool isSuccess = false;
do
{
// シェーダーソースコードが記述されているファイルを読み込み
const csmChar* frameworkShaderPath = "FrameworkShaders/CubismEffect.fx";
csmLoadFileFunction fileLoader = Csm::CubismFramework::GetLoadFileFunction();
csmReleaseBytesFunction bytesReleaser = Csm::CubismFramework::GetReleaseBytesFunction();
if (!fileLoader)
{
CubismLogError("File loader is not set.");
break;
}
if (!bytesReleaser)
{
CubismLogError("Byte releaser is not set.");
break;
}
csmSizeInt shaderSize;
csmByte* shaderSrc = fileLoader(frameworkShaderPath, &shaderSize);
if (shaderSrc == NULL)
{
CubismLogError("Failed to load shader");
break;
}
csmString shaderString = csmString(reinterpret_cast<const csmChar*>(shaderSrc), shaderSize);
_shaderSrc.Clear();
for (csmInt32 i = 0; i < shaderString.GetLength(); i++)
{
_shaderSrc.PushBack(shaderString.GetRawString()[i]);
}
// ファイル読み込みで確保したバイト列を開放
bytesReleaser(shaderSrc);
// マスク
if(!LoadShaderProgram(device, false, ShaderNames_SetupMask, static_cast<const csmChar*>("VertSetupMask")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_SetupMask, static_cast<const csmChar*>("PixelSetupMask")))
{
break;
}
// 頂点シェーダ
if (!LoadShaderProgram(device, false, ShaderNames_Normal, static_cast<const csmChar*>("VertNormal")))
{
break;
}
if (!LoadShaderProgram(device, false, ShaderNames_NormalMasked, static_cast<const csmChar*>("VertMasked")))
{
break;
}
// ピクセルシェーダ
if (!LoadShaderProgram(device, true, ShaderNames_Normal, static_cast<const csmChar*>("PixelNormal")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_NormalMasked, static_cast<const csmChar*>("PixelMasked")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_NormalMaskedInverted, static_cast<csmChar*>("PixelMaskedInverted")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_NormalPremultipliedAlpha, static_cast<csmChar*>("PixelNormalPremult")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_NormalMaskedPremultipliedAlpha, static_cast<const csmChar*>("PixelMaskedPremult")))
{
break;
}
if (!LoadShaderProgram(device, true, ShaderNames_NormalMaskedInvertedPremultipliedAlpha, static_cast<csmChar*>("PixelMaskedInvertedPremult")))
{
break;
}
// 成功
isSuccess = true;
} while (0);
if(!isSuccess)
{
CubismLogError("Fail Compile shader");
CSM_ASSERT(0);
return;
}
// シェーダーコードからレイアウト取得
UINT compileFlag = 0;
#ifdef CSM_DEBUG
// デバッグならば
compileFlag |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* layoutError = NULL;
ID3DBlob* layoutBlobr = NULL;
HRESULT hr = D3DCompile(
_shaderSrc.GetPtr(), // メモリー内のシェーダーへのポインターです。
_shaderSrc.GetSize(), // メモリー内のシェーダーのサイズです。
NULL, // シェーダー コードが格納されているファイルの名前です。
NULL, // マクロ定義の配列へのポインターです
NULL, // インクルード ファイルを扱うインターフェイスへのポインターです
"VertNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前です。
"vs_4_0", // シェーダー モデルを指定する文字列。
compileFlag, // シェーダーコンパイルフラグ
0, // シェーダーエフェクトのフラグ
&layoutBlobr, // 結果
&layoutError); // エラーが出る場合はここで
if (FAILED(hr))
{
CubismLogError("Fail create input layout");
CSM_ASSERT(0);
}
else
{
// この描画で使用する頂点フォーマット
D3D11_INPUT_ELEMENT_DESC elems[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = device->CreateInputLayout(elems, ARRAYSIZE(elems), layoutBlobr->GetBufferPointer(), layoutBlobr->GetBufferSize(), &_vertexFormat);
if (FAILED(hr))
{
CubismLogWarning("CreateVertexDeclaration failed");
}
}
// blobの開放
if (layoutError)
{
layoutError->Release();
}
if (layoutBlobr)
{
layoutBlobr->Release();
}
}
Csm::csmBool CubismShader_D3D11::LoadShaderProgram(ID3D11Device* device, bool isPs, csmInt32 assign, const csmChar* entryPoint)
{
csmBool bRet = false;
if (!device) return false;
ID3DBlob* errorBlob = NULL;
ID3DBlob* vertexBlob = NULL;
ID3D11VertexShader* vertexShader = NULL;
ID3D11PixelShader* pixelShader = NULL;
HRESULT hr = S_OK;
do
{
UINT compileFlag = 0;
#ifdef CSM_DEBUG
// デバッグならば
compileFlag |= D3DCOMPILE_DEBUG;
#endif
hr = D3DCompile(
_shaderSrc.GetPtr(), // メモリー内のシェーダーへのポインターです。
_shaderSrc.GetSize(), // メモリー内のシェーダーのサイズです。
NULL, // シェーダー コードが格納されているファイルの名前です。
NULL, // マクロ定義の配列へのポインターです
NULL, // インクルード ファイルを扱うインターフェイスへのポインターです
entryPoint, // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前です。
isPs ? "ps_4_0" :"vs_4_0", // シェーダー モデルを指定する文字列。
compileFlag, // シェーダーコンパイルフラグ
0, // シェーダーエフェクトのフラグ
&vertexBlob,
&errorBlob); // エラーが出る場合はここで
if (FAILED(hr))
{
CubismLogWarning("Fail Compile Shader : %s", entryPoint==NULL ? "" : entryPoint);
break;
}
hr = isPs ? device->CreatePixelShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), NULL, &pixelShader) :
device->CreateVertexShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), NULL, &vertexShader);
if (FAILED(hr))
{
CubismLogWarning("Fail Create Shader");
break;
}
if(isPs)
{
_shaderSetsPS[assign] = pixelShader;
}
else
{
_shaderSetsVS[assign] = vertexShader;
}
// 成功
bRet = true;
} while (0);
if(errorBlob)
{
errorBlob->Release();
}
if (vertexBlob)
{
vertexBlob->Release();
}
return bRet;
}
ID3D11VertexShader* CubismShader_D3D11::GetVertexShader(csmUint32 assign)
{
if(assign<ShaderNames_Max)
{
return _shaderSetsVS[assign];
}
return NULL;
}
ID3D11PixelShader* CubismShader_D3D11::GetPixelShader(csmUint32 assign)
{
if (assign<ShaderNames_Max)
{
return _shaderSetsPS[assign];
}
return NULL;
}
void CubismShader_D3D11::SetupShader(ID3D11Device* device, ID3D11DeviceContext* renderContext)
{
// まだシェーダ・頂点宣言未作成ならば作成する
GenerateShaders(device);
if (!renderContext || !_vertexFormat)
{
return;
}
renderContext->IASetInputLayout(_vertexFormat);
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -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.
*/
#pragma once
#include "CubismNativeInclude_D3D11.hpp"
#include "../CubismRenderer.hpp"
#include "CubismType_D3D11.hpp"
#include "CubismFramework.hpp"
#include "Type/csmVector.hpp"
namespace Live2D { namespace Cubism { namespace Framework {
enum ShaderNames
{
// SetupMask
ShaderNames_SetupMask,
//Normal
ShaderNames_Normal,
ShaderNames_NormalMasked,
ShaderNames_NormalMaskedInverted,
ShaderNames_NormalPremultipliedAlpha,
ShaderNames_NormalMaskedPremultipliedAlpha,
ShaderNames_NormalMaskedInvertedPremultipliedAlpha,
//Add
ShaderNames_Add,
ShaderNames_AddMasked,
ShaderNames_AddMaskedInverted,
ShaderNames_AddPremultipliedAlpha,
ShaderNames_AddMaskedPremultipliedAlpha,
ShaderNames_AddMaskedInvertedPremultipliedAlpha,
//Mult
ShaderNames_Mult,
ShaderNames_MultMasked,
ShaderNames_MultMaskedInverted,
ShaderNames_MultPremultipliedAlpha,
ShaderNames_MultMaskedPremultipliedAlpha,
ShaderNames_MultMaskedInvertedPremultipliedAlpha,
ShaderNames_Max,
};
}}}
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
// 前方宣言
class CubismRenderer_D3D11;
class CubismClippingContext;
/**
* @bref D3D11シェーダ管理
*/
class CubismShaderSet
{
public:
CubismShaderSet()
: _vertexShader(NULL)
, _pixelShader(NULL)
{
}
ID3D11VertexShader* _vertexShader;
ID3D11PixelShader* _pixelShader;
};
/**
* @brief Cubismで使用するシェーダ管理クラス
* CubismRenderer_D3D11のstatic変数として一つだけ実体化される
*
*/
class CubismShader_D3D11
{
friend class CubismRenderer_D3D11;
public:
/**
* @brief privateなコンストラクタ
*/
CubismShader_D3D11();
/**
* @brief privateなデストラクタ
*/
virtual ~CubismShader_D3D11();
/**
* @brief シェーダプログラムを解放する
*/
void ReleaseShaderProgram();
/**
* @brief 頂点シェーダの取得
*
*/
ID3D11VertexShader* GetVertexShader(csmUint32 assign);
/**
* @brief ピクセルシェーダの取得
*
*/
ID3D11PixelShader* GetPixelShader(csmUint32 assign);
/**
* @brief 頂点宣言のデバイスへの設定、シェーダがまだ未設定ならロード
*/
void SetupShader(ID3D11Device* device, ID3D11DeviceContext* renderContext);
private:
/**
* @brief シェーダプログラムを初期化する
*/
void GenerateShaders(ID3D11Device* device);
/**
* @brief シェーダプログラムをロード
*
* @param[in] device 使用デバイス
*
* @return 成功時はtrue、失敗時はfalse
*/
Csm::csmBool LoadShaderProgram(ID3D11Device* device, bool isPs, csmInt32 assign, const csmChar* entryPoint);
csmVector<csmChar> _shaderSrc; ///< シェーダーソースコード
csmVector<CubismShaderSet*> _shaderSets; ///< ロードしたシェーダプログラムを保持する変数
csmVector<ID3D11VertexShader*> _shaderSetsVS; ///< ロードしたシェーダプログラムを保持する変数(VS)
csmVector<ID3D11PixelShader*> _shaderSetsPS; ///< ロードしたシェーダプログラムを保持する変数(PS)
ID3D11InputLayout* _vertexFormat; ///< 描画で使用する型宣言
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,36 @@
/**
* 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
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework {
/**
* @brief D3D11基本頂点
*/
struct CubismVertexD3D11
{
float x, y; // Position
float u, v; // UVs
};
/**
* @brief シェーダーコンスタントバッファ
*/
struct CubismConstantBufferD3D11
{
DirectX::XMFLOAT4X4 projectMatrix;
DirectX::XMFLOAT4X4 clipMatrix;
DirectX::XMFLOAT4 baseColor;
DirectX::XMFLOAT4 multiplyColor;
DirectX::XMFLOAT4 screenColor;
DirectX::XMFLOAT4 channelFlag;
};
}}}
@@ -0,0 +1,135 @@
cbuffer ConstantBuffer {
float4x4 projectMatrix;
float4x4 clipMatrix;
float4 baseColor;
float4 multiplyColor;
float4 screenColor;
float4 channelFlag;
}
Texture2D mainTexture : register(t0);
SamplerState mainSampler : register(s0);
Texture2D maskTexture : register(t1);
// Vertex shader input
struct VS_IN {
float2 pos : POSITION;
float2 uv : TEXCOORD0;
};
// Vertex shader output
struct VS_OUT {
float4 Position : SV_POSITION;
float2 uv : TEXCOORD0;
float4 clipPosition : TEXCOORD1;
};
// Mask shader
VS_OUT VertSetupMask(VS_IN In) {
VS_OUT Out = (VS_OUT)0;
Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);
Out.clipPosition = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);
Out.uv.x = In.uv.x;
Out.uv.y = 1.0f - +In.uv.y;
return Out;
}
float4 PixelSetupMask(VS_OUT In) : SV_Target{
float isInside =
step(baseColor.x, In.clipPosition.x / In.clipPosition.w)
* step(baseColor.y, In.clipPosition.y / In.clipPosition.w)
* step(In.clipPosition.x / In.clipPosition.w, baseColor.z)
* step(In.clipPosition.y / In.clipPosition.w, baseColor.w);
return channelFlag * mainTexture.Sample(mainSampler, In.uv).a * isInside;
}
// Vertex shader
// normal
VS_OUT VertNormal(VS_IN In) {
VS_OUT Out = (VS_OUT)0;
Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);
Out.uv.x = In.uv.x;
Out.uv.y = 1.0f - +In.uv.y;
return Out;
}
// masked
VS_OUT VertMasked(VS_IN In) {
VS_OUT Out = (VS_OUT)0;
Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);
Out.clipPosition = mul(float4(In.pos, 0.0f, 1.0f), clipMatrix);
Out.uv.x = In.uv.x;
Out.uv.y = 1.0f - In.uv.y;
return Out;
}
// Pixel Shader
// normal
float4 PixelNormal(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
color.xyz *= color.w;
return color;
}
// normal premult alpha
float4 PixelNormalPremult(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb * texColor.a) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
return color;
}
// masked
float4 PixelMasked(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
color.xyz *= color.w;
float4 clipMask = (1.0f - maskTexture.Sample(mainSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;
float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;
color = color * maskVal;
return color;
}
// masked inverted
float4 PixelMaskedInverted(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
color.xyz *= color.w;
float4 clipMask = (1.0f - maskTexture.Sample(mainSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;
float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;
color = color * (1.0f - maskVal);
return color;
}
// masked premult alpha
float4 PixelMaskedPremult(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb * texColor.a) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
float4 clipMask = (1.0f - maskTexture.Sample(mainSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;
float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;
color = color * maskVal;
return color;
}
// masked inverted premult alpha
float4 PixelMaskedInvertedPremult(VS_OUT In) : SV_Target{
float4 texColor = mainTexture.Sample(mainSampler, In.uv);
texColor.rgb = texColor.rgb * multiplyColor.rgb;
texColor.rgb = (texColor.rgb + screenColor.rgb * texColor.a) - (texColor.rgb * screenColor.rgb);
float4 color = texColor * baseColor;
float4 clipMask = (1.0f - maskTexture.Sample(mainSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;
float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;
color = color * (1.0f - maskVal);
return color;
}
@@ -0,0 +1,13 @@
target_sources(${LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CubismNativeInclude_D3D9.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismOffscreenSurface_D3D9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismOffscreenSurface_D3D9.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer_D3D9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderer_D3D9.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderState_D3D9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismRenderState_D3D9.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismShader_D3D9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismShader_D3D9.hpp
${CMAKE_CURRENT_SOURCE_DIR}/CubismType_D3D9.hpp
)
@@ -0,0 +1,18 @@
/**
* 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 "CubismFrameworkConfig.hpp"
#ifdef CSM_DEBUG
// d3dヘッダの前にこれを定義するとデバッグ情報が増える 必要に応じてOn
#define D3D_DEBUG_INFO
#endif
#include <d3d9.h>
#include <d3dx9.h>
@@ -0,0 +1,206 @@
/**
* 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 "CubismOffscreenSurface_D3D9.hpp"
#include "CubismRenderer_D3D9.hpp"
#include "CubismShader_D3D9.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
CubismOffscreenSurface_D3D9::CubismOffscreenSurface_D3D9()
: _texture(NULL)
, _textureSurface(NULL)
, _depthSurface(NULL)
, _backupRender(NULL)
, _backupDepth(NULL)
, _bufferWidth(0)
, _bufferHeight(0)
{
}
void CubismOffscreenSurface_D3D9::BeginDraw(LPDIRECT3DDEVICE9 device)
{
if(_depthSurface==NULL || _texture==NULL)
{
return;
}
// オフスクリーン描画は一度通常描画を打ち切る必要がある
device->EndScene();
device->BeginScene();
_backupRender = NULL;
_backupDepth = NULL;
// バックバッファのサーフェイスを記憶しておく
device->GetRenderTarget(0, &_backupRender);
// ステンシルバッファを取得しておく
device->GetDepthStencilSurface(&_backupDepth);
LPDIRECT3DSURFACE9 surface;
_textureSurface = NULL;
if (SUCCEEDED(_texture->GetSurfaceLevel(0, &surface)))
{
// 記憶しておく
_textureSurface = surface;
// マスク描画レンダーターゲットセット
device->SetRenderTarget(0, surface);
device->SetDepthStencilSurface(_depthSurface);
}
}
void CubismOffscreenSurface_D3D9::EndDraw(LPDIRECT3DDEVICE9 device)
{
if (_depthSurface == NULL || _texture == NULL)
{
return;
}
device->EndScene();
// 元に戻す
if (_textureSurface)
{
device->SetRenderTarget(0, _backupRender);
device->SetDepthStencilSurface(_backupDepth);
// GetSurfaceLevelでincされたものを下げる必要がある
{
_textureSurface->Release();
_textureSurface = NULL;
}
}
// BeginでGetした分のRelease
if(_backupDepth)
{
_backupDepth->Release();
_backupDepth = NULL;
}
if(_backupRender)
{
_backupRender->Release();
_backupRender = NULL;
}
device->BeginScene();
}
void CubismOffscreenSurface_D3D9::Clear(LPDIRECT3DDEVICE9 device, float r, float g, float b, float a)
{
// マスクをクリアする
device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(r, g, b, a), 1.0f, 0);
}
csmBool CubismOffscreenSurface_D3D9::CreateOffscreenSurface(LPDIRECT3DDEVICE9 device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight)
{
// 一旦削除
DestroyOffscreenSurface();
if (FAILED(D3DXCreateTexture(
device,
displayBufferWidth,
displayBufferHeight,
0,
D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&_texture)))
{
return false;
}
if (FAILED(device->CreateDepthStencilSurface(
displayBufferWidth,
displayBufferHeight,
D3DFMT_D16,
D3DMULTISAMPLE_NONE,
0,
TRUE,
&_depthSurface,
NULL)))
{
if(_texture)
{
_texture->Release();
_texture = NULL;
}
return false;
}
_bufferWidth = displayBufferWidth;
_bufferHeight = displayBufferHeight;
return true;
}
void CubismOffscreenSurface_D3D9::DestroyOffscreenSurface()
{
// これらがあるのはEndDrawが来なかった場合
if(_backupDepth)
{
_backupDepth->Release();
_backupDepth = NULL;
}
if (_backupRender)
{
_backupRender->Release();
_backupRender = NULL;
}
if (_textureSurface)
{
_textureSurface->Release();
_textureSurface = NULL;
}
if(_depthSurface)
{
_depthSurface->Release();
_depthSurface = NULL;
}
if (_texture)
{
_texture->Release();
_texture = NULL;
}
}
LPDIRECT3DTEXTURE9 CubismOffscreenSurface_D3D9::GetTexture() const
{
return _texture;
}
csmUint32 CubismOffscreenSurface_D3D9::GetBufferWidth() const
{
return _bufferWidth;
}
csmUint32 CubismOffscreenSurface_D3D9::GetBufferHeight() const
{
return _bufferHeight;
}
csmBool CubismOffscreenSurface_D3D9::IsValid() const
{
if (_depthSurface == NULL || _texture == NULL)
{
return false;
}
return true;
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,99 @@
/**
* 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 "CubismNativeInclude_D3D9.hpp"
#include "Math/CubismMatrix44.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
/**
* @brief オフスクリーン描画用構造体
*/
class CubismOffscreenSurface_D3D9
{
public:
CubismOffscreenSurface_D3D9();
/**
* @brief 指定の描画ターゲットに向けて描画開始
*
* @param device[in] D3dデバイス
*/
void BeginDraw(LPDIRECT3DDEVICE9 device);
/**
* @brief 描画終了
*
* @param device[in] D3dデバイス
*/
void EndDraw(LPDIRECT3DDEVICE9 device);
/**
* @brief レンダリングターゲットのクリア
* 呼ぶ場合はBeginDrawの後で呼ぶこと
* @param r 赤(0.0~1.0)
* @param g 緑(0.0~1.0)
* @param b 青(0.0~1.0)
* @param a α(0.0~1.0)
*/
void Clear(LPDIRECT3DDEVICE9 device, float r, float g, float b, float a);
/**
* @brief CubismOffscreenSurface作成
* @param device[in] D3dデバイス
* @param displayBufferWidth[in] 作成するバッファ幅
* @param displayBufferHeight[in] 作成するバッファ高さ
*/
csmBool CreateOffscreenSurface(LPDIRECT3DDEVICE9 device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight);
/**
* @brief CubismOffscreenSurfaceの削除
*/
void DestroyOffscreenSurface();
/**
* @brief テクスチャメンバーへのアクセッサ
*/
LPDIRECT3DTEXTURE9 GetTexture() const;
/**
* @brief バッファ幅取得
*/
csmUint32 GetBufferWidth() const;
/**
* @brief バッファ高さ取得
*/
csmUint32 GetBufferHeight() const;
/**
* @brief 現在有効かどうか
*/
csmBool IsValid() const;
private:
LPDIRECT3DTEXTURE9 _texture; ///< 生成テクスチャ
LPDIRECT3DSURFACE9 _textureSurface; ///< レンダリングサーフェス
LPDIRECT3DSURFACE9 _depthSurface; ///< Z
LPDIRECT3DSURFACE9 _backupRender; ///< 元々のターゲットを退避
LPDIRECT3DSURFACE9 _backupDepth; ///< 元々のZを退避
csmUint32 _bufferWidth; ///< Create時に指定されたサイズ
csmUint32 _bufferHeight; ///< Create時に指定されたサイズ
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,319 @@
/**
* 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 "CubismRenderState_D3D9.hpp"
#include "CubismShader_D3D9.hpp"
#include "CubismRenderer_D3D9.hpp"
#include "Type/csmVector.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
CubismRenderState_D3D9::CubismRenderState_D3D9()
{
//
memset(_stored._valid, 0, sizeof(_stored._valid));
}
CubismRenderState_D3D9::~CubismRenderState_D3D9()
{
_pushed.Clear();
}
void CubismRenderState_D3D9::StartFrame()
{
memset(_stored._valid, 0, sizeof(_stored._valid));
_pushed.Clear();
}
void CubismRenderState_D3D9::Save()
{
// 現時点のステートをPush
_pushed.PushBack(_stored);
}
void CubismRenderState_D3D9::Restore(LPDIRECT3DDEVICE9 device)
{
const csmUint32 size = _pushed.GetSize();
if (size == 0)
{
return;
}
//forで辿って最後に設定した個所までチェック
csmBool isSet[State_Max];
memset(isSet, 0, sizeof(isSet));
for (csmInt32 i = static_cast<csmInt32>(_pushed.GetSize())-1; i>=0; i--)
{
Stored &current = _pushed[i];
if (_pushed[i]._valid[State_Blend] && !isSet[State_Blend])
{
SetBlend(device, current.BlendEnable, current.BlendAlphaSeparateEnable, current.BlendSourceMul, current.BlendBlendFunc, current.BlendDestMul,
current.BlendSourceAlpha, current.BlendAlphaFunc, current.BlendDestAlpha, true);
isSet[State_Blend] = true;
}
if (_pushed[i]._valid[State_Viewport] && !isSet[State_Viewport])
{
SetViewport(device, current.ViewportX, current.ViewportY, current.ViewportWidth, current.ViewportHeight, current.ViewportMinZ, current.ViewportMaxZ, true);
isSet[State_Viewport] = true;
}
if (_pushed[i]._valid[State_ColorMask] && !isSet[State_ColorMask])
{
SetColorMask(device, current.ColorMaskMask, true);
isSet[State_ColorMask] = true;
}
if (_pushed[i]._valid[State_ZEnable] && !isSet[State_ZEnable])
{
SetZEnable(device, current.ZEnable, current.ZFunc, true);
isSet[State_ZEnable] = true;
}
if (_pushed[i]._valid[State_CullMode] && !isSet[State_CullMode])
{
SetCullMode(device, current.CullModeFaceMode, true);
isSet[State_CullMode] = true;
}
if (_pushed[i]._valid[State_TextureFilterStage0] && !isSet[State_TextureFilterStage0])
{
SetTextureFilter(device, 0, current.MinFilter[0], current.MagFilter[0], current.MipFilter[0], current.AddressU[0], current.AddressV[0], current.Anisotropy[0], true);
isSet[State_TextureFilterStage0] = true;
}
if (_pushed[i]._valid[State_TextureFilterStage1] && !isSet[State_TextureFilterStage1])
{
SetTextureFilter(device, 1, current.MinFilter[1], current.MagFilter[1], current.MipFilter[1], current.AddressU[1], current.AddressV[1], current.Anisotropy[1], true);
isSet[State_TextureFilterStage1] = true;
}
}
Stored store = _pushed[size - 1];
_pushed.Remove(size - 1);
if(_pushed.GetSize()==0)
{
_pushed.Clear();
}
_stored = store;
}
void CubismRenderState_D3D9::SetBlend(LPDIRECT3DDEVICE9 device, bool enable, bool alphaSeparateEnable,
D3DBLEND srcmul, D3DBLENDOP blendFunc, D3DBLEND destmul,
D3DBLEND srcalpha, D3DBLENDOP alphaFunc, D3DBLEND destalpha,
csmBool force)
{
if (!_stored._valid[State_Blend] || force ||
_stored.BlendEnable != enable || _stored.BlendAlphaSeparateEnable != alphaSeparateEnable ||
_stored.BlendSourceMul != srcmul || _stored.BlendBlendFunc != blendFunc || _stored.BlendDestMul != destmul ||
_stored.BlendSourceAlpha != srcalpha || _stored.BlendAlphaFunc != alphaFunc || _stored.BlendDestAlpha != destalpha)
{
device->SetRenderState(D3DRS_SRCBLEND, srcmul);
device->SetRenderState(D3DRS_BLENDOP, blendFunc);
device->SetRenderState(D3DRS_DESTBLEND, destmul);
device->SetRenderState(D3DRS_SRCBLENDALPHA, srcalpha);
device->SetRenderState(D3DRS_BLENDOPALPHA, alphaFunc);
device->SetRenderState(D3DRS_DESTBLENDALPHA, destalpha);
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, alphaSeparateEnable);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);
}
_stored.BlendEnable = enable;
_stored.BlendAlphaSeparateEnable = alphaSeparateEnable;
_stored.BlendSourceMul = srcmul;
_stored.BlendBlendFunc = blendFunc;
_stored.BlendDestMul = destmul;
_stored.BlendSourceAlpha = srcalpha;
_stored.BlendAlphaFunc = alphaFunc;
_stored.BlendDestAlpha = destalpha;
_stored._valid[State_Blend] = true;
}
void CubismRenderState_D3D9::SetViewport(LPDIRECT3DDEVICE9 device, DWORD left, DWORD top, DWORD width, DWORD height, float zMin, float zMax, csmBool force)
{
if (!_stored._valid[State_Blend] || force ||
_stored.ViewportX != left || _stored.ViewportY != top || _stored.ViewportWidth != width || _stored.ViewportHeight != height ||
_stored.ViewportMinZ != zMin || _stored.ViewportMaxZ != zMax)
{
// コンテキストにセット
D3DVIEWPORT9 viewport;
viewport.X = left;
viewport.Y = top;
viewport.Width = width;
viewport.Height = height;
viewport.MinZ = zMin;
viewport.MaxZ = zMax;
device->SetViewport(&viewport);
}
_stored.ViewportX = left;
_stored.ViewportY = top;
_stored.ViewportWidth = width;
_stored.ViewportHeight = height;
_stored.ViewportMinZ = zMin;
_stored.ViewportMaxZ = zMax;
_stored._valid[State_Viewport] = true;
}
void CubismRenderState_D3D9::SetColorMask(LPDIRECT3DDEVICE9 device, DWORD mask, csmBool force)
{
if (!_stored._valid[State_Blend] || force ||
_stored.ColorMaskMask != mask)
{
device->SetRenderState(D3DRS_COLORWRITEENABLE, mask);
}
_stored.ColorMaskMask = mask;
_stored._valid[State_ColorMask] = true;
}
void CubismRenderState_D3D9::SetZEnable(LPDIRECT3DDEVICE9 device, D3DZBUFFERTYPE enable, D3DCMPFUNC zfunc, csmBool force)
{
if (!_stored._valid[State_ZEnable] || force ||
_stored.ZEnable != enable || _stored.ZFunc != zfunc)
{
device->SetRenderState(D3DRS_ZENABLE, enable);
device->SetRenderState(D3DRS_ZFUNC, zfunc);
}
_stored.ZEnable = enable;
_stored.ZFunc = zfunc;
_stored._valid[State_ZEnable] = true;
}
void CubismRenderState_D3D9::SetCullMode(LPDIRECT3DDEVICE9 device, D3DCULL cullFace, csmBool force)
{
if (!_stored._valid[State_CullMode] || force ||
_stored.CullModeFaceMode != cullFace)
{
device->SetRenderState(D3DRS_CULLMODE, cullFace);
}
_stored.CullModeFaceMode = cullFace;
_stored._valid[State_CullMode] = true;
}
void CubismRenderState_D3D9::SetTextureFilter(LPDIRECT3DDEVICE9 device, csmInt32 stage, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter, D3DTEXTUREADDRESS addressU, D3DTEXTUREADDRESS addressV, csmFloat32 anisotropy, csmBool force)
{
const csmInt32 stateIndex = State_TextureFilterStage0 + stage;
// ステージインデックスの範囲内検知
CSM_ASSERT((stateIndex == State_TextureFilterStage0) || (stateIndex == State_TextureFilterStage1));
if (!_stored._valid[stateIndex] || force ||
_stored.MinFilter[stage] != minFilter ||
_stored.MagFilter[stage] != magFilter ||
_stored.MipFilter[stage] != mipFilter ||
_stored.AddressU[stage] != addressU ||
_stored.AddressV[stage] != addressV ||
_stored.Anisotropy[stage] != anisotropy)
{
device->SetSamplerState(stage, D3DSAMP_MINFILTER, minFilter);
device->SetSamplerState(stage, D3DSAMP_MAGFILTER, magFilter);
device->SetSamplerState(stage, D3DSAMP_MIPFILTER, mipFilter);
device->SetSamplerState(stage, D3DSAMP_ADDRESSU, addressU);
device->SetSamplerState(stage, D3DSAMP_ADDRESSV, addressV);
// 1以下だと無効
if (anisotropy > 1.0f)
{
device->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, anisotropy);
}
else
{
device->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 1.0f);
}
}
_stored.MinFilter[stage] = minFilter;
_stored.MagFilter[stage] = magFilter;
_stored.MipFilter[stage] = mipFilter;
_stored.AddressU[stage] = addressU;
_stored.AddressV[stage] = addressV;
_stored.Anisotropy[stage] = anisotropy;
_stored._valid[stateIndex] = true;
}
void CubismRenderState_D3D9::SaveCurrentNativeState(LPDIRECT3DDEVICE9 device)
{
// まずは全破棄
_pushed.Clear();
// 未設定扱いに
memset(_stored._valid, 0, sizeof(_stored._valid));
DWORD setting[16]; // 数は適当
// Blend
device->GetRenderState(D3DRS_ALPHABLENDENABLE, &setting[0]);
device->GetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, &setting[1]);
device->GetRenderState(D3DRS_SRCBLEND, &setting[2]);
device->GetRenderState(D3DRS_BLENDOP, &setting[3]);
device->GetRenderState(D3DRS_DESTBLEND, &setting[4]);
device->GetRenderState(D3DRS_SRCBLENDALPHA, &setting[5]);
device->GetRenderState(D3DRS_BLENDOPALPHA, &setting[6]);
device->GetRenderState(D3DRS_DESTBLENDALPHA, &setting[7]);
SetBlend(device,
(setting[0] ? true : false),
(setting[1] ? true : false),
static_cast<D3DBLEND>(setting[2]), static_cast<D3DBLENDOP>(setting[3]), static_cast<D3DBLEND>(setting[4]),
static_cast<D3DBLEND>(setting[5]), static_cast<D3DBLENDOP>(setting[6]), static_cast<D3DBLEND>(setting[7]), true);
// Viewport
D3DVIEWPORT9 viewport;
device->GetViewport(&viewport);
SetViewport(device, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinZ, viewport.MaxZ, true);
// ColorMask
device->GetRenderState(D3DRS_COLORWRITEENABLE, &setting[0]);
SetColorMask(device, setting[0], true);
// ZEnable
device->GetRenderState(D3DRS_ZENABLE, &setting[0]);
device->GetRenderState(D3DRS_ZFUNC, &setting[1]);
SetZEnable(device, static_cast<D3DZBUFFERTYPE>(setting[0]), static_cast<D3DCMPFUNC>(setting[1]), true);
// Cull
device->GetRenderState(D3DRS_CULLMODE, &setting[0]);
SetCullMode(device, static_cast<D3DCULL>(setting[0]), true);
// TextureFilter
for (csmInt32 stage = 0; stage < 2; stage++) {
device->GetSamplerState(stage, D3DSAMP_MINFILTER, &setting[0]);
device->GetSamplerState(stage, D3DSAMP_MAGFILTER, &setting[1]);
device->GetSamplerState(stage, D3DSAMP_MIPFILTER, &setting[2]);
device->GetSamplerState(stage, D3DSAMP_ADDRESSU, &setting[3]);
device->GetSamplerState(stage, D3DSAMP_ADDRESSV, &setting[4]);
device->GetSamplerState(stage, D3DSAMP_MAXANISOTROPY, &setting[5]);
SetTextureFilter(device, stage, static_cast<D3DTEXTUREFILTERTYPE>(setting[0]), static_cast<D3DTEXTUREFILTERTYPE>(setting[1]), static_cast<D3DTEXTUREFILTERTYPE>(setting[2]),
static_cast<D3DTEXTUREADDRESS>(setting[3]), static_cast<D3DTEXTUREADDRESS>(setting[4]), static_cast<D3DTEXTUREADDRESS>(setting[5]), true);
}
// 最後に上記の値を保存
Save();
}
void CubismRenderState_D3D9::RestoreNativeState(LPDIRECT3DDEVICE9 device)
{
// 全て再現
for (csmInt32 i = static_cast<csmInt32>(_pushed.GetSize()) - 1; i >= 0; i--)
{
Restore(device);
}
}
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,236 @@
/**
* 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 "CubismNativeInclude_D3D9.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmMap.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
class CubismRenderer_D3D9;
/**
* @brief CubismD3D9内部で設定するステートのうち、途中で変更する可能性のあるものを管理。
* CubismRenderer_D3D9がシングルトンとして管理。
*/
class CubismRenderState_D3D9
{
friend class CubismRenderer_D3D9;
public:
enum
{
State_None,
State_Blend, ///< ブレンドモード
State_Viewport, ///< ビューポート
State_ColorMask, ///< カラーマスク
State_RenderTarget, ///< レンダーターゲット
State_DepthTarget, ///< 深度ターゲット
State_ZEnable, ///< Z有効無効
State_CullMode, ///< カリングモード
State_TextureFilterStage0, ///< テクスチャフィルター(ステージ0)
State_TextureFilterStage1, ///< テクスチャフィルター(ステージ1)
State_Max,
};
/**
* @notice デフォルトの=でコピーします
*/
struct Stored
{
Stored()
{
BlendEnable = false;
BlendAlphaSeparateEnable = false;
BlendSourceMul = D3DBLEND_ZERO;
BlendBlendFunc = D3DBLENDOP_ADD;
BlendDestMul = D3DBLEND_ZERO;
BlendSourceAlpha = D3DBLEND_ZERO;
BlendAlphaFunc = D3DBLENDOP_ADD;
BlendDestAlpha = D3DBLEND_ZERO;
ViewportX = 0;
ViewportY = 0;
ViewportWidth = 0;
ViewportHeight = 0;
ViewportMinZ = 0.0f;
ViewportMaxZ = 0.0f;
ColorMaskMask = 0;
ZEnable = D3DZB_FALSE;
ZFunc = D3DCMP_NEVER;
CullModeFaceMode = D3DCULL_NONE;
MinFilter[0] = D3DTEXF_NONE;
MagFilter[0] = D3DTEXF_NONE;
MipFilter[0] = D3DTEXF_NONE;
AddressU[0] = D3DTADDRESS_WRAP;
AddressV[0] = D3DTADDRESS_WRAP;
Anisotropy[0] = 1.0f;
MinFilter[1] = D3DTEXF_NONE;
MagFilter[1] = D3DTEXF_NONE;
MipFilter[1] = D3DTEXF_NONE;
AddressU[1] = D3DTADDRESS_WRAP;
AddressV[1] = D3DTADDRESS_WRAP;
Anisotropy[1] = 1.0f;
memset(_valid, 0, sizeof(_valid));
}
// State_Blend
bool BlendEnable;
bool BlendAlphaSeparateEnable;
D3DBLEND BlendSourceMul;
D3DBLENDOP BlendBlendFunc;
D3DBLEND BlendDestMul;
D3DBLEND BlendSourceAlpha;
D3DBLENDOP BlendAlphaFunc;
D3DBLEND BlendDestAlpha;
// State_Viewport
DWORD ViewportX;
DWORD ViewportY;
DWORD ViewportWidth;
DWORD ViewportHeight;
float ViewportMinZ;
float ViewportMaxZ;
// State_ColorMask
DWORD ColorMaskMask;
// State_ZEnable
D3DZBUFFERTYPE ZEnable;
D3DCMPFUNC ZFunc;
// State_CullMode
D3DCULL CullModeFaceMode; // 消す面を指定 CWだと時計回りが消える
// State_TextureFilter サンプラーフィルター(0番, 1番)
D3DTEXTUREFILTERTYPE MinFilter[2];
D3DTEXTUREFILTERTYPE MagFilter[2];
D3DTEXTUREFILTERTYPE MipFilter[2];
D3DTEXTUREADDRESS AddressU[2];
D3DTEXTUREADDRESS AddressV[2];
float Anisotropy[2];
csmBool _valid[State_Max]; ///< 設定したかどうか。現在はStartFrameで一通りは呼んでいる
};
/**
* @brief フレーム先頭で呼び出す処理
*/
void StartFrame();
/**
* @brief 管理中のステートをPush
*/
void Save();
/**
* @brief Push下ステートをPop
* @notice Saveの際にCubismRenderState_D3D9で設定していなかった項目は戻せないことに注意
*/
void Restore(LPDIRECT3DDEVICE9 device);
/**
* @brief ブレンドモードセット
*
* @param device[in] 描画デバイス
* @param enable[in] αブレンド有効無効
* @param alphaSeparateEnable[in] αブレンドのうち、rgbとaの計算式を分離するかどうか
* @param srcmul[in] Srcカラー
* @param blendFunc[in] ブレンド関数
* @param destmul[in] Destカラー
* @param srcalpha[in] Srcアルファ
* @param alphaFunc[in] α値ブレンド関数
* @param destalpha[in] Destアルファ
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetBlend(LPDIRECT3DDEVICE9 device, bool enable, bool alphaSeparateEnable,
D3DBLEND srcmul, D3DBLENDOP blendFunc, D3DBLEND destmul,
D3DBLEND srcalpha, D3DBLENDOP alphaFunc, D3DBLEND destalpha,
csmBool force=false);
/**
* @brief ビューポートセット
*
* @param device[in] 描画デバイス
* @param left[in] ビューポート左座標
* @param top[in] ビューポート上座標
* @param width[in] ビューポート右座標
* @param height[in] ビューポート下座標
* @param zMin[in] Z最小値
* @param zMax[in] Z最大値
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetViewport(LPDIRECT3DDEVICE9 device, DWORD left, DWORD top, DWORD width, DWORD height, float zMin, float zMax, csmBool force = false);
/**
* @brief カラーマスクセット
*/
void SetColorMask(LPDIRECT3DDEVICE9 device, DWORD mask, csmBool force = false);
/**
* @brief Z有効無効セット
*
* @param device[in] 描画デバイス
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetZEnable(LPDIRECT3DDEVICE9 device, D3DZBUFFERTYPE enable, D3DCMPFUNC zfunc, csmBool force = false);
/**
* @brief カリングモードセット
*
* @param device[in] 描画デバイス
* @param cullFace[in] 切除するべき面 指定された面を切る Cwだと時計回りを切除
* @param force[in] trueの場合は今の設定が何であろうと強制設定
*/
void SetCullMode(LPDIRECT3DDEVICE9 device, D3DCULL cullFace, csmBool force = false);
/**
* @brief テクスチャサンプラーにフィルタセット
*
* @param device[in] 描画デバイス
* @param stage[in] サンプラーステージインデックス(サンプラー番号)
* @param minFilter[in] 縮小時フィルタ
* @param magFilter[in] 拡大時フィルタ
* @param mipFilter[in] ミップフィルタ
* @param addressU[in] アドレッシングモードU
* @param addressV[in] アドレッシングモードV
*/
void SetTextureFilter(LPDIRECT3DDEVICE9 device, csmInt32 stage, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter, D3DTEXTUREADDRESS addressU, D3DTEXTUREADDRESS addressV, csmFloat32 anisotropy = 1.0f, csmBool force = false);
private:
CubismRenderState_D3D9();
~CubismRenderState_D3D9();
/**
* @brief D3DDeviceから、Cubismに関係する値を取得したうえでCubismRenderState_D3D9に反映しSaveを呼び出し、_pushedは破棄
* Cubismフレーム処理の最初、StartFrameの後で呼んでいる
*/
void SaveCurrentNativeState(LPDIRECT3DDEVICE9 device);
/**
* @brief 最初にPushしたステートまで戻す
*/
void RestoreNativeState(LPDIRECT3DDEVICE9 device);
Stored _stored; ///< ストアされた各種設定
csmVector<Stored> _pushed;
};
}}}}
//------------ LIVE2D NAMESPACE ------------
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,437 @@
/**
* 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 "CubismNativeInclude_D3D9.hpp"
#include "../CubismRenderer.hpp"
#include "../CubismClippingManager.hpp"
#include "CubismFramework.hpp"
#include "Type/csmVector.hpp"
#include "Type/csmRectF.hpp"
#include "Math/CubismVector2.hpp"
#include "Type/csmMap.hpp"
#include "Rendering/D3D9/CubismOffscreenSurface_D3D9.hpp"
#include "CubismRenderState_D3D9.hpp"
#include "CubismType_D3D9.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
// 前方宣言
class CubismRenderer_D3D9;
class CubismShader_D3D9;
class CubismClippingContext_D3D9;
/**
* @brief D3DXMATRIXに変換
*/
D3DXMATRIX ConvertToD3DX(CubismMatrix44& mtx);
/**
* @brief
*
*/
class CubismClippingManager_DX9 : public CubismClippingManager<CubismClippingContext_D3D9, CubismOffscreenSurface_D3D9>
{
public:
/**
* @brief
*
* @param[in] model ->
* @param[in] renderer ->
*/
void SetupClippingContext(LPDIRECT3DDEVICE9 device, CubismModel& model, CubismRenderer_D3D9* renderer, csmInt32 offscreenCurrent);
};
/**
* @brief
*/
class CubismClippingContext_D3D9 : public CubismClippingContext
{
friend class CubismClippingManager_DX9;
friend class CubismShader_D3D9;
friend class CubismRenderer_D3D9;
public:
/**
* @brief
*
*/
CubismClippingContext_D3D9(CubismClippingManager<CubismClippingContext_D3D9, CubismOffscreenSurface_D3D9>* manager, CubismModel& model, const csmInt32* clippingDrawableIndices, csmInt32 clipCount);
/**
* @brief
*/
virtual ~CubismClippingContext_D3D9();
/**
* @brief
*
* @return
*/
CubismClippingManager<CubismClippingContext_D3D9, CubismOffscreenSurface_D3D9>* GetClippingManager();
private:
CubismClippingManager<CubismClippingContext_D3D9, CubismOffscreenSurface_D3D9>* _owner; ///< このマスクを管理しているマネージャのインスタンス
};
/**
* @brief DirectX9用の描画命令を実装したクラス
*
*/
class CubismRenderer_D3D9 : public CubismRenderer
{
friend class CubismRenderer;
friend class CubismClippingManager_DX9;
friend class CubismShader_D3D9;
public:
/**
* @brief
*
*
* @param[in] bufferSetNum -> 1
* @param[in] device -> 使
*/
static void InitializeConstantSettings(csmUint32 bufferSetNum, LPDIRECT3DDEVICE9 device);
/**
* @brief CubismRenderStateにデフォルトの設定をセットする
*/
static void SetDefaultRenderState();
/**
* @brief Cubism描画関連の先頭で行う処理
* Cubism処理前にこれを呼んでもらう
*
* @param[in] device -> 使
*/
static void StartFrame(LPDIRECT3DDEVICE9 device, csmUint32 viewportWidth, csmUint32 viewportHeight);
/**
* @brief Cubism描画関連の終了時行う処理
* Cubism処理前にこれを呼んでもらう
*
* @param[in] device -> 使
*/
static void EndFrame(LPDIRECT3DDEVICE9 device);
/**
* @brief CubismRenderer_D3D9で使用するレンダーステート管理マネージャ取得
*/
static CubismRenderState_D3D9* GetRenderStateManager();
/**
* @brief
*/
static void DeleteRenderStateManager();
/**
* @brief
*/
static CubismShader_D3D9* GetShaderManager();
/**
* @brief
*/
static void DeleteShaderManager();
/**
* @brief
*/
static void OnDeviceLost();
/**
* @brief 使
*/
static void GenerateShader(LPDIRECT3DDEVICE9 device);
virtual void CubismRenderer_D3D9::Initialize(CubismModel* model);
/**
* @brief <br>
*
*
* @param[in] model ->
*/
virtual void Initialize(Framework::CubismModel* model, csmInt32 maskBufferCount) override;
/**
* @brief
*/
void FrameRenderingInit();
/**
* @brief <br>
* CubismRendererにテクスチャを設定しCubismRenderer中でその画像を参照するためのIndex値を戻り値とする
*
* @param[in] modelTextureAssign ->
* @param[in] texture -> 使
*
*/
void BindTexture(csmUint32 modelTextureAssign, const LPDIRECT3DTEXTURE9 texture);
/**
* @brief
*
* @return
*/
const csmMap<csmInt32, LPDIRECT3DTEXTURE9>& GetBindedTextures() const;
/**
* @brief <br>
* OffscreenSurfaceを破棄
*
* @param[in] size ->
*
*/
void SetClippingMaskBufferSize(csmFloat32 width, csmFloat32 height);
/**
* @brief
*
* @return
*
*/
csmInt32 GetRenderTextureCount() const;
/**
* @brief
*
* @return
*
*/
CubismVector2 GetClippingMaskBufferSize() const;
/**
* @brief
*
* @return
*
*/
CubismOffscreenSurface_D3D9* GetMaskBuffer(csmUint32 backbufferNum, csmInt32 offscreenIndex);
protected:
/**
* @brief
*/
CubismRenderer_D3D9();
/**
* @brief
*/
virtual ~CubismRenderer_D3D9();
/**
* @brief
*
*/
virtual void DoDrawModel() override;
/**
* @brief <br>
*
*
* @param[in] gfxc ->
* @param[in] drawableIndex ->
* @param[in] colorBlendMode ->
* @param[in] invertedMask -> 使使
*/
void DrawMeshDX9(const CubismModel& model, const csmInt32 index);
/**
* @brief 使
*
* @param[in] model ->
* @param[in] index ->
*/
void ExecuteDrawForDraw(const CubismModel& model, const csmInt32 index);
/**
* @brief 使
*
* @param[in] model ->
* @param[in] index ->
*/
void ExecuteDrawForMask(const CubismModel& model, const csmInt32 index);
private:
/**
* @brief <br>
*/
static void DoStaticRelease();
/**
* @brief 使
*/
static void ReleaseShader();
// Prevention of copy Constructor
CubismRenderer_D3D9(const CubismRenderer_D3D9&);
CubismRenderer_D3D9& operator=(const CubismRenderer_D3D9&);
/**
* @brief <br>
*
*/
void PreDraw();
/**
* @brief <br>
*
*/
void PostDraw();
/**
* @brief
*/
virtual void SaveProfile() override;
/**
* @brief
*/
virtual void RestoreProfile() override;
/**
* @brief
*/
void SetClippingContextBufferForMask(CubismClippingContext_D3D9* clip);
/**
* @brief
*
* @return
*/
CubismClippingContext_D3D9* GetClippingContextBufferForMask() const;
/**
* @brief
*/
void SetClippingContextBufferForDraw(CubismClippingContext_D3D9* clip);
/**
* @brief
*
* @return
*/
CubismClippingContext_D3D9* GetClippingContextBufferForDraw() const;
/**
* @brief GetDrawableVertices,GetDrawableVertexUvsの内容を内部バッファへコピー
*/
void CopyToBuffer(csmInt32 drawAssign, const csmInt32 vcount, const csmFloat32* varray, const csmFloat32* uvarray);
/**
* @brief modelのindexにバインドされているテクスチャを返す<br>
* indexを指定した場合NULLが返る
* @param[in] model ->
* @param[in] index ->
*
* @return
*/
LPDIRECT3DTEXTURE9 GetTextureWithIndex(const CubismModel& model, const csmInt32 index);
/**
* @brief
*
* @return
*/
const csmBool inline IsGeneratingMask() const;
/**
* @brief
*
* @return
*/
void SetBlendMode(CubismBlendMode blendMode) const;
/**
* @brief D3D9のテクニックを設定する
*
* @param[in] model ->
* @param[in] index ->
*/
void SetTechniqueForDraw(const CubismModel& model, const csmInt32 index) const;
/**
* @brief RenderStateManagerにテクスチャフィルターを設定する
*/
void SetTextureFilter() const;
/**
* @brief
*
* @param[in] shaderEffect ->
* @param[in] baseColor ->
* @param[in] multiplyColor ->
* @param[in] screenColor ->
*/
void SetColorVectors(ID3DXEffect* shaderEffect, CubismTextureColor& baseColor, CubismTextureColor& multiplyColor, CubismTextureColor& screenColor);
/**
* @brief
*
* @param[in] model ->
* @param[in] index ->
* @param[in] shaderEffect ->
*/
void SetExecutionTextures(const CubismModel& model, const csmInt32 index, ID3DXEffect* shaderEffect);
/**
* @brief 使
*
* @param[in] shaderEffect ->
* @param[in] contextBuffer ->
*/
void SetColorChannel(ID3DXEffect* shaderEffect, CubismClippingContext_D3D9* contextBuffer);
/**
* @brief 使
*
* @param[in] shaderEffect ->
* @param[in] matrix ->
*/
void SetProjectionMatrix(ID3DXEffect* shaderEffect, CubismMatrix44& matrix);
/**
* @brief DrawIndexedPrimitiveUP
*
* @param[in] model ->
* @param[in] index ->
*/
void DrawIndexedPrimiteveWithSetup(const CubismModel& model, const csmInt32 index);
csmUint32 _drawableNum; ///< _vertexBuffers, _indexBuffersの確保数
/**
* @note D3D9ではDrawPrimitiveUPで描画コマンドを積んでおり
*
*/
CubismVertexD3D9** _vertexStore; ///< 頂点をストアしておく領域
csmUint16** _indexStore; ///< インデックスをストアしておく領域
csmInt32 _commandBufferNum; ///< 描画バッファを複数作成する場合の数
csmInt32 _commandBufferCurrent; ///< 現在使用中のバッファ番号
csmVector<csmInt32> _sortedDrawableIndexList; ///< 描画オブジェクトのインデックスを描画順に並べたリスト
csmMap<csmInt32, LPDIRECT3DTEXTURE9> _textures; ///< モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ
csmVector<csmVector<CubismOffscreenSurface_D3D9> > _offscreenSurfaces; ///< マスク描画用のフレームバッファ
CubismClippingManager_DX9* _clippingManager; ///< クリッピングマスク管理オブジェクト
CubismClippingContext_D3D9* _clippingContextBufferForMask; ///< マスクテクスチャに描画するためのクリッピングコンテキスト
CubismClippingContext_D3D9* _clippingContextBufferForDraw; ///< 画面上描画するためのクリッピングコンテキスト
};
}}}}
//------------ LIVE2D NAMESPACE ------------
@@ -0,0 +1,141 @@
/**
* 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 "CubismShader_D3D9.hpp"
#include "CubismRenderer_D3D9.hpp"
//------------ LIVE2D NAMESPACE ------------
namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering {
void CubismShader_D3D9::ReleaseShaderProgram()
{
_shaderSrc.Clear();
if(_vertexFormat)
{
_vertexFormat->Release();
_vertexFormat = NULL;
}
if(_shaderEffect)
{
_shaderEffect->Release();
_shaderEffect = NULL;
}
}
CubismShader_D3D9::CubismShader_D3D9()
: _shaderEffect(NULL)
, _vertexFormat(NULL)
{
}
CubismShader_D3D9::~CubismShader_D3D9()
{
ReleaseShaderProgram();
}
void CubismShader_D3D9::GenerateShaders(LPDIRECT3DDEVICE9 device)
{
if(_shaderEffect || _vertexFormat)
{// 既に有る
return;
}
if(!device)
{
return;
}
// シェーダーソースコードが記述されているファイルを読み込み
const csmChar* frameworkShaderPath = "FrameworkShaders/CubismEffect.fx";
csmLoadFileFunction fileLoader = Csm::CubismFramework::GetLoadFileFunction();
csmReleaseBytesFunction bytesReleaser = Csm::CubismFramework::GetReleaseBytesFunction();
if (!fileLoader)
{
CubismLogError("File loader is not set.");
return;
}
if (!bytesReleaser)
{
CubismLogError("Byte releaser is not set.");
return;
}
csmSizeInt shaderSize;
csmByte* shaderSrc = fileLoader(frameworkShaderPath, &shaderSize);
if (shaderSrc == NULL)
{
CubismLogError("Failed to load shader");
return;
}
csmString shaderString = csmString(reinterpret_cast<const csmChar*>(shaderSrc), shaderSize);
_shaderSrc.Clear();
for (csmInt32 i = 0; i < shaderString.GetLength(); i++)
{
_shaderSrc.PushBack(shaderString.GetRawString()[i]);
}
// ファイル読み込みで確保したバイト列を開放
bytesReleaser(shaderSrc);
//
if(!LoadShaderProgram(device))
{
CubismLogError("CreateShader failed");
CSM_ASSERT(0);
}
// この描画で使用する頂点フォーマット
D3DVERTEXELEMENT9 elems[] = {
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
if (device->CreateVertexDeclaration(elems, &_vertexFormat))
{
CubismLogError("CreateVertexDeclaration failed");
CSM_ASSERT(0);
}
}
Csm::csmBool CubismShader_D3D9::LoadShaderProgram(LPDIRECT3DDEVICE9 device)
{
if (!device) return false;
ID3DXBuffer* error = NULL;
if (FAILED(D3DXCreateEffect(device, _shaderSrc.GetPtr(), _shaderSrc.GetSize(), 0, 0, 0, 0, &_shaderEffect, &error)))
{
return false;
}
return true;
}
ID3DXEffect* CubismShader_D3D9::GetShaderEffect() const
{
return _shaderEffect;
}
void CubismShader_D3D9::SetupShader(LPDIRECT3DDEVICE9 device)
{
// まだシェーダ・頂点宣言未作成ならば作成する
GenerateShaders(device);
if (!device || !_vertexFormat) return;
device->SetVertexDeclaration(_vertexFormat);
}
}}}}
//------------ LIVE2D NAMESPACE ------------

Some files were not shown because too many files have changed in this diff Show More