Skip to content

Commit

Permalink
Merge pull request #288 from taulazer/optimise-polar-slider-path
Browse files Browse the repository at this point in the history
  • Loading branch information
naoei authored May 23, 2022
2 parents bbdbc82 + 5e2ba80 commit 5c1fca5
Show file tree
Hide file tree
Showing 6 changed files with 374 additions and 122 deletions.
30 changes: 30 additions & 0 deletions osu.Game.Rulesets.Tau.Tests/NonVisual/PolarSliderPathTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NUnit.Framework;
using osu.Game.Rulesets.Tau.Objects;
using System.Linq;

namespace osu.Game.Rulesets.Tau.Tests.NonVisual
{
Expand Down Expand Up @@ -84,6 +85,35 @@ public void TestCalculatedDistance()
Assert.AreEqual(0, path.Version.Value);
Assert.AreEqual(40, path.CalculatedDistance);
Assert.AreEqual(0, path.Version.Value);
Assert.AreEqual(20, path.CalculateLazyDistance(10));
Assert.AreEqual(0, path.CalculateLazyDistance(20));
}

[Test]
public void TestSegments()
{
var path = new PolarSliderPath(new SliderNode[]
{
new(0, 50),
new(200, 70),
new(400, 50),
});

var segments = path.SegmentsBetween(100, 300).ToArray();
Assert.AreEqual(2, segments.Length);
Assert.AreEqual(60, segments[0].From.Angle);
Assert.AreEqual(60, segments[1].To.Angle);

segments = path.SegmentsBetween(50, 100).ToArray();
Assert.AreEqual(1, segments.Length);
Assert.AreEqual(55, segments[0].From.Angle);
Assert.AreEqual(60, segments[0].To.Angle);

segments = path.SegmentsBetween(0, 400).ToArray();
Assert.AreEqual(2, segments.Length);
Assert.AreEqual(50, segments[0].From.Angle);
Assert.AreEqual(70, segments[0].To.Angle);
Assert.AreEqual(50, segments[1].To.Angle);
}
}
}
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Tau/Beatmaps/TauBeatmapConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private TauHitObject convertToSlider(HitObject original, IHasCombo comboData, IH
NodeSamples = data.NodeSamples,
RepeatCount = data.RepeatCount,
Angle = firstAngle,
Path = new PolarSliderPath(nodes.ToArray()),
Path = new PolarSliderPath(nodes),
NewCombo = comboData?.NewCombo ?? false,
ComboOffset = comboData?.ComboOffset ?? 0,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using osu.Game.Rulesets.Tau.UI;
using osuTK;

namespace osu.Game.Rulesets.Tau.Objects.Drawables
Expand All @@ -13,74 +14,46 @@ private void updatePath()
if (nodes.Count == 0)
return;

var time = Time.Current - HitObject.StartTime + HitObject.TimePreempt;
var startTime = Math.Max(time - HitObject.TimePreempt - FadeTime, nodes[0].Time);
var midTime = Math.Max(time - HitObject.TimePreempt, nodes[0].Time);
var endTime = Math.Min(time, nodes[^1].Time);
double time = Time.Current - HitObject.StartTime + HitObject.TimePreempt;
double startTime = Math.Max(time - HitObject.TimePreempt - FadeTime, nodes[0].Time);
double midTime = Math.Max(time - HitObject.TimePreempt, nodes[0].Time);
double endTime = Math.Min(time, nodes[^1].Time);

if (time < startTime)
return;

int nodeIndex = 0;
bool capAdded = false;
var polarPath = HitObject.Path;

generatePathSegmnt(ref nodeIndex, ref capAdded, time, startTime, midTime);
nodeIndex--;
var pos = path.Vertices.Any() ? path.Vertices[^1].Xy : Vector2.Zero;
generatePathSegmnt(ref nodeIndex, ref capAdded, time, midTime, endTime);

path.Position = pos;
path.OriginPosition = path.PositionInBoundingBox(pos);
}

