From: John Tsiombikas Date: Tue, 11 Sep 2018 18:07:17 +0000 (+0300) Subject: added spaceball on linux X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=9ecf7c26db456b3cef34a7d6d79ffb164cad17c5 added spaceball on linux --- diff --git a/src/dos/main.c b/src/dos/main.c index 3ac7616..aed4e8a 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -90,7 +90,6 @@ int main(int argc, char **argv) } if(use_sball && sball_pending()) { sball_event ev; - printf("got sball event\n"); while(sball_getevent(&ev)) { handle_sball_event(&ev); } diff --git a/src/hairball.c b/src/hairball.c index 5140f99..49b5f78 100644 --- a/src/hairball.c +++ b/src/hairball.c @@ -7,6 +7,7 @@ #include "screen.h" #include "util.h" #include "cfgopt.h" +#include "mesh.h" #ifdef MSDOS @@ -15,10 +16,11 @@ void wait_vsync(void); #endif -#define NSPAWNPOS 128 +#define NSPAWNPOS 64 #define SPAWN_RATE 16.0f -#define GRAV (-6.0f) -#define HAIR_LENGTH 32 +//#define GRAV (-6.0f) +#define GRAV 0.0f +#define HAIR_LENGTH 20 struct particle { vec3_t pos; @@ -58,9 +60,12 @@ static struct screen scr = { static long start_time; -static vec3_t *spawnpos, *spawndir; +static float cam_theta, cam_phi = 15; +static float cam_dist = 8; +static vec3_t *spawnpos, *spawndir; static struct hairball hball; +static struct g3d_mesh sphmesh; struct screen *hairball_screen(void) { @@ -71,6 +76,8 @@ static int init(void) { int i; + gen_sphere_mesh(&sphmesh, 1.0f, 12, 6); + hball.xform[0] = hball.xform[5] = hball.xform[10] = hball.xform[15] = 1.0f; hball.rot.w = 1.0f; @@ -114,19 +121,24 @@ static void update(void) prev_mx = mouse_x; prev_my = mouse_y; - if(mouse_bmask) { - hball.pos.x += mouse_dx * 0.05; - hball.pos.y -= mouse_dy * 0.05; - } - //hball.rot = quat_rotate(hball.rot, dt * 2.0f, 0, 1, 0); + if(opt.sball) { + memcpy(hball.xform, sball_matrix, 16 * sizeof(float)); + } else { + if(mouse_bmask & MOUSE_BN_MIDDLE) { + hball.pos.x += mouse_dx * 0.05; + hball.pos.y -= mouse_dy * 0.05; + } - quat_to_mat(hball.xform, hball.rot); - hball.xform[12] = hball.pos.x; - hball.xform[13] = hball.pos.y; - hball.xform[14] = hball.pos.z; + quat_to_mat(hball.xform, hball.rot); + hball.xform[12] = hball.pos.x; + hball.xform[13] = hball.pos.y; + hball.xform[14] = hball.pos.z; + } update_hairball(&hball, dt); + + mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); } static void draw(void) @@ -140,7 +152,9 @@ static void draw(void) g3d_matrix_mode(G3D_MODELVIEW); g3d_load_identity(); - g3d_translate(0, 0, -8); + g3d_translate(0, 0, -cam_dist); + g3d_rotate(cam_phi, 1, 0, 0); + g3d_rotate(cam_theta, 0, 1, 0); draw_hairball(&hball); @@ -211,18 +225,44 @@ static void update_hairball(struct hairball *hb, float dt) static void draw_hairball(struct hairball *hb) { - int i, j, col; + int i, col; struct particle *p; vec3_t prevpos; + vec3_t start[NSPAWNPOS]; + + for(i=0; ixform[0] * spawnpos[i].x + hb->xform[4] * spawnpos[i].y + hb->xform[8] * spawnpos[i].z + hb->xform[12]; + start[i].y = hb->xform[1] * spawnpos[i].x + hb->xform[5] * spawnpos[i].y + hb->xform[9] * spawnpos[i].z + hb->xform[13]; + start[i].z = hb->xform[2] * spawnpos[i].x + hb->xform[6] * spawnpos[i].y + hb->xform[10] * spawnpos[i].z + hb->xform[14]; + } g3d_begin(G3D_LINES); for(i=0; i= hb->pos.z) continue; p = hb->plist[i]; - prevpos.x = hb->xform[0] * spawnpos[i].x + hb->xform[4] * spawnpos[i].y + hb->xform[8] * spawnpos[i].z + hb->xform[12]; - prevpos.y = hb->xform[1] * spawnpos[i].x + hb->xform[5] * spawnpos[i].y + hb->xform[9] * spawnpos[i].z + hb->xform[13]; - prevpos.z = hb->xform[2] * spawnpos[i].x + hb->xform[6] * spawnpos[i].y + hb->xform[10] * spawnpos[i].z + hb->xform[14]; + prevpos = start[i]; + while(p) { + g3d_color3b(p->r, p->g, p->b); + g3d_vertex(prevpos.x, prevpos.y, prevpos.z); + g3d_vertex(p->pos.x, p->pos.y, p->pos.z); + prevpos = p->pos; + p = p->next; + } + } + g3d_end(); - j = 0; + + g3d_push_matrix(); + g3d_mult_matrix(hb->xform); + zsort_mesh(&sphmesh); + draw_mesh(&sphmesh); + g3d_pop_matrix(); + + g3d_begin(G3D_LINES); + for(i=0; ipos.z) continue; + p = hb->plist[i]; + prevpos = start[i]; while(p) { g3d_color3b(p->r, p->g, p->b); g3d_vertex(prevpos.x, prevpos.y, prevpos.z); @@ -232,6 +272,7 @@ static void draw_hairball(struct hairball *hb) } } g3d_end(); + } diff --git a/src/mesh.c b/src/mesh.c index 40b1bb1..ce26e68 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -223,6 +223,79 @@ void normalize_mesh_normals(struct g3d_mesh *mesh) } } + +static void sphvec(float *res, float theta, float phi, float rad) +{ + theta = -theta; + res[0] = sin(theta) * sin(phi); + res[1] = cos(phi); + res[2] = cos(theta) * sin(phi); +} + +int gen_sphere_mesh(struct g3d_mesh *mesh, float rad, int usub, int vsub) +{ + int i, j; + int nfaces, uverts, vverts; + struct g3d_vertex *vptr; + uint16_t *iptr; + + mesh->prim = G3D_QUADS; + + if(usub < 4) usub = 4; + if(vsub < 2) vsub = 2; + + uverts = usub + 1; + vverts = vsub + 1; + + mesh->vcount = uverts * vverts; + nfaces = usub * vsub; + mesh->icount = nfaces * 4; + + if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) { + fprintf(stderr, "gen_sphere_mesh: failed to allocate vertex buffer (%d vertices)\n", mesh->vcount); + return -1; + } + if(!(mesh->iarr = malloc(mesh->icount * sizeof *mesh->iarr))) { + fprintf(stderr, "gen_sphere_mesh: failed to allocate index buffer (%d indices)\n", mesh->icount); + return -1; + } + vptr = mesh->varr; + iptr = mesh->iarr; + + for(i=0; ix, theta, phi, rad); + vptr->w = 1.0f; + + vptr->nx = vptr->x / rad; + vptr->ny = vptr->y / rad; + vptr->nz = vptr->z / rad; + vptr->u = u; + vptr->v = v; + vptr->r = chess ? 255 : 64; + vptr->g = 128; + vptr->b = chess ? 64 : 255; + ++vptr; + + if(i < usub && j < vsub) { + int idx = i * vverts + j; + *iptr++ = idx; + *iptr++ = idx + 1; + *iptr++ = idx + vverts + 1; + *iptr++ = idx + vverts; + } + } + } + return 0; +} + int gen_plane_mesh(struct g3d_mesh *m, float width, float height, int usub, int vsub) { int i, j; diff --git a/src/mesh.h b/src/mesh.h index eb0256d..e80c090 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -22,6 +22,7 @@ int indexify_mesh(struct g3d_mesh *mesh); void normalize_mesh_normals(struct g3d_mesh *mesh); +int gen_sphere_mesh(struct g3d_mesh *mesh, float rad, int usub, int vsub); int gen_plane_mesh(struct g3d_mesh *mesh, float width, float height, int usub, int vsub); int gen_cube_mesh(struct g3d_mesh *mesh, float sz, int sub); int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub); diff --git a/src/sdl/main.c b/src/sdl/main.c index e7e161e..b9ed604 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -1,15 +1,22 @@ #include #include +#include #include #include #include "demo.h" #include "tinyfps.h" #include "timer.h" #include "cfgopt.h" +#include "sball.h" +#include "vmath.h" static void handle_event(SDL_Event *ev); static void toggle_fullscreen(void); +static int handle_sball_event(sball_event *ev); +static void recalc_sball_matrix(float *xform); + + static int quit; static SDL_Surface *fbsurf; @@ -17,6 +24,11 @@ static int fbscale = 2; static int xsz, ysz; static unsigned int sdl_flags = SDL_SWSURFACE; +static int use_sball; +static vec3_t pos = {0, 0, 0}; +static quat_t rot = {0, 0, 0, 1}; + + int main(int argc, char **argv) { int s, i, j; @@ -54,6 +66,11 @@ int main(int argc, char **argv) SDL_Quit(); return 1; } + + if(opt.sball && sball_init() == 0) { + use_sball = 1; + } + reset_timer(); while(!quit) { @@ -63,6 +80,15 @@ int main(int argc, char **argv) if(quit) goto break_evloop; } + if(use_sball) { + while(sball_pending()) { + sball_event ev; + sball_getevent(&ev); + handle_sball_event(&ev); + } + recalc_sball_matrix(sball_matrix); + } + time_msec = get_msec(); demo_draw(); drawFps(fb_pixels); @@ -185,3 +211,51 @@ static void toggle_fullscreen(void) fbsurf = newsurf; sdl_flags = newflags; } + + + +#define TX(ev) ((ev)->motion.motion[0]) +#define TY(ev) ((ev)->motion.motion[1]) +#define TZ(ev) ((ev)->motion.motion[2]) +#define RX(ev) ((ev)->motion.motion[3]) +#define RY(ev) ((ev)->motion.motion[4]) +#define RZ(ev) ((ev)->motion.motion[5]) + +static int handle_sball_event(sball_event *ev) +{ + switch(ev->type) { + case SBALL_EV_MOTION: + if(RX(ev) | RY(ev) | RZ(ev)) { + float rx = (float)RX(ev); + float ry = (float)RY(ev); + float rz = (float)RZ(ev); + float axis_len = sqrt(rx * rx + ry * ry + rz * rz); + if(axis_len > 0.0) { + rot = quat_rotate(rot, axis_len * 0.001, -rx / axis_len, + -ry / axis_len, -rz / axis_len); + } + } + + pos.x += TX(ev) * 0.001; + pos.y += TY(ev) * 0.001; + pos.z += TZ(ev) * 0.001; + break; + + case SBALL_EV_BUTTON: + if(ev->button.pressed) { + pos = v3_cons(0, 0, 0); + rot = quat_cons(1, 0, 0, 0); + } + break; + } + + return 0; +} + +void recalc_sball_matrix(float *xform) +{ + quat_to_mat(xform, rot); + xform[12] = pos.x; + xform[13] = pos.y; + xform[14] = pos.z; +} diff --git a/src/sdl/sball.c b/src/sdl/sball.c new file mode 100644 index 0000000..d19a97f --- /dev/null +++ b/src/sdl/sball.c @@ -0,0 +1,206 @@ +#include "sball.h" + +#ifdef __unix__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPNAV_SOCK_PATH "/var/run/spnav.sock" +#define IS_OPEN (sock != -1) + +struct event_node { + sball_event event; + struct event_node *next; +}; + +/* only used for non-X mode, with spnav_remove_events */ +static struct event_node *ev_queue, *ev_queue_tail; + +/* AF_UNIX socket used for alternative communication with daemon */ +static int sock = -1; + +static int conn_unix(int s, const char *path) +{ + struct sockaddr_un addr; + + memset(&addr, 0, sizeof addr); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof(addr.sun_path)); + + return connect(s, (struct sockaddr*)&addr, sizeof addr); +} + + +int sball_init(void) +{ + int s; + + if(IS_OPEN) { + return -1; + } + + if(!(ev_queue = malloc(sizeof *ev_queue))) { + return -1; + } + ev_queue->next = 0; + ev_queue_tail = ev_queue; + + if((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + if(conn_unix(s, SPNAV_SOCK_PATH) == -1) { + perror("failed to connect"); + close(s); + return -1; + } + + sock = s; + return 0; +} + +void sball_shutdown(void) +{ + if(!IS_OPEN) { + return; + } + + if(sock != -1) { + while(ev_queue) { + void *tmp = ev_queue; + ev_queue = ev_queue->next; + free(tmp); + } + + close(sock); + sock = -1; + } +} + +int sball_getdev(void) +{ + return sock; +} + +/* Checks both the event queue and the daemon socket for pending events. + * In either case, it returns immediately with true/false values (doesn't block). + */ +int sball_pending(void) +{ + fd_set rd_set; + struct timeval tv; + + if(ev_queue->next) { + return 1; + } + + FD_ZERO(&rd_set); + FD_SET(sock, &rd_set); + + /* don't block, just poll */ + tv.tv_sec = tv.tv_usec = 0; + + if(select(sock + 1, &rd_set, 0, 0, &tv) > 0) { + return 1; + } + return 0; +} + + +/* If there are events waiting in the event queue, dequeue one and + * return that, otherwise read one from the daemon socket. + * This might block unless we called event_pending() first and it returned true. + */ +static int read_event(int s, sball_event *event) +{ + int i, rd; + int data[8]; + + /* if we have a queued event, deliver that one */ + if(ev_queue->next) { + struct event_node *node = ev_queue->next; + ev_queue->next = ev_queue->next->next; + + /* dequeued the last event, must update tail pointer */ + if(ev_queue_tail == node) { + ev_queue_tail = ev_queue; + } + + memcpy(event, &node->event, sizeof *event); + free(node); + return event->type; + } + + /* otherwise read one from the connection */ + do { + rd = read(s, data, sizeof data); + } while(rd == -1 && errno == EINTR); + + if(rd <= 0) { + return 0; + } + + if(data[0] < 0 || data[0] > 2) { + return 0; + } + event->type = data[0] ? SBALL_EV_BUTTON : SBALL_EV_MOTION; + + if(event->type == SBALL_EV_MOTION) { + for(i=0; i<6; i++) { + event->motion.motion[i] = data[i + 1]; + } + event->motion.motion[2] = -event->motion.motion[2]; + event->motion.motion[5] = -event->motion.motion[5]; + } else { + event->button.pressed = data[0] == 1 ? 1 : 0; + event->button.id = data[1]; + } + + return event->type; +} + + +int sball_getevent(sball_event *ev) +{ + if(sock) { + if(read_event(sock, ev) > 0) { + return ev->type; + } + } + return 0; +} + +#else /* not __unix__ */ + +int sball_init(void) +{ + return 0; +} + +void sball_shutdown(void) +{ +} + +int sball_getdev(void) +{ + return -1; +} + +int sball_pending(void) +{ + return 0; +} + +int sball_getevent(sball_event *ev) +{ + return SBALL_EV_NONE; +} + +#endif