53323279c7
Still need to configure the build
213 lines
5.3 KiB
Java
213 lines
5.3 KiB
Java
package universalelectricity.core.vector;
|
|
|
|
/**
|
|
* Quaternion class designed to be used for the rotation of objects.
|
|
*
|
|
* Do not use in MC 1.6.4, subject to change!
|
|
*
|
|
* @author DarkGuardsman, Calclavia
|
|
*/
|
|
public class Quaternion implements Cloneable
|
|
{
|
|
public static final float TOLERANCE = 0.00001f;
|
|
public double x, y, z, w;
|
|
|
|
public Quaternion()
|
|
{
|
|
this(0, 0, 0, 1);
|
|
}
|
|
|
|
public Quaternion(Quaternion copy)
|
|
{
|
|
this(copy.x, copy.y, copy.z, copy.w);
|
|
}
|
|
|
|
public Quaternion(double x, double y, double z, double w)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w;
|
|
}
|
|
|
|
/**
|
|
* Convert from Euler Angles. Basically we create 3 Quaternions, one for pitch, one for yaw, one
|
|
* for roll and multiply those together. the calculation below does the same, just shorter
|
|
*/
|
|
public Quaternion(float pitch, float yaw, float roll)
|
|
{
|
|
float p = (float) (pitch * (Math.PI / 180) / 2.0);
|
|
float y = (float) (yaw * (Math.PI / 180) / 2.0);
|
|
float r = (float) (roll * (Math.PI / 180) / 2.0);
|
|
|
|
float sinp = (float) Math.sin(p);
|
|
float siny = (float) Math.sin(y);
|
|
float sinr = (float) Math.sin(r);
|
|
float cosp = (float) Math.cos(p);
|
|
float cosy = (float) Math.cos(y);
|
|
float cosr = (float) Math.cos(r);
|
|
|
|
this.x = sinr * cosp * cosy - cosr * sinp * siny;
|
|
this.y = cosr * sinp * cosy + sinr * cosp * siny;
|
|
this.z = cosr * cosp * siny - sinr * sinp * cosy;
|
|
this.w = cosr * cosp * cosy + sinr * sinp * siny;
|
|
|
|
this.normalize();
|
|
}
|
|
|
|
public Quaternion(Vector3 vector, double w)
|
|
{
|
|
this(vector.x, vector.y, vector.z, w);
|
|
}
|
|
|
|
public static Quaternion IDENTITY()
|
|
{
|
|
return new Quaternion();
|
|
}
|
|
|
|
public Quaternion set(Quaternion quaternion)
|
|
{
|
|
this.w = quaternion.w;
|
|
this.x = quaternion.x;
|
|
this.y = quaternion.y;
|
|
this.z = quaternion.z;
|
|
return this;
|
|
}
|
|
|
|
public Quaternion set(double x, double y, double z, double w)
|
|
{
|
|
return this.set(new Quaternion(x, y, z, w));
|
|
}
|
|
|
|
public Quaternion normalize()
|
|
{
|
|
double magnitude = this.magnitude();
|
|
this.x /= magnitude;
|
|
this.y /= magnitude;
|
|
this.z /= magnitude;
|
|
this.w /= magnitude;
|
|
return this;
|
|
}
|
|
|
|
public double magnitude()
|
|
{
|
|
return Math.sqrt(this.magnitudeSquared());
|
|
}
|
|
|
|
public double magnitudeSquared()
|
|
{
|
|
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
}
|
|
|
|
public Quaternion inverse()
|
|
{
|
|
double d = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
return new Quaternion(this.x / d, -this.y / d, -this.z / d, -this.w / d);
|
|
}
|
|
|
|
/**
|
|
* Gets the conjugate of this Quaternion
|
|
*/
|
|
public Quaternion getConjugate()
|
|
{
|
|
return this.clone().conjugate();
|
|
}
|
|
|
|
public Quaternion conjugate()
|
|
{
|
|
this.y = -this.y;
|
|
this.z = -this.z;
|
|
this.w = -this.w;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Let the current quaternion be "a". Multiplying the a with b applies the rotation a to b.
|
|
*/
|
|
public Quaternion getMultiply(Quaternion b)
|
|
{
|
|
return this.clone().multiply(b);
|
|
}
|
|
|
|
public Quaternion multiply(Quaternion b)
|
|
{
|
|
Quaternion a = this;
|
|
double newX = a.x * b.x - a.y * b.y - a.z * b.z - a.w * b.w;
|
|
double newY = a.x * b.y + a.y * b.x + a.z * b.w - a.w * b.z;
|
|
double newZ = a.x * b.z - a.y * b.w + a.z * b.x + a.w * b.y;
|
|
double newW = a.x * b.w + a.y * b.z - a.z * b.y + a.w * b.x;
|
|
this.set(newX, newY, newZ, newW);
|
|
return this;
|
|
}
|
|
|
|
public Quaternion divide(Quaternion b)
|
|
{
|
|
Quaternion a = this;
|
|
return a.inverse().multiply(b);
|
|
}
|
|
|
|
/** Multi a vector against this in other words applying rotation */
|
|
public Vector3 multi(Vector3 vec)
|
|
{
|
|
Vector3 vn = vec.clone();
|
|
|
|
Quaternion vecQuat = new Quaternion(0, 0, 0, 1), resQuat;
|
|
vecQuat.x = (float) vn.x;
|
|
vecQuat.y = (float) vn.y;
|
|
vecQuat.z = (float) vn.z;
|
|
vecQuat.w = 0.0f;
|
|
|
|
resQuat = vecQuat.multiply(this.getConjugate());
|
|
resQuat = this.multiply(resQuat);
|
|
|
|
return new Vector3(resQuat.x, resQuat.y, resQuat.z);
|
|
}
|
|
|
|
public static Quaternion fromAxis(Vector3 vector, double angle)
|
|
{
|
|
angle *= 0.5f;
|
|
Vector3 vn = vector.clone().normalize();
|
|
float sinAngle = (float) Math.sin(angle);
|
|
return new Quaternion(vn.x * sinAngle, vn.y * sinAngle, vn.z * sinAngle, Math.cos(angle));
|
|
}
|
|
|
|
/*
|
|
* Convert to Matrix public Matrix4 getMatrix() { float x2 = (float) (x * x); float y2 = (float)
|
|
* (y * y); float z2 = (float) (z * z); float xy = (float) (x * y); float xz = (float) (x * z);
|
|
* float yz = (float) (y * z); float wx = (float) (w * x); float wy = (float) (w * y); float wz
|
|
* = (float) (w * z);
|
|
*
|
|
* // This calculation would be a lot more complicated for non-unit length quaternions // Note:
|
|
* The constructor of Matrix4 expects the Matrix in column-major format like expected // by //
|
|
* OpenGL return new Matrix4(1.0f - 2.0f * (y2 + z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f,
|
|
* 2.0f * (xy + wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f, 2.0f * (xz - wy), 2.0f *
|
|
* (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); }
|
|
*/
|
|
|
|
/**
|
|
* Convert to Axis/Angles
|
|
*
|
|
* @param axis - The axis of rotation
|
|
* @param angle - The angle of rotation
|
|
*/
|
|
public void getAxisAngle(Vector3 axis, float angle)
|
|
{
|
|
float scale = (float) axis.getMagnitude();
|
|
this.x = this.x / scale;
|
|
this.y = this.y / scale;
|
|
this.z = this.z / scale;
|
|
angle = (float) (Math.acos(this.w) * 2.0f);
|
|
}
|
|
|
|
@Override
|
|
public Quaternion clone()
|
|
{
|
|
return new Quaternion(this);
|
|
}
|
|
|
|
@Override
|
|
public String toString()
|
|
{
|
|
return "Quaternion [" + x + ", " + y + ", " + z + ", " + w + "]";
|
|
}
|
|
}
|