Specify whether Curve uses scaled or unscaled coordinates.
Unscaled coordinates will be used in a future commit (hopefully). Added a normalize() method to Vec2f. Throw RuntimeExceptions for any Curve initialization errors; the game would crash anyway, and this way the objects can be substituted for DummyObjects for a graceful failure. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
6c956e927f
commit
d360b73bf5
|
@ -18,13 +18,10 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu.objects.curves;
|
package itdelatrisu.opsu.objects.curves;
|
||||||
|
|
||||||
import itdelatrisu.opsu.ErrorHandler;
|
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import org.newdawn.slick.SlickException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of Catmull Curve with equidistant points.
|
* Representation of Catmull Curve with equidistant points.
|
||||||
*
|
*
|
||||||
|
@ -36,7 +33,16 @@ public class CatmullCurve extends EqualDistanceMultiCurve {
|
||||||
* @param hitObject the associated HitObject
|
* @param hitObject the associated HitObject
|
||||||
*/
|
*/
|
||||||
public CatmullCurve(HitObject hitObject) {
|
public CatmullCurve(HitObject hitObject) {
|
||||||
super(hitObject);
|
this(hitObject, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param hitObject the associated HitObject
|
||||||
|
* @param scaled whether to use scaled coordinates
|
||||||
|
*/
|
||||||
|
public CatmullCurve(HitObject hitObject, boolean scaled) {
|
||||||
|
super(hitObject, scaled);
|
||||||
LinkedList<CurveType> catmulls = new LinkedList<CurveType>();
|
LinkedList<CurveType> catmulls = new LinkedList<CurveType>();
|
||||||
int ncontrolPoints = hitObject.getSliderX().length + 1;
|
int ncontrolPoints = hitObject.getSliderX().length + 1;
|
||||||
LinkedList<Vec2f> points = new LinkedList<Vec2f>(); // temporary list of points to separate different curves
|
LinkedList<Vec2f> points = new LinkedList<Vec2f>(); // temporary list of points to separate different curves
|
||||||
|
@ -51,24 +57,15 @@ public class CatmullCurve extends EqualDistanceMultiCurve {
|
||||||
for (int i = 0; i < ncontrolPoints; i++) {
|
for (int i = 0; i < ncontrolPoints; i++) {
|
||||||
points.addLast(new Vec2f(getX(i), getY(i)));
|
points.addLast(new Vec2f(getX(i), getY(i)));
|
||||||
if (points.size() >= 4) {
|
if (points.size() >= 4) {
|
||||||
try {
|
catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0])));
|
||||||
catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0])));
|
|
||||||
} catch (SlickException e) {
|
|
||||||
ErrorHandler.error(null, e, true);
|
|
||||||
}
|
|
||||||
points.removeFirst();
|
points.removeFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getX(ncontrolPoints - 1) != getX(ncontrolPoints - 2) ||
|
if (getX(ncontrolPoints - 1) != getX(ncontrolPoints - 2) ||
|
||||||
getY(ncontrolPoints - 1) != getY(ncontrolPoints - 2))
|
getY(ncontrolPoints - 1) != getY(ncontrolPoints - 2))
|
||||||
points.addLast(new Vec2f(getX(ncontrolPoints - 1), getY(ncontrolPoints - 1)));
|
points.addLast(new Vec2f(getX(ncontrolPoints - 1), getY(ncontrolPoints - 1)));
|
||||||
if (points.size() >= 4) {
|
if (points.size() >= 4)
|
||||||
try {
|
catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0])));
|
||||||
catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0])));
|
|
||||||
} catch (SlickException e) {
|
|
||||||
ErrorHandler.error(null, e, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init(catmulls);
|
init(catmulls);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu.objects.curves;
|
package itdelatrisu.opsu.objects.curves;
|
||||||
|
|
||||||
import org.newdawn.slick.SlickException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a Centripetal Catmull–Rom spline.
|
* Representation of a Centripetal Catmull–Rom spline.
|
||||||
* (Currently not technically Centripetal Catmull–Rom.)
|
* (Currently not technically Centripetal Catmull–Rom.)
|
||||||
|
@ -37,11 +35,10 @@ public class CentripetalCatmullRom extends CurveType {
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param points the control points of the curve
|
* @param points the control points of the curve
|
||||||
* @throws SlickException
|
|
||||||
*/
|
*/
|
||||||
protected CentripetalCatmullRom(Vec2f[] points) throws SlickException {
|
protected CentripetalCatmullRom(Vec2f[] points) {
|
||||||
if (points.length != 4)
|
if (points.length != 4)
|
||||||
throw new SlickException(String.format("Need exactly 4 points to initialize CentripetalCatmullRom, %d provided.", points.length));
|
throw new RuntimeException(String.format("Need exactly 4 points to initialize CentripetalCatmullRom, %d provided.", points.length));
|
||||||
|
|
||||||
this.points = points;
|
this.points = points;
|
||||||
time = new float[4];
|
time = new float[4];
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu.objects.curves;
|
package itdelatrisu.opsu.objects.curves;
|
||||||
|
|
||||||
import itdelatrisu.opsu.ErrorHandler;
|
|
||||||
import itdelatrisu.opsu.Utils;
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
|
|
||||||
|
@ -54,7 +53,16 @@ public class CircumscribedCircle extends Curve {
|
||||||
* @param hitObject the associated HitObject
|
* @param hitObject the associated HitObject
|
||||||
*/
|
*/
|
||||||
public CircumscribedCircle(HitObject hitObject) {
|
public CircumscribedCircle(HitObject hitObject) {
|
||||||
super(hitObject);
|
this(hitObject, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param hitObject the associated HitObject
|
||||||
|
* @param scaled whether to use scaled coordinates
|
||||||
|
*/
|
||||||
|
public CircumscribedCircle(HitObject hitObject, boolean scaled) {
|
||||||
|
super(hitObject, scaled);
|
||||||
|
|
||||||
// construct the three points
|
// construct the three points
|
||||||
this.start = new Vec2f(getX(0), getY(0));
|
this.start = new Vec2f(getX(0), getY(0));
|
||||||
|
@ -68,8 +76,6 @@ public class CircumscribedCircle extends Curve {
|
||||||
Vec2f norb = mid.cpy().sub(end).nor();
|
Vec2f norb = mid.cpy().sub(end).nor();
|
||||||
|
|
||||||
this.circleCenter = intersect(mida, nora, midb, norb);
|
this.circleCenter = intersect(mida, nora, midb, norb);
|
||||||
if (circleCenter == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// find the angles relative to the circle center
|
// find the angles relative to the circle center
|
||||||
Vec2f startAngPoint = start.cpy().sub(circleCenter);
|
Vec2f startAngPoint = start.cpy().sub(circleCenter);
|
||||||
|
@ -90,13 +96,8 @@ public class CircumscribedCircle extends Curve {
|
||||||
startAng -= TWO_PI;
|
startAng -= TWO_PI;
|
||||||
else if (Math.abs(startAng - (endAng - TWO_PI)) < TWO_PI && isIn(startAng, midAng, endAng - (TWO_PI)))
|
else if (Math.abs(startAng - (endAng - TWO_PI)) < TWO_PI && isIn(startAng, midAng, endAng - (TWO_PI)))
|
||||||
endAng -= TWO_PI;
|
endAng -= TWO_PI;
|
||||||
else {
|
else
|
||||||
ErrorHandler.error(
|
throw new RuntimeException(String.format("Cannot find angles between midAng (%.3f %.3f %.3f).", startAng, midAng, endAng));
|
||||||
String.format("Cannot find angles between midAng (%.3f %.3f %.3f).",
|
|
||||||
startAng, midAng, endAng), null, true
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// find an angle with an arc length of pixelLength along this circle
|
// find an angle with an arc length of pixelLength along this circle
|
||||||
|
@ -149,10 +150,8 @@ public class CircumscribedCircle extends Curve {
|
||||||
//u = ((b.y-a.y)ta.x +(a.x-b.x)ta.y) / (tb.x*ta.y - tb.y*ta.x);
|
//u = ((b.y-a.y)ta.x +(a.x-b.x)ta.y) / (tb.x*ta.y - tb.y*ta.x);
|
||||||
|
|
||||||
float des = tb.x * ta.y - tb.y * ta.x;
|
float des = tb.x * ta.y - tb.y * ta.x;
|
||||||
if (Math.abs(des) < 0.00001f) {
|
if (Math.abs(des) < 0.00001f)
|
||||||
ErrorHandler.error("Vectors are parallel.", null, true);
|
throw new RuntimeException("Vectors are parallel.");
|
||||||
return null;
|
|
||||||
}
|
|
||||||
float u = ((b.y - a.y) * ta.x + (a.x - b.x) * ta.y) / des;
|
float u = ((b.y - a.y) * ta.x + (a.x - b.x) * ta.y) / des;
|
||||||
return b.cpy().add(tb.x * u, tb.y * u);
|
return b.cpy().add(tb.x * u, tb.y * u);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,13 +64,21 @@ public abstract class Curve {
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param hitObject the associated HitObject
|
* @param hitObject the associated HitObject
|
||||||
|
* @param scaled whether to use scaled coordinates
|
||||||
*/
|
*/
|
||||||
protected Curve(HitObject hitObject) {
|
protected Curve(HitObject hitObject, boolean scaled) {
|
||||||
this.hitObject = hitObject;
|
this.hitObject = hitObject;
|
||||||
this.x = hitObject.getScaledX();
|
if (scaled) {
|
||||||
this.y = hitObject.getScaledY();
|
this.x = hitObject.getScaledX();
|
||||||
this.sliderX = hitObject.getScaledSliderX();
|
this.y = hitObject.getScaledY();
|
||||||
this.sliderY = hitObject.getScaledSliderY();
|
this.sliderX = hitObject.getScaledSliderX();
|
||||||
|
this.sliderY = hitObject.getScaledSliderY();
|
||||||
|
} else {
|
||||||
|
this.x = hitObject.getX();
|
||||||
|
this.y = hitObject.getY();
|
||||||
|
this.sliderX = hitObject.getSliderX();
|
||||||
|
this.sliderY = hitObject.getSliderY();
|
||||||
|
}
|
||||||
this.renderState = null;
|
this.renderState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,16 @@ public abstract class EqualDistanceMultiCurve extends Curve {
|
||||||
* @param hitObject the associated HitObject
|
* @param hitObject the associated HitObject
|
||||||
*/
|
*/
|
||||||
public EqualDistanceMultiCurve(HitObject hitObject) {
|
public EqualDistanceMultiCurve(HitObject hitObject) {
|
||||||
super(hitObject);
|
this(hitObject, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param hitObject the associated HitObject
|
||||||
|
* @param scaled whether to use scaled coordinates
|
||||||
|
*/
|
||||||
|
public EqualDistanceMultiCurve(HitObject hitObject, boolean scaled) {
|
||||||
|
super(hitObject, scaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,7 +35,17 @@ public class LinearBezier extends EqualDistanceMultiCurve {
|
||||||
* @param line whether a new curve should be generated for each sequential pair
|
* @param line whether a new curve should be generated for each sequential pair
|
||||||
*/
|
*/
|
||||||
public LinearBezier(HitObject hitObject, boolean line) {
|
public LinearBezier(HitObject hitObject, boolean line) {
|
||||||
super(hitObject);
|
this(hitObject, line, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param hitObject the associated HitObject
|
||||||
|
* @param line whether a new curve should be generated for each sequential pair
|
||||||
|
* @param scaled whether to use scaled coordinates
|
||||||
|
*/
|
||||||
|
public LinearBezier(HitObject hitObject, boolean line, boolean scaled) {
|
||||||
|
super(hitObject, scaled);
|
||||||
|
|
||||||
LinkedList<CurveType> beziers = new LinkedList<CurveType>();
|
LinkedList<CurveType> beziers = new LinkedList<CurveType>();
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,17 @@ public class Vec2f {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns this vector into a unit vector.
|
||||||
|
* @return itself (for chaining)
|
||||||
|
*/
|
||||||
|
public Vec2f normalize() {
|
||||||
|
float len = len();
|
||||||
|
x /= len;
|
||||||
|
y /= len;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of this vector.
|
* Returns a copy of this vector.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user