From fd805886f7247b706340514d582409777d202fb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 23:51:30 +0900 Subject: [PATCH] [renderer] Get fisheye working again Only for gl and sw at the moment (want to merge things further before I do anything for glsl or vulkan). However, with with I've learned getting gl and sw to work, glsl and vulkan will be trivial. --- libs/video/renderer/gl/gl_rmain.c | 133 +++++++------- libs/video/renderer/sw/sw_rmain.c | 282 +++++++++++------------------- libs/video/renderer/sw/sw_rmisc.c | 4 +- 3 files changed, 173 insertions(+), 246 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 7126a6c2d..a48035799 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -471,18 +471,18 @@ R_RenderView_ (void) R_ZGraph (); } -//FIXME static void R_RenderViewFishEye (void); +static void R_RenderViewFishEye (void); void gl_R_RenderView (void) { - R_RenderView_ (); - /*if(!scr_fisheye->int_val) + if(!scr_fisheye->int_val) R_RenderView_ (); else - R_RenderViewFishEye ();*/ + R_RenderViewFishEye (); } -/*FIXME + +//FIXME // Algorithm: // Draw up to six views, one in each direction. // Save the picture to cube map texture, use GL_ARB_texture_cube_map. @@ -499,7 +499,34 @@ gl_R_RenderView (void) #define BOX_TOP 4 #define BOX_BOTTOM 5 -#define FPOLYCNT 16 +static mat4f_t box_rotations[] = { + { { 1, 0, 0, 0}, // front + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0,-1, 0, 0}, // right + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { {-1, 0, 0, 0}, // back + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 1, 0, 0}, // left + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 0, 1, 0}, // top + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} }, + { { 0, 0,-1, 0}, // bottom + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} }, +}; + +#define FPOLYCNT 128 struct xyz { float x, y, z; @@ -548,79 +575,51 @@ do { \ printf ("%s: gl error %d\n", s, (int) err); \ } while (0); -#define NO(x) \ -do { \ - if (x < 0) \ - x += 360; \ - else if (x >= 360) \ - x -= 360; \ -} while (0) static void R_RenderCubeSide (int side) { - float pitch, n_pitch; - float yaw, n_yaw; - float roll, n_roll; - float s_roll; + mat4f_t camera; + mat4f_t camera_inverse; + mat4f_t rotinv; - pitch = n_pitch = r_refdef.viewangles[PITCH]; - yaw = n_yaw = r_refdef.viewangles[YAW]; - // setting ROLL for now to 0, correct roll handling - // requre more exhaustive changes in rotation - // TODO: implement via matrix -// roll = n_roll = r_refdef.viewangles[ROLL]; - s_roll = r_refdef.viewangles[ROLL]; - roll = n_roll = 0; -// roll -= scr_fviews->int_val * 10; -// n_roll = roll; - - switch (side) { - case BOX_FRONT: - break; - case BOX_RIGHT: - n_pitch = roll; - n_yaw -= 90; - n_roll = -pitch; - break; - case BOX_LEFT: - n_pitch = -roll; - n_yaw += 90; - n_roll = pitch; -// static int f = 0; -// if (!(f++ % 100)) -// printf ("%4d %4d %4d | %4d %4d %4d\n", (int) pitch, (int) yaw, -// (int) roll, (int) n_pitch, (int) n_yaw, (int) n_roll); - break; - case BOX_TOP: - n_pitch -= 90; - break; - case BOX_BOTTOM: - n_pitch += 90; - break; - case BOX_BEHIND: - n_pitch = -pitch; - n_yaw += 180; - break; - } - NO (n_pitch); - NO (n_yaw); - NO (n_roll); - r_refdef.viewangles[PITCH] = n_pitch; - r_refdef.viewangles[YAW] = n_yaw; - r_refdef.viewangles[ROLL] = n_roll; + memcpy (camera, r_refdef.camera, sizeof (camera)); + memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); + mmulf (r_refdef.camera, camera, box_rotations[side]); + mat4ftranspose (rotinv, box_rotations[side]); + mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); + //FIXME see fixme in r_screen.c + r_refdef.frame.mat[0] = -r_refdef.camera[1]; + r_refdef.frame.mat[1] = r_refdef.camera[0]; + r_refdef.frame.mat[2] = r_refdef.camera[2]; + r_refdef.frame.mat[3] = r_refdef.camera[3]; +#if 0 + printf ("side: %d\n", side); + printf ("c: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 3)); + printf ("f: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 3)); +#endif + qfglClear (GL_DEPTH_BUFFER_BIT); R_RenderView_ (); qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex); qfglCopyTexSubImage2D (box2cube_map[side], 0, 0, 0, 0, 0, gl_cube_map_size, gl_cube_map_size); -// CHKGLERR ("qfglCopyTexSubImage2D"); + CHKGLERR ("qfglCopyTexSubImage2D"); qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); - r_refdef.viewangles[PITCH] = pitch; - r_refdef.viewangles[YAW] = yaw; - r_refdef.viewangles[ROLL] = s_roll; + memcpy (r_refdef.camera, camera, sizeof (camera)); + memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } static qboolean gl_cube_map_capable = false; @@ -779,7 +778,7 @@ R_RenderViewFishEye (void) R_SetupGL_Viewport_and_Perspective (); qfglMatrixMode (GL_MODELVIEW); qfglCallList (fisheye_grid); -}*/ +} void gl_R_ClearState (void) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index f5d157ac0..95498b0df 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -823,7 +823,7 @@ R_RenderView_ (void) R_HighFPPrecision (); } -//XXX FIXME static void R_RenderViewFishEye (void); +static void R_RenderViewFishEye (void); void R_RenderView (void) @@ -843,12 +843,10 @@ R_RenderView (void) if ((intptr_t) (&r_warpbuffer) & 3) Sys_Error ("Globals are missaligned"); - R_RenderView_ (); -/*XXX FIXME if (!scr_fisheye->int_val) R_RenderView_ (); else - R_RenderViewFishEye ();*/ + R_RenderViewFishEye (); } void @@ -862,161 +860,55 @@ R_InitTurb (void) // AMP2 not 20 } } -/*XXX FIXME + #define BOX_FRONT 0 +#define BOX_RIGHT 1 #define BOX_BEHIND 2 #define BOX_LEFT 3 -#define BOX_RIGHT 1 #define BOX_TOP 4 #define BOX_BOTTOM 5 -#define DEG(x) (x / M_PI * 180.0) -#define RAD(x) (x * M_PI / 180.0) - -struct my_coords -{ - double x, y, z; +static mat4f_t box_rotations[] = { + { { 1, 0, 0, 0}, // front + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0,-1, 0, 0}, // right + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { {-1, 0, 0, 0}, // back + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 1, 0, 0}, // left + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 0, 1, 0}, // top + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} }, + { { 0, 0,-1, 0}, // bottom + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} }, }; -struct my_angles -{ - double yaw, pitch, roll; -}; - -static void -x_rot (struct my_coords *c, double pitch) -{ - double nx, ny, nz; - - nx = c->x; - ny = (c->y * cos(pitch)) - (c->z * sin(pitch)); - nz = (c->y * sin(pitch)) + (c->z * cos(pitch)); - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -y_rot (struct my_coords *c, double yaw) -{ - double nx, ny, nz; - - nx = (c->x * cos(yaw)) - (c->z * sin(yaw)); - ny = c->y; - nz = (c->x * sin(yaw)) + (c->z * cos(yaw)); - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -z_rot (struct my_coords *c, double roll) -{ - double nx, ny, nz; - - nx = (c->x * cos(roll)) - (c->y * sin(roll)); - ny = (c->x * sin(roll)) + (c->y * cos(roll)); - nz = c->z; - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -my_get_angles (struct my_coords *in_o, struct my_coords *in_u, struct my_angles *a) -{ - double rad_yaw, rad_pitch; - struct my_coords o, u; - - a->pitch = 0.0; - a->yaw = 0.0; - a->roll = 0.0; - - // make a copy of the coords - o.x = in_o->x; o.y = in_o->y; o.z = in_o->z; - u.x = in_u->x; u.y = in_u->y; u.z = in_u->z; - - // special case when looking straight up or down - if ((o.x == 0.0) && (o.z == 0.0)) { - a->yaw = 0.0; - if (o.y > 0.0) { a->pitch = -90.0; a->roll = 180.0 - DEG(atan2(u.x, u.z)); } // down - else { a->pitch = 90.0; a->roll = DEG(atan2(u.x, u.z)); } // up - return; - } - - // get yaw angle and then rotate o and u so that yaw = 0 - rad_yaw = atan2 (-o.x, o.z); - a->yaw = DEG (rad_yaw); - - y_rot (&o, -rad_yaw); - y_rot (&u, -rad_yaw); - - // get pitch and then rotate o and u so that pitch = 0 - rad_pitch = atan2 (-o.y, o.z); - a->pitch = DEG (rad_pitch); - - x_rot (&o, -rad_pitch); - x_rot (&u, -rad_pitch); - - // get roll - a->roll = DEG (-atan2(u.x, u.y)); -} - -static void -get_ypr (double yaw, double pitch, double roll, int side, struct my_angles *a) -{ - struct my_coords o, u; - - // get 'o' (observer) and 'u' ('this_way_up') depending on box side - switch(side) { - case BOX_FRONT: - o.x = 0.0; o.y = 0.0; o.z = 1.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_BEHIND: - o.x = 0.0; o.y = 0.0; o.z = -1.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_LEFT: - o.x = -1.0; o.y = 0.0; o.z = 0.0; - u.x = -1.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_RIGHT: - o.x = 1.0; o.y = 0.0; o.z = 0.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_TOP: - o.x = 0.0; o.y = -1.0; o.z = 0.0; - u.x = 0.0; u.y = 0.0; u.z = -1.0; - break; - case BOX_BOTTOM: - o.x = 0.0; o.y = 1.0; o.z = 0.0; - u.x = 0.0; u.y = 0.0; u.z = -1.0; - break; - } - z_rot (&o, roll); z_rot (&u, roll); - x_rot (&o, pitch); x_rot (&u, pitch); - y_rot (&o, yaw); y_rot (&u, yaw); - - my_get_angles (&o, &u, a); - - // normalise angles - while (a->yaw < 0.0) a->yaw += 360.0; - while (a->yaw > 360.0) a->yaw -= 360.0; - while (a->pitch < 0.0) a->pitch += 360.0; - while (a->pitch > 360.0) a->pitch -= 360.0; - while (a->roll < 0.0) a->roll += 360.0; - while (a->roll > 360.0) a->roll -= 360.0; -} +static int sw_cube_map_size; static void fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) { int x, y; + int scrsize = sw_cube_map_size * sw_cube_map_size; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { double dx = x-width/2; double dy = -(y-height/2); double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width); - double roll = -atan2(dy, dx); + double roll = atan2(dy, dx); double sx = sin(yaw) * cos(roll); double sy = sin(yaw) * sin(roll); double sz = cos(yaw); @@ -1035,26 +927,26 @@ fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); } } - #define RC(x) ((x / 2.06) + 0.5) - #define R2(x) ((x / 2.03) + 0.5) + #define RC(x) ((x / 2) + 0.5) + #define R2(x) ((x / 2) + 0.5) // scale up our vector [x,y,z] to the box switch(side) { - case BOX_FRONT: xs = RC( sx / sz); ys = R2( sy / sz); break; - case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2( sy / -sz); break; - case BOX_LEFT: xs = RC( sz / -sx); ys = R2( sy / -sx); break; - case BOX_RIGHT: xs = RC(-sz / sx); ys = R2( sy / sx); break; - case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / -sy); break; //bot - case BOX_BOTTOM: xs = RC(-sx / sy); ys = R2( sz / -sy); break; //top?? + case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break; + case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break; + case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break; + case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break; + case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break; + case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break; } if (xs < 0.0) xs = 0.0; if (xs >= 1.0) xs = 0.999; if (ys < 0.0) ys = 0.0; if (ys >= 1.0) ys = 0.999; - *buf++ = scrp+(((int)(xs*(double)width))+ - ((int)(ys*(double)height))*width)+ - side*width*height; + int sxs = xs * sw_cube_map_size; + int sys = ys * sw_cube_map_size; + *buf++ = scrp+side * scrsize + sys * sw_cube_map_size + sxs; } } } @@ -1070,18 +962,45 @@ rendercopy (void *dest) } static void -renderside (byte* bufs, double yaw, double pitch, double roll, int side) +renderside (byte *bufs, int side) { - struct my_angles a; + mat4f_t camera; + mat4f_t camera_inverse; + mat4f_t rotinv; + + memcpy (camera, r_refdef.camera, sizeof (camera)); + memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); + mmulf (r_refdef.camera, camera, box_rotations[side]); + mat4ftranspose (rotinv, box_rotations[side]); + mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); + + //FIXME see fixme in r_screen.c + r_refdef.frame.mat[0] = -r_refdef.camera[1]; + r_refdef.frame.mat[1] = r_refdef.camera[0]; + r_refdef.frame.mat[2] = r_refdef.camera[2]; + r_refdef.frame.mat[3] = r_refdef.camera[3]; + + float fov_x = r_refdef.fov_x; + float fov_y = r_refdef.fov_y; + unsigned width = vid.width; + unsigned height = vid.height; + vrect_t rect = r_refdef.vrect; + r_refdef.fov_x = r_refdef.fov_y = 90; + r_refdef.vrect.x = r_refdef.vrect.y = 0; + r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size; + vid.height = vid.width = sw_cube_map_size; + R_ViewChanged (); - get_ypr (RAD(yaw), RAD(pitch), RAD(roll), side, &a); - if (side == BOX_RIGHT) { a.roll = -a.roll; a.pitch = -a.pitch; } - if (side == BOX_LEFT) { a.roll = -a.roll; a.pitch = -a.pitch; } - if (side == BOX_TOP) { a.yaw += 180.0; a.pitch = 180.0 - a.pitch; } - r_refdef.viewangles[YAW] = a.yaw; - r_refdef.viewangles[PITCH] = a.pitch; - r_refdef.viewangles[ROLL] = a.roll; rendercopy (bufs); + + r_refdef.vrect = rect; + vid.height = height; + vid.width = width; + r_refdef.fov_x = fov_x; + r_refdef.fov_y = fov_y; + + memcpy (r_refdef.camera, camera, sizeof (camera)); + memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } static void @@ -1099,14 +1018,12 @@ renderlookup (byte **offs, byte* bufs) static void R_RenderViewFishEye (void) { + sw_cube_map_size = vid.width; int width = vid.width; //r_refdef.vrect.width; int height = vid.height; //r_refdef.vrect.height; - int scrsize = width*height; + int scrsize = sw_cube_map_size * sw_cube_map_size; int fov = scr_ffov->int_val; int views = scr_fviews->int_val; - double yaw = r_refdef.viewangles[YAW]; - double pitch = r_refdef.viewangles[PITCH]; - double roll = 0; //r_refdef.viewangles[ROLL]; static int pwidth = -1; static int pheight = -1; static int pfov = -1; @@ -1119,14 +1036,15 @@ R_RenderViewFishEye (void) if (pwidth != width || pheight != height || pfov != fov) { if (scrbufs) free (scrbufs); if (offs) free (offs); - scrbufs = malloc (scrsize*6); // front|right|back|left|top|bottom + // front|right|back|left|top|bottom + scrbufs = malloc (scrsize*6); SYS_CHECKMEM (scrbufs); - offs = malloc (scrsize*sizeof(byte*)); + offs = malloc (width*height*sizeof(byte*)); SYS_CHECKMEM (offs); pwidth = width; pheight = height; pfov = fov; - fisheyelookuptable (offs, width, height, scrbufs, ((double)fov)*M_PI/180.0); + fisheyelookuptable (offs, width, height, scrbufs, fov*M_PI/180.0); } if (views != pviews) { @@ -1135,19 +1053,27 @@ R_RenderViewFishEye (void) } switch (views) { - case 6: renderside (scrbufs+scrsize*2, yaw, pitch, roll, BOX_BEHIND); - case 5: renderside (scrbufs+scrsize*5, yaw, pitch, roll, BOX_BOTTOM); - case 4: renderside (scrbufs+scrsize*4, yaw, pitch, roll, BOX_TOP); - case 3: renderside (scrbufs+scrsize*3, yaw, pitch, roll, BOX_LEFT); - case 2: renderside (scrbufs+scrsize, yaw, pitch, roll, BOX_RIGHT); - default: renderside (scrbufs, yaw, pitch, roll, BOX_FRONT); + case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND); + case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM); + case 4: renderside (scrbufs + scrsize * BOX_TOP, BOX_TOP); + case 3: renderside (scrbufs + scrsize * BOX_LEFT, BOX_LEFT); + case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT); + default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT); } - - r_refdef.viewangles[YAW] = yaw; - r_refdef.viewangles[PITCH] = pitch; - r_refdef.viewangles[ROLL] = roll; +#if 0 + memset (scrbufs + scrsize*0, 31, sw_cube_map_size); + memset (scrbufs + scrsize*1, 31, sw_cube_map_size); + memset (scrbufs + scrsize*2, 31, sw_cube_map_size); + memset (scrbufs + scrsize*3, 31, sw_cube_map_size); + memset (scrbufs + scrsize*4, 31, sw_cube_map_size); + memset (scrbufs + scrsize*5, 31, sw_cube_map_size); + for (int y = 0; y < sw_cube_map_size * 6; y++) { + scrbufs[y * sw_cube_map_size] = 31; + scrbufs[y * sw_cube_map_size + sw_cube_map_size - 1] = 31; + } +#endif renderlookup (offs, scrbufs); -}*/ +} void R_ClearState (void) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index d29b68186..1d7bc491f 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -233,7 +233,9 @@ R_SetupFrame (void) (h / (float) vid.height))); R_ViewChanged (); } - } else { + } else if (!scr_fisheye->int_val) { + //FIXME the above test shouldn't be necessary (this whole section + //is a bit of a mess, though) r_refdef.vrect.x = vr_data.scr_view->xpos; r_refdef.vrect.y = vr_data.scr_view->ypos; r_refdef.vrect.width = vr_data.scr_view->xlen;