diff -rup quakeforge-0.5.2/include/r_cvar.h quakeforge-0.5.2-p/include/r_cvar.h --- quakeforge-0.5.2/include/r_cvar.h 2002-08-24 00:55:59.000000000 +0300 +++ quakeforge-0.5.2-p/include/r_cvar.h 2002-12-15 15:17:49.000000000 +0200 @@ -81,6 +81,7 @@ extern struct cvar_s *r_shadows; extern struct cvar_s *r_skyname; extern struct cvar_s *r_speeds; extern struct cvar_s *r_timegraph; +extern struct cvar_s *r_torches; extern struct cvar_s *r_wateralpha; extern struct cvar_s *r_waterripple; extern struct cvar_s *r_waterwarp; @@ -90,6 +91,10 @@ extern struct cvar_s *scr_centertime extern struct cvar_s *scr_consize; extern struct cvar_s *scr_conspeed; extern struct cvar_s *scr_fov; +extern struct cvar_s *scr_pan; +extern struct cvar_s *scr_pfov; +extern struct cvar_s *scr_slices; +extern struct cvar_s *scr_pyscale; extern struct cvar_s *scr_printspeed; extern struct cvar_s *scr_showpause; extern struct cvar_s *scr_showram; diff -rup quakeforge-0.5.2/libs/video/renderer/gl/gl_mod_alias.c quakeforge-0.5.2-p/libs/video/renderer/gl/gl_mod_alias.c --- quakeforge-0.5.2/libs/video/renderer/gl/gl_mod_alias.c 2002-09-10 02:06:08.000000000 +0300 +++ quakeforge-0.5.2-p/libs/video/renderer/gl/gl_mod_alias.c 2002-12-15 18:19:55.000000000 +0200 @@ -522,7 +522,8 @@ R_DrawAliasModel (entity_t *e) radius = model->radius; if (e->scale != 1.0) radius *= e->scale; - if (R_CullSphere (e->origin, radius)) + if (!(scr_pan->int_val && scr_pfov->int_val > 180) && + R_CullSphere (e->origin, radius)) return; VectorSubtract (r_origin, e->origin, modelorg); diff -rup quakeforge-0.5.2/libs/video/renderer/gl/gl_rmain.c quakeforge-0.5.2-p/libs/video/renderer/gl/gl_rmain.c --- quakeforge-0.5.2/libs/video/renderer/gl/gl_rmain.c 2002-08-20 03:48:59.000000000 +0300 +++ quakeforge-0.5.2-p/libs/video/renderer/gl/gl_rmain.c 2002-12-15 18:36:39.000000000 +0200 @@ -298,7 +298,7 @@ R_SetupFrame (void) } static void -MYgluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) +MYgluPerspectiveY (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { GLdouble xmin, xmax, ymin, ymax; @@ -311,6 +311,24 @@ MYgluPerspective (GLdouble fovy, GLdoubl qfglFrustum (xmin, xmax, ymin, ymax, zNear, zFar); } +// calc projection based on fov_x is more accurate for panorama mode +static void +MYgluPerspectiveX (GLdouble fovx, GLdouble aspect, GLdouble zNear, GLdouble zFar) +{ + GLdouble xmin, xmax, ymin, ymax; + + xmax = zNear * tan( fovx * M_PI / 360.0 ); + xmin = -xmax; + + ymin = xmin / aspect; + ymax = xmax / aspect; + + qfglFrustum (xmin, xmax, ymin, ymax, zNear, zFar); +} + +// FIXME +static double panyaw; + static void R_SetupGL (void) { @@ -349,8 +367,12 @@ R_SetupGL (void) qfglViewport (glx + x, gly + y2, w, h); screenaspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value, - r_farclip->value); + if (!scr_pan->int_val) + MYgluPerspectiveY (r_refdef.fov_y, screenaspect, r_nearclip->value, + r_farclip->value); + else + MYgluPerspectiveX (r_refdef.fov_x, screenaspect, r_nearclip->value, + r_farclip->value); if (mirror) { if (mirror_plane->normal[2]) @@ -366,6 +388,9 @@ R_SetupGL (void) qfglRotatef (-90, 1, 0, 0); // put Z going up qfglRotatef (90, 0, 0, 1); // put Z going up + // doing this before all other makes mlook work correctly + if (scr_pan->int_val) + qfglRotatef(panyaw, 0, 0, 1); qfglRotatef (-r_refdef.viewangles[2], 1, 0, 0); qfglRotatef (-r_refdef.viewangles[0], 0, 1, 0); qfglRotatef (-r_refdef.viewangles[1], 0, 0, 1); @@ -484,12 +509,12 @@ R_Mirror (void) } /* - R_RenderView + R_RenderView_ r_refdef must be set before the first call */ void -R_RenderView (void) +R_RenderView_ (void) { if (r_norefresh->int_val) return; @@ -514,3 +539,41 @@ R_RenderView (void) if (r_zgraph->int_val) R_ZGraph (); } + +void +R_RenderView (void) +{ + if(!scr_pan->int_val) { + R_RenderView_ (); + } else { + double slices = scr_slices->value; + double pfov = scr_pfov->value; + refdef_t t = r_refdef; + int slw = t.vrect.width/slices; + int i, glc = gl_clear->int_val; + + r_refdef.vrect.width = slw; + r_refdef.fov_y = 100; + while (1) { + r_refdef.fov_x = pfov/slices + 0.5; + r_refdef.vrect.height = (t.vrect.width/pfov)*scr_pyscale->value; + if (r_refdef.vrect.height > t.vrect.height) { + Cvar_SetValue(scr_pfov, pfov += 1); + } else { + break; + } + } + r_refdef.vrect.y = (t.vrect.height-r_refdef.vrect.height)/2; + r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); + for (i = 0; i < scr_slices->int_val; i++) { + if (glc) + gl_clear->int_val = i ? 0 : 1; + panyaw = (i-slices/2+0.5)*(pfov/slices); + r_refdef.vrect.x = i*slw+(t.vrect.width-slw*slices)/2; + R_RenderView_ (); + } + r_refdef = t; + gl_clear->int_val = glc; + //Sbar_Changed(); + } +} diff -rup quakeforge-0.5.2/libs/video/renderer/gl/gl_rsurf.c quakeforge-0.5.2-p/libs/video/renderer/gl/gl_rsurf.c --- quakeforge-0.5.2/libs/video/renderer/gl/gl_rsurf.c 2002-08-25 08:55:28.000000000 +0300 +++ quakeforge-0.5.2-p/libs/video/renderer/gl/gl_rsurf.c 2002-12-15 18:20:11.000000000 +0200 @@ -287,7 +287,8 @@ R_DrawBrushModel (entity_t *e) if (e->scale != 1.0) radius *= e->scale; #endif - if (R_CullSphere (e->origin, radius)) + if (!(scr_pan->int_val && scr_pfov->int_val > 180) && + R_CullSphere (e->origin, radius)) return; } else { rotated = false; @@ -299,7 +300,8 @@ R_DrawBrushModel (entity_t *e) VectorScale (maxs, e->scale, maxs); } #endif - if (R_CullBox (mins, maxs)) + if (!(scr_pan->int_val && scr_pfov->int_val > 180) && + R_CullBox (mins, maxs)) return; } @@ -414,7 +416,8 @@ R_RecursiveWorldNode (mnode_t *node) if (node->visframe != r_visframecount) return; - if (R_CullBox (node->minmaxs, node->minmaxs + 3)) + if (!(scr_pan->int_val && scr_pfov->int_val > 180) && + R_CullBox (node->minmaxs, node->minmaxs + 3)) return; // if a leaf node, draw stuff diff -rup quakeforge-0.5.2/libs/video/renderer/r_cvar.c quakeforge-0.5.2-p/libs/video/renderer/r_cvar.c --- quakeforge-0.5.2/libs/video/renderer/r_cvar.c 2002-08-24 00:55:59.000000000 +0300 +++ quakeforge-0.5.2-p/libs/video/renderer/r_cvar.c 2002-12-15 18:43:24.000000000 +0200 @@ -121,6 +121,7 @@ cvar_t *r_shadows; cvar_t *r_skyname; cvar_t *r_speeds; cvar_t *r_timegraph; +cvar_t *r_torches; cvar_t *r_wateralpha; cvar_t *r_waterripple; cvar_t *r_waterwarp; @@ -130,6 +131,10 @@ cvar_t *scr_centertime; cvar_t *scr_consize; cvar_t *scr_conspeed; cvar_t *scr_fov; +cvar_t *scr_pan; +cvar_t *scr_pfov; +cvar_t *scr_slices; +cvar_t *scr_pyscale; cvar_t *scr_printspeed; cvar_t *scr_showpause; cvar_t *scr_showram; @@ -192,6 +197,25 @@ r_particles_nearclip_f (cvar_t *var) r_farclip->value)); } +static void +scr_pan_f (cvar_t *var) +{ + if (var->int_val) { + Cvar_Set (r_torches, "0"); + Cvar_Set (gl_clear, "1"); + } else { + Cvar_Set (r_torches, "1"); + Cvar_Set (gl_clear, "0"); + } +} + +static void +scr_slices_f (cvar_t *var) +{ + if ((var->int_val & 1) == 0) + Cvar_SetValue (scr_slices, var->int_val + 1); +} + void R_Init_Cvars (void) { @@ -377,6 +401,8 @@ R_Init_Cvars (void) "time and statistics of what is being viewed"); r_timegraph = Cvar_Get ("r_timegraph", "0", CVAR_NONE, NULL, "Toggle the display of a performance graph"); + r_torches = Cvar_Get ("r_torches", "1", CVAR_NONE, NULL, + "Toggle rendering of torches"); r_wateralpha = Cvar_Get ("r_wateralpha", "1", CVAR_ARCHIVE, NULL, "Determine the opacity of liquids. 1 = opaque, " "0 = transparent, otherwise translucent."); @@ -396,6 +422,13 @@ R_Init_Cvars (void) "How quickly the console scrolls up or down"); scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, NULL, "Your field of view in " "degrees. Smaller than 90 zooms in."); + scr_pan = Cvar_Get ("pan", "0", CVAR_NONE, scr_pan_f, "Toggle panorama mode. "); + scr_pfov = Cvar_Get ("pfov", "200", CVAR_NONE, NULL, "Your field of view in " + "degrees in panorama mode."); + scr_slices = Cvar_Get ("slices", "13", CVAR_NONE, scr_slices_f, "The number " + "of slices in the view in panorama mode."); + scr_pyscale = Cvar_Get ("pyscale", "120", CVAR_NONE, NULL, "The Y fov " + "scale of the panorama rendering."); scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL, "How fast the text is displayed at the end of " "the single player episodes");