Skip to content

Commit 4772b8d

Browse files
Merge pull request Live2D#33 from Live2D/4-r.3-beta.1
[RC] Update to Cubism 4 SDK for Native R3
2 parents 1a9b8cf + 2aed8fb commit 4772b8d

25 files changed

+3743
-154
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77

8+
## [4-r.3-beta.1] - 2021-05-13
9+
10+
### Added
11+
12+
* Add a Renderer for Cocos2d-x v4.0.
13+
* Implement a function to get the correct value when the time axis of the Bezier handle cannot be linear.
14+
* Add an argument to the function `SetClippingMaskBufferSize` to set the height and width of the clipping mask buffer.
15+
16+
### Changed
17+
18+
* Improve the quality of Clipping Mask on high precision masking.
19+
20+
821
## [4-r.2] - 2021-02-17
922

1023
### Added
@@ -85,6 +98,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
8598
* Fix invalid expressions of `CubismCdiJson`.
8699

87100

101+
[4-r.3-beta.1]: https://github.com/Live2D/CubismNativeFramework/compare/4-r.2...4-r.3-beta.1
88102
[4-r.2]: https://github.com/Live2D/CubismNativeFramework/compare/4-r.1...4-r.2
89103
[4-r.1]: https://github.com/Live2D/CubismNativeFramework/compare/4-beta.2...4-r.1
90104
[4-beta.2]: https://github.com/Live2D/CubismNativeFramework/compare/4-beta.1...4-beta.2

LICENSE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Cubism Native Framework is included in Live2D Cubism Components.
66

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

9+
Cubism Native Framework 包括在 Live2D Cubism Components 中。
910

1011
## Cubism SDK Release License
1112

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

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

