Skip to content

Commit

Permalink
Gameplay: Implement rendering for 0ms arcs
Browse files Browse the repository at this point in the history
  • Loading branch information
0thElement committed Apr 2, 2024
1 parent 3b5b47e commit fa66aac
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 10 deletions.
28 changes: 26 additions & 2 deletions Assets/Scripts/Gameplay/Data/Events/Arc.Rendering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,22 @@ public void UpdateRender(int currentTiming, double currentFloorPosition, GroupPr
continue;
}

var (bodyMatrix, shadowMatrix) = segment.GetMatrices(currentFloorPosition, groupProperties.FallDirection, z, pos.y);
Vector3 midpoint = pos + ((segment.StartPosition + segment.EndPosition) / 2);
midpoint.z = (zPos + endZPos) / 2;
float depth = Services.Camera.CalculateDepthSquared(midpoint);

var (bodyMatrix, shadowMatrix, cornerOffset) =
(EndTiming > Timing || IsTrace) ?
segment.GetMatrices(currentFloorPosition, groupProperties.FallDirection, z, pos.y) :
segment.GetMatricesSlam(
currentFloorPosition,
groupProperties.FallDirection,
z,
pos,
TimingGroupInstance,
NextArc,
Values.ArcMeshOffset);

if (IsTrace)
{
Services.Render.DrawTraceSegment(matrix * bodyMatrix, color, IsSelected, depth);
Expand All @@ -223,7 +235,7 @@ public void UpdateRender(int currentTiming, double currentFloorPosition, GroupPr
Services.Render.DrawArcSegment(Color, highlight, matrix * bodyMatrix, color, IsSelected, redArcValue, basePos.y + segment.EndPosition.y, depth);
if (!groupProperties.NoShadow)
{
Services.Render.DrawArcShadow(matrix * shadowMatrix, color);
Services.Render.DrawArcShadow(matrix * shadowMatrix, color, cornerOffset);
}
}
}
Expand Down Expand Up @@ -315,6 +327,18 @@ public float ArcYAt(int timing)
return ArcFormula.Y(YStart, YEnd, p, LineType);
}

public bool TryGetFirstSegement(out ArcSegmentData segment)
{
if (segments.Count >= 1)
{
segment = segments[0];
return true;
}

segment = default;
return false;
}

private void RebuildSegments()
{
if (Values.EnableArcRebuildSegment || segments.Count == 0)
Expand Down
96 changes: 93 additions & 3 deletions Assets/Scripts/Gameplay/Data/Events/ArcSegmentData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using ArcCreate.Gameplay.Chart;
using UnityEngine;

namespace ArcCreate.Gameplay.Data
Expand All @@ -25,7 +25,7 @@ public float CalculateZPos(double currentFloorPosition)
public float CalculateEndZPos(double currentFloorPosition)
=> ArcFormula.FloorPositionToZ(EndFloorPosition - currentFloorPosition);

public (Matrix4x4 body, Matrix4x4 shadow) GetMatrices(double floorPosition, Vector3 fallDirection, float baseZ, float baseY)
public (Matrix4x4 body, Matrix4x4 shadow, Vector4 cornerOffset) GetMatrices(double floorPosition, Vector3 fallDirection, float baseZ, float baseY)
{
float startZ = ArcFormula.FloorPositionToZ(FloorPosition - floorPosition);
float endZ = ArcFormula.FloorPositionToZ(EndFloorPosition - floorPosition);
Expand All @@ -46,7 +46,97 @@ public float CalculateEndZPos(double currentFloorPosition)
new Vector4(dir.x, 0, dir.z, 0),
new Vector4(startPos.x, -baseY, startPos.z, 1));

return (bodyMatrix, shadowMatrix);
return (bodyMatrix, shadowMatrix, Vector4.zero);
}

