import javax.vecmath.Quat4f;
import javax.vecmath.Quat4d;
import javax.vecmath.Tuple4f;
import javax.vecmath.Tuple4d;

final public class MyQuat4f extends Quat4f {

  public MyQuat4f() {
    super();
  }
  public MyQuat4f(float[] v) {
    x = v[0];
    y = v[1];
    z = v[2];
    w = v[3];
  }
  public MyQuat4f(float fx, float fy, float fz, float fw) {
    x = fx;
    y = fy;
    z = fz;
    w =fw;
  }

  public MyQuat4f(Quat4f q) {
    x = q.x;
    y = q.y;
    z = q.z;
    w = q.w;
  }

  public MyQuat4f(Quat4d q) {
    x = (float) q.x;
    y = (float) q.y;
    z = (float) q.z;
    w = (float) q.w;
  }

  public MyQuat4f(Tuple4f t) {
    x = t.x;
    y = t.y;
    z = t.z;
    w = t.w;
  }

  public MyQuat4f(Tuple4d t) {
    x = (float) t.x;
    y = (float) t.y;
    z = (float) t.z;
    w = (float) t.w;
  }

  /**
   * Multiply the quaternion with the Vector v as though the vector were a 
   * quaternion with its scalar component equal to zero
   */
  public void mul(MyVector3f v) {
    float x1 = w * v.x + y * v.z - z * v.y;
    float y1 = w * v.y + z * v.x - x * v.z;
    float z1 = w * v.z + x * v.y - y * v.x;
    w = -(x * v.x + y * v.y + z * v.z);
    x = x1; y = y1; z = z1;
  }

  /**
   * Multiply the Quaternion q, with the Vector v as though the vector were a 
   * quaternion with its scalar component equal to zero
   */
  public void mul(MyQuat4f q, MyVector3f v) {
    x = q.w * v.x + q.y * v.z - q.z * v.y;
    y = q.w * v.y + q.z * v.x - q.x * v.z;
    z = q.w * v.z + q.x * v.y - q.y * v.x;
    w = -(q.x * v.x + q.y * v.y + q.z * v.z);
  }


  /**
   * Multiply the a quaternion with the Vector v as though the vector were a 
   * quaternion with its scalar component equal to zero
   */
  public void mul(MyVector3f v, MyQuat4f q) {
    x = q.w * v.x + q.z * v.y - q.y * v.z;
    y = q.w * v.y + q.x * v.z - q.z * v.x; 
    z = q.w * v.z + q.y * v.x - q.x * v.y;
    w = -(q.x * v.x + q.y * v.y + q.z * v.z);
  }

  /**
   * Return the x,y,z values of the quaternion as a Vector
   */
  public MyVector3f getVector() {
    return new MyVector3f(x, y, z);
  }

  /**
   * Use the quaternion to rotate the Vector v, and return the result
   */
  public MyVector3f rotatePoint(MyVector3f v) {

    MyMatrix3f m = new MyMatrix3f(
			( 2.0f * ((w * w - 0.5f)  + (x * x))),
			( 2.0f * ((x * y)        + (w * z))),
			( 2.0f * ((x * z)        - (w * y))),

			( 2.0f * ((x * y)        - (w * z))),
			( 2.0f * ((w * w - 0.5f)  + (y * y))),
			( 2.0f * ((y * z)        + (w * x))),

			( 2.0f * ((x * z)        + (w * y))),
			( 2.0f * ((y * z)        - (w * x))),
			( 2.0f * ((w * w - 0.5f)  + (z * z)))
				 );
    return m.mul(v);
  }

  /**
   * Use the quaternion to rotate the Vector v, and return the result
   */
  public MyVector3f rotatePoint2(MyVector3f v) {
    MyQuat4f tmp = new MyQuat4f();
    MyQuat4f conj = new MyQuat4f();
    conj.conjugate(this);

    tmp.mul(this, v);
    tmp.mul(conj);
   
    return tmp.getVector();
  }

}
