yeah, right...
the matrix array goes from 0 to 15 for both (DX and OGL)...
how they are interpreted internally is irrelevant, 0-3 is either a row or a column, but it's always the same (0-3) in the array !!!
LH or RH doesn't matter at the moment...
if the result rotates the wrong direction I simply have to negate the angle...
I ported your code and the needed methods from Irrlicht to Java...
but I still can't get it to work !!!
it gives strange non-linear rotations on some axes... :O
it works perfectly in Irrlicht !!!
this are the ported Irrlicht methods:
Code: Select all
void setRotationAxisDegrees(float[] M, float angle, Vector3d axis ){
double angle_rad = Math.toRadians(angle);
double c = Math.cos(angle_rad);
double s = Math.sin(angle_rad);
double t = 1.0 - c;
double tx = t * axis.x;
double ty = t * axis.y;
double tz = t * axis.z;
double sx = s * axis.x;
double sy = s * axis.y;
double sz = s * axis.z;
M[0] = (float) (tx * axis.x + c);
M[1] = (float) (tx * axis.y + sz);
M[2] = (float) (tx * axis.z - sy);
M[4] = (float) (ty * axis.x - sz);
M[5] = (float) (ty * axis.y + c);
M[6] = (float) (ty * axis.z + sx);
M[8] = (float) (tz * axis.x + sy);
M[9] = (float) (tz * axis.y - sx);
M[10] = (float) (tz * axis.z + c);
}
void rotateVect(float[] M, Vector3d vect){
Vector3d tmp = new Vector3d(vect);
vect.x = tmp.x * M[0] + tmp.y * M[4] + tmp.z * M[8];
vect.y = tmp.x * M[1] + tmp.y * M[5] + tmp.z * M[9];
vect.z = tmp.x * M[2] + tmp.y * M[6] + tmp.z * M[10];
}
void setRotationDegrees(float[] M, Vector3d rotation){
double radX = Math.toRadians(rotation.x);
double radY = Math.toRadians(rotation.y);
double radZ = Math.toRadians(rotation.z);
double cr = Math.cos(radX);
double sr = Math.sin(radX);
double cp = Math.cos(radY);
double sp = Math.sin(radY);
double cy = Math.cos(radZ);
double sy = Math.sin(radZ);
double srsp = sr * sp;
double crsp = cr * sp;
M[0] = (float)(cp * cy);
M[1] = (float)(cp * sy);
M[2] = (float)(-sp);
M[4] = (float)(srsp * cy - cr * sy);
M[5] = (float)(srsp * sy + cr * cy);
M[6] = (float)(sr * cp);
M[8] = (float)(crsp * cy + sr * sy);
M[9] = (float)(crsp * sy - sr * cy);
M[10] = (float)(cr * cp);
}
Vector3d getScale(float[] M){
// Deal with the 0 rotation case first
if( (M[1] == 0) && (M[2] == 0) &&
(M[4] == 0) && (M[6] == 0) &&
(M[8] == 0) && (M[9] == 0))
return new Vector3d(M[0], M[5], M[10]);
// We have to do the full calculation.
return new Vector3d((float)Math.sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
(float)Math.sqrt(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
(float)Math.sqrt(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
}
float clamp(float value, float low, float high) {
return Math.min(Math.max(value,low), high);
}
Vector3d getRotationDegrees(float[] M){
Vector3d scale = getScale(M);
// we need to check for negative scale on to axes, which would bring up wrong results
if (scale.y < 0 && scale.z < 0) {
scale.y = -scale.y;
scale.z = -scale.z;
}
else if (scale.x < 0 && scale.z < 0) {
scale.x = -scale.x;
scale.z = -scale.z;
}
else if (scale.x<0 && scale.y<0) {
scale.x = -scale.x;
scale.y = -scale.y;
}
Vector3d invScale = new Vector3d((1f / scale.x), (1f / scale.y), (1f / scale.z));
double Y = -Math.asin(clamp(M[2] * invScale.x, -1.f, 1.f));
double C = Math.cos(Y);
Y = Math.toDegrees(Y);
double rotx, roty, X, Z;
if (C != 0){
double invC = 1f / C;
rotx = M[10] * invC * invScale.z;
roty = M[6] * invC * invScale.y;
X = Math.toDegrees(Math.atan2( roty, rotx ));
rotx = M[0] * invC * invScale.x;
roty = M[1] * invC * invScale.x;
Z = Math.toDegrees(Math.atan2( roty, rotx ));
} else {
X = 0.0;
rotx = M[5] * invScale.y;
roty = -M[4] * invScale.y;
Z = Math.toDegrees(Math.atan2( roty, rotx ));
}
// fix values that get below zero
if (X < 0.0) X += 360.0;
if (Y < 0.0) Y += 360.0;
if (Z < 0.0) Z += 360.0;
return new Vector3d((float)X, (float)Y, (float)Z);
}
and this is your code from the other thread:
Code: Select all
public void spinAxes(float x, float y, float z) {
float[] transformation = new float[16];
float[] matRotX = new float[16];
float[] matRotY = new float[16];
float[] matRotZ = new float[16];
Matrix.setIdentityM(transformation, 0);
Matrix.setIdentityM(matRotX, 0);
Matrix.setIdentityM(matRotY, 0);
Matrix.setIdentityM(matRotZ, 0);
setRotationDegrees(transformation, Rotation);
Vector3d axisX = new Vector3d(1,0,0);
Vector3d axisY = new Vector3d(0,1,0);
Vector3d axisZ = new Vector3d(0,0,1);
rotateVect(transformation, axisX);
rotateVect(transformation, axisY);
rotateVect(transformation, axisZ);
setRotationAxisDegrees(matRotX, x, axisX);
setRotationAxisDegrees(matRotY, y, axisY);
setRotationAxisDegrees(matRotZ, z, axisZ);
float[] newTransform = new float[16];
Matrix.setIdentityM(newTransform, 0);
// not sure about the order here, I tried different orders...
Matrix.multiplyMM(newTransform, 0, newTransform, 0, transformation, 0);
Matrix.multiplyMM(newTransform, 0, newTransform, 0, matRotZ, 0);
Matrix.multiplyMM(newTransform, 0, newTransform, 0, matRotY, 0);
Matrix.multiplyMM(newTransform, 0, newTransform, 0, matRotX, 0);
Rotation = getRotationDegrees(newTransform);
}