first
This commit is contained in:
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}}}
|
||||
Reference in New Issue
Block a user