I've created a very simple form of a Cubic Bézier in Java in order to retrieve the Y value of the point retrieved given the time (t). In my implementation My first (P1) and last (P4) points are always (0, 0) and (1, 1) respectively, and I'm only going to be manipulating P1 and P2. The purpose of this is to create a modifiable curve used to retrieve a value that will be used to multiply and manipulate other values, like a difficulty ramp in video games.
I've tested my implementation using P2=(0.1, 0.1) and P3=(0.9,0.9), so the curve should effectively be a straight line, and whatever my input value (t) is, the output should mimic:
Here is my CubicBezier class:
@AllArgsConstructor
public class CubicBezier {
private static final Point P1 = new Point(0, 0);
private static final Point P4 = new Point(1, 1);
private Point p2;
private Point p3;
public double getValue(double t) {
double dt = 1d - t;
double dt2 = dt*dt;
double t2 = t*t;
Point temp = p2.copy();
return P1.copy()
.scale(dt2 * dt)
.add(temp.scale(3 * dt2 * t))
.add(temp.set(p3).scale(3 * dt * t2))
.add(temp.set(P4).scale(t2 * t))
.getY();
}
}
And my Point class:
@Data
@AllArgsConstructor
public class Point {
private double x;
private double y;
public Point(Point point) {
this.x = point.x;
this.y = point.y;
}
public Point copy() {
return new Point(this);
}
public Point set(Point point) {
this.x = point.x;
this.y = point.y;
return this;
}
public Point add(double scalar) {
this.x += scalar;
this.y += scalar;
return this;
}
public Point add(double x, double y) {
this.x += x;
this.y += y;
return this;
}
public Point add(Point point) {
return add(point.x, point.y);
}
public Point scale(double scalar) {
this.x *= scalar;
this.y *= scalar;
return this;
}
public Point scale(double x, double y) {
this.x *= x;
this.y *= y;
return this;
}
public Point scale(Point point) {
return scale(point.x, point.y);
}
}
My main method:
public static void main(String[] args) {
CubicBezier bezier = new CubicBezier(new Point(0.1d, 0.1d), new Point(0.9d, 0.9d));
double value = 0.4;
System.out.println(value + ": " + bezier.getValue(value));
}
Expected output should be:
0.4: 0.4
However, the output I receive is:
0.4: 0.36640000000000006
And I can't understand why. My getValue
method is modelled using the Cubic Bézier explicit form specified on Wikipedia. Am I missing something?
Note: I'm using Lombok to remove some boilerplate. I can specify this boilerplate if necessary.
EDIT:
So it appears that my bezier curve is actually working as it should, and that I've been mistaking t
as a value on the x
axis, assuming that the y
value of the calculated bezier curve will be in relation to the x
axis. The functionality I want is that, with the resulting curve, given a value x
, return the y
value in relation. So in the screenshot above, where the curve is a straight line, x
should equal y
.