I'm trying to implement a 3D camera of the "Orbit around the origin" variety in a game engine I'm developing in order to learn about 3D graphics and game programming. I have a basic handle on the required math, and have implemented my own crude 3D math library and matrix stack (functionally similar to the one in OpenGL's compatibility profile). My first attempts at a camera failed miserably, until I decided that I should use quaternions to represent rotation. Once I'd done that, I had a camera that moved in the direction I expected it to at about the right speed and fairly smoothly, but there is an odd spatial distortion effect that I can't seem to get rid of. I have posted a brief video on YouTube showing exactly what is happening.
I honestly don't know what could be causing this issue, the magnitude of the distortion appears to reach a maximum at certain angles, but beyond that I'm not sure what I should be looking at. Right now my chief suspect is my quaternion math code, because the matrix stack appears to be behaving itself and if something was wrong with my matrix math code I would be having more serious issues than this.
I'm not sure what information or code I can provide that would be of any use, so I'll start with the code that handles quaternion math.
public class Quaternion {
private float w;
private float x;
private float y;
private float z;
public Quaternion(){
this(1.0f,0.0f,0.0f,0.0f);
}
public Quaternion(float W, float X, float Y, float Z){
w = W;
x = X;
y = Y;
z = Z;
}
public void loadIdentity(){
w = 1.0f;
x = 0.0f;
y = 0.0f;
z = 0.0f;
}
public float magnitude(){
//AKA the "norm"
return (float) Math.sqrt(w*w + x*x + y*y + z*z);
}
public void qNormalize(){
float mag = this.magnitude();
w /= mag;
x /= mag;
y /= mag;
z /= mag;
}
public void qMultiply(Quaternion q){
this.qMultiply(q.w, q.x, q.y, q.z);
}
private void qMultiply(float w2, float x2, float y2, float z2){
//Performs A*B, where this Quaternion is A
this.w = w*w2 - x*x2 - y*y2 - z*z2;
this.x = w*x2 + x*w2 + y*z2 - z*y2;
this.y = w*y2 + y*w2 + z*x2 - x*z2;
this.z = w*z2 + z*w2 + x*y2 - y*x2;
}
public float[] qMatrix(){
//Return a 4x4 matrix representation of this Quaternion, column-major like OpenGL prefers
float w2 = w*w;
float x2 = x*x;
float y2 = y*y;
float z2 = z*z;
if(Math.abs(w2+x2+y2+z2 - 1.0) >= 0.000001){
this.qNormalize();
return this.qMatrix();
}
return new float[]{
1.0f - 2.0f*y2 -2.0f*z2, 2.0f*x*y + 2.0f*w*z, 2.0f*x*z - 2.0f*w*y, 0.0f,
2.0f*x*y - 2.0f*w*z, 1.0f - 2.0f*x2 - 2.0f*z2, 2.0f*y*z + 2.0f*w*x,0.0f,
2.0f*x*z - 2.0f*w*y, 2.0f*y*z + 2.0f*w*x, 1.0f - 2.0f*x2 - 2.0f*y2,0.0f,
0.0f,0.0f,0.0f,1.0f
};
}
public void qFromAA(float angle, float[] axis){
//create a Quaternion from an axis-angle representation
if(Vector.magnitude(axis) == 0.0f){
this.loadIdentity();
return;
}
float theta = angle/2.0f;
axis = Vector.scale((float)Math.sin(theta), Vector.normalize(axis));
w = (float)Math.cos(theta);
x = axis[0];
y = axis[1];
z = axis[2];
}
public String toString(){
return "w: "+w+"\tx: "+x+"\ty: "+y+"\tz: "+z+"\tmag: "+(x*x+y*y+z*z+w*w);
}
}
Any ideas about where I should start?
Answer
Are you sure your code for quaternion multiplication and your code for quaternion matrix converion is correct?
I had a typo in one of my formulas once that cost me nearly half a day.
btw... http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/index.htm is a great reference for quaternion math.
No comments:
Post a Comment