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
@@ -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;
};
}}}