#include <math.h>
#include <assert.h>
#include <stdio.h>
struct vector3_t
{
float x, y, z;
};
struct matrix3_t
{
union
{
struct
{
float _11, _12, _13;
float _21, _22, _23;
float _31, _32, _33;
};
float m[3][3];
};
};
void matrix_multiply(struct matrix3_t *out, const struct matrix3_t *m1, const struct matrix3_t *m2)
{
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
out->m[i][j] =
m1->m[i][0]*m2->m[0][j] +
m1->m[i][1]*m2->m[1][j] +
m1->m[i][2]*m2->m[2][j];
}
}
}
void from_euler_angles_xyz(struct matrix3_t *out, const struct vector3_t *euler)
{
float fcos, fsin;
float yaw, pitch, roll;
struct matrix3_t xm, ym, zm, tmp;
yaw = euler->x;
pitch = euler->y;
roll = euler->z;
fcos = cosf(yaw);
fsin = sinf(yaw);
xm._11 = 1.0f; xm._12 = 0.0f, xm._13 = 0.0f;
xm._21 = 0.0f; xm._22 = fcos, xm._23 = -fsin;
xm._31 = 0.0f; xm._32 = fsin, xm._33 = fcos;
fcos = cosf(pitch);
fsin = sinf(pitch);
ym._11 = fcos; ym._12 = 0.0f, ym._13 = fsin;
ym._21 = 0.0f; ym._22 = 1.0f, ym._23 = 0.0f;
ym._31 = -fsin; ym._32 = 0.0f, ym._33 = fcos;
fcos = cosf(roll);
fsin = sinf(roll);
zm._11 = fcos; zm._12 = -fsin, zm._13 = 0.0f;
zm._21 = fsin; zm._22 = fcos, zm._23 = 0.0f;
zm._31 = 0.0f; zm._32 = 0.0f, zm._33 = 1.0f;
matrix_multiply(&tmp, &ym, &zm);
matrix_multiply(out, &xm, &tmp);
}
void vector_transform(struct vector3_t *out, const struct vector3_t *v, const struct matrix3_t *rm)
{
int i;
float *ptr;
ptr = (float*) &out->x;
for (i = 0; i < 3; i++) {
ptr[i] =
v->x * rm->m[0][i] +
v->y * rm->m[1][i] +
v->z * rm->m[2][i];
}
}
int main(void)
{
struct vector3_t source;
struct vector3_t euler;
struct vector3_t result;
struct matrix3_t rotations;
source.x = 1.0f;
source.y = 1.0f;
source.z = 1.0f;
euler.x = 3.1415f;
euler.y = 0.0f;
euler.z = 0.0f;
from_euler_angles_xyz(&rotations, &euler);
vector_transform(&result, &source, &rotations);
printf("rotated vector is: x=%f, y=%f, z=%f\n", result.
x, result.
y, result.
z);
return 0;
}
I2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCnN0cnVjdCB2ZWN0b3IzX3QKewoJZmxvYXQgeCwgeSwgejsKfTsKCnN0cnVjdCBtYXRyaXgzX3QKewoJdW5pb24KCXsKCQlzdHJ1Y3QKCQl7CgkJCWZsb2F0CV8xMSwgXzEyLCBfMTM7CgkJCWZsb2F0CV8yMSwgXzIyLCBfMjM7CgkJCWZsb2F0CV8zMSwgXzMyLCBfMzM7CgkJfTsKCgkJZmxvYXQJbVszXVszXTsKCX07Cn07Cgp2b2lkIG1hdHJpeF9tdWx0aXBseShzdHJ1Y3QgbWF0cml4M190ICpvdXQsIGNvbnN0IHN0cnVjdCBtYXRyaXgzX3QgKm0xLCBjb25zdCBzdHJ1Y3QgbWF0cml4M190ICptMikKewoJaW50IGksIGo7CgoJYXNzZXJ0KG91dCk7Cglhc3NlcnQobTEpOwoJYXNzZXJ0KG0yKTsKCglmb3IgKGkgPSAwOyBpIDwgMzsgaSsrKSB7CgkgICAgZm9yIChqID0gMDsgaiA8IDM7IGorKykgewoJICAgICAgICBvdXQtPm1baV1bal0gPSAKCSAgICAgICAgICAgIG0xLT5tW2ldWzBdKm0yLT5tWzBdW2pdICsKCSAgICAgICAgICAgIG0xLT5tW2ldWzFdKm0yLT5tWzFdW2pdICsKCSAgICAgICAgICAgIG0xLT5tW2ldWzJdKm0yLT5tWzJdW2pdOwoJICAgIH0KCX0KCn0KCnZvaWQgZnJvbV9ldWxlcl9hbmdsZXNfeHl6KHN0cnVjdCBtYXRyaXgzX3QgKm91dCwgY29uc3Qgc3RydWN0IHZlY3RvcjNfdCAqZXVsZXIpCnsKCWZsb2F0IGZjb3MsIGZzaW47CglmbG9hdCB5YXcsIHBpdGNoLCByb2xsOwoJc3RydWN0IG1hdHJpeDNfdCB4bSwgeW0sIHptLCB0bXA7CgoJYXNzZXJ0KGV1bGVyKTsKCWFzc2VydChvdXQpOwoKCXlhdyA9IGV1bGVyLT54OwoJcGl0Y2ggPSBldWxlci0+eTsKCXJvbGwgPSBldWxlci0+ejsKCQoJZmNvcyA9IGNvc2YoeWF3KTsKCWZzaW4gPSBzaW5mKHlhdyk7CgoJeG0uXzExID0gMS4wZjsgeG0uXzEyID0gMC4wZiwgeG0uXzEzID0gMC4wZjsKCXhtLl8yMSA9IDAuMGY7IHhtLl8yMiA9IGZjb3MsIHhtLl8yMyA9IC1mc2luOwoJeG0uXzMxID0gMC4wZjsgeG0uXzMyID0gZnNpbiwgeG0uXzMzID0gZmNvczsKCQoJZmNvcyA9IGNvc2YocGl0Y2gpOwoJZnNpbiA9IHNpbmYocGl0Y2gpOwoKCXltLl8xMSA9IGZjb3M7IHltLl8xMiA9IDAuMGYsIHltLl8xMyA9IGZzaW47Cgl5bS5fMjEgPSAwLjBmOyB5bS5fMjIgPSAxLjBmLCB5bS5fMjMgPSAwLjBmOwoJeW0uXzMxID0gLWZzaW47IHltLl8zMiA9IDAuMGYsIHltLl8zMyA9IGZjb3M7CgoJZmNvcyA9IGNvc2Yocm9sbCk7Cglmc2luID0gc2luZihyb2xsKTsKCgl6bS5fMTEgPSBmY29zOyB6bS5fMTIgPSAtZnNpbiwgem0uXzEzID0gMC4wZjsKCXptLl8yMSA9IGZzaW47IHptLl8yMiA9IGZjb3MsIHptLl8yMyA9IDAuMGY7Cgl6bS5fMzEgPSAwLjBmOyB6bS5fMzIgPSAwLjBmLCB6bS5fMzMgPSAxLjBmOwoKCW1hdHJpeF9tdWx0aXBseSgmdG1wLCAmeW0sICZ6bSk7CgltYXRyaXhfbXVsdGlwbHkob3V0LCAmeG0sICZ0bXApOwp9Cgp2b2lkIHZlY3Rvcl90cmFuc2Zvcm0oc3RydWN0IHZlY3RvcjNfdCAqb3V0LCBjb25zdCBzdHJ1Y3QgdmVjdG9yM190ICp2LCBjb25zdCBzdHJ1Y3QgbWF0cml4M190ICpybSkKewoJaW50IGk7CglmbG9hdCAqcHRyOwoKCWFzc2VydChvdXQpOwoJYXNzZXJ0KHYpOwoJYXNzZXJ0KHJtKTsKCglwdHIgPSAoZmxvYXQqKSAmb3V0LT54OwoJZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewoJICAgIHB0cltpXSA9CgkgICAgICAgIHYtPnggKiBybS0+bVswXVtpXSArCgkgICAgICAgIHYtPnkgKiBybS0+bVsxXVtpXSArCgkgICAgICAgIHYtPnogKiBybS0+bVsyXVtpXTsKCX0KfQoKaW50IG1haW4odm9pZCkKewoJc3RydWN0IHZlY3RvcjNfdCBzb3VyY2U7CglzdHJ1Y3QgdmVjdG9yM190IGV1bGVyOwoJc3RydWN0IHZlY3RvcjNfdCByZXN1bHQ7CglzdHJ1Y3QgbWF0cml4M190IHJvdGF0aW9uczsKCglzb3VyY2UueCA9IDEuMGY7Cglzb3VyY2UueSA9IDEuMGY7Cglzb3VyY2UueiA9IDEuMGY7CgoJZXVsZXIueCA9IDMuMTQxNWY7CglldWxlci55ID0gMC4wZjsKCWV1bGVyLnogPSAwLjBmOwoKCWZyb21fZXVsZXJfYW5nbGVzX3h5eigmcm90YXRpb25zLCAmZXVsZXIpOwoJdmVjdG9yX3RyYW5zZm9ybSgmcmVzdWx0LCAmc291cmNlLCAmcm90YXRpb25zKTsKCglwcmludGYoInJvdGF0ZWQgdmVjdG9yIGlzOiB4PSVmLCB5PSVmLCB6PSVmXG4iLCByZXN1bHQueCwgcmVzdWx0LnksIHJlc3VsdC56KTsKCXB1dHMoInByZXNzIGVudGVyLi4uIik7CgoJZ2V0Y2hhcigpOwoKICAgIHJldHVybiAwOwp9