21+
如果您的企业在最近一个会计年度的销售额达到或超过1000万日元,您必须得到Cubism SDK的出版授权许可(出版许可协议)。
22+
23+
* [Cubism SDK发行许可证](https://www.live2d.com/zh-CHS/download/cubism-sdk/release-license/)
24+
2025

2126
## Live2D Open Software License
2227

2328
Live2D Cubism Components is available under Live2D Open Software License.
2429

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

2834

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

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

3643

3744
---

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
# Cubism Native Framework
1+
# \[Beta Version\] Cubism Native Framework
22

33
Live2D Cubism 4 Editor で出力したモデルをアプリケーションで利用するためのフレームワークです。
44

55
モデルを表示、操作するための各種機能を提供します。
66
モデルをロードするには Cubism Core ライブラリと組み合わせて使用します。
77

8+
**本 SDK は、 Beta バージョンとなります。先行して新機能を取り込んでいるため、不安定な挙動を示す場合がございます。安定した製品をお求めの方は、公式サイトから配布されている正式版のパッケージ又は `develop` `master` ブランチをご利用ください。**
9+
10+
**\[Beta Version\] の SDK の不具合、各種ご意見等に関しましては、 Live2D コミュニティ にてご連絡ください。直接のコードに対する指摘、修正等は、直接 Pull requests としてご投稿ください。**
11+
812

913
## ライセンス
1014

src/Math/CubismMath.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace Live2D {namespace Cubism {namespace Framework {
1111

1212
const csmFloat32 CubismMath::Pi = 3.1415926535897932384626433832795f;
13+
const csmFloat32 CubismMath::Epsilon = 0.00001f;
1314

1415
csmFloat32 CubismMath::DegreesToRadian(csmFloat32 degrees)
1516
{
@@ -71,4 +72,93 @@ CubismVector2 CubismMath::RadianToDirection(csmFloat32 totalAngle)
7172
return ret;
7273
}
7374

75+
csmFloat32 CubismMath::QuadraticEquation(csmFloat32 a, csmFloat32 b, csmFloat32 c)
76+
{
77+
if (CubismMath::AbsF(a) < CubismMath::Epsilon)
78+
{
79+
if (CubismMath::AbsF(b) < CubismMath::Epsilon)
80+
{
81+
return -c;
82+
}
83+
return -c / b;
84+
}
85+
86+
return -(b + CubismMath::SqrtF(b * b - 4.0f * a * c)) / (2.0f * a);
87+
}
88+
89+
csmFloat32 CubismMath::CardanoAlgorithmForBezier(csmFloat32 a, csmFloat32 b, csmFloat32 c, csmFloat32 d)
90+
{
91+
if ( CubismMath::AbsF( a ) < CubismMath::Epsilon )
92+
{
93+
return CubismMath::RangeF( QuadraticEquation(b, c, d), 0.0f, 1.0f);
94+
}
95+
96+
csmFloat32 ba = b / a;
97+
csmFloat32 ca = c / a;
98+
csmFloat32 da = d / a;
99+
100+
101+
csmFloat32 p = (3.0f * ca - ba*ba) / 3.0f;
102+
csmFloat32 p3 = p / 3.0f;
103+
csmFloat32 q = (2.0f * ba*ba*ba - 9.0f * ba*ca + 27.0f * da) / 27.0f;
104+
csmFloat32 q2 = q / 2.0f;
105+
csmFloat32 discriminant = q2*q2 + p3*p3*p3;
106+
107+
const csmFloat32 center = 0.5f;
108+
const csmFloat32 threshold = center + 0.01f;
109+
110+
if (discriminant < 0.0f) {
111+
csmFloat32 mp3 = -p / 3.0f;
112+
csmFloat32 mp33 = mp3*mp3*mp3;
113+
csmFloat32 r = CubismMath::SqrtF(mp33);
114+
csmFloat32 t = -q / (2.0f * r);
115+
csmFloat32 cosphi = RangeF(t, -1.0f, 1.0f);
116+
csmFloat32 phi = acos(cosphi);
117+
csmFloat32 crtr = cbrt(r);
118+
csmFloat32 t1 = 2.0f * crtr;
119+
120+
csmFloat32 root1 = t1 * CubismMath::CosF(phi / 3.0f) - ba / 3.0f;
121+
if ( abs( root1 - center) < threshold)
122+
{
123+
return RangeF( root1, 0.0f, 1.0f);
124+
}
125+
126+
csmFloat32 root2 = t1 * CubismMath::CosF((phi + 2.0f * CubismMath::Pi) / 3.0f) - ba / 3.0f;
127+
if (abs(root2 - center) < threshold)
128+
{
129+
return RangeF(root2, 0.0f, 1.0f);
130+
}
131+
132+
csmFloat32 root3 = t1 * CubismMath::CosF((phi + 4.0f * CubismMath::Pi) / 3.0f) - ba / 3.0f;
133+
return RangeF(root3, 0.0f, 1.0f);
134+
}
135+
136+
if (discriminant == 0.0f) {
137+
csmFloat32 u1;
138+
if (q2 < 0.0f)
139+
{
140+
u1 = cbrt(-q2);
141+
}
142+
else
143+
{
144+
u1 = -cbrt(q2);
145+
}
146+
147+
csmFloat32 root1 = 2.0f * u1 - ba / 3.0f;
148+
if (abs(root1 - center) < threshold)
149+
{
150+
return RangeF(root1, 0.0f, 1.0f);
151+
}
152+
153+
csmFloat32 root2 = -u1 - ba / 3.0f;
154+
return RangeF(root2, 0.0f, 1.0f);
155+
}
156+
157+
csmFloat32 sd = CubismMath::SqrtF(discriminant);
158+
csmFloat32 u1 = cbrt(sd - q2);
159+
csmFloat32 v1 = cbrt(sd + q2);
160+
csmFloat32 root1 = u1 - v1 - ba / 3.0f;
161+
return RangeF(root1, 0.0f, 1.0f);
162+
}
163+
74164
}}}

src/Math/CubismMath.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class CubismMath
2222
{
2323
public:
2424
static const csmFloat32 Pi;
25+
static const csmFloat32 Epsilon;
2526

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

167+
/**
168+
* @brief 三次方程式の三次項の係数が0になったときに補欠的に二次方程式の解をもとめる。
169+
* a * x^2 + b * x + c = 0
170+
*
171+
* @param a -> 二次項の係数値
172+
* @param b -> 一次項の係数値
173+
* @param c -> 定数項の値
174+
* @return 二次方程式の解
175+
*/
176+
static csmFloat32 QuadraticEquation(csmFloat32 a, csmFloat32 b, csmFloat32 c);
177+
178+
/**
179+
* @brief カルダノの公式によってベジェのt値に該当する3次方程式の解を求める。
180+
* 重解になったときには0.0~1.0の値になる解を返す。
181+
*
182+
* a * x^3 + b * x^2 + c * x + d = 0
183+
*
184+
* @param a -> 三次項の係数値
185+
* @param b -> 二次項の係数値
186+
* @param c -> 一次項の係数値
187+
* @param d -> 定数項の値
188+
* @return 0.0~1.0の間にある解
189+
*/
190+
static csmFloat32 CardanoAlgorithmForBezier(csmFloat32 a, csmFloat32 b, csmFloat32 c, csmFloat32 d);
191+
166192
private:
167193
/**
168194
*@brief privateコンストラクタ

src/Math/CubismModelMatrix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**
1+
/**
22
* Copyright(c) Live2D Inc. All rights reserved.
33
*
44
* Use of this source code is governed by the Live2D Open Software license

src/Motion/CubismMotion.cpp

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const csmChar* TargetNameModel = "Model";
2626
const csmChar* TargetNameParameter = "Parameter";
2727
const csmChar* TargetNamePartOpacity = "PartOpacity";
2828

29+
/**
30+
* Cubism SDK R2 以前のモーションを再現させるなら true 、アニメータのモーションを正しく再現するなら false 。
31+
*/
32+
const csmBool UseOldBeziersCurveMotion = false;
33+
2934
CubismMotionPoint LerpPoints(const CubismMotionPoint a, const CubismMotionPoint b, const csmFloat32 t)
3035
{
3136
CubismMotionPoint result;
@@ -67,6 +72,108 @@ csmFloat32 BezierEvaluate(const CubismMotionPoint* points, const csmFloat32 time
6772
return LerpPoints(p012, p123, t).Value;
6873
}
6974

75+
csmFloat32 BezierEvaluateBinarySearch(const CubismMotionPoint* points, const csmFloat32 time)
76+
{
77+
const csmFloat32 x_error = 0.01f;
78+
79+
const csmFloat32 x = time;
80+
csmFloat32 x1 = points[0].Time;
81+
csmFloat32 x2 = points[3].Time;
82+
csmFloat32 cx1 = points[1].Time;
83+
csmFloat32 cx2 = points[2].Time;
84+
85+
csmFloat32 ta = 0.0f;
86+
csmFloat32 tb = 1.0f;
87+
csmFloat32 t = 0.0f;
88+
int i = 0;
89+
90+
for (csmBool var33 = true; i < 20; ++i) {
91+
if (x < x1 + x_error) {
92+
t = ta;
93+
break;
94+
}
95+
96+
if (x2 - x_error < x) {
97+
t = tb;
98+
break;
99+
}
100+
101+
csmFloat32 centerx = (cx1 + cx2) * 0.5f;
102+
cx1 = (x1 + cx1) * 0.5f;
103+
cx2 = (x2 + cx2) * 0.5f;
104+
csmFloat32 ctrlx12 = (cx1 + centerx) * 0.5f;
105+
csmFloat32 ctrlx21 = (cx2 + centerx) * 0.5f;
106+
centerx = (ctrlx12 + ctrlx21) * 0.5f;
107+
if (x < centerx) {
108+
tb = (ta + tb) * 0.5f;
109+
if (centerx - x_error < x) {
110+
t = tb;
111+
break;
112+
}
113+
114+
x2 = centerx;
115+
cx2 = ctrlx12;
116+
}
117+
else {
118+
ta = (ta + tb) * 0.5f;
119+
if (x < centerx + x_error) {
120+
t = ta;
121+
break;
122+
}
123+
124+
x1 = centerx;
125+
cx1 = ctrlx21;
126+
}
127+
}
128+
129+
if (i == 20) {
130+
t = (ta + tb) * 0.5f;
131+
}
132+
133+
if (t < 0.0f)
134+
{
135+
t = 0.0f;
136+
}
137+
if (t > 1.0f)
138+
{
139+
t = 1.0f;
140+
}
141+
142+
const CubismMotionPoint p01 = LerpPoints(points[0], points[1], t);
143+
const CubismMotionPoint p12 = LerpPoints(points[1], points[2], t);
144+
const CubismMotionPoint p23 = LerpPoints(points[2], points[3], t);
145+
146+
const CubismMotionPoint p012 = LerpPoints(p01, p12, t);
147+
const CubismMotionPoint p123 = LerpPoints(p12, p23, t);
148+
149+
return LerpPoints(p012, p123, t).Value;
150+
}
151+
152+
csmFloat32 BezierEvaluateCardanoInterpretation(const CubismMotionPoint* points, const csmFloat32 time)
153+
{
154+
const csmFloat32 x = time;
155+
csmFloat32 x1 = points[0].Time;
156+
csmFloat32 x2 = points[3].Time;
157+
csmFloat32 cx1 = points[1].Time;
158+
csmFloat32 cx2 = points[2].Time;
159+
160+
csmFloat32 a = x2 - 3.0f * cx2 + 3.0f * cx1 - x1;
161+
csmFloat32 b = 3.0f * cx2 - 6.0f * cx1 + 3.0f * x1;
162+
csmFloat32 c = 3.0f * cx1 - 3.0f * x1;
163+
csmFloat32 d = x1 - x;
164+
165+
csmFloat32 t = CubismMath::CardanoAlgorithmForBezier(a, b, c, d);
166+
167+
const CubismMotionPoint p01 = LerpPoints(points[0], points[1], t);
168+
const CubismMotionPoint p12 = LerpPoints(points[1], points[2], t);
169+
const CubismMotionPoint p23 = LerpPoints(points[2], points[3], t);
170+
171+
const CubismMotionPoint p012 = LerpPoints(p01, p12, t);
172+
const CubismMotionPoint p123 = LerpPoints(p12, p23, t);
173+
174+
return LerpPoints(p012, p123, t).Value;
175+
}
176+
70177
csmFloat32 SteppedEvaluate(const CubismMotionPoint* points, const csmFloat32 time)
71178
{
72179
return points[0].Value;
@@ -409,6 +516,8 @@ void CubismMotion::Parse(const csmByte* motionJson, const csmSizeInt size)
409516
_motionData->Fps = json->GetMotionFps();
410517
_motionData->EventCount = json->GetEventCount();
411518

519+
csmBool areBeziersRestructed = json->GetEvaluationOptionFlag( EvaluationOptionFlag_AreBeziersRistricted );
520+
412521
if (json->IsExistMotionFadeInTime())
413522
{
414523
_fadeInSeconds = (json->GetMotionFadeInTime() < 0.0f)
@@ -504,7 +613,13 @@ void CubismMotion::Parse(const csmByte* motionJson, const csmSizeInt size)
504613
}
505614
case CubismMotionSegmentType_Bezier: {
506615
_motionData->Segments[totalSegmentCount].SegmentType = CubismMotionSegmentType_Bezier;
507-
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluate;
616+
if (areBeziersRestructed || UseOldBeziersCurveMotion) {
617+
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluate;
618+
}
619+
else
620+
{
621+
_motionData->Segments[totalSegmentCount].Evaluate = BezierEvaluateCardanoInterpretation;
622+
}
508623

509624
_motionData->Points[totalPointCount].Time = json->GetMotionCurveSegment(curveCount, (segmentPosition + 1));
510625
_motionData->Points[totalPointCount].Value = json->GetMotionCurveSegment(curveCount, (segmentPosition + 2));

src/Motion/CubismMotionJson.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace {
1616
const csmChar* Meta = "Meta";
1717
const csmChar* Duration = "Duration";
1818
const csmChar* Loop = "Loop";
19+
const csmChar* AreBeziersRestricted = "AreBeziersRestricted";
1920
const csmChar* CurveCount = "CurveCount";
2021
const csmChar* Fps = "Fps";
2122
const csmChar* TotalSegmentCount = "TotalSegmentCount";
@@ -53,6 +54,16 @@ csmBool CubismMotionJson::IsMotionLoop() const
5354
return _json->GetRoot()[Meta][Loop].ToBoolean();
5455
}
5556

57+
csmBool CubismMotionJson::GetEvaluationOptionFlag(const csmInt32 flagType) const
58+
{
59+
if (EvaluationOptionFlag_AreBeziersRistricted == flagType)
60+
{
61+
return _json->GetRoot()[Meta][AreBeziersRestricted].ToBoolean();
62+
}
63+
64+
return false;
65+
}
66+
5667
csmInt32 CubismMotionJson::GetMotionCurveCount() const
5768
{
5869
return _json->GetRoot()[Meta][CurveCount].ToInt();

0 commit comments

Comments
 (0)