Refactor Bezier splines drawing and editing to property evaluate value and match curve evaluation
#3051
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 9,
|
"Minor": 9,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6605
|
"Build": 6606
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
||||||
|
|||||||
@@ -231,11 +231,10 @@ namespace FlaxEditor.GUI
|
|||||||
else if (_isMovingTangent)
|
else if (_isMovingTangent)
|
||||||
{
|
{
|
||||||
var viewRect = _editor._mainPanel.GetClientArea();
|
var viewRect = _editor._mainPanel.GetClientArea();
|
||||||
var direction = _movingTangent.IsIn ? -1.0f : 1.0f;
|
|
||||||
var k = _editor.GetKeyframe(_movingTangent.Index);
|
var k = _editor.GetKeyframe(_movingTangent.Index);
|
||||||
var kv = _editor.GetKeyframeValue(k);
|
var kv = _editor.GetKeyframeValue(k);
|
||||||
var value = _editor.Accessor.GetCurveValue(ref kv, _movingTangent.Component);
|
var value = _editor.Accessor.GetCurveValue(ref kv, _movingTangent.Component);
|
||||||
_movingTangent.TangentValue = direction * (PointToKeyframes(location, ref viewRect).Y - value);
|
_movingTangent.TangentValue = PointToKeyframes(location, ref viewRect).Y - value;
|
||||||
_editor.UpdateTangents();
|
_editor.UpdateTangents();
|
||||||
Cursor = CursorType.SizeNS;
|
Cursor = CursorType.SizeNS;
|
||||||
_movedKeyframes = true;
|
_movedKeyframes = true;
|
||||||
|
|||||||
@@ -682,9 +682,9 @@ namespace FlaxEditor.GUI
|
|||||||
var minPosPoint = _contents.PointToParent(ref minPos);
|
var minPosPoint = _contents.PointToParent(ref minPos);
|
||||||
var scroll = new Float2(_mainPanel.HScrollBar?.TargetValue ?? 0, _mainPanel.VScrollBar?.TargetValue ?? 0);
|
var scroll = new Float2(_mainPanel.HScrollBar?.TargetValue ?? 0, _mainPanel.VScrollBar?.TargetValue ?? 0);
|
||||||
scroll = ApplyUseModeMask(EnablePanning, minPosPoint, scroll);
|
scroll = ApplyUseModeMask(EnablePanning, minPosPoint, scroll);
|
||||||
if (_mainPanel.HScrollBar != null && _mainPanel.HScrollBar.Enabled)
|
if (_mainPanel.HScrollBar != null)
|
||||||
_mainPanel.HScrollBar.TargetValue = scroll.X;
|
_mainPanel.HScrollBar.TargetValue = scroll.X;
|
||||||
if (_mainPanel.VScrollBar != null && _mainPanel.VScrollBar.Enabled)
|
if (_mainPanel.VScrollBar != null)
|
||||||
_mainPanel.VScrollBar.TargetValue = scroll.Y;
|
_mainPanel.VScrollBar.TargetValue = scroll.Y;
|
||||||
|
|
||||||
UpdateKeyframes();
|
UpdateKeyframes();
|
||||||
@@ -1649,6 +1649,7 @@ namespace FlaxEditor.GUI
|
|||||||
var o = _keyframes[p.Index - 1];
|
var o = _keyframes[p.Index - 1];
|
||||||
var oValue = Accessor.GetCurveValue(ref o.Value, p.Component);
|
var oValue = Accessor.GetCurveValue(ref o.Value, p.Component);
|
||||||
var slope = (value - oValue) / (k.Time - o.Time);
|
var slope = (value - oValue) / (k.Time - o.Time);
|
||||||
|
slope = -slope;
|
||||||
Accessor.SetCurveValue(slope, ref k.TangentIn, p.Component);
|
Accessor.SetCurveValue(slope, ref k.TangentIn, p.Component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2199,12 +2200,12 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
var tangent = t.TangentValue;
|
var tangent = t.TangentValue;
|
||||||
var direction = t.IsIn ? -1.0f : 1.0f;
|
var direction = t.IsIn ? -1.0f : 1.0f;
|
||||||
var offset = 30.0f * direction;
|
var offset = 30.0f;
|
||||||
var location = GetKeyframePoint(ref k, selectedComponent);
|
var location = GetKeyframePoint(ref k, selectedComponent);
|
||||||
t.Size = KeyframesSize / ViewScale;
|
t.Size = KeyframesSize / ViewScale;
|
||||||
t.Location = new Float2
|
t.Location = new Float2
|
||||||
(
|
(
|
||||||
location.X * UnitsPerSecond - t.Width * 0.5f + offset,
|
location.X * UnitsPerSecond - t.Width * 0.5f + offset * direction,
|
||||||
location.Y * -UnitsPerSecond - t.Height * 0.5f + curveContentAreaBounds.Height - offset * tangent
|
location.Y * -UnitsPerSecond - t.Height * 0.5f + curveContentAreaBounds.Height - offset * tangent
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2280,14 +2281,13 @@ namespace FlaxEditor.GUI
|
|||||||
var startTangent = Accessor.GetCurveValue(ref startK.TangentOut, component);
|
var startTangent = Accessor.GetCurveValue(ref startK.TangentOut, component);
|
||||||
var endTangent = Accessor.GetCurveValue(ref endK.TangentIn, component);
|
var endTangent = Accessor.GetCurveValue(ref endK.TangentIn, component);
|
||||||
|
|
||||||
var offset = (end.X - start.X) * 0.5f;
|
var tangentScale = (endK.Time - startK.Time) / 3.0f;
|
||||||
|
|
||||||
var p1 = PointFromKeyframes(start, ref viewRect);
|
var p1 = PointFromKeyframes(start, ref viewRect);
|
||||||
var p2 = PointFromKeyframes(start + new Float2(offset, startTangent * offset), ref viewRect);
|
var p2 = PointFromKeyframes(start + new Float2(0, startTangent * tangentScale), ref viewRect);
|
||||||
var p3 = PointFromKeyframes(end - new Float2(offset, endTangent * offset), ref viewRect);
|
var p3 = PointFromKeyframes(end + new Float2(0, endTangent * tangentScale), ref viewRect);
|
||||||
var p4 = PointFromKeyframes(end, ref viewRect);
|
var p4 = PointFromKeyframes(end, ref viewRect);
|
||||||
|
|
||||||
Render2D.DrawBezier(p1, p2, p3, p4, color);
|
Render2D.DrawSpline(p1, p2, p3, p4, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Draw all ticks
|
// Draw all ticks
|
||||||
int l = Mathf.Clamp(smallestTick + level, 0, _tickSteps.Length - 1);
|
int l = Mathf.Clamp(smallestTick + level, 0, _tickSteps.Length - 2);
|
||||||
var lStep = _tickSteps[l];
|
var lStep = _tickSteps[l];
|
||||||
var lNextStep = _tickSteps[l + 1];
|
var lNextStep = _tickSteps[l + 1];
|
||||||
int startTick = Mathf.FloorToInt(min / lStep);
|
int startTick = Mathf.FloorToInt(min / lStep);
|
||||||
|
|||||||
@@ -66,27 +66,23 @@ namespace AnimationUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
FORCE_INLINE static void GetTangent(const T& a, const T& b, float length, T& result)
|
FORCE_INLINE static void GetTangent(const T& value, const T& tangent, float tangentScale, T& result)
|
||||||
{
|
{
|
||||||
const float oneThird = 1.0f / 3.0f;
|
result = value + tangent * tangentScale;
|
||||||
result = a + b * (length * oneThird);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
FORCE_INLINE void GetTangent<Quaternion>(const Quaternion& a, const Quaternion& b, float length, Quaternion& result)
|
FORCE_INLINE void GetTangent<Quaternion>(const Quaternion& value, const Quaternion& tangent, float tangentScale, Quaternion& result)
|
||||||
{
|
{
|
||||||
const float oneThird = 1.0f / 3.0f;
|
Quaternion::Slerp(value, tangent, 1.0f / 3.0f, result);
|
||||||
Quaternion::Slerp(a, b, oneThird, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
FORCE_INLINE void GetTangent<Transform>(const Transform& a, const Transform& b, float length, Transform& result)
|
FORCE_INLINE void GetTangent<Transform>(const Transform& value, const Transform& tangent, float tangentScale, Transform& result)
|
||||||
{
|
{
|
||||||
const float oneThird = 1.0f / 3.0f;
|
GetTangent(value.Translation, tangent.Translation, tangentScale, result.Translation);
|
||||||
const float oneThirdLength = length * oneThird;
|
GetTangent(value.Orientation, tangent.Orientation, tangentScale, result.Orientation);
|
||||||
result.Translation = a.Translation + b.Translation * oneThirdLength;
|
GetTangent(value.Scale, tangent.Scale, tangentScale, result.Scale);
|
||||||
Quaternion::Slerp(a.Orientation, b.Orientation, oneThird, result.Orientation);
|
|
||||||
result.Scale = a.Scale + (b.Scale - a.Scale) * oneThirdLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ namespace FlaxEngine
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value.</param>
|
/// <param name="value">The value.</param>
|
||||||
/// <param name="tangent">The tangent.</param>
|
/// <param name="tangent">The tangent.</param>
|
||||||
/// <param name="lengthThird">The length divided by 3.</param>
|
/// <param name="tangentScale">The tangent scale factor.</param>
|
||||||
/// <param name="result">The result.</param>
|
/// <param name="result">The result.</param>
|
||||||
void GetTangent(ref U value, ref U tangent, float lengthThird, out U result);
|
void GetTangent(ref U value, ref U tangent, float tangentScale, out U result);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the linear interpolation at the specified alpha.
|
/// Calculates the linear interpolation at the specified alpha.
|
||||||
@@ -67,7 +67,7 @@ namespace FlaxEngine
|
|||||||
IKeyframeAccess<Color32>,
|
IKeyframeAccess<Color32>,
|
||||||
IKeyframeAccess<Color>
|
IKeyframeAccess<Color>
|
||||||
{
|
{
|
||||||
public void GetTangent(ref bool value, ref bool tangent, float lengthThird, out bool result)
|
public void GetTangent(ref bool value, ref bool tangent, float tangentScale, out bool result)
|
||||||
{
|
{
|
||||||
result = value;
|
result = value;
|
||||||
}
|
}
|
||||||
@@ -82,9 +82,9 @@ namespace FlaxEngine
|
|||||||
result = p0;
|
result = p0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref int value, ref int tangent, float lengthThird, out int result)
|
public void GetTangent(ref int value, ref int tangent, float tangentScale, out int result)
|
||||||
{
|
{
|
||||||
result = value + (int)(tangent * lengthThird);
|
result = value + (int)(tangent * tangentScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref int a, ref int b, float alpha, out int result)
|
public void Linear(ref int a, ref int b, float alpha, out int result)
|
||||||
@@ -102,9 +102,9 @@ namespace FlaxEngine
|
|||||||
result = Mathf.Lerp(p012, p123, alpha);
|
result = Mathf.Lerp(p012, p123, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref double value, ref double tangent, float lengthThird, out double result)
|
public void GetTangent(ref double value, ref double tangent, float tangentScale, out double result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref double a, ref double b, float alpha, out double result)
|
public void Linear(ref double a, ref double b, float alpha, out double result)
|
||||||
@@ -122,9 +122,9 @@ namespace FlaxEngine
|
|||||||
result = Mathf.Lerp(p012, p123, alpha);
|
result = Mathf.Lerp(p012, p123, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref float value, ref float tangent, float lengthThird, out float result)
|
public void GetTangent(ref float value, ref float tangent, float tangentScale, out float result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref float a, ref float b, float alpha, out float result)
|
public void Linear(ref float a, ref float b, float alpha, out float result)
|
||||||
@@ -142,9 +142,9 @@ namespace FlaxEngine
|
|||||||
result = Mathf.Lerp(p012, p123, alpha);
|
result = Mathf.Lerp(p012, p123, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Vector2 value, ref Vector2 tangent, float lengthThird, out Vector2 result)
|
public void GetTangent(ref Vector2 value, ref Vector2 tangent, float tangentScale, out Vector2 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Vector2 a, ref Vector2 b, float alpha, out Vector2 result)
|
public void Linear(ref Vector2 a, ref Vector2 b, float alpha, out Vector2 result)
|
||||||
@@ -162,9 +162,9 @@ namespace FlaxEngine
|
|||||||
Vector2.Lerp(ref p012, ref p123, alpha, out result);
|
Vector2.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Vector3 value, ref Vector3 tangent, float lengthThird, out Vector3 result)
|
public void GetTangent(ref Vector3 value, ref Vector3 tangent, float tangentScale, out Vector3 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Vector3 a, ref Vector3 b, float alpha, out Vector3 result)
|
public void Linear(ref Vector3 a, ref Vector3 b, float alpha, out Vector3 result)
|
||||||
@@ -182,9 +182,9 @@ namespace FlaxEngine
|
|||||||
Vector3.Lerp(ref p012, ref p123, alpha, out result);
|
Vector3.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Vector4 value, ref Vector4 tangent, float lengthThird, out Vector4 result)
|
public void GetTangent(ref Vector4 value, ref Vector4 tangent, float tangentScale, out Vector4 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Vector4 a, ref Vector4 b, float alpha, out Vector4 result)
|
public void Linear(ref Vector4 a, ref Vector4 b, float alpha, out Vector4 result)
|
||||||
@@ -202,9 +202,9 @@ namespace FlaxEngine
|
|||||||
Vector4.Lerp(ref p012, ref p123, alpha, out result);
|
Vector4.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Float2 value, ref Float2 tangent, float lengthThird, out Float2 result)
|
public void GetTangent(ref Float2 value, ref Float2 tangent, float tangentScale, out Float2 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Float2 a, ref Float2 b, float alpha, out Float2 result)
|
public void Linear(ref Float2 a, ref Float2 b, float alpha, out Float2 result)
|
||||||
@@ -222,9 +222,9 @@ namespace FlaxEngine
|
|||||||
Float2.Lerp(ref p012, ref p123, alpha, out result);
|
Float2.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Float3 value, ref Float3 tangent, float lengthThird, out Float3 result)
|
public void GetTangent(ref Float3 value, ref Float3 tangent, float tangentScale, out Float3 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Float3 a, ref Float3 b, float alpha, out Float3 result)
|
public void Linear(ref Float3 a, ref Float3 b, float alpha, out Float3 result)
|
||||||
@@ -242,9 +242,9 @@ namespace FlaxEngine
|
|||||||
Float3.Lerp(ref p012, ref p123, alpha, out result);
|
Float3.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Float4 value, ref Float4 tangent, float lengthThird, out Float4 result)
|
public void GetTangent(ref Float4 value, ref Float4 tangent, float tangentScale, out Float4 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Float4 a, ref Float4 b, float alpha, out Float4 result)
|
public void Linear(ref Float4 a, ref Float4 b, float alpha, out Float4 result)
|
||||||
@@ -262,9 +262,9 @@ namespace FlaxEngine
|
|||||||
Float4.Lerp(ref p012, ref p123, alpha, out result);
|
Float4.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Double2 value, ref Double2 tangent, float lengthThird, out Double2 result)
|
public void GetTangent(ref Double2 value, ref Double2 tangent, float tangentScale, out Double2 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Double2 a, ref Double2 b, float alpha, out Double2 result)
|
public void Linear(ref Double2 a, ref Double2 b, float alpha, out Double2 result)
|
||||||
@@ -282,9 +282,9 @@ namespace FlaxEngine
|
|||||||
Double2.Lerp(ref p012, ref p123, alpha, out result);
|
Double2.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Double3 value, ref Double3 tangent, float lengthThird, out Double3 result)
|
public void GetTangent(ref Double3 value, ref Double3 tangent, float tangentScale, out Double3 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Double3 a, ref Double3 b, float alpha, out Double3 result)
|
public void Linear(ref Double3 a, ref Double3 b, float alpha, out Double3 result)
|
||||||
@@ -302,9 +302,9 @@ namespace FlaxEngine
|
|||||||
Double3.Lerp(ref p012, ref p123, alpha, out result);
|
Double3.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Double4 value, ref Double4 tangent, float lengthThird, out Double4 result)
|
public void GetTangent(ref Double4 value, ref Double4 tangent, float tangentScale, out Double4 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Double4 a, ref Double4 b, float alpha, out Double4 result)
|
public void Linear(ref Double4 a, ref Double4 b, float alpha, out Double4 result)
|
||||||
@@ -322,7 +322,7 @@ namespace FlaxEngine
|
|||||||
Double4.Lerp(ref p012, ref p123, alpha, out result);
|
Double4.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Quaternion value, ref Quaternion tangent, float lengthThird, out Quaternion result)
|
public void GetTangent(ref Quaternion value, ref Quaternion tangent, float tangentScale, out Quaternion result)
|
||||||
{
|
{
|
||||||
Quaternion.Slerp(ref value, ref tangent, 1.0f / 3.0f, out result);
|
Quaternion.Slerp(ref value, ref tangent, 1.0f / 3.0f, out result);
|
||||||
}
|
}
|
||||||
@@ -342,9 +342,9 @@ namespace FlaxEngine
|
|||||||
Quaternion.Slerp(ref p012, ref p123, alpha, out result);
|
Quaternion.Slerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Color32 value, ref Color32 tangent, float lengthThird, out Color32 result)
|
public void GetTangent(ref Color32 value, ref Color32 tangent, float tangentScale, out Color32 result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Color32 a, ref Color32 b, float alpha, out Color32 result)
|
public void Linear(ref Color32 a, ref Color32 b, float alpha, out Color32 result)
|
||||||
@@ -362,9 +362,9 @@ namespace FlaxEngine
|
|||||||
Color32.Lerp(ref p012, ref p123, alpha, out result);
|
Color32.Lerp(ref p012, ref p123, alpha, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTangent(ref Color value, ref Color tangent, float lengthThird, out Color result)
|
public void GetTangent(ref Color value, ref Color tangent, float tangentScale, out Color result)
|
||||||
{
|
{
|
||||||
result = value + tangent * lengthThird;
|
result = value + tangent * tangentScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Linear(ref Color a, ref Color b, float alpha, out Color result)
|
public void Linear(ref Color a, ref Color b, float alpha, out Color result)
|
||||||
@@ -860,9 +860,9 @@ namespace FlaxEngine
|
|||||||
|
|
||||||
// Evaluate the key at the curve
|
// Evaluate the key at the curve
|
||||||
result.Time = leftKey.Time + length * t;
|
result.Time = leftKey.Time + length * t;
|
||||||
float lengthThird = length / 3.0f;
|
float tangentScale = length / 3.0f;
|
||||||
_accessor.GetTangent(ref leftKey.Value, ref leftKey.TangentOut, lengthThird, out var leftTangent);
|
_accessor.GetTangent(ref leftKey.Value, ref leftKey.TangentOut, tangentScale, out var leftTangent);
|
||||||
_accessor.GetTangent(ref rightKey.Value, ref rightKey.TangentIn, lengthThird, out var rightTangent);
|
_accessor.GetTangent(ref rightKey.Value, ref rightKey.TangentIn, tangentScale, out var rightTangent);
|
||||||
_accessor.Bezier(ref leftKey.Value, ref leftTangent, ref rightTangent, ref rightKey.Value, t, out result.Value);
|
_accessor.Bezier(ref leftKey.Value, ref leftTangent, ref rightTangent, ref rightKey.Value, t, out result.Value);
|
||||||
result.TangentIn = leftKey.TangentOut;
|
result.TangentIn = leftKey.TangentOut;
|
||||||
result.TangentOut = rightKey.TangentIn;
|
result.TangentOut = rightKey.TangentIn;
|
||||||
@@ -895,9 +895,9 @@ namespace FlaxEngine
|
|||||||
float t = Mathf.NearEqual(length, 0.0f) ? 0.0f : (time - leftKey.Time) / length;
|
float t = Mathf.NearEqual(length, 0.0f) ? 0.0f : (time - leftKey.Time) / length;
|
||||||
|
|
||||||
// Evaluate the value at the curve
|
// Evaluate the value at the curve
|
||||||
float lengthThird = length / 3.0f;
|
float tangentScale = length / 3.0f;
|
||||||
_accessor.GetTangent(ref leftKey.Value, ref leftKey.TangentOut, lengthThird, out var leftTangent);
|
_accessor.GetTangent(ref leftKey.Value, ref leftKey.TangentOut, tangentScale, out var leftTangent);
|
||||||
_accessor.GetTangent(ref rightKey.Value, ref rightKey.TangentIn, lengthThird, out var rightTangent);
|
_accessor.GetTangent(ref rightKey.Value, ref rightKey.TangentIn, tangentScale, out var rightTangent);
|
||||||
_accessor.Bezier(ref leftKey.Value, ref leftTangent, ref rightTangent, ref rightKey.Value, t, out result);
|
_accessor.Bezier(ref leftKey.Value, ref leftTangent, ref rightTangent, ref rightKey.Value, t, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -247,16 +247,18 @@ public:
|
|||||||
static void Interpolate(const BezierCurveKeyframe& a, const BezierCurveKeyframe& b, float alpha, float length, T& result)
|
static void Interpolate(const BezierCurveKeyframe& a, const BezierCurveKeyframe& b, float alpha, float length, T& result)
|
||||||
{
|
{
|
||||||
T leftTangent, rightTangent;
|
T leftTangent, rightTangent;
|
||||||
AnimationUtils::GetTangent(a.Value, a.TangentOut, length, leftTangent);
|
const float tangentScale = length / 3.0f;
|
||||||
AnimationUtils::GetTangent(b.Value, b.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(a.Value, a.TangentOut, tangentScale, leftTangent);
|
||||||
|
AnimationUtils::GetTangent(b.Value, b.TangentIn, tangentScale, rightTangent);
|
||||||
AnimationUtils::Bezier(a.Value, leftTangent, rightTangent, b.Value, alpha, result);
|
AnimationUtils::Bezier(a.Value, leftTangent, rightTangent, b.Value, alpha, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InterpolateFirstDerivative(const BezierCurveKeyframe& a, const BezierCurveKeyframe& b, float alpha, float length, T& result)
|
static void InterpolateFirstDerivative(const BezierCurveKeyframe& a, const BezierCurveKeyframe& b, float alpha, float length, T& result)
|
||||||
{
|
{
|
||||||
T leftTangent, rightTangent;
|
T leftTangent, rightTangent;
|
||||||
AnimationUtils::GetTangent(a.Value, a.TangentOut, length, leftTangent);
|
const float tangentScale = length / 3.0f;
|
||||||
AnimationUtils::GetTangent(b.Value, b.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(a.Value, a.TangentOut, tangentScale, leftTangent);
|
||||||
|
AnimationUtils::GetTangent(b.Value, b.TangentIn, tangentScale, rightTangent);
|
||||||
AnimationUtils::BezierFirstDerivative(a.Value, leftTangent, rightTangent, b.Value, alpha, result);
|
AnimationUtils::BezierFirstDerivative(a.Value, leftTangent, rightTangent, b.Value, alpha, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,8 +266,9 @@ public:
|
|||||||
{
|
{
|
||||||
result.Time = a.Time + length * alpha;
|
result.Time = a.Time + length * alpha;
|
||||||
T leftTangent, rightTangent;
|
T leftTangent, rightTangent;
|
||||||
AnimationUtils::GetTangent(a.Value, a.TangentOut, length, leftTangent);
|
const float tangentScale = length / 3.0f;
|
||||||
AnimationUtils::GetTangent(b.Value, b.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(a.Value, a.TangentOut, tangentScale, leftTangent);
|
||||||
|
AnimationUtils::GetTangent(b.Value, b.TangentIn, tangentScale, rightTangent);
|
||||||
AnimationUtils::Bezier(a.Value, leftTangent, rightTangent, b.Value, alpha, result.Value);
|
AnimationUtils::Bezier(a.Value, leftTangent, rightTangent, b.Value, alpha, result.Value);
|
||||||
result.TangentIn = a.TangentOut;
|
result.TangentIn = a.TangentOut;
|
||||||
result.TangentOut = b.TangentIn;
|
result.TangentOut = b.TangentIn;
|
||||||
|
|||||||
@@ -158,10 +158,10 @@ float Spline::GetSplineLength() const
|
|||||||
const auto& b = Curve[i];
|
const auto& b = Curve[i];
|
||||||
Vector3 prevPoint = a.Value.Translation * scale;
|
Vector3 prevPoint = a.Value.Translation * scale;
|
||||||
|
|
||||||
const float length = Math::Abs(b.Time - a.Time);
|
const float tangentScale = Math::Abs(b.Time - a.Time) / 3.0f;
|
||||||
Vector3 leftTangent, rightTangent;
|
Vector3 leftTangent, rightTangent;
|
||||||
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent);
|
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent);
|
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, tangentScale, rightTangent);
|
||||||
|
|
||||||
for (int32 slice = 1; slice < slices; slice++)
|
for (int32 slice = 1; slice < slices; slice++)
|
||||||
{
|
{
|
||||||
@@ -189,10 +189,10 @@ float Spline::GetSplineSegmentLength(int32 index) const
|
|||||||
const Vector3 scale = _transform.Scale;
|
const Vector3 scale = _transform.Scale;
|
||||||
Vector3 prevPoint = a.Value.Translation * scale;
|
Vector3 prevPoint = a.Value.Translation * scale;
|
||||||
{
|
{
|
||||||
const float length = Math::Abs(b.Time - a.Time);
|
const float tangentScale = Math::Abs(b.Time - a.Time) / 3.0f;
|
||||||
Vector3 leftTangent, rightTangent;
|
Vector3 leftTangent, rightTangent;
|
||||||
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent);
|
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent);
|
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, tangentScale, rightTangent);
|
||||||
|
|
||||||
for (int32 slice = 1; slice < slices; slice++)
|
for (int32 slice = 1; slice < slices; slice++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -184,9 +184,9 @@ void SplineModel::OnSplineUpdated()
|
|||||||
auto& instance = _instances[segment];
|
auto& instance = _instances[segment];
|
||||||
const auto& start = keyframes[segment];
|
const auto& start = keyframes[segment];
|
||||||
const auto& end = keyframes[segment + 1];
|
const auto& end = keyframes[segment + 1];
|
||||||
const float length = end.Time - start.Time;
|
const float tangentScale = (end.Time - start.Time) / 3.0f;
|
||||||
AnimationUtils::GetTangent(start.Value, start.TangentOut, length, leftTangent);
|
AnimationUtils::GetTangent(start.Value, start.TangentOut, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(end.Value, end.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(end.Value, end.TangentIn, tangentScale, rightTangent);
|
||||||
|
|
||||||
// Find maximum scale over the segment spline and collect the segment positions for bounds
|
// Find maximum scale over the segment spline and collect the segment positions for bounds
|
||||||
segmentPoints.Clear();
|
segmentPoints.Clear();
|
||||||
@@ -256,9 +256,9 @@ void SplineModel::UpdateDeformationBuffer()
|
|||||||
auto& instance = _instances[segment];
|
auto& instance = _instances[segment];
|
||||||
const auto& start = keyframes[segment];
|
const auto& start = keyframes[segment];
|
||||||
const auto& end = keyframes[segment + 1];
|
const auto& end = keyframes[segment + 1];
|
||||||
const float length = end.Time - start.Time;
|
const float tangentScale = (end.Time - start.Time) / 3.0f;
|
||||||
AnimationUtils::GetTangent(start.Value, start.TangentOut, length, leftTangent);
|
AnimationUtils::GetTangent(start.Value, start.TangentOut, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(end.Value, end.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(end.Value, end.TangentIn, tangentScale, rightTangent);
|
||||||
for (int32 chunk = 0; chunk < chunksPerSegment; chunk++)
|
for (int32 chunk = 0; chunk < chunksPerSegment; chunk++)
|
||||||
{
|
{
|
||||||
const float alpha = (chunk == chunksPerSegment - 1) ? 1.0f : ((float)chunk * chunksPerSegmentInv);
|
const float alpha = (chunk == chunksPerSegment - 1) ? 1.0f : ((float)chunk * chunksPerSegmentInv);
|
||||||
@@ -291,10 +291,10 @@ void SplineModel::UpdateDeformationBuffer()
|
|||||||
{
|
{
|
||||||
const auto& start = keyframes[segments - 1];
|
const auto& start = keyframes[segments - 1];
|
||||||
const auto& end = keyframes[segments];
|
const auto& end = keyframes[segments];
|
||||||
const float length = end.Time - start.Time;
|
const float tangentScale = (end.Time - start.Time) / 3.0f;
|
||||||
const float alpha = 1.0f - ZeroTolerance; // Offset to prevent zero derivative at the end of the curve
|
const float alpha = 1.0f - ZeroTolerance; // Offset to prevent zero derivative at the end of the curve
|
||||||
AnimationUtils::GetTangent(start.Value, start.TangentOut, length, leftTangent);
|
AnimationUtils::GetTangent(start.Value, start.TangentOut, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(end.Value, end.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(end.Value, end.TangentIn, tangentScale, rightTangent);
|
||||||
AnimationUtils::Bezier(start.Value, leftTangent, rightTangent, end.Value, alpha, transform);
|
AnimationUtils::Bezier(start.Value, leftTangent, rightTangent, end.Value, alpha, transform);
|
||||||
Vector3 direction;
|
Vector3 direction;
|
||||||
AnimationUtils::BezierFirstDerivative(start.Value.Translation, leftTangent.Translation, rightTangent.Translation, end.Value.Translation, alpha, direction);
|
AnimationUtils::BezierFirstDerivative(start.Value.Translation, leftTangent.Translation, rightTangent.Translation, end.Value.Translation, alpha, direction);
|
||||||
|
|||||||
@@ -214,9 +214,9 @@ void SplineCollider::GetGeometry(CollisionShape& collision)
|
|||||||
auto offsetIndices = segment * collisionIndices.Count();
|
auto offsetIndices = segment * collisionIndices.Count();
|
||||||
const auto& start = keyframes[segment];
|
const auto& start = keyframes[segment];
|
||||||
const auto& end = keyframes[segment + 1];
|
const auto& end = keyframes[segment + 1];
|
||||||
const float length = end.Time - start.Time;
|
const float tangentScale = (end.Time - start.Time) / 3.0f;
|
||||||
AnimationUtils::GetTangent(start.Value, start.TangentOut, length, leftTangent);
|
AnimationUtils::GetTangent(start.Value, start.TangentOut, tangentScale, leftTangent);
|
||||||
AnimationUtils::GetTangent(end.Value, end.TangentIn, length, rightTangent);
|
AnimationUtils::GetTangent(end.Value, end.TangentIn, tangentScale, rightTangent);
|
||||||
|
|
||||||
// Vertex buffer is deformed along the spline
|
// Vertex buffer is deformed along the spline
|
||||||
auto srcVertices = collisionVertices.Get();
|
auto srcVertices = collisionVertices.Get();
|
||||||
|
|||||||
@@ -1882,19 +1882,46 @@ void Render2D::DrawBezier(const Float2& p1, const Float2& p2, const Float2& p3,
|
|||||||
const Float2 d3 = p4 - p3;
|
const Float2 d3 = p4 - p3;
|
||||||
const float len = d1.Length() + d2.Length() + d3.Length();
|
const float len = d1.Length() + d2.Length() + d3.Length();
|
||||||
const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
|
const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
|
||||||
const float segmentCountInv = 1.0f / segmentCount;
|
const float segmentCountInv = 1.0f / (float)segmentCount;
|
||||||
|
|
||||||
// Draw segmented curve
|
// Draw segmented curve
|
||||||
Float2 p;
|
|
||||||
AnimationUtils::Bezier(p1, p2, p3, p4, 0, p);
|
|
||||||
Lines2.Clear();
|
Lines2.Clear();
|
||||||
Lines2.Add(p);
|
Lines2.Add(p1);
|
||||||
for (int32 i = 1; i <= segmentCount; i++)
|
for (int32 i = 1; i < segmentCount; i++)
|
||||||
{
|
{
|
||||||
const float t = i * segmentCountInv;
|
const float t = (float)i * segmentCountInv;
|
||||||
|
Float2 p;
|
||||||
AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
|
AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
|
||||||
Lines2.Add(p);
|
Lines2.Add(p);
|
||||||
}
|
}
|
||||||
|
Lines2.Add(p4);
|
||||||
|
DrawLines(Lines2.Get(), Lines2.Count(), color, color, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render2D::DrawSpline(const Float2& p1, const Float2& p2, const Float2& p3, const Float2& p4, const Color& color, float thickness)
|
||||||
|
{
|
||||||
|
RENDER2D_CHECK_RENDERING_STATE;
|
||||||
|
|
||||||
|
// Find amount of segments to use
|
||||||
|
const Float2 d1 = p2 - p1;
|
||||||
|
const Float2 d2 = p3 - p2;
|
||||||
|
const Float2 d3 = p4 - p3;
|
||||||
|
const float len = d1.Length() + d2.Length() + d3.Length();
|
||||||
|
const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
|
||||||
|
const float segmentCountInv = 1.0f / (float)segmentCount;
|
||||||
|
|
||||||
|
// Draw segmented curve
|
||||||
|
Lines2.Clear();
|
||||||
|
Lines2.Add(p1);
|
||||||
|
for (int32 i = 1; i < segmentCount; i++)
|
||||||
|
{
|
||||||
|
const float t = (float)i * segmentCountInv;
|
||||||
|
Float2 p;
|
||||||
|
p.X = Math::Lerp(p1.X, p4.X, t);
|
||||||
|
AnimationUtils::Bezier(p1.Y, p2.Y, p3.Y, p4.Y, t, p.Y);
|
||||||
|
Lines2.Add(p);
|
||||||
|
}
|
||||||
|
Lines2.Add(p4);
|
||||||
DrawLines(Lines2.Get(), Lines2.Count(), color, color, thickness);
|
DrawLines(Lines2.Get(), Lines2.Count(), color, color, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -389,6 +389,17 @@ public:
|
|||||||
/// <param name="thickness">The line thickness.</param>
|
/// <param name="thickness">The line thickness.</param>
|
||||||
API_FUNCTION() static void DrawBezier(const Float2& p1, const Float2& p2, const Float2& p3, const Float2& p4, const Color& color, float thickness = 1.0f);
|
API_FUNCTION() static void DrawBezier(const Float2& p1, const Float2& p2, const Float2& p3, const Float2& p4, const Color& color, float thickness = 1.0f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a spline curve (Bezier but X axis represents uniform time).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p1">The start point.</param>
|
||||||
|
/// <param name="p2">The first control point.</param>
|
||||||
|
/// <param name="p3">The second control point.</param>
|
||||||
|
/// <param name="p4">The end point.</param>
|
||||||
|
/// <param name="color">The line color</param>
|
||||||
|
/// <param name="thickness">The line thickness.</param>
|
||||||
|
API_FUNCTION() static void DrawSpline(const Float2& p1, const Float2& p2, const Float2& p3, const Float2& p4, const Color& color, float thickness = 1.0f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws the GUI material.
|
/// Draws the GUI material.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user