From: John Tsiombikas Date: Sat, 29 Sep 2018 02:40:38 +0000 (+0300) Subject: spaceball X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=o2demo;a=commitdiff_plain;h=4b32bd7bc643379bd4a63c5714cec68c32a0c3c1 spaceball --- diff --git a/src/demo.c b/src/demo.c index 5af3c86..2e444cf 100644 --- a/src/demo.c +++ b/src/demo.c @@ -2,13 +2,20 @@ #include #include #include +#include #include #include #include "demo.h" #include "screen.h" #include "cfgopt.h" +static void recalc_sball_matrix(float *xform, float *inv_xform); + static int console_active; +static int sball_update_pending; + +static float pos[3]; +static float rot[4] = {0, 0, 0, 1}; int demo_init(int argc, char **argv) { @@ -28,6 +35,9 @@ int demo_init(int argc, char **argv) glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); + sball_matrix[0] = sball_matrix[5] = sball_matrix[10] = sball_matrix[15] = 1.0f; + sball_inv_matrix[0] = sball_inv_matrix[5] = sball_inv_matrix[10] = sball_inv_matrix[15] = 1.0f; + if(scr_init() == -1) { return -1; } @@ -52,6 +62,11 @@ void demo_cleanup(void) void demo_draw(void) { + if(sball_update_pending) { + recalc_sball_matrix(sball_matrix, sball_inv_matrix); + sball_update_pending = 0; + } + scr_update(); scr_draw(); } @@ -165,3 +180,121 @@ void demo_mbutton(int bn, int pressed, int x, int y) void demo_mmotion(int x, int y) { } + + +static void quat_rotate(float *qres, const float *q, float angle, float x, float y, float z); +static void quat_mul(float *qres, const float *q1, const float *q2); +static void quat_to_mat(float *res, const float *q); + +void demo_sball_motion(int x, int y, int z) +{ + pos[0] += (float)x * 0.01; + pos[1] += (float)y * 0.01; + pos[2] -= (float)z * 0.01; + sball_update_pending = 1; +} + +void demo_sball_rotate(int x, int y, int z) +{ + float rx = (float)x; + float ry = (float)y; + float rz = (float)z; + float axis_len = sqrt(rx * rx + ry * ry + rz * rz); + if(axis_len > 0.0) { + quat_rotate(rot, rot, axis_len * 0.001, -rx / axis_len, + -ry / axis_len, rz / axis_len); + } + sball_update_pending = 1; +} + +void demo_sball_button(int bn, int pressed) +{ + if(!pressed) return; + + switch(bn) { + case 0: + pos[0] = pos[1] = pos[2] = 0; + rot[0] = rot[1] = rot[2] = 0; + rot[3] = 1; + break; + + default: + break; + } +} + +static void recalc_sball_matrix(float *xform, float *inv_xform) +{ + float tx, ty, tz; + + quat_to_mat(xform, rot); + xform[12] = pos[0]; + xform[13] = pos[1]; + xform[14] = pos[2]; + + inv_xform[0] = xform[0]; + inv_xform[5] = xform[5]; + inv_xform[10] = xform[10]; + inv_xform[15] = 1.0f; + + inv_xform[1] = xform[4]; + inv_xform[2] = xform[8]; + inv_xform[6] = xform[9]; + inv_xform[4] = xform[1]; + inv_xform[8] = xform[2]; + inv_xform[9] = xform[6]; + + inv_xform[3] = inv_xform[7] = inv_xform[11] = 0.0f; + tx = -pos[0]; + ty = -pos[1]; + tz = -pos[2]; + + inv_xform[12] = tx * inv_xform[0] + ty * inv_xform[4] + tz * inv_xform[8]; + inv_xform[13] = tx * inv_xform[1] + ty * inv_xform[5] + tz * inv_xform[9]; + inv_xform[14] = tx * inv_xform[2] + ty * inv_xform[6] + tz * inv_xform[10]; +} + +static void quat_rotate(float *qres, const float *q, float angle, float x, float y, float z) +{ + float rq[4]; + float half_angle = angle * 0.5f; + float sin_half = sin(half_angle); + + rq[3] = cos(half_angle); + rq[0] = x * sin_half; + rq[1] = y * sin_half; + rq[2] = z * sin_half; + + quat_mul(qres, q, rq); +} + +static void quat_mul(float *qres, const float *q1, const float *q2) +{ + float w = q1[3] * q2[3] - (q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2]); + float x = q2[0] * q1[3] + q1[0] * q2[3] + (q1[1] * q2[2] - q1[2] * q2[1]); + float y = q2[1] * q1[3] + q1[1] * q2[3] + (q1[2] * q2[0] - q1[0] * q2[2]); + float z = q2[2] * q1[3] + q1[2] * q2[3] + (q1[0] * q2[1] - q1[1] * q2[0]); + qres[0] = x; + qres[1] = y; + qres[2] = z; + qres[3] = w; +} + +static void quat_to_mat(float *res, const float *q) +{ + res[0] = 1.0f - 2.0f * q[1]*q[1] - 2.0f * q[2]*q[2]; + res[1] = 2.0f * q[0] * q[1] - 2.0f * q[3] * q[2]; + res[2] = 2.0f * q[2] * q[0] + 2.0f * q[3] * q[1]; + res[3] = 0.0f; + res[4] = 2.0f * q[0] * q[1] + 2.0f * q[3] * q[2]; + res[5] = 1.0f - 2.0f * q[0]*q[0] - 2.0f * q[2]*q[2]; + res[6] = 2.0f * q[1] * q[2] - 2.0f * q[3] * q[0]; + res[7] = 0.0f; + res[8] = 2.0f * q[2] * q[0] - 2.0f * q[3] * q[1]; + res[9] = 2.0f * q[1] * q[2] + 2.0f * q[3] * q[0]; + res[10] = 1.0f - 2.0f * q[0]*q[0] - 2.0f * q[1]*q[1]; + res[11] = 0.0f; + res[12] = res[13] = res[14] = 0.0f; + res[15] = 1.0f; +} + diff --git a/src/demo.h b/src/demo.h index 6d12d65..3bb190a 100644 --- a/src/demo.h +++ b/src/demo.h @@ -5,6 +5,8 @@ int win_width, win_height; float win_aspect; unsigned int time_msec; +float sball_matrix[16], sball_inv_matrix[16]; + int demo_init(int argc, char **argv); void demo_cleanup(void); @@ -15,6 +17,10 @@ void demo_keyboard(int key, int pressed); void demo_mbutton(int bn, int pressed, int x, int y); void demo_mmotion(int x, int y); +void demo_sball_motion(int x, int y, int z); +void demo_sball_rotate(int x, int y, int z); +void demo_sball_button(int bn, int pressed); + /* defined in main.c */ void demo_quit(void); unsigned int get_msec(void); diff --git a/src/main.c b/src/main.c index 433993d..97d7469 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ static void keydown(unsigned char c, int x, int y); static void keyup(unsigned char c, int x, int y); static void mouse(int bn, int st, int x, int y); static void motion(int x, int y); +static void sball_button(int bn, int pressed); static unsigned int start_time; @@ -29,6 +30,9 @@ int main(int argc, char **argv) glutKeyboardUpFunc(keyup); glutMouseFunc(mouse); glutMotionFunc(motion); + glutSpaceballMotionFunc(demo_sball_motion); + glutSpaceballRotateFunc(demo_sball_rotate); + glutSpaceballButtonFunc(sball_button); if(demo_init(argc, argv) == -1) { return 1; @@ -96,3 +100,8 @@ static void motion(int x, int y) { demo_mmotion(x, y); } + +static void sball_button(int bn, int pressed) +{ + demo_sball_button(bn - 1, pressed == GLUT_DOWN ? 1 : 0); +} diff --git a/src/parts/example.c b/src/parts/example.c index fbfdf7d..d52f20f 100644 --- a/src/parts/example.c +++ b/src/parts/example.c @@ -64,6 +64,7 @@ static void draw(void) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glMultMatrixf(sball_inv_matrix); glTranslatef(0, 0, -cam_dist); glRotatef(cam_phi, 1, 0, 0); glRotatef(cam_theta, 0, 1, 0);