Skip to content

Commit

Permalink
Merge pull request #34 from Live2D/develop
Browse files Browse the repository at this point in the history
Update to Cubism 4 SDK for Native R3
  • Loading branch information
itoh-at-live2d-com authored Jun 10, 2021
2 parents b898afb + 523f617 commit 1d92b20
Show file tree
Hide file tree
Showing 24 changed files with 3,741 additions and 153 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).


## [4-r.3] - 2021-06-10

## [4-r.3-beta.1] - 2021-05-13

### Added

* Add a Renderer for Cocos2d-x v4.0.
* Implement a function to get the correct value when the time axis of the Bezier handle cannot be linear.
* Add an argument to the function `SetClippingMaskBufferSize` to set the height and width of the clipping mask buffer.

### Changed

* Improve the quality of Clipping Mask on high precision masking.


## [4-r.2] - 2021-02-17

### Added
Expand Down Expand Up @@ -85,6 +100,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Fix invalid expressions of `CubismCdiJson`.


[4-r.3]: https://github.com/Live2D/CubismNativeFramework/compare/4-r.3-beta.1...4-r.3
[4-r.3-beta.1]: https://github.com/Live2D/CubismNativeFramework/compare/4-r.2...4-r.3-beta.1
[4-r.2]: https://github.com/Live2D/CubismNativeFramework/compare/4-r.1...4-r.2
[4-r.1]: https://github.com/Live2D/CubismNativeFramework/compare/4-beta.2...4-r.1
[4-beta.2]: https://github.com/Live2D/CubismNativeFramework/compare/4-beta.1...4-beta.2
Expand Down
7 changes: 7 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Cubism Native Framework is included in Live2D Cubism Components.

Cubism Native Framework は Live2D Cubism Components に含まれます。

Cubism Native Framework 包括在 Live2D Cubism Components 中。

## Cubism SDK Release License

Expand All @@ -17,13 +18,18 @@ Cubism Native Framework は Live2D Cubism Components に含まれます。