private void generatePathSegmnt(ref int nodeIndex, ref bool capAdded, double time, double startTime, double endTime)
{
var nodes = HitObject.Path.Nodes;
if (nodeIndex >= nodes.Count)
return;

while (nodeIndex + 1 < nodes.Count && nodes[nodeIndex + 1].Time <= startTime)
nodeIndex++;

const double delta_time = 20;
const double max_angle_per_ms = 5;
float radius = TauPlayfield.BaseSize.X / 2;

float distanceAt(double t) => inversed
? (float)(2 * PathDistance - (time - t) / HitObject.TimePreempt * PathDistance)
: (float)((time - t) / HitObject.TimePreempt * PathDistance);
? (float)(2 * radius - (time - t) / HitObject.TimePreempt * radius)
: (float)((time - t) / HitObject.TimePreempt * radius);

void addVertex(double t, double angle)
{
var p = Extensions.FromPolarCoordinates(distanceAt(t), (float)angle);
var index = (int)(t / trackingCheckpointInterval);
int index = (int)(t / trackingCheckpointInterval);

path.AddVertex(new Vector3(p.X, p.Y, trackingCheckpoints.ValueAtOrLastOr(index, true) ? 1 : 0));
}

do
foreach (var segment in polarPath.SegmentsBetween((float)startTime, (float)endTime))
{
var prevNode = nodes[nodeIndex];
var nextNode = nodeIndex + 1 < nodes.Count ? nodes[nodeIndex + 1] : prevNode;

var from = Math.Max(startTime, prevNode.Time);
var to = Math.Min(endTime, nextNode.Time);
var duration = nextNode.Time - prevNode.Time;

var deltaAngle = Extensions.GetDeltaAngle(nextNode.Angle, prevNode.Angle);
var anglePerMs = duration != 0 ? deltaAngle / duration : 0;
var timeStep = Math.Min(delta_time, Math.Abs(max_angle_per_ms / anglePerMs));

if (!capAdded)
addVertex(from, prevNode.Angle + anglePerMs * (from - prevNode.Time));
for (var t = from + timeStep; t < to; t += timeStep)
addVertex(t, prevNode.Angle + anglePerMs * (t - prevNode.Time));
if (duration != 0)
addVertex(to, prevNode.Angle + anglePerMs * (to - prevNode.Time));
else
addVertex(to, nextNode.Angle);
foreach (var node in segment.Split(excludeFirst: capAdded))
{
addVertex(node.Time, node.Angle);
}

capAdded = true;
nodeIndex++;
} while (nodeIndex < nodes.Count && nodes[nodeIndex].Time < endTime);
}

var midNode = polarPath.NodeAt((float)midTime);
var pos = Extensions.FromPolarCoordinates(distanceAt(midNode.Time), midNode.Angle);

path.Position = pos;
path.OriginPosition = path.PositionInBoundingBox(pos);
}

private bool checkIfTracking()
Expand Down
22 changes: 11 additions & 11 deletions osu.Game.Rulesets.Tau/Objects/Drawables/DrawableSliderRepeat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@ protected override void Update()
AlwaysPresent = true;
}

public Drawable InnerDrawableBox;
public Drawable InnerDrawableBox = new Container
{
RelativePositionAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 0,
AlwaysPresent = true,
Child = new BeatPiece()
};

protected override void LoadComplete()
{
base.LoadComplete();
AddInternal(InnerDrawableBox = new Container
{
RelativePositionAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 0,
AlwaysPresent = true,
Size = DrawableBox.Size,
Child = new BeatPiece()
});
InnerDrawableBox.Size = DrawableBox.Size;
AddInternal(InnerDrawableBox);

DrawableBox.Size = Vector2.Multiply(DrawableBox.Size, 15f / 16f);
DrawableBox.Rotation = 45;
Expand Down
Loading

0 comments on commit 5c1fca5

Please sign in to comment.