1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

Adiciona comentários em Curve

This commit is contained in:
Danilo 2024-09-10 11:16:18 -03:00
parent 869703d814
commit 6238a462c2
2 changed files with 133 additions and 96 deletions

View File

@ -5,11 +5,50 @@
#include <algorithm>
namespace xna {
//Specifies different tangent types to be calculated for CurveKey points in a Curve.
enum class CurveTangent
{
//A Flat tangent always has a value equal to zero
Flat,
//A Linear tangent at a CurveKey is equal to the difference between its Value and the Value of the preceding or succeeding CurveKey.
Linear,
//A Smooth tangent smooths the inflection between a TangentIn and TangentOut by taking into account the values of both neighbors of the CurveKey.
Smooth,
};
//Defines how the value of a Curve will be determined for positions before the first point on the Curve or after the last point on the Curve.
enum class CurveLoopType {
//The Curve will evaluate to its first key for positions before the first point in the Curve and to the last key for positions after the last point.
Constant,
//Positions specified past the ends of the curve will wrap around to the opposite side of the Curve.
Cycle,
//Positions specified past the ends of the curve will wrap around to the opposite side of the Curve. The value will be offset by the difference between the values of the first and last CurveKey multiplied by the number of times the position wraps around. If the position is before the first point in the Curve, the difference will be subtracted from its value; otherwise, the difference will be added.
CycleOffset,
//Positions specified past the ends of the Curve act as an offset from the same side of the Curve toward the opposite side.
Oscillate,
//Linear interpolation will be performed to determine the value.
Linear,
};
//Defines the continuity of CurveKeys on a Curve.
enum class CurveContinuity {
//Interpolation can be used between this CurveKey and the next.
Smooth,
//Interpolation cannot be used between this CurveKey and the next. Specifying a position between the two points returns this point.
Step,
};
//Represents a point in a multi-point curve.
struct CurveKey {
//Position of the CurveKey in the curve.
float Position{ 0 };
//Describes the value of this point.
float Value{ 0 };
//Describes the tangent when leaving this point to the next point in the curve.
float TangentOut{ 0 };
//Describes the tangent when approaching this point from the previous point in the curve
float TangentIn{ 0 };
//Describes whether the segment between this point and the next point in the curve is discrete or continuous.
CurveContinuity Continuity{ CurveContinuity::Smooth };
constexpr CurveKey() = default;
@ -33,9 +72,11 @@ namespace xna {
}
};
//Contains the CurveKeys making up a Curve.
struct CurveKeyCollection {
constexpr CurveKeyCollection() = default;
//Determines the index of a CurveKey in the CurveKeyCollection.
constexpr size_t IndexOf(CurveKey const& item) {
auto it = std::find(Keys.begin(), Keys.end(), item);
auto value = std::distance(it, Keys.begin());
@ -43,6 +84,7 @@ namespace xna {
return static_cast<size_t>(value);
}
//Removes the CurveKey at the specified index.
constexpr void RemoveAt(size_t index) {
if (index >= Keys.size())
return;
@ -51,6 +93,7 @@ namespace xna {
IsCachedAvailable = false;
}
//Gets or sets the element at the specified index.
constexpr CurveKey& operator[](size_t index) {
if (index >= Keys.size())
index = Keys.size() - 1;
@ -58,19 +101,17 @@ namespace xna {
return Keys[index];
}
//Adds a CurveKey to the CurveKeyCollection.
constexpr void Add(CurveKey const& item, bool sortItems = true) {
Keys.push_back(item);
if (sortItems)
std::sort(Keys.begin(), Keys.end());
Sort();
IsCachedAvailable = false;
}
constexpr void Sort() {
std::sort(Keys.begin(), Keys.end());
}
}
//Removes all CurveKeys from the CurveKeyCollection.
constexpr void Clear() {
Keys.clear();
TimeRange = 0.0f;
@ -78,14 +119,17 @@ namespace xna {
IsCachedAvailable = false;
}
//Determines whether the CurveKeyCollection contains a specific CurveKey.
constexpr bool Contains(CurveKey const& item) const {
auto it = std::find(Keys.begin(), Keys.end(), item);
return it == Keys.end();
}
//Gets the number of elements contained in the CurveKeyCollection.
constexpr size_t Count() const { return Keys.size(); }
//Removes the first occurrence of a specific CurveKey from the CurveKeyCollection.
constexpr bool Remove(CurveKey const& item) {
auto it = std::find(Keys.begin(), Keys.end(), item);
@ -110,6 +154,11 @@ namespace xna {
IsCachedAvailable = true;
}
//Sort all keys
constexpr void Sort() {
std::sort(Keys.begin(), Keys.end());
}
public:
std::vector<CurveKey> Keys;
@ -122,93 +171,32 @@ namespace xna {
bool IsCachedAvailable{ true };
};
//Stores an arbitrary collection of 2D CurveKey points, and provides methods for evaluating features of the curve they define.
struct Curve {
//Specifies how to handle weighting values that are less than the first control point in the curve.
CurveLoopType PreLoop{ CurveLoopType::Constant };
//Specifies how to handle weighting values that are greater than the last control point in the curve.
CurveLoopType PostLoop{ CurveLoopType::Constant };
//The points that make up the curve.
CurveKeyCollection Keys{};
constexpr Curve() = default;
constexpr bool IsConstant() const { return Keys.Count() <= 1; }
constexpr void ComputeTangent(size_t keyIndex, CurveTangent tangentType) {
ComputeTangent(keyIndex, tangentType, tangentType);
}
constexpr void ComputeTangent(size_t keyIndex, CurveTangent tangentInType, CurveTangent tangentOutType) {
if (Keys.Count() <= keyIndex)
return;
auto& key = Keys[keyIndex];
auto num1 = key.Position;
auto num2 = key.Position;
auto num3 = key.Position;
auto num5 = key.Value;
auto num6 = key.Value;
auto num7 = key.Value;
if (keyIndex > 0)
{
num3 = Keys[keyIndex - 1].Position;
num7 = Keys[keyIndex - 1].Value;
}
if (keyIndex + 1 < Keys.Count())
{
num1 = Keys[keyIndex + 1].Position;
num5 = Keys[keyIndex + 1].Value;
}
switch (tangentInType)
{
case CurveTangent::Linear: {
key.TangentIn = num6 - num7;
break;
}
case CurveTangent::Smooth: {
auto num8 = num1 - num3;
auto num9 = num5 - num7;
key.TangentIn = std::abs(num9) >= 1.1920928955078125E-07 ? num9 * std::abs(num3 - num2) / num8 : 0.0f;
break;
}
default: {
key.TangentIn = 0.0f;
break;
}
}
switch (tangentOutType)
{
case CurveTangent::Linear: {
key.TangentOut = num5 - num6;
break;
}
case CurveTangent::Smooth: {
auto num10 = num1 - num3;
auto num11 = num5 - num7;
if (std::abs(num11) < 1.1920928955078125E-07)
{
key.TangentOut = 0.0f;
break;
}
key.TangentOut = num11 * std::abs(num1 - num2) / num10;
break;
}
default: {
key.TangentOut = 0.0f;
break;
}
}
}
//Gets a value indicating whether the curve is constant.
constexpr bool IsConstant() const { return Keys.Count() <= 1; }
//Computes all tangents for all CurveKeys in the Curve.
constexpr void ComputeTangents(CurveTangent tangentType) {
ComputeTangents(tangentType, tangentType);
}
//Computes all tangents for all CurveKeys in the Curve.
constexpr void ComputeTangents(CurveTangent tangentInType, CurveTangent tangentOutType) {
for (size_t keyIndex = 0; keyIndex < Keys.Count(); ++keyIndex)
ComputeTangent(keyIndex, tangentInType, tangentOutType);
}
//Finds the value at a position on the Curve.
constexpr float Evaluate(float position) {
if (Keys.Count() == 0)
return 0.0f;
@ -279,6 +267,75 @@ namespace xna {
}
private:
constexpr void ComputeTangent(size_t keyIndex, CurveTangent tangentType) {
ComputeTangent(keyIndex, tangentType, tangentType);
}
constexpr void ComputeTangent(size_t keyIndex, CurveTangent tangentInType, CurveTangent tangentOutType) {
if (Keys.Count() <= keyIndex)
return;
auto& key = Keys[keyIndex];
auto num1 = key.Position;
auto num2 = key.Position;
auto num3 = key.Position;
auto num5 = key.Value;
auto num6 = key.Value;
auto num7 = key.Value;
if (keyIndex > 0)
{
num3 = Keys[keyIndex - 1].Position;
num7 = Keys[keyIndex - 1].Value;
}
if (keyIndex + 1 < Keys.Count())
{
num1 = Keys[keyIndex + 1].Position;
num5 = Keys[keyIndex + 1].Value;
}
switch (tangentInType)
{
case CurveTangent::Linear: {
key.TangentIn = num6 - num7;
break;
}
case CurveTangent::Smooth: {
auto num8 = num1 - num3;
auto num9 = num5 - num7;
key.TangentIn = std::abs(num9) >= 1.1920928955078125E-07 ? num9 * std::abs(num3 - num2) / num8 : 0.0f;
break;
}
default: {
key.TangentIn = 0.0f;
break;
}
}
switch (tangentOutType)
{
case CurveTangent::Linear: {
key.TangentOut = num5 - num6;
break;
}
case CurveTangent::Smooth: {
auto num10 = num1 - num3;
auto num11 = num5 - num7;
if (std::abs(num11) < 1.1920928955078125E-07)
{
key.TangentOut = 0.0f;
break;
}
key.TangentOut = num11 * std::abs(num1 - num2) / num10;
break;
}
default: {
key.TangentOut = 0.0f;
break;
}
}
}
constexpr float CalcCycle(float t) {
auto num = (t - Keys[0].Position) * Keys.InvTimeRange;

View File

@ -114,26 +114,6 @@ namespace xna {
using CompareFunction = ComparisonFunction;
enum class CurveContinuity {
Smooth,
Step,
};
enum class CurveTangent
{
Flat,
Linear,
Smooth,
};
enum class CurveLoopType {
Constant,
Cycle,
CycleOffset,
Oscillate,
Linear,
};
enum class CullMode {
None,
CullClockwiseFace,