public (Matrix4x4 body, Matrix4x4 shadow, Vector4 cornerOffset)
GetMatricesSlam(double floorPosition, Vector3 fallDirection, float baseZ, Vector3 basePos, TimingGroup group, Arc next, float offset)
{
if (From > 0)
{
return (Matrix4x4.zero, Matrix4x4.zero, Vector4.zero);
}

float startZ = ArcFormula.FloorPositionToZ(FloorPosition - floorPosition);
Vector3 startPos = StartPosition + ((startZ - baseZ) * fallDirection);
Vector3 endPos = EndPosition + ((startZ - baseZ) * fallDirection);
Vector3 dir = endPos - startPos;

Matrix4x4 bodyMatrix = new Matrix4x4(
new Vector4(1, 0, 0, 0),
new Vector4(0, 1, 0, 0),
new Vector4(dir.x, dir.y, dir.z, 0),
new Vector4(startPos.x, startPos.y, startPos.z, 1));

// Accounting for angled arcs being less wide than straight arcs
float zLength = offset * 2;
if (next != null && next.TryGetFirstSegement(out ArcSegmentData nextFirstSeg)
&& nextFirstSeg.EndTiming > nextFirstSeg.Timing)
{
float dz = Mathf.Abs(ArcFormula.FloorPositionToZ(nextFirstSeg.EndFloorPosition - nextFirstSeg.FloorPosition));
float dx = Mathf.Abs(nextFirstSeg.StartPosition.x - nextFirstSeg.EndPosition.x);
zLength = Mathf.Sqrt(4 * offset * offset * dz * dz / ((dz * dz) + (dx * dx)));
}

double fpOffset = ArcFormula.ZToFloorPosition(zLength);

// Arc might go backward or forward in time, need to check both direction.
int slamForwardTiming = group.GetTimingFromFloorPosition(FloorPosition + fpOffset);
int slamBackwardTiming = group.GetTimingFromFloorPosition(FloorPosition - fpOffset);
int endOfSlamTiming = Mathf.Max(slamForwardTiming, slamBackwardTiming);

// Likely speed=0. Do not render shadow.
if (endOfSlamTiming <= Timing)
{
return (bodyMatrix, Matrix4x4.zero, Vector4.zero);
}

bool isPositiveSpeed = slamForwardTiming > slamBackwardTiming;

// Get the necessary coords.
// nf ^ Z axis
// + x +flx - - - - - - - - +frx |
// | | | shadow . |
// | next arc | pf . |
// +----x-----+nlx - - +-----x----+nrx |
// nn | prev arc | |
// | | | |
// | x | |
// pn |
// ----------------------------------> X axis
float pf = startPos.x;
float nn = endPos.x;
float nf = (next == null || next.EndTiming <= next.Timing) ? nn : next.WorldXAt(endOfSlamTiming) - basePos.x;

float nrx, nlx, frx, flx = 0;
if (nn < pf)
{
nrx = pf + offset;
nlx = nn + offset;
flx = Mathf.Min(nf + offset, nrx);
frx = Mathf.Max(nf + offset, nrx);
}
else
{
nlx = pf - offset;
nrx = nn - offset;
flx = Mathf.Min(nf - offset, nlx);
frx = Mathf.Max(nf - offset, nlx);
}

zLength *= isPositiveSpeed ? 1 : -1;
float zn = startPos.z;
float zf = zn + zLength;

float width = (nrx - nlx) / (offset * 2);
Matrix4x4 shadowMatrix = new Matrix4x4(
new Vector4(width, 0, 0, 0),
new Vector4(0, 1, 0, 0),
new Vector4(0, 0, zLength, 0),
new Vector4((nlx + nrx) / 2, -basePos.y, 0, 1));

Vector4 cornerOffset = new Vector4(0, frx - nrx, 0, flx - nlx) / width;
return (bodyMatrix, shadowMatrix, cornerOffset);
}
}
}
2 changes: 1 addition & 1 deletion Assets/Scripts/Gameplay/Render/IRenderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface IRenderService

void DrawArcSegment(int colorId, bool highlight, Matrix4x4 matrix, Color color, bool selected, float redValue, float y, float depth);

void DrawArcShadow(Matrix4x4 matrix, Color color);
void DrawArcShadow(Matrix4x4 matrix, Color color, Vector4 cornerOffset);

void DrawArcTap(bool sfx, Texture texture, Matrix4x4 matrix, Color color, bool selected);

Expand Down
6 changes: 3 additions & 3 deletions Assets/Scripts/Gameplay/Render/RenderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ public void DrawTraceSegment(Matrix4x4 matrix, Color color, bool selected, float
});
}

public void DrawArcShadow(Matrix4x4 matrix, Color color)
public void DrawArcShadow(Matrix4x4 matrix, Color color, Vector4 cornerOffset)
{
arcShadowDrawer.RegisterInstance(matrix, color);
arcShadowDrawer.RegisterInstance(matrix, color, cornerOffset);
}

public void DrawTraceShadow(Matrix4x4 matrix, Color color)
Expand Down Expand Up @@ -280,7 +280,7 @@ public void SetShadowMaterial(Material material)
arcShadowDrawer = new InstancedRendererPool(
material,
ArcMeshGenerator.GetShadowMesh(false),
false);
true);

traceShadowDrawer?.Dispose();
traceShadowDrawer = new InstancedRendererPool(
Expand Down
9 changes: 8 additions & 1 deletion Assets/Shaders/Shadow.shader
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(half4, _Color)
UNITY_DEFINE_INSTANCED_PROP(float4, _Properties)
UNITY_INSTANCING_BUFFER_END(Props)

float4 _ShadowColor;
Expand All @@ -56,9 +57,15 @@
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);

o.uv = TRANSFORM_TEX(v.uv, _MainTex);
float4 offset = UNITY_ACCESS_INSTANCED_PROP(Props, _Properties);
v.vertex.x += ((o.uv.x < 0.5) && (o.uv.y < 0.5)) * offset.x;
v.vertex.x += ((o.uv.x < 0.5) && (o.uv.y > 0.5)) * offset.y;
v.vertex.x += ((o.uv.x > 0.5) && (o.uv.y < 0.5)) * offset.z;
v.vertex.x += ((o.uv.x > 0.5) && (o.uv.y > 0.5)) * offset.w;

o.worldpos = mul(unity_ObjectToWorld, v.vertex);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}

Expand Down

0 comments on commit fa66aac

Please sign in to comment.