Note that I got myself all out of kilter in the order to fill my float buffer matrix. I have tried both ways as you can see by the commented out code without much difference except direction of rotation. Both ways experience the skewing.
Here is my Quarternion class.
Using java Syntax Highlighting
- package com.exit4.lavaball;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- import javax.microedition.khronos.opengles.GL10;
- public class Quarternion {
- public float w,x,y,z;
- public Quarternion ()
- {
- w = 1;
- x = 0;
- y = 0;
- z = 0;
- }
- // Note angle is in radians
- public Quarternion(float angle, float[] axis)
- {
- set(angle,axis);
- }
- // Note that angle is in radians
- public void set (float angle, float[] axis)
- {
- w = (float) Math.cos(angle/2);
- float temp = (float) Math.sin(angle/2);
- x = axis[0] * temp;
- y = axis[1] * temp;
- z = axis[2] * temp;
- }
- public float magnitude()
- {
- float mag = (float) Math.sqrt(w*w + x*x + y*y + z*z);
- return mag;
- }
- public void normalize()
- {
- float mag = magnitude();
- w = w/mag;
- x = x/mag;
- y = y/mag;
- z = z/mag;
- }
- // multiplication is in the order other*this with result stored in
- // this.
- public void multiply(Quarternion other)
- {
- float tw,tx,ty,tz;
- tw = other.w*w - other.x*x - other.y*y - other.z*z;
- tx = other.w*x + other.x*w + other.y*z - other.z*y;
- ty = other.w*y - other.x*z + other.y*w + other.z*x;
- tz = other.w*z + other.x*y - other.y*x + other.z*w;
- w = tw;
- x = tx;
- y = ty;
- z = tz;
- }
- float[] M = null;
- public void fill_matrix()
- {
- if (M == null)
- M = new float[16];
- /*/ Column one
- M[0] = 1 - 2*y*y - 2*z*z;
- M[4] = 2*x*y + 2*w*z;
- M[8] = 2*x*z - 2*w*y;
- M[12] = 0.0f;
- // Column two
- M[1] = 2*x*y - 2*w*z;
- M[5] = 1 - 2*x*x - 2*z*z;
- M[9] = 2*y*z - 2*w*x;
- M[13] = 0.0f;
- // Column three
- M[2] = 2*x*z + 2*w*y;
- M[6] = 2*y*z - 2*w*x;
- M[10] = 1 - 2*x*x - 2*y*y;
- M[14] = 0;
- // Column four
- M[3] = 0;
- M[7] = 0;
- M[11] = 0;
- M[15] = 1;
- */
- // Column one
- M[0] = 1 - 2*y*y - 2*z*z;
- M[1] = 2*x*y + 2*w*z;
- M[2] = 2*x*z - 2*w*y;
- M[3] = 0.0f;
- // Column two
- M[4] = 2*x*y - 2*w*z;
- M[5] = 1 - 2*x*x - 2*z*z;
- M[6] = 2*y*z - 2*w*x;
- M[7] = 0.0f;
- // Column three
- M[8] = 2*x*z + 2*w*y;
- M[9] = 2*y*z - 2*w*x;
- M[10] = 1 - 2*x*x - 2*y*y;
- M[11] = 0;
- // Column four
- M[12] = 0;
- M[13] = 0;
- M[14] = 0;
- M[15] = 1;
- }
- public void glRotate(GL10 gl)
- {
- fill_matrix();
- FloatBuffer buf = makeFloatBuffer(M);
- gl.glMultMatrixf(buf);
- }
- protected static FloatBuffer makeFloatBuffer(float[] arr)
- {
- ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
- bb.order(ByteOrder.nativeOrder());
- FloatBuffer fb = bb.asFloatBuffer();
- fb.put(arr);
- fb.position(0);
- return fb;
- }
- }
Parsed in 0.041 seconds, using GeSHi 1.0.8.4
Here is an example of adding some new rotation to the Quarternion for the ball.
Using java Syntax Highlighting
- Quarternion q = new Quarternion();
- Quarternion tq = new Quarternion();
- float[] rtemp = new float[3];
- public void adjust_rotation(float[] vector)
- {
- if (grounded_rotation)
- {
- // rotation axis is the cross of the grounded plane normal
- // and the vector of movement
- rtemp = vector3d.normalize(vector);
- axis = vector3d.cross_product(gnormal,rtemp);
- }
- // amount of rotation is the length of the vector
- rangle = vector3d.length(vector)*2;
- tq.set(rangle, axis);
- q.multiply(tq);
- // Note that I don't actually normalize here.
- // I just added this to this example to show that I am normalizing elsewhere.
- // I am normalizing after all frame rotations are multiplied together.
- q.normalize();
- }
Parsed in 0.032 seconds, using GeSHi 1.0.8.4
This is where I do the matrix translations when drawing the ball.
Using java Syntax Highlighting
- public void draw(GL10 gl)
- {
- gl.glPushMatrix();
- gl.glTranslatef(position[0],position[1],position[2]);
- q.glRotate(gl);
- this.mesh.draw(gl);
- gl.glPopMatrix();
- }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4
Any help or suggestions would be greatly appreciated!
I should note that I think I have ruled out problems in my quarternion multiply because I get the same skewing if
I just use a fixed quarternion rather than my accumulated one. Also, I have checked my quarternion to matrix formulas so many times it hurts against two sources. They look right. And, as I mentioned, I have filled my matrix both ways. Just for kicks, I tried rotating by the quarternion before the translation. As expected, this rotated around the world origin which is not right of course. I am missing something fundamental I fear.
Thanks,
Seed



