package box2dLight;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.StringBuilder;
public class Spinor {
float real;
float complex;
private static final float COSINE_THRESHOLD = 0.001f;
public Spinor() {
}
public Spinor(float angle) {
set(angle);
}
public Spinor(Spinor copyFrom) {
set(copyFrom);
}
public Spinor(float real, float complex) {
set(real, complex);
}
public Spinor set(float angle) {
angle /= 2;
set((float) Math.cos(angle), (float) Math.sin(angle));
return this;
}
public Spinor set(Spinor copyFrom) {
set(copyFrom.real, copyFrom.complex);
return this;
}
public Spinor set(float real, float complex) {
this.real = real;
this.complex = complex;
return this;
}
public Spinor scale(float t) {
real *= t;
complex *= t;
return this;
}
public Spinor invert() {
complex = -complex;
scale(len2());
return this;
}
public Spinor add(Spinor other) {
real += other.real;
complex += other.complex;
return this;
}
public Spinor add(float angle) {
angle /= 2;
real += Math.cos(angle);
complex += Math.sin(angle);
return this;
}
public Spinor sub(Spinor other) {
real -= other.real;
complex -= other.complex;
return this;
}
public Spinor sub(float angle) {
angle /= 2;
real -= Math.cos(angle);
complex -= Math.sin(angle);
return this;
}
public float len() {
return (float) Math.sqrt(real * real + complex * complex);
}
public float len2() {
return real * real + complex * complex;
}
public Spinor mul(Spinor other) {
set(real * other.real - complex * other.complex, real * other.complex
+ complex * other.real);
return this;
}
public Spinor nor() {
float length = len();
real /= length;
complex /= length;
return this;
}
public float angle() {
return (float) Math.atan2(complex, real) * 2;
}
public Spinor lerp(Spinor end, float alpha, Spinor tmp) {
scale(1 - alpha);
tmp.set(end).scale(alpha);
add(tmp);
nor();
return this;
}
public Spinor slerp(Spinor dest, float t) {
float tr, tc, omega, cosom, sinom, scale0, scale1;
// cosine
cosom = real * dest.real + complex * dest.complex;
// adjust signs
if (cosom < 0) {
cosom = -cosom;
tc = -dest.complex;
tr = -dest.real;
} else {
tc = dest.complex;
tr = dest.real;
}
// coefficients
if (1f - cosom > COSINE_THRESHOLD) {
omega = (float) Math.acos(cosom);
sinom = (float) Math.sin(omega);
scale0 = (float) Math.sin((1f - t) * omega) / sinom;
scale1 = (float) Math.sin(t * omega) / sinom;
} else {
scale0 = 1f - t;
scale1 = t;
}
// final calculation
complex = scale0 * complex + scale1 * tc;
real = scale0 * real + scale1 * tr;
return this;
}
@Override public String toString() {
StringBuilder result = new StringBuilder();
float radians = angle();
result.append("radians: ");
result.append(radians);
result.append(", degrees: ");
result.append(radians * MathUtils.radiansToDegrees);
return result.toString();
}
}