Using Quaternions to do a 3D rotation

Hello,

I started a media computer science class at my university a year ago. One part of the class is math. To be confirmed for the next test I have to make a small project in processing. I barley have any code skills and I am pretty desperate right now. I don't want you to do the whole work for me, but as I said i am quite bad at coding..

My docent wants me to show a small 3D roation in processing using Quaternions. We never had Quaternions in math before and its not a topic for the following test. I've read a lot about Quaternions in the internet so far. To be honest, I only understand around 10% of it haha.

I tried to google A LOT how to do a 3D roation with Quaternions in processing. Actually I found a class written for Quaternions with a method "rotate". (Class will be posted below). I've tried to "show" the rotation in the draw method, but i failed.

Using the cursor to show the rotation is one of the best solutions. At least thats what I think. Do you have any tipps how to solve this problem? Maybe one of you programmed such a code before?

Thank you for your time!

The Quaternion class:

public class Quaternion { public float W, X, Y, Z; // components of a quaternion

// default constructor public Quaternion() { W = 0.0; X = 0.0; Y = 0.0; Z = 0.0; }

// initialized constructor

public Quaternion(float w, float x, float y, float z) { W = w; X = x; Y = y; Z = z; }

// quaternion multiplication public Quaternion mult (Quaternion q) { float w = Wq.W - (Xq.X + Yq.Y + Zq.Z);

float x = W*q.X + q.W*X + Y*q.Z - Z*q.Y;
float y = W*q.Y + q.W*Y + Z*q.X - X*q.Z;
float z = W*q.Z + q.W*Z + X*q.Y - Y*q.X;

W = w;
X = x;
Y = y;
Z = z;
return this;

}

// conjugates the quaternion public Quaternion conjugate () { W = W; X = -X; Y = -Y; Z = -Z; return this; }

// inverts the quaternion public Quaternion reciprical () { float norme = sqrt(WW + XX + YY + ZZ); if (norme == 0.0) norme = 1.0;

float recip = 1.0 / norme;

W =  W * recip;
X = -X * recip;
Y = -Y * recip;
Z = -Z * recip;

return this;

}

// sets to unit quaternion public Quaternion normalize() { float norme = sqrt(WW + XX + YY + ZZ); if (norme == 0.0) { W = 1.0; X = Y = Z = 0.0; } else { float recip = 1.0/norme;

  W *= recip;
  X *= recip;
  Y *= recip;
  Z *= recip;
}
return this;

}

// Makes quaternion from axis public Quaternion fromAxis(float Angle, float x, float y, float z) { float omega, s, c; int i;

s = sqrt(x*x + y*y + z*z);

if (abs(s) > Float.MIN_VALUE)
{
  c = 1.0/s;

  x *= c;
  y *= c;
  z *= c;

  omega = -0.5f * Angle;
  s = (float)sin(omega);

  X = s*x;
  Y = s*y;
  Z = s*z;
  W = (float)cos(omega);
}
else
{
  X = Y = 0.0f;
  Z = 0.0f;
  W = 1.0f;
}
normalize();
return this;

}

public Quaternion fromAxis(float Angle, PVector axis) { return this.fromAxis(Angle, axis.x, axis.y, axis.z); }

// Rotates towards other quaternion public void slerp(Quaternion a, Quaternion b, float t) { float omega, cosom, sinom, sclp, sclq; int i;

cosom = a.X*b.X + a.Y*b.Y + a.Z*b.Z + a.W*b.W;


if ((1.0f+cosom) > Float.MIN_VALUE)
{
  if ((1.0f-cosom) > Float.MIN_VALUE)
  {
    omega = acos(cosom);
    sinom = sin(omega);
    sclp = sin((1.0f-t)*omega) / sinom;
    sclq = sin(t*omega) / sinom;
  }
  else
  {
    sclp = 1.0f - t;
    sclq = t;
  }

  X = sclp*a.X + sclq*b.X;
  Y = sclp*a.Y + sclq*b.Y;
  Z = sclp*a.Z + sclq*b.Z;
  W = sclp*a.W + sclq*b.W;
}
else
{
  X =-a.Y;
  Y = a.X;
  Z =-a.W;
  W = a.Z;

  sclp = sin((1.0f-t) * PI * 0.5);
  sclq = sin(t * PI * 0.5);

  X = sclp*a.X + sclq*b.X;
  Y = sclp*a.Y + sclq*b.Y;
  Z = sclp*a.Z + sclq*b.Z;
}

}

public Quaternion exp() {
float Mul; float Length = sqrt(XX + YY + Z*Z);

if (Length > 1.0e-4)
  Mul = sin(Length)/Length;
else
  Mul = 1.0;

W = cos(Length);

X *= Mul;
Y *= Mul;
Z *= Mul; 

return this;

}

public Quaternion log() { float Length;

Length = sqrt(X*X + Y*Y + Z*Z);
Length = atan(Length/W);

W = 0.0;

X *= Length;
Y *= Length;
Z *= Length;

return this;

} };

//Example of rotating PVector about a directional PVector //PVector rotate(PVector v, PVector r, float a) { // Quaternion Q1 = new Quaternion(0, v.x, v.y, v.z); // Quaternion Q2 = new Quaternion(cos(a / 2), r.x * sin(a / 2), r.y * sin(a / 2), r.z * sin(a / 2)); // //Quaternion Q3 = Q2.mult(Q1).mult(Q2.conjugate()); // Quaternion Q4 = Q2.mult(Q1); // Quaternion Q5 = Q4.mult(Q2.conjugate()); // f= new PVector(Q5.X, Q5.Y, Q5.Z); // return f; // //return new PVector(Q3.X, Q3.Y, Q3.Z); //}

Quaternion rotate(float x, float y, float z, float a, float b, float c, float j) { Quaternion p = new Quaternion(0, x,y,z); Quaternion q = new Quaternion(cos(j / 2), a * sin(a / 2), b * sin(a / 2), c * sin(a / 2)); Quaternion Q3 = Q2.mult(Q1).mult(Q2.conjugate());

//return new PVector(Q3.X, Q3.Y, Q3.Z); }

void drawAxes() {

line(-80, 0, 0, 80, 0, 0); text("+x", 85, 0, 0); //text("-x", -330, 0, 0); stroke(0, 255, 0); line(0, -80, 0, 0, 80, 0); text("+y", 0, -85, 0); //text("-y", 0, -300, 0); stroke(0, 0, 255); line(0, 0, -80, 0, 0, 80); text("+z", 0, 0, 85); //text("-z", 0, 0, -300); }

Tagged:

Answers

Sign In or Register to comment.