We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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); }
Answers
https://forum.processing.org/two/discussion/15473/readme-how-to-format-code-and-text#latest
Please format your code as per the link above -- forum members can't read your code or run it to test without formatting, so it is difficult to help you.
Did you google quaternions on this forum?
Chrisir
The Shapes3D library uses quarternions to perform 3D rotations. The main class is called
Rot
which is effectively a quarterian by another name and is a port from the Apache maths project. This class provides many constructors for creatingRot
objects which can be used for rotating PVector objects.