attempt to fix merged sliders rendering wrong cones

This commit is contained in:
yugecin 2018-10-26 22:52:23 +02:00
parent 8d6e34faaf
commit a027330be3
No known key found for this signature in database
GPG Key ID: 2C5AC035A7068E44
8 changed files with 84 additions and 77 deletions

View File

@ -957,7 +957,7 @@ public class GameData {
private void drawHitAnimations(HitObjectResult hitResult, int trackPosition) { private void drawHitAnimations(HitObjectResult hitResult, int trackPosition) {
// fade out slider curve // fade out slider curve
if (hitResult.result != HIT_SLIDER_REPEAT && hitResult.result != HIT_SLIDER_REPEAT_M && hitResult.curve != null) { if (hitResult.result != HIT_SLIDER_REPEAT && hitResult.result != HIT_SLIDER_REPEAT_M && hitResult.curve != null) {
if (!OPTION_SHRINKING_SLIDERS.state) { if (!OPTION_SHRINKING_SLIDERS.state && hitResult.curve.getCurvePoints().length > 0) {
float progress = AnimationEquation.OUT_CUBIC.calc( float progress = AnimationEquation.OUT_CUBIC.calc(
(float) Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME) / HITCIRCLE_FADE_TIME); (float) Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME) / HITCIRCLE_FADE_TIME);
float alpha = 1f - progress; float alpha = 1f - progress;

View File

@ -124,7 +124,7 @@ public class Slider extends GameObject {
private int comboColorIndex; private int comboColorIndex;
public int baseSliderFrom; public int curveStartIndex;
/** /**
* Initializes the Slider data type with images and dimensions. * Initializes the Slider data type with images and dimensions.
@ -205,9 +205,9 @@ public class Slider extends GameObject {
final int fadeInTime = game.getFadeInTime(); final int fadeInTime = game.getFadeInTime();
float scale = timeDiff / (float) approachTime; float scale = timeDiff / (float) approachTime;
float approachScale = 1 + scale * 3; float approachScale = 1 + scale * 3;
double fadeinScale = (timeDiff - approachTime + fadeInTime) / (double) fadeInTime; float fadeinScale = (timeDiff - approachTime + fadeInTime) / (float) fadeInTime;
float alpha = Utils.clamp(1 - (float) fadeinScale, 0, 1); float alpha = Utils.clamp(1f - fadeinScale, 0f, 1f);
float decorationsAlpha = Utils.clamp(-2.0f * (float) fadeinScale, 0, 1); float decorationsAlpha = Utils.clamp(-2.0f * fadeinScale, 0f, 1f);
boolean overlayAboveNumber = SkinService.skin.isHitCircleOverlayAboveNumber(); boolean overlayAboveNumber = SkinService.skin.isHitCircleOverlayAboveNumber();
float oldAlpha = Colors.WHITE_FADE.a; float oldAlpha = Colors.WHITE_FADE.a;
Colors.WHITE_FADE.a = color.a = alpha; Colors.WHITE_FADE.a = color.a = alpha;
@ -222,7 +222,7 @@ public class Slider extends GameObject {
} }
curveColor.a = sliderAlpha; curveColor.a = sliderAlpha;
boolean isCurveCompletelyDrawn = drawSliderTrack(trackPosition, Utils.clamp(1d - fadeinScale, 0d, 1d)); boolean isCurveCompletelyDrawn = drawSliderTrack(trackPosition, Utils.clamp(1f - fadeinScale, 0f, 1f));
color.a = alpha; color.a = alpha;
// end circle (only draw if ball still has to go there) // end circle (only draw if ball still has to go there)
@ -448,38 +448,46 @@ public class Slider extends GameObject {
} }
} }
private boolean drawSliderTrack(int trackPosition, double snakingSliderProgress) { /**
double curveIntervalTo = OPTION_SNAKING_SLIDERS.state ? snakingSliderProgress : 1d; * @return {@code true} if track is completely drawn (snaking, shrinking etc)
double curveIntervalFrom = 0d; */
private boolean drawSliderTrack(int trackPosition, float snakingSliderProgress)
{
int curvelen = curve.curve.length;
if (curvelen == 0) {
return true;
}
float curveIntervalTo = OPTION_SNAKING_SLIDERS.state ? snakingSliderProgress : 1f;
float curveIntervalFrom = 0f;
if (OPTION_SHRINKING_SLIDERS.state) { if (OPTION_SHRINKING_SLIDERS.state) {
double sliderprogress = (trackPosition - getTime() - ((double) sliderTime * (repeats - 1))) / (double) sliderTime; float sliderprogress = (trackPosition - getTime() - sliderTime * (repeats - 1)) / sliderTime;
if (sliderprogress > 0) { if (sliderprogress > 0) {
curveIntervalFrom = sliderprogress; curveIntervalFrom = sliderprogress;
} }
} }
int curvelen = curve.getCurvePoints().length;
if (!OPTION_FALLBACK_SLIDERS.state && OPTION_MERGING_SLIDERS.state) { if (!OPTION_FALLBACK_SLIDERS.state && OPTION_MERGING_SLIDERS.state) {
if (OPTION_SHRINKING_SLIDERS.state && curveIntervalFrom > 0) { if (OPTION_SHRINKING_SLIDERS.state && curveIntervalFrom > 0d) {
if (hitObject.getRepeatCount() % 2 == 0) { if (hitObject.getRepeatCount() % 2 == 0) {
game.addMergedSliderPointsToRender(baseSliderFrom, baseSliderFrom + (int) ((1d - curveIntervalFrom) * curvelen)); game.addMergedSliderPointsToRender(curveStartIndex, curveStartIndex + (int) ((1d - curveIntervalFrom) * curvelen));
} else { } else {
game.addMergedSliderPointsToRender(baseSliderFrom + (int) (curveIntervalFrom * curvelen) + 1, baseSliderFrom + (int) (curveIntervalTo * curve.getCurvePoints().length)); game.addMergedSliderPointsToRender(curveStartIndex + (int) (curveIntervalFrom * curvelen) + 1, curveStartIndex + (int) (curveIntervalTo * (curvelen - 1)));
} }
} else { } else {
game.addMergedSliderPointsToRender(baseSliderFrom, baseSliderFrom + (int) (curveIntervalTo * curve.getCurvePoints().length)); int to = (int) (curveIntervalTo * (curvelen - 1));
game.addMergedSliderPointsToRender(curveStartIndex, curveStartIndex + to);
} }
} else { } else {
if (OPTION_SHRINKING_SLIDERS.state && curveIntervalFrom > 0 && repeats % 2 == 0) { if (OPTION_SHRINKING_SLIDERS.state && curveIntervalFrom > 0 && repeats % 2 == 0) {
if (OPTION_FALLBACK_SLIDERS.state) { if (OPTION_FALLBACK_SLIDERS.state) {
curveIntervalTo = 1d - curveIntervalFrom; curveIntervalTo = 1f - curveIntervalFrom;
} else { } else {
curve.splice((int) ((1d - curveIntervalFrom) * curvelen), curvelen); curve.splice((int) ((1f - curveIntervalFrom) * curvelen), curvelen);
} }
curveIntervalFrom = 0d; curveIntervalFrom = 0f;
} }
curve.draw(curveColor, (int) (curveIntervalFrom * curvelen), (int) (curveIntervalTo * curvelen)); curve.draw(curveColor, (int) (curveIntervalFrom * curvelen), (int) (curveIntervalTo * curvelen));
} }
return curveIntervalTo == 1d; return curveIntervalTo == 1f;
} }
/** /**
@ -830,6 +838,16 @@ public class Slider extends GameObject {
return curve; return curve;
} }
public Vec2f[] getCurvePoints()
{
return curve.curve;
}
public int getCurvePointsCount()
{
return curve.curve.length;
}
public int getRepeats() { public int getRepeats() {
return repeats; return repeats;
} }

View File

@ -91,10 +91,8 @@ public abstract class Curve {
} }
/** /**
* Set the width and height of the container that Curves get drawn into. * Init curves for given circle diameter
* Should be called before any curves are drawn. * Should be called before any curves are drawn.
* @param width the container width
* @param height the container height
* @param circleDiameter the circle diameter * @param circleDiameter the circle diameter
* @param borderColor the curve border color * @param borderColor the curve border color
*/ */

View File

@ -75,7 +75,7 @@ public class CurveRenderState {
private final int mirrors; private final int mirrors;
/** /**
* Set the width and height of the container that Curves get drawn into. * Init curves for given circle diameter
* Should be called before any curves are drawn. * Should be called before any curves are drawn.
* @param circleDiameter the circle diameter * @param circleDiameter the circle diameter
*/ */
@ -83,7 +83,6 @@ public class CurveRenderState {
// equivalent to what happens in Slider.init() // equivalent to what happens in Slider.init()
scale = (int) (circleDiameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480) scale = (int) (circleDiameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
//scale = scale * 118 / 128; //for curves exactly as big as the sliderball //scale = scale * 118 / 128; //for curves exactly as big as the sliderball
FrameBufferCache.init(width, height);
NewCurveStyleState.initUnitCone(); NewCurveStyleState.initUnitCone();
} }
@ -293,31 +292,20 @@ public class CurveRenderState {
*/ */
private void createVertexBuffer(int bufferID) { private void createVertexBuffer(int bufferID) {
int arrayBufferBinding = GL11.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING); int arrayBufferBinding = GL11.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING);
FloatBuffer buff = BufferUtils.createByteBuffer(4 * (4 + 2) * (2 * curve.length - 1) * mirrors * (NewCurveStyleState.DIVIDES + 2)).asFloatBuffer(); FloatBuffer buff = BufferUtils.createByteBuffer(4 * (4 + 2) * (curve.length) * mirrors * (NewCurveStyleState.DIVIDES + 2)).asFloatBuffer();
if (curve.length > 0) {
fillCone(buff, curve[0].x, curve[0].y, 0);
}
for (int mirror = 0; mirror < mirrors; mirror++) { for (int mirror = 0; mirror < mirrors; mirror++) {
final float angle = 360f * mirror / mirrors; final float angle = 360f * mirror / mirrors;
float lastx = curve[0].x;
float lasty = curve[0].y;
fillCone(buff, lastx, lasty, angle);
for (int i = 1; i < curve.length; ++i) { for (int i = 1; i < curve.length; ++i) {
float x = curve[i].x; float x = curve[i].x;
float y = curve[i].y; float y = curve[i].y;
fillCone(buff, x, y, angle); fillCone(buff, x, y, angle);
float last_x = curve[i - 1].x; //fillCone(buff, (x + lastx) / 2f, (y + lasty) / 2f, angle);
float last_y = curve[i - 1].y; //lastx = x;
double diff_x = x - last_x; //lasty = y;
double diff_y = y - last_y;
float dist = Utils.distance(x, y, last_x, last_y);
if (dist < gameObjectRenderer.circleDiameter / 8) {
x = (float) (x - diff_x / 2);
y = (float) (y - diff_y / 2);
} else {
// don't mind me
x = -100f;
y = -100f;
}
fillCone(buff, x, y, angle);
} }
} }
buff.flip(); buff.flip();
@ -349,16 +337,15 @@ public class CurveRenderState {
if (clearFirst) { if (clearFirst) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
} }
int max = mirrors; final int mirrors = OPTION_DANCE_MIRROR.state ? this.mirrors : 1;
if (!OPTION_DANCE_MIRROR.state) { for (int i = 0; i < mirrors; i++) {
max = 1;
}
for (int i = 0; i < max; i++) {
if (pointsToRender == null) { if (pointsToRender == null) {
renderCurve(from, to, i); renderCurve(from, to, i);
} else { } else {
renderCurve(i); renderCurve(i);
} }
//from++;
//to++;
} }
GL11.glFlush(); GL11.glFlush();
GL20.glDisableVertexAttribArray(staticState.texCoordLoc); GL20.glDisableVertexAttribArray(staticState.texCoordLoc);
@ -367,15 +354,16 @@ public class CurveRenderState {
} }
private void renderCurve(int from, int to, int mirror) { private void renderCurve(int from, int to, int mirror) {
// since there are len*2-1 points, subtract mirror index
if (from > 0) { if (from > 0) {
from -= mirror; from -= mirror;
} }
to -= mirror; to -= mirror;
for (int i = from * 2; i < to * 2 - 1; ++i) { for (int i = from; i < to - 1; ++i) {
if (spliceFrom <= i && i <= spliceTo) { if (spliceFrom <= i && i <= spliceTo) {
continue; continue;
} }
final int index = i + curve.length * 2 * mirror; final int index = i + curve.length * mirror;
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, index * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2); GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, index * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2);
} }
} }
@ -383,8 +371,8 @@ public class CurveRenderState {
private void renderCurve(int mirror) { private void renderCurve(int mirror) {
Iterator<Integer> iter = pointsToRender.iterator(); Iterator<Integer> iter = pointsToRender.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
for (int i = iter.next() * 2, end = iter.next() * 2 - 1; i < end; ++i) { for (int i = iter.next(), end = iter.next(); i < end; ++i) {
final int index = i + curve.length * 2 * mirror; final int index = i + curve.length * mirror;
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, index * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2); GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, index * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2);
} }
} }

View File

@ -23,6 +23,8 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static yugecin.opsudance.core.InstanceContainer.*;
/** /**
* This is cache for OpenGL FrameBufferObjects. This is currently only used * This is cache for OpenGL FrameBufferObjects. This is currently only used
* to draw curve objects of the new slider style. Does currently not integrate * to draw curve objects of the new slider style. Does currently not integrate
@ -40,20 +42,6 @@ public class FrameBufferCache {
/** */ /** */
private ArrayList<Rendertarget> cache; private ArrayList<Rendertarget> cache;
/** Container dimensions. */
public static int width, height;
/**
* Set the width and height of the framebuffers in this cache.
* Should be called before anything is inserted into the map.
* @param width the container width
* @param height the container height
*/
public static void init(int width, int height) {
FrameBufferCache.width = width;
FrameBufferCache.height = height;
}
/** /**
* Constructor. * Constructor.
*/ */

View File

@ -68,6 +68,7 @@ import yugecin.opsudance.utils.GLHelper;
import static itdelatrisu.opsu.GameImage.*; import static itdelatrisu.opsu.GameImage.*;
import static itdelatrisu.opsu.ui.Colors.*; import static itdelatrisu.opsu.ui.Colors.*;
import static java.lang.System.arraycopy;
import static org.lwjgl.input.Keyboard.*; import static org.lwjgl.input.Keyboard.*;
import static yugecin.opsudance.options.Options.*; import static yugecin.opsudance.options.Options.*;
import static yugecin.opsudance.core.InstanceContainer.*; import static yugecin.opsudance.core.InstanceContainer.*;
@ -1672,22 +1673,36 @@ public class Game extends ComplexOpsuState {
} }
if (knorkesliders == null) { if (knorkesliders == null) {
// let's create knorkesliders // let's create knorkesliders
List<Vec2f> curvepoints = new ArrayList<>(); int totalpoints = 0;
for (GameObject gameObject : gameObjects) { ArrayList<Slider> sliders = new ArrayList<>();
if (gameObject.isSlider()) { for (GameObject o : gameObjects) {
((Slider) gameObject).baseSliderFrom = curvepoints.size(); if (o.isSlider()) {
curvepoints.addAll(Arrays.asList(((Slider) gameObject).getCurve().getCurvePoints())); final Slider s = (Slider) o;
final int len = s.getCurvePointsCount();
if (len > 0) {
sliders.add(s);
s.curveStartIndex = totalpoints;
totalpoints += s.getCurvePointsCount();
} }
} }
if (curvepoints.size() > 0) { }
knorkesliders = new FakeCombinedCurve(curvepoints.toArray(new Vec2f[curvepoints.size()])); if (totalpoints > 0) {
Vec2f[] combinedcurve = new Vec2f[totalpoints];
int idx = 0;
for (Slider s : sliders) {
int len = s.getCurvePointsCount();
arraycopy(s.getCurvePoints(), 0, combinedcurve, idx, len);
idx += len;
}
knorkesliders = new FakeCombinedCurve(combinedcurve);
} }
} else { } else {
int base = 0; int startIndex = 0;
for (GameObject gameObject : gameObjects) { for (GameObject gameObject : gameObjects) {
if (gameObject.isSlider()) { if (gameObject.isSlider()) {
((Slider) gameObject).baseSliderFrom = base; final Slider s = (Slider) gameObject;
base += ((Slider) gameObject).getCurve().getCurvePoints().length; s.curveStartIndex = startIndex;
startIndex += s.getCurvePointsCount();
} }
} }
} }

View File

@ -50,7 +50,7 @@ public class OptionGroups {
OPTION_FALLBACK_SLIDERS, OPTION_FALLBACK_SLIDERS,
OPTION_SHRINKING_SLIDERS, OPTION_SHRINKING_SLIDERS,
OPTION_MERGING_SLIDERS, OPTION_MERGING_SLIDERS,
//OPTION_MERGING_SLIDERS_MIRROR_POOL, OPTION_MERGING_SLIDERS_MIRROR_POOL,
OPTION_DRAW_SLIDER_ENDCIRCLES, OPTION_DRAW_SLIDER_ENDCIRCLES,
}), }),
new OptionTab("DANCING HITCIRCLES", new Option[] { new OptionTab("DANCING HITCIRCLES", new Option[] {

View File

@ -496,7 +496,7 @@ public class Options {
} }
}; };
public static final NumericOption OPTION_MERGING_SLIDERS_MIRROR_POOL = new NumericOption("Merging sliders mirror pool", "MergingSliderMirrorPool", "Amount of mirrors to calculate for merging sliders (impacts performance)", 2, 1, 5) { public static final NumericOption OPTION_MERGING_SLIDERS_MIRROR_POOL = new NumericOption("Mirrors", "MergingSliderMirrorPool", "Amount of mirrors to calculate for merging sliders (impacts performance)", 2, 2, 6) {
@Override @Override
public String getValueString () { public String getValueString () {
return String.valueOf(val); return String.valueOf(val);