* [Cubism SDK リリースライセンス](https://www.live2d.com/ja/download/cubism-sdk/release-license/)

如果您的企业在最近一个会计年度的销售额达到或超过1000万日元,您必须得到Cubism SDK的出版授权许可(出版许可协议)。

* [Cubism SDK发行许可证](https://www.live2d.com/zh-CHS/download/cubism-sdk/release-license/)


## Live2D Open Software License

Live2D Cubism Components is available under Live2D Open Software License.

* [Live2D Open Software License Agreement](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html)
* [Live2D Open Software 使用許諾契約書](https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html)
* [Live2D Open Software 使用授权协议](https://www.live2d.com/eula/live2d-open-software-license-agreement_cn.html)


## Live2D Proprietary Software License
Expand All @@ -32,6 +38,7 @@ Live2D Cubism Core is available under Live2D Proprietary Software License.

* [Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html)
* [Live2D Proprietary Software 使用許諾契約書](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_jp.html)
* [Live2D Proprietary Software 使用授权协议](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_cn.html)


---
Expand Down
90 changes: 90 additions & 0 deletions src/Math/CubismMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Live2D {namespace Cubism {namespace Framework {

const csmFloat32 CubismMath::Pi = 3.1415926535897932384626433832795f;
const csmFloat32 CubismMath::Epsilon = 0.00001f;

csmFloat32 CubismMath::DegreesToRadian(csmFloat32 degrees)
{
Expand Down Expand Up @@ -71,4 +72,93 @@ CubismVector2 CubismMath::RadianToDirection(csmFloat32 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);
}

}}}
26 changes: 26 additions & 0 deletions src/Math/CubismMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class CubismMath
{
public:
static const csmFloat32 Pi;
static const csmFloat32 Epsilon;

/**
*@brief 第一引数の値を最小値と最大値の範囲に収めた値を返す
Expand Down Expand Up @@ -163,6 +164,31 @@ class CubismMath
*/
static CubismVector2 RadianToDirection(csmFloat32 totalAngle);

/**
* @brief 三次方程式の三次項の係数が0になったときに補欠的に二次方程式の解をもとめる。
* a * x^2 + b * x + c = 0
*
* @param a -> 二次項の係数値
* @param b -> 一次項の係数値
* @param c -> 定数項の値
* @return 二次方程式の解
*/
static csmFloat32 QuadraticEquation(csmFloat32 a, csmFloat32 b, csmFloat32 c);

/**
* @brief カルダノの公式によってベジェのt値に該当する3次方程式の解を求める。
* 重解になったときには0.0~1.0の値になる解を返す。
*
* a * x^3 + b * x^2 + c * x + d = 0
*
* @param a -> 三次項の係数値
* @param b -> 二次項の係数値
* @param c -> 一次項の係数値
* @param d -> 定数項の値
* @return 0.0~1.0の間にある解
*/
static csmFloat32 CardanoAlgorithmForBezier(csmFloat32 a, csmFloat32 b, csmFloat32 c, csmFloat32 d);

private:
/**
*@brief privateコンストラクタ
Expand Down
2 changes: 1 addition & 1 deletion src/Math/CubismModelMatrix.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
Expand Down
117 changes: 116 additions & 1 deletion src/Motion/CubismMotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const csmChar* TargetNameModel = "Model";
const csmChar* TargetNameParameter = "Parameter";
const csmChar* TargetNamePartOpacity = "PartOpacity";

/**
* Cubism SDK R2 以前のモーションを再現させるなら true 、アニメータのモーションを正しく再現するなら false 。
*/
const csmBool UseOldBeziersCurveMotion = false;

CubismMotionPoint LerpPoints(const CubismMotionPoint a, const CubismMotionPoint b, const csmFloat32 t)
{
CubismMotionPoint result;
Expand Down Expand Up @@ -67,6 +72,108 @@ csmFloat32 BezierEvaluate(const CubismMotionPoint* points, const csmFloat32 time
return LerpPoints(p012, p123, t).Value;
}

csmFloat32 BezierEvaluateBinarySearch(const CubismMotionPoint* points, const csmFloat32 time)
{
const csmFloat32 x_error = 0.01f;

const csmFloat32 x = time;
csmFloat32 x1 = points[0].Time;
csmFloat32 x2 = points[3].Time;
csmFloat32 cx1 = points[1].Time;
csmFloat32 cx2 = points[2].Time;

csmFloat32 ta = 0.0f;
csmFloat32 tb = 1.0f;
csmFloat32 t = 0.0f;
int i = 0;

for (csmBool var33 = true; i < 20; ++i) {
if (x < x1 + x_error) {
t = ta;
break;
}

if (x2 - x_error < x) {
t = tb;
break;
}

csmFloat32 centerx = (cx1 + cx2) * 0.5f;
cx1 = (x1 + cx1) * 0.5f;
cx2 = (x2 + cx2) * 0.5f;
csmFloat32 ctrlx12 = (cx1 + centerx) * 0.5f;
csmFloat32 ctrlx21 = (cx2 + centerx) * 0.5f;
centerx = (ctrlx12 + ctrlx21) * 0.5f;
if (x < centerx) {
tb = (ta + tb) * 0.5f;
if (centerx - x_error < x) {
t = tb;
break;
}

x2 = centerx;
cx2 = ctrlx12;
}
else {
ta = (ta + tb) * 0.5f;
if (x < centerx + x_error) {
t = ta;
break;
}

x1 = centerx;
cx1 = ctrlx21;
}
}

if (i == 20) {
t = (ta + tb) * 0.5f;
}

if (t < 0.0f)
{
t = 0.0f;
}
if (t > 1.0f)
{
t = 1.0f;
}

const CubismMotionPoint p01 = LerpPoints(points[0], points[1], t);
const CubismMotionPoint p12 = LerpPoints(points[1], points[2], t);
const CubismMotionPoint p23 = LerpPoints(points[2], points[3], t);

const CubismMotionPoint p012 = LerpPoints(p01, p12, t);
const CubismMotionPoint p123 = LerpPoints(p12, p23, t);

return LerpPoints(p012, p123, t).Value;
}

csmFloat32 BezierEvaluateCardanoInterpretation(const CubismMotionPoint* points, const csmFloat32 time)
{
const csmFloat32 x = time;
csmFloat32 x1 = points[0].Time;
csmFloat32 x2 = points[3].Time;
csmFloat32 cx1 = points[1].Time;
csmFloat32 cx2 = points[2].Time;

csmFloat32 a = x2 - 3.0f * cx2 + 3.0f * cx1 - x1;
csmFloat32 b = 3.0f * cx2 - 6.0f * cx1 + 3.0f * x1;
csmFloat32 c = 3.0f * cx1 - 3.0f * x1;
csmFloat32 d = x1 - x;

csmFloat32 t = CubismMath::CardanoAlgorithmForBezier(a, b, c, d);

const CubismMotionPoint p01 = LerpPoints(points[0], points[1], t);
const CubismMotionPoint p12 = LerpPoints(points[1], points[2], t);
const CubismMotionPoint p23 = LerpPoints(points[2], points[3], t);

const CubismMotionPoint p012 = LerpPoints(p01, p12, t);
const CubismMotionPoint p123 = LerpPoints(p12, p23, t);

return LerpPoints(p012, p123, t).Value;
}

csmFloat32 SteppedEvaluate(const CubismMotionPoint* points, const csmFloat32 time)
{
return points[0].Value;
Expand Down Expand Up @@ -409,6 +516,8 @@ void CubismMotion::Parse(const csmByte* motionJson, const csmSizeInt size)
_motionData->Fps = json->GetMotionFps();
_motionData->EventCount = json->GetEventCount();

csmBool areBeziersRestructed = json->GetEvaluationOptionFlag( EvaluationOptionFlag_AreBeziersRistricted );

if (json->IsExistMotionFadeInTime())
{
_fadeInSeconds = (json->GetMotionFadeInTime() < 0.0f)
Expand Down Expand Up @@ -504,7 +613,13 @@ void CubismMotion::Parse(const csmByte* motionJson, const csmSizeInt size)
}
case CubismMotionSegmentType_Bezier: {
_motionData->Segments[totalSegmentCount].SegmentType = CubismMotionSegmentType_Bezier;
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluate;
if (areBeziersRestructed || UseOldBeziersCurveMotion) {
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluate;
}
else
{
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluateCardanoInterpretation;
}

_motionData->Points[totalPointCount].Time = json->GetMotionCurveSegment(curveCount, (segmentPosition + 1));
_motionData->Points[totalPointCount].Value = json->GetMotionCurveSegment(curveCount, (segmentPosition + 2));
Expand Down
11 changes: 11 additions & 0 deletions src/Motion/CubismMotionJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace {
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";
Expand Down Expand Up @@ -53,6 +54,16 @@ csmBool CubismMotionJson::IsMotionLoop() const
return _json->GetRoot()[Meta][Loop].ToBoolean();
}

csmBool CubismMotionJson::GetEvaluationOptionFlag(const csmInt32 flagType) const
{
if (EvaluationOptionFlag_AreBeziersRistricted == flagType)
{
return _json->GetRoot()[Meta][AreBeziersRestricted].ToBoolean();
}

return false;
}

csmInt32 CubismMotionJson::GetMotionCurveCount() const
{
return _json->GetRoot()[Meta][CurveCount].ToInt();
Expand Down
Loading

0 comments on commit 1d92b20

Please sign in to comment.