Quat4f and rotation around local axis

I assume there is a better way to do what I want to do.
I haven’t problem with rotation cube around axis unfortunately global axis.
When I want to make the rotation around local axis I just remember central point of my cube then move cube to position x=0, y=0, z=0 and I start rotation.
After rotation I move cube back to saved position.
Is there any way to do it without moving cobe?
This is my code responsible for rotation.


private static float angle = 4;
	private Quat4f roll = new Quat4f();
	private Quat4f quantBase = new Quat4f();
	private AxisAngle4f angle4f = new AxisAngle4f();
	private void update(boolean rotX, boolean rotY, boolean rotZ){
		if(rotX){
			angle4f.set(new Vector3f(1, 0, 0), angle * (float) (Math.PI / 180));
		} if(rotY) {
			angle4f.set(new Vector3f(0, 1, 0), angle * (float) (Math.PI / 180));
		} if(rotZ) {
			angle4f.set(new Vector3f(0, 0, 1), angle * (float) (Math.PI / 180));
		}
		roll.set(angle4f);
		
		for(int i = 0;i<array.length;i+=3) {
			quantBase.x = array[i];
			quantBase.y = array[i+1];
			quantBase.z = array[i+2];
			quantBase.w = 0f;
			quantBase.mul(roll, quantBase);
			if(rotX) {
				array[i+1] = quantBase.y;
				array[i+2] = quantBase.z;
			}
			if(rotY) {
				array[i] = quantBase.x;
				array[i+2] = quantBase.z;
			}
			if(rotZ) {
				array[i] = quantBase.x;
				array[i+1] = quantBase.y;
			}
		}
		 vertexData.put(array);
	     vertexData.flip();
	}

For clarity, this is how I understand the local and global axis.

http://img805.imageshack.us/img805/8876/picaxis.png

If you’re going to transform more than a couple of points, you want to convert to a matrix. see here: http://www.java-gaming.org/topics/skeletal-animation/25483/view.html

I did it in this way
When i press key to rotate my cube I call this method which only remember central point cube.


float localX = 0;
float localY = 0;
float localZ = 0;
private void setPosition(){
	float lX = 0;
	float lY = 0;
	float lZ = 0;
	for(int i = 0;i<array.length;i+=3) {
		lX+=array[i];
		lY+=array[i+1];
		lZ+=array[i+2];
		localX=lX/24;
		localY=lY/24;
		localZ=lZ/24;
	}
	System.out.println("x: "+localX+" y: "+localY+" z: "+localZ );
}

and then start the rotation


private Vector4f vBase = new Vector4f();
private Vector4f angle = new Vector4f();
private void update(boolean rotX, boolean rotY, boolean rotZ){
	if (rotX) {
		angle = rotationX(angle, DEGTORAD);
	}
	if (rotY) {
		angle = rotationY(angle, DEGTORAD);
	}
	if (rotZ) {
		angle = rotationZ(angle, DEGTORAD);
	}
	
	for(int i = 0;i<array.length;i+=3) {
		vBase.x = array[i];
		vBase.y = array[i+1];
		vBase.z = array[i+2];
		vBase.w = (DEGTORAD);
		
		Vector4f vFin = new Vector4f();
		
		vBase.x -= localX;
		vBase.y -= localY;
		vBase.z -= localZ;
		mul(vFin, angle, vBase);
		vFin.x +=localX;
		vFin.y +=localY;
		vFin.z +=localZ;
		
		if(rotX) {
			array[i+1] = vFin.y;
			array[i+2] = vFin.z;
		}
		if(rotY) {
			array[i] = vFin.x;
			array[i+2] = vFin.z;
		}
		if(rotZ) {
			array[i] = vFin.x;
			array[i+1] = vFin.y;
		}
	}
	 vertexData.put(array);
	 vertexData.flip();
}

private Vector4f rotationX(Vector4f q, float a){
	System.out.println("-- rotationX --");
	a *= 0.5f;
	float sinA = (float) Math.sin(a);
	float cosA = (float) Math.cos(a);
	q.set(sinA, 0, 0, cosA);
	return q;
}

private Vector4f rotationY(Vector4f q, float a){
	System.out.println("-- rotationY --");
	a *= 0.5f;
	float sinA = (float) Math.sin(a);
	float cosA = (float) Math.cos(a);
	q.set(0.0f, sinA, 0.0f, cosA);
	return q;
}

private Vector4f rotationZ(Vector4f q, float a){
	System.out.println("-- rotationZ --");
	a *= 0.5f;
	float sinA = (float) Math.sin(a);
	float cosA = (float) Math.cos(a);
	q.set(0.0f, 0.0f, sinA, cosA);
	return q;
}

void mul(Vector4f out, Vector4f q1, Vector4f q2) {
	System.out.println("-- mul --");
	out.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
	out.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z;
	out.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x;
	out.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
}

All this works quite well.
But now I want to something more I want to change size but not all cube only width or height or thickness and I want to do this
on rotated cube.
I know I must to do something like this
Px’ = S1 * Px
but it is not enough beacause from this

http://img707.imageshack.us/img707/9752/porot.png

I’m geting this

http://img849.imageshack.us/img849/1831/pic1ox.png

Scaling works only on not rotated cube. I assume that I need to add a multiplication by the angle but I am not store information about angle.
Can you give me some advice?

Try to apply this:


    public static void mul(Vector4f q, Vector3f vCoord, Vector3f scale, Vector3f result) {
        Matrix3f m1 = new Matrix3f();

        setFromQuat(q.getX(), q.getY(), q.getZ(), q.getW(), m1);

        Matrix3f tmp = new Matrix3f();

        tmp.setIdentity();
        tmp.m00(scale.getX());
        tmp.m11(scale.getY());
        tmp.m22(scale.getZ());

        m1.mul(tmp);

        transform(m1, vCoord, result);
    }

    private static void setFromQuat(float a, float b, float c, float d, Matrix3f m) {
        final float n = a * a + b * b + c * c + d * d;
        final float s = (n > 0.0f) ? (2.0f / n) : 0.0f;

        final float xs = a * s, ys = b * s, zs = c * s;
        final float wx = d * xs, wy = d * ys, wz = d * zs;
        final float xx = a * xs, xy = a * ys, xz = a * zs;
        final float yy = b * ys, yz = b * zs, zz = c * zs;

        m.m00(1.0f - (yy + zz));
        m.m01(xy - wz);
        m.m02(xz + wy);
        m.m10(xy + wz);
        m.m11(1.0f - (xx + zz));
        m.m12(yz - wx);
        m.m20(xz - wy);
        m.m21(yz + wx);
        m.m22(1.0f - (xx + yy));
    }

    private static void transform(Matrix3f m, Vector3f t3f, Vector3f result) {
        result.set(m.m00() * t3f.getX() + m.m01() * t3f.getY() + m.m02() * t3f.getZ(),
                m.m10() * t3f.getX() + m.m11() * t3f.getY() + m.m12() * t3f.getZ(),
                m.m20() * t3f.getX() + m.m21() * t3f.getY() + m.m22() * t3f.getZ()
        );
    }

It’s a draft solution. Unfortunately, I can’t test it now, so hopefully it will work with a little changes.