From c2995f2c4c030b1c3adb163fd84b4ea5b3d2b104 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Fri, 15 Feb 2002 22:28:08 +0000 Subject: [PATCH] moved a lot of 2D/screen stuff out of gl_screen.c into cl_screen.c moved remainder of gl_screen.c into gl_backend.c removed gl_screen.c inlined GL_BrightenScreen in gl_draw.c moved a lot of GL stuff out of gl_rmain.c into gl_backend.c converted polyblend to R_Mesh based replaced lighthalf/gl_lightmode with v_overbrightbits renamed contrast to brightness, and brightness to contrast (to match monitor controls) merged hardware and software brightness/contrast/gamma into v_contrast, v_brightness, v_gamma, etc, switchable using v_hwgamma (automatically forced off if hardware gamma support is unavailable) added ghostable menu items (unavailable gamma, for example) rearranged options menu 2D resolution slider added (from 320x240 to full resolution) fixed misuse of strncmp for bindings menu (thanks Elric) adjustable crosshair size renamed GL_BeginRendering to VID_GetWindowSize renamed GL_EndRendering to VID_Finish made screenshot and envmap share one function for grabbing images moved underwater warping into cl_screen code starting work on new entity protocol (not hooked up yet) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1523 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_screen.c | 693 ++++++++++++++++++++++++++++++++++- cl_screen.h | 2 + gl_backend.c | 291 ++++++++++++++- gl_draw.c | 148 ++++---- gl_rmain.c | 124 ++----- gl_rsurf.c | 27 +- gl_screen.c | 969 ------------------------------------------------- glquake.h | 13 +- makefile | 2 +- menu.c | 209 ++++++----- model_brush.h | 2 +- palette.c | 64 ++-- palette.h | 8 +- protocol.c | 44 +++ protocol.h | 65 +++- r_crosshairs.c | 13 +- render.h | 2 +- screen.h | 4 +- vid.h | 6 +- vid_3dfxsvga.c | 22 +- vid_glx.c | 19 +- vid_wgl.c | 15 +- 22 files changed, 1395 insertions(+), 1347 deletions(-) delete mode 100644 gl_screen.c diff --git a/cl_screen.c b/cl_screen.c index 0d6ba443..814e9b3f 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1,12 +1,526 @@ #include "quakedef.h" +cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"}; +cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300 +cvar_t scr_centertime = {0, "scr_centertime","2"}; +cvar_t scr_showram = {CVAR_SAVE, "showram","1"}; +cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"}; +cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"}; +cvar_t scr_printspeed = {0, "scr_printspeed","8"}; +cvar_t scr_2dresolution = {CVAR_SAVE, "scr_2dresolution", "1"}; + +qboolean scr_initialized; // ready to draw + +float scr_con_current; +float scr_conlines; // lines of console to display + +int clearconsole; +int clearnotify; + +qboolean scr_disabled_for_loading; +//qboolean scr_drawloading; +//float scr_disabled_time; + static byte menuplyr_pixels[4096]; +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.conheight*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.conwidth - l*8)/2; + if (l > 0) + { + if (remaining < l) + l = remaining; + DrawQ_String(x, y, start, l, 8, 8, 1, 1, 1, 1, 0); + remaining -= l; + if (remaining <= 0) + return; + } + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } while (1); +} + +void SCR_CheckDrawCenterString (void) +{ + if (scr_center_lines > scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ +// if (!scr_showram.integer) +// return; +// DrawQ_Pic (32, 0, "ram", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (cls.state != ca_connected) + return; + + if (!scr_showturtle.integer) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (cls.state != ca_connected) + return; + if (realtime - cl.last_received_message < 0.3) + return; + if (cls.demoplayback) + return; + + DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + cachepic_t *pic; + + if (cls.state != ca_connected) + return; + + if (!scr_showpause.integer) // turn off for screenshots + return; + + if (!cl.paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp"); + DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/pause.lmp", 0, 0, 1, 1, 1, 1, 0); +} + + + +/* +============== +SCR_DrawLoading +============== +*/ +/* +void SCR_DrawLoading (void) +{ + cachepic_t *pic; + + if (!scr_drawloading) + return; + + pic = Draw_CachePic ("gfx/loading.lmp"); + DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0); +} +*/ + + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + +// decide on the height of the console + con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; + + if (con_forcedup) + { + scr_conlines = vid.conheight; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.conheight/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_realframetime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_realframetime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + Con_DrawConsole (scr_con_current); + clearconsole = 0; + } + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + +/* +=============== +SCR_BeginLoadingPlaque + +================ +*/ +/* +void SCR_BeginLoadingPlaque (void) +{ + S_StopAllSounds (true); + +// if (cls.state != ca_connected) +// return; +// if (cls.signon != SIGNONS) +// return; + +// redraw with no console and the loading plaque +// Con_ClearNotify (); +// scr_centertime_off = 0; +// scr_con_current = 0; + + scr_drawloading = true; + SCR_UpdateScreen (); + +// scr_disabled_for_loading = true; +// scr_disabled_time = realtime; +} +*/ + +/* +=============== +SCR_EndLoadingPlaque + +================ +*/ +/* +void SCR_EndLoadingPlaque (void) +{ +// scr_disabled_for_loading = false; + scr_drawloading = false; + Con_ClearNotify (); +} +*/ + +//============================================================================= + +char *scr_notifystring; + +void SCR_DrawNotifyString (void) +{ + char *start; + int l; + int x, y; + + start = scr_notifystring; + + y = vid.conheight*0.35; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.conwidth - l*8)/2; + DrawQ_String (x, y, start, l, 8, 8, 1, 1, 1, 1, 0); + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } + while (1); +} + +void DrawCrosshair(int num); + +char r_speeds_string[1024]; +int speedstringcount, r_timereport_active; +double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0; + +void R_TimeReport(char *desc) +{ + char tempbuf[256]; + int length; + int t; + + if (!r_timereport_active) + return; + + r_timereport_temp = r_timereport_current; + r_timereport_current = Sys_DoubleTime(); + t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0); + + sprintf(tempbuf, "%8i %s", t, desc); + length = strlen(tempbuf); + while (length < 20) + tempbuf[length++] = ' '; + tempbuf[length] = 0; + if (speedstringcount + length > (vid.conwidth / 8)) + { + strcat(r_speeds_string, "\n"); + speedstringcount = 0; + } + // skip the space at the beginning if it's the first on the line + if (speedstringcount == 0) + { + strcat(r_speeds_string, tempbuf + 1); + speedstringcount = length - 1; + } + else + { + strcat(r_speeds_string, tempbuf); + speedstringcount += length; + } +} + +void R_TimeReport_Start(void) +{ + r_timereport_active = r_speeds.integer && cl.worldmodel && cls.state == ca_connected; + r_speeds_string[0] = 0; + if (r_timereport_active) + { + speedstringcount = 0; + AngleVectors (r_refdef.viewangles, vpn, NULL, NULL); + //sprintf(r_speeds_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", + // r_refdef.vieworg[0] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[0]), r_refdef.vieworg[1] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[1]), r_refdef.vieworg[2] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[2]), + // r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), + // vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]), + sprintf(r_speeds_string, + "org:'%+8.2f %+8.2f %+8.2f' ang:'%+4.0f %+4.0f %+4.0f' dir:'%+2.3f %+2.3f %+2.3f'\n" + "world:%6i faces%6i nodes%6i leafs%6i walls%6i dlitwalls\n" + "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n" + "%6i modeltris%6i transmeshs%6i transtris%6i meshs%6i meshtris\n", + r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0], r_refdef.viewangles[1], r_refdef.viewangles[2], vpn[0], vpn[1], vpn[2], + c_faces, c_nodes, c_leafs, c_brush_polys, c_light_polys, + c_models, c_bmodels, c_sprites, c_particles, c_dlights, + c_alias_polys, c_transmeshs, c_transtris, c_meshs, c_meshtris); + + c_brush_polys = 0; + c_alias_polys = 0; + c_light_polys = 0; + c_faces = 0; + c_nodes = 0; + c_leafs = 0; + c_models = 0; + c_bmodels = 0; + c_sprites = 0; + c_particles = 0; + // c_dlights = 0; + + r_timereport_start = Sys_DoubleTime(); + } +} + +void R_TimeReport_End(void) +{ + r_timereport_current = r_timereport_start; + R_TimeReport("total"); + + if (r_timereport_active) + { + int i, j, lines, y; + lines = 1; + for (i = 0;r_speeds_string[i];i++) + if (r_speeds_string[i] == '\n') + lines++; + y = vid.conheight - sb_lines - lines * 8/* - 8*/; + i = j = 0; + DrawQ_Fill(0, y, vid.conwidth, lines * 8, 0, 0, 0, 0.5, 0); + while (r_speeds_string[i]) + { + j = i; + while (r_speeds_string[i] && r_speeds_string[i] != '\n') + i++; + if (i - j > 0) + DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0); + if (r_speeds_string[i] == '\n') + i++; + y += 8; + } + } +} + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value+10); +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); +} + void CL_Screen_Init(void) { qpic_t *dat; + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + Cvar_RegisterVariable(&scr_2dresolution); + + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + scr_initialized = true; + // HACK HACK HACK // load the image data for the player image in the config menu dat = (qpic_t *)COM_LoadFile ("gfx/menuplyr.lmp", false); @@ -146,24 +660,100 @@ void DrawQ_PicTranslate (int x, int y, char *picname, byte *translation) DrawQ_Pic(x, y, picname, 0, 0, 1, 1, 1, 1, 0); } -void V_CalcRefdef (void); -void CL_UpdateScreen(void) + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) { - DrawQ_Clear(); + // calculate vision size and alter by aspect, then convert back to angle + return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI; +} - SHOWLMP_drawall(); +/* +================= +SCR_CalcRefdef - V_UpdateBlends(); - V_CalcRefdef (); +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + float size; + int contents; - SCR_UpdateScreen(); -} +//======================================== -void CL_Screen_NewMap(void) -{ - SHOWLMP_clear(); +// bound viewsize + if (scr_viewsize.value < 30) + Cvar_Set ("viewsize","30"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + +// bound field of view + if (scr_fov.value < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + +// intermission is always full screen + if (cl.intermission) + { + size = 1; + sb_lines = 0; + } + else + { + if (scr_viewsize.value >= 120) + sb_lines = 0; // no status bar at all + else if (scr_viewsize.value >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + size = scr_viewsize.value * (1.0 / 100.0); + } + + if (size >= 1) + { + r_refdef.width = vid.realwidth; + r_refdef.height = vid.realheight; + r_refdef.x = 0; + r_refdef.y = 0; + } + else + { + r_refdef.width = vid.realwidth * size; + r_refdef.height = vid.realheight * size; + r_refdef.x = (vid.realwidth - r_refdef.width)/2; + r_refdef.y = (vid.realheight - r_refdef.height)/2; + } + + r_refdef.width = bound(0, r_refdef.width, vid.realwidth); + r_refdef.height = bound(0, r_refdef.height, vid.realheight); + r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width) + vid.realx; + r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height) + vid.realy; + + r_refdef.fov_x = scr_fov.value; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height); + + if (cl.worldmodel) + { + Mod_CheckLoaded(cl.worldmodel); + contents = Mod_PointInLeaf(r_refdef.vieworg, cl.worldmodel)->contents; + if (contents != CONTENTS_EMPTY && contents != CONTENTS_SOLID) + { + r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.03 + 0.97); + r_refdef.fov_y *= (sin(cl.time * 3.0) * 0.03 + 0.97); + } + } } + +void V_CalcRefdef (void); + //============================================================================= // LordHavoc: SHOWLMP stuff @@ -247,3 +837,84 @@ void SHOWLMP_clear(void) for (i = 0;i < SHOWLMP_MAXLABELS;i++) showlmp[i].isactive = false; } + +void CL_UpdateScreen(void) +{ + static float old2dresolution = -1; + + if (scr_disabled_for_loading) + return; + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + R_TimeReport("other"); + + VID_GetWindowSize (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight); + + VID_UpdateGamma(false); + + if (scr_2dresolution.value != old2dresolution) + { + Cvar_SetValue("scr_2dresolution", bound(0.0f, scr_2dresolution.value, 1.0f)); + old2dresolution = scr_2dresolution.value; + } + + if (vid.realwidth > 320) + { + vid.conwidth = (vid.realwidth - 320) * scr_2dresolution.value + 320; + vid.conwidth = bound(320, vid.conwidth, vid.realwidth); + } + else + vid.conwidth = 320; + + if (vid.realheight > 240) + { + vid.conheight = (vid.realheight - 240) * scr_2dresolution.value + 240; + vid.conheight = bound(240, vid.conheight, vid.realheight); + } + else + vid.conheight = 240; + + SCR_SetUpToDrawConsole(); + + // determine size of refresh window + SCR_CalcRefdef(); + + DrawQ_Clear(); + + V_UpdateBlends(); + V_CalcRefdef (); + + R_TimeReport("setup"); + + SCR_DrawRam(); + SCR_DrawNet(); + SCR_DrawTurtle(); + SCR_DrawPause(); + SCR_CheckDrawCenterString(); + Sbar_Draw(); + SHOWLMP_drawall(); + + SCR_DrawConsole(); + + ui_draw(); + + R_TimeReport("2d"); + + // add r_speeds text to queue + R_TimeReport_End(); + + // start a new timing run + R_TimeReport_Start(); + + // make menu fade everything else on the screen + M_Draw(); + + SCR_UpdateScreen(); +} + +void CL_Screen_NewMap(void) +{ + SHOWLMP_clear(); +} diff --git a/cl_screen.h b/cl_screen.h index 21e3e951..9d5290d4 100644 --- a/cl_screen.h +++ b/cl_screen.h @@ -28,6 +28,8 @@ void SHOWLMP_decodeshow(void); void SHOWLMP_drawall(void); void SHOWLMP_clear(void); +extern cvar_t scr_2dresolution; + void CL_Screen_NewMap(void); void CL_Screen_Init(void); void CL_UpdateScreen(void); diff --git a/gl_backend.c b/gl_backend.c index e1bd699f..0c43daf1 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -1,6 +1,16 @@ #include "quakedef.h" +cvar_t r_render = {0, "r_render", "1"}; +cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering + +int lightscalebit; +float lightscale; +float overbrightscale; + +void SCR_ScreenShot_f (void); +static void R_Envmap_f (void); + static int max_meshs; static int max_batch; static int max_verts; // always max_meshs * 3 @@ -245,6 +255,16 @@ int polyindexarray[768]; void gl_backend_init(void) { int i; + + Cvar_RegisterVariable (&r_render); + Cvar_RegisterVariable (&gl_dither); +#ifdef NORENDER + Cvar_SetValue("r_render", 0); +#endif + + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("envmap", R_Envmap_f); + Cvar_RegisterVariable(&gl_mesh_maxtriangles); Cvar_RegisterVariable(&gl_mesh_batchtriangles); Cvar_RegisterVariable(&gl_mesh_merge); @@ -263,6 +283,73 @@ void gl_backend_init(void) } } +static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) +{ + GLdouble xmax, ymax; + + xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect; + ymax = zNear * tan( fovy * M_PI / 360.0 ); + + glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar ); +} + + +/* +============= +GL_SetupFrame +============= +*/ +static void GL_SetupFrame (void) +{ + if (!r_render.integer) + return; + +// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen + gldepthmin = 0; + gldepthmax = 1; + glDepthFunc (GL_LEQUAL); + + glDepthRange (gldepthmin, gldepthmax); + + // update farclip based on previous frame + r_farclip = r_newfarclip; + + // set up viewpoint + glMatrixMode(GL_PROJECTION); + glLoadIdentity (); + + // y is weird beause OpenGL is bottom to top, we use top to bottom + glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height); +// yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI; + MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip); + + glCullFace(GL_FRONT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity (); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + glRotatef (-r_refdef.viewangles[2], 1, 0, 0); + glRotatef (-r_refdef.viewangles[0], 0, 1, 0); + glRotatef (-r_refdef.viewangles[1], 0, 0, 1); + glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); + +// glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); + + // + // set drawing parms + // +// if (gl_cull.integer) + glEnable(GL_CULL_FACE); +// else +// glDisable(GL_CULL_FACE); + + glEnable(GL_BLEND); // was Disable + glEnable(GL_DEPTH_TEST); + glDepthMask(1); +} + static float viewdist; int c_meshs, c_meshtris, c_transmeshs, c_transtris; @@ -293,6 +380,8 @@ void R_Mesh_Clear(void) c_meshtris = 0; c_transmeshs = 0; c_transtris = 0; + + GL_SetupFrame(); } #ifdef DEBUGGL @@ -1157,8 +1246,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m) if (overbright) scaler *= 0.25f; } - if (lighthalf) - scaler *= 0.5f; + scaler *= overbrightscale; } if (m->transparent) @@ -1391,8 +1479,7 @@ void R_Mesh_DrawDecal(const rmeshinfo_t *m) if (overbright) scaler *= 0.25f; } - if (lighthalf) - scaler *= 0.5f; + scaler *= overbrightscale; if (m->transparent) { @@ -1544,3 +1631,199 @@ void R_Mesh_DrawDecal(const rmeshinfo_t *m) // buf_texcoord_t must be the same size as the decal texcoord array (or vice versa) memcpy(&texcoord[0].t[0], m->texcoords[0], 4 * sizeof(buf_texcoord_t)); } + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + +float CalcFov (float fov_x, float width, float height); +void R_ClearScreen(void); + +void SCR_ScreenShot(char *filename, int x, int y, int width, int height) +{ + int i; + byte *buffer; + + buffer = Mem_Alloc(tempmempool, width*height*3); + glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); + CHECKGLERROR + + // LordHavoc: compensate for v_overbrightbits when using hardware gamma + if (v_hwgamma.integer) + for (i = 0;i < width * height * 3;i++) + buffer[i] <<= v_overbrightbits.integer; + + Image_WriteTGARGB_preflipped(filename, width, height, buffer); + + Mem_Free(buffer); +} + +/* +================== +SCR_ScreenShot_f +================== +*/ +void SCR_ScreenShot_f (void) +{ + int i; + char filename[16]; + char checkname[MAX_OSPATH]; +// +// find a file name to save it to +// + strcpy(filename, "dp0000.tga"); + + for (i=0 ; i<=9999 ; i++) + { + filename[2] = (i/1000)%10 + '0'; + filename[3] = (i/ 100)%10 + '0'; + filename[4] = (i/ 10)%10 + '0'; + filename[5] = (i/ 1)%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, filename); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==10000) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); + return; + } + + SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight); + Con_Printf ("Wrote %s\n", filename); +} + +/* +=============== +R_Envmap_f + +Grab six views for environment mapping tests +=============== +*/ +struct +{ + float angles[3]; + char *name; +} +envmapinfo[6] = +{ + {{ 0, 0, 0}, "ft"}, + {{ 0, 90, 0}, "rt"}, + {{ 0, 180, 0}, "bk"}, + {{ 0, 270, 0}, "lf"}, + {{-90, 90, 0}, "up"}, + {{ 90, 90, 0}, "dn"} +}; +static void R_Envmap_f (void) +{ + int j, size; + char filename[256], basename[256]; + + if (Cmd_Argc() != 3) + { + Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); + return; + } + + if (!r_render.integer) + return; + + strcpy(basename, Cmd_Argv(1)); + size = atoi(Cmd_Argv(2)); + if (size != 128 && size != 256 && size != 512 && size != 1024) + { + Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); + return; + } + if (size > vid.realwidth || size > vid.realheight) + { + Con_Printf("envmap: your resolution is not big enough to render that size\n"); + return; + } + + envmap = true; + + r_refdef.x = 0; + r_refdef.y = 0; + r_refdef.width = size; + r_refdef.height = size; + + r_refdef.fov_x = 90; + r_refdef.fov_y = 90; + + for (j = 0;j < 6;j++) + { + sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name); + VectorCopy(envmapinfo[j].angles, r_refdef.viewangles); + R_ClearScreen(); + R_RenderView (); + SCR_ScreenShot(filename, vid.realx, vid.realy, size, size); + } + + envmap = false; +} + +//============================================================================= + +void R_ClearScreen(void) +{ + if (r_render.integer) + { + glClearColor(0,0,0,0); + CHECKGLERROR + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) + CHECKGLERROR + if (gl_dither.integer) + glEnable(GL_DITHER); + else + glDisable(GL_DITHER); + CHECKGLERROR + } +} + +/* +================== +SCR_UpdateScreen + +This is called every frame, and can also be called explicitly to flush +text to the screen. +================== +*/ +void SCR_UpdateScreen (void) +{ + //Mem_CheckSentinelsGlobal(); + //R_TimeReport("memtest"); + + glFinish (); + CHECKGLERROR + + VID_Finish (); + + R_TimeReport("finish"); + + if (gl_combine.integer && !gl_combine_extension) + Cvar_SetValue("gl_combine", 0); + + lightscalebit = v_overbrightbits.integer; + if (gl_combine.integer && r_multitexture.integer) + lightscalebit += 2; + + lightscale = 1.0f / (float) (1 << lightscalebit); + overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer); + + R_TimeReport("setup"); + + R_ClearScreen(); + + R_TimeReport("clear"); + + if (scr_conlines < vid.conheight) + R_RenderView(); + + // draw 2D stuff + R_DrawQueue(); +} diff --git a/gl_draw.c b/gl_draw.c index 59281208..959e712d 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -301,85 +301,9 @@ void GL_Draw_Init (void) R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap); } -void GL_BrightenScreen(void) -{ - float f; - - if (r_brightness.value < 0.1f) - Cvar_SetValue("r_brightness", 0.1f); - if (r_brightness.value > 5.0f) - Cvar_SetValue("r_brightness", 5.0f); - - if (r_contrast.value < 0.2f) - Cvar_SetValue("r_contrast", 0.2f); - if (r_contrast.value > 1.0f) - Cvar_SetValue("r_contrast", 1.0f); - - if (!(lighthalf && !hardwaregammasupported) && r_brightness.value < 1.01f && r_contrast.value > 0.99f) - return; - - if (!r_render.integer) - return; - - glDisable(GL_TEXTURE_2D); - CHECKGLERROR - glEnable(GL_BLEND); - CHECKGLERROR - f = r_brightness.value; - // only apply lighthalf using software color correction if hardware is not available (speed reasons) - if (lighthalf && !hardwaregammasupported) - f *= 2; - if (f >= 1.01f) - { - glBlendFunc (GL_DST_COLOR, GL_ONE); - CHECKGLERROR - glBegin (GL_TRIANGLES); - while (f >= 1.01f) - { - if (f >= 2) - glColor3f (1, 1, 1); - else - glColor3f (f-1, f-1, f-1); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - f *= 0.5; - } - glEnd (); - CHECKGLERROR - } - if (r_contrast.value <= 0.99f) - { - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - CHECKGLERROR - if (lighthalf && hardwaregammasupported) - glColor4f (0.5, 0.5, 0.5, 1 - r_contrast.value); - else - glColor4f (1, 1, 1, 1 - r_contrast.value); - CHECKGLERROR - glBegin (GL_TRIANGLES); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - glEnd (); - CHECKGLERROR - } - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - CHECKGLERROR - - glEnable (GL_CULL_FACE); - CHECKGLERROR - glEnable (GL_DEPTH_TEST); - CHECKGLERROR - glDisable(GL_BLEND); - CHECKGLERROR - glEnable(GL_TEXTURE_2D); - CHECKGLERROR -} - void R_DrawQueue(void) { - int pos, num, chartexnum; + int pos, num, chartexnum, overbright; float x, y, w, h, s, t, u, v; cachepic_t *pic; drawqueue_t *dq; @@ -401,7 +325,6 @@ void R_DrawQueue(void) glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -434,6 +357,7 @@ void R_DrawQueue(void) } */ + overbright = v_overbrightbits.integer; batch = false; for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size) { @@ -467,10 +391,7 @@ void R_DrawQueue(void) if (color != dq->color) { color = dq->color; - if (lighthalf) - glColor4ub((byte)((color >> 25) & 0x7F), (byte)((color >> 17) & 0x7F), (byte)((color >> 9) & 0x7F), (byte)(color & 0xFF)); - else - glColor4ub((byte)((color >> 24) & 0xFF), (byte)((color >> 16) & 0xFF), (byte)((color >> 8) & 0xFF), (byte)(color & 0xFF)); + glColor4ub((byte)((color >> 24) & 0xFF) >> overbright, (byte)((color >> 16) & 0xFF) >> overbright, (byte)((color >> 8) & 0xFF) >> overbright, (byte)(color & 0xFF)); } x = dq->x; y = dq->y; @@ -571,11 +492,68 @@ void R_DrawQueue(void) if (batch) glEnd(); CHECKGLERROR - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - CHECKGLERROR - GL_BrightenScreen(); + if (!v_hwgamma.integer) + { + glDisable(GL_TEXTURE_2D); + CHECKGLERROR + t = v_contrast.value * (float) (1 << v_overbrightbits.integer); + if (t >= 1.01f) + { + glBlendFunc (GL_DST_COLOR, GL_ONE); + CHECKGLERROR + glBegin (GL_TRIANGLES); + while (t >= 1.01f) + { + if (t >= 2) + glColor3f (1, 1, 1); + else + glColor3f (t-1, t-1, t-1); + glVertex2f (-5000, -5000); + glVertex2f (10000, -5000); + glVertex2f (-5000, 10000); + t *= 0.5; + } + glEnd (); + CHECKGLERROR + } + else if (t <= 0.99f) + { + glBlendFunc(GL_ZERO, GL_SRC_COLOR); + CHECKGLERROR + glBegin(GL_TRIANGLES); + glColor3f(t, t, t); + glVertex2f(-5000, -5000); + glVertex2f(10000, -5000); + glVertex2f(-5000, 10000); + glEnd(); + CHECKGLERROR + } + if (v_brightness.value >= 0.01f) + { + glBlendFunc (GL_ONE, GL_ONE); + CHECKGLERROR + glColor3f (v_brightness.value, v_brightness.value, v_brightness.value); + CHECKGLERROR + glBegin (GL_TRIANGLES); + glVertex2f (-5000, -5000); + glVertex2f (10000, -5000); + glVertex2f (-5000, 10000); + glEnd (); + CHECKGLERROR + } + glEnable(GL_TEXTURE_2D); + CHECKGLERROR + } + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + CHECKGLERROR + glEnable (GL_CULL_FACE); + CHECKGLERROR + glEnable (GL_DEPTH_TEST); + CHECKGLERROR + glDisable(GL_BLEND); + CHECKGLERROR glColor3f(1,1,1); CHECKGLERROR } diff --git a/gl_rmain.c b/gl_rmain.c index 6deea8ea..d75dc164 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -68,7 +68,6 @@ cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"}; cvar_t r_waterripple = {CVAR_SAVE, "r_waterripple","0"}; cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"}; -cvar_t gl_lightmode = {CVAR_SAVE, "gl_lightmode", "1"}; // LordHavoc: overbright lighting //cvar_t r_dynamicbothsides = {CVAR_SAVE, "r_dynamicbothsides", "1"}; // LordHavoc: can disable dynamic lighting of backfaces, but quake maps are weird so it doesn't always work right... cvar_t gl_fogenable = {0, "gl_fogenable", "0"}; @@ -161,8 +160,6 @@ loc0: goto loc0; } -qboolean lighthalf; - vec3_t fogcolor; vec_t fogdensity; float fog_density, fog_red, fog_green, fog_blue; @@ -255,7 +252,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable (&r_drawentities); Cvar_RegisterVariable (&r_drawviewmodel); Cvar_RegisterVariable (&r_speeds); - Cvar_RegisterVariable (&gl_lightmode); // Cvar_RegisterVariable (&r_dynamicwater); // Cvar_RegisterVariable (&r_dynamicbothsides); Cvar_RegisterVariable (&r_fullbrights); @@ -297,7 +293,6 @@ extern void GL_Main_Init(void); extern void GL_Models_Init(void); extern void R_Sky_Init(void); extern void GL_Surf_Init(void); -extern void GL_Screen_Init(void); extern void R_Crosshairs_Init(void); extern void R_Light_Init(void); extern void R_Particles_Init(void); @@ -318,7 +313,6 @@ void Render_Init(void) GL_Models_Init(); R_Sky_Init(); GL_Surf_Init(); - GL_Screen_Init(); R_Crosshairs_Init(); R_Light_Init(); R_Particles_Init(); @@ -544,87 +538,45 @@ static void R_SetupFrame (void) } -static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmax, ymax; - - xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect; - ymax = zNear * tan( fovy * M_PI / 360.0 ); - - if (r_viewleaf->contents != CONTENTS_EMPTY && r_viewleaf->contents != CONTENTS_SOLID) - { - xmax *= (sin(cl.time * 4.7) * 0.03 + 0.97); - ymax *= (sin(cl.time * 3.0) * 0.03 + 0.97); - } - - glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar ); -} - - -/* -============= -R_SetupGL -============= -*/ -static void R_SetupGL (void) -{ - if (!r_render.integer) - return; - -// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen - gldepthmin = 0; - gldepthmax = 1; - glDepthFunc (GL_LEQUAL); - - glDepthRange (gldepthmin, gldepthmax); - - // update farclip based on previous frame - r_farclip = r_newfarclip; - - // set up viewpoint - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - - // y is weird beause OpenGL is bottom to top, we use top to bottom - glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height); -// yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI; - MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip); - - glCullFace(GL_FRONT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); - -// glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); - - // - // set drawing parms - // -// if (gl_cull.integer) - glEnable(GL_CULL_FACE); -// else -// glDisable(GL_CULL_FACE); - - glEnable(GL_BLEND); // was Disable - glEnable(GL_DEPTH_TEST); - glDepthMask(1); -} +static int blendviewpolyindex[3] = {0, 1, 2}; static void R_BlendView(void) { + rmeshinfo_t m; + float tvxyz[3][4]; + if (!r_render.integer) return; if (r_refdef.viewblend[3] < 0.01f) return; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.depthdisable = true; // magic + m.numtriangles = 1; + m.numverts = 3; + m.index = blendviewpolyindex; + m.vertex = &tvxyz[0][0]; + m.vertexstep = sizeof(float[4]); + m.cr = r_refdef.viewblend[0]; + m.cg = r_refdef.viewblend[1]; + m.cb = r_refdef.viewblend[2]; + m.ca = r_refdef.viewblend[3]; + tvxyz[0][0] = r_origin[0] + vpn[0] * 8 - vright[0] * 16 - vup[0] * 16; + tvxyz[0][1] = r_origin[1] + vpn[1] * 8 - vright[1] * 16 - vup[1] * 16; + tvxyz[0][2] = r_origin[2] + vpn[2] * 8 - vright[2] * 16 - vup[2] * 16; + tvxyz[1][0] = tvxyz[0][0] + vup[0] * 48; + tvxyz[1][1] = tvxyz[0][1] + vup[1] * 48; + tvxyz[1][2] = tvxyz[0][2] + vup[2] * 48; + tvxyz[2][0] = tvxyz[0][0] + vright[0] * 48; + tvxyz[2][1] = tvxyz[0][1] + vright[1] * 48; + tvxyz[2][2] = tvxyz[0][2] + vright[2] * 48; + R_Mesh_Draw(&m); + + /* glMatrixMode(GL_PROJECTION); glLoadIdentity (); glOrtho (0, 1, 1, 0, -99999, 99999); @@ -636,10 +588,7 @@ static void R_BlendView(void) glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin (GL_TRIANGLES); - if (lighthalf) - glColor4f (r_refdef.viewblend[0] * 0.5f, r_refdef.viewblend[1] * 0.5f, r_refdef.viewblend[2] * 0.5f, r_refdef.viewblend[3]); - else - glColor4fv (r_refdef.viewblend); + glColor4f (r_refdef.viewblend[0] * overbrightscale, r_refdef.viewblend[1] * overbrightscale, r_refdef.viewblend[2] * overbrightscale, r_refdef.viewblend[3]); glVertex2f (-5, -5); glVertex2f (10, -5); glVertex2f (-5, 10); @@ -649,6 +598,7 @@ static void R_BlendView(void) glEnable (GL_DEPTH_TEST); glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); + */ } /* @@ -669,14 +619,14 @@ void R_RenderView (void) R_SetupFrame(); R_SetFrustum(); - R_SetupGL(); R_SetupFog(); R_SkyStartFrame(); - R_Mesh_Clear(); if (r_ser.integer) R_Clip_StartFrame(); R_BuildLightList(); + R_Mesh_Clear(); + R_TimeReport("setup"); R_DrawWorld(); @@ -746,13 +696,13 @@ void R_RenderView (void) R_DrawCoronas(); R_TimeReport("coronas"); + R_BlendView(); + R_TimeReport("blendview"); + // render any queued meshs R_Mesh_Render(); R_TimeReport("meshrender"); - R_BlendView(); - R_TimeReport("blendview"); - //Mem_CheckSentinelsGlobal(); //R_TimeReport("memtest"); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 6b1df59b..465e124c 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -923,13 +923,7 @@ static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *s) m.numtriangles = s->mesh.numtriangles; m.numverts = s->mesh.numverts; m.index = s->mesh.index; - m.cr = 1; - if (lighthalf) - m.cr *= 2; - if (gl_combine.integer) - m.cr *= 4; - m.cg = m.cr; - m.cb = m.cr; + m.cr = m.cg = m.cb = (float) (1 << lightscalebit); m.ca = currentrenderentity->alpha; m.tex[0] = R_GetTexture(s->currenttexture->texture); m.tex[1] = R_GetTexture(s->lightmaptexture); @@ -1003,18 +997,7 @@ static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *s) m.numtriangles = s->mesh.numtriangles; m.numverts = s->mesh.numverts; m.index = s->mesh.index; - if (lighthalf) - { - m.cr = 2; - m.cg = 2; - m.cb = 2; - } - else - { - m.cr = 1; - m.cg = 1; - m.cb = 1; - } + m.cr = m.cg = m.cb = (float) (1 << v_overbrightbits.integer); m.ca = 1; m.tex[0] = R_GetTexture(s->currenttexture->texture); m.texcoords[0] = &s->mesh.vertex->st[0]; @@ -1049,11 +1032,7 @@ static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *s) m.numtriangles = s->mesh.numtriangles; m.numverts = s->mesh.numverts; m.index = s->mesh.index; - m.cr = 1; - if (lighthalf) - m.cr *= 2.0f; - m.cg = m.cr; - m.cb = m.cr; + m.cr = m.cg = m.cb = (float) (1 << v_overbrightbits.integer); m.ca = 1; m.tex[0] = R_GetTexture(s->lightmaptexture); m.texcoords[0] = &s->mesh.vertex->uv[0]; diff --git a/gl_screen.c b/gl_screen.c deleted file mode 100644 index 9aa96b08..00000000 --- a/gl_screen.c +++ /dev/null @@ -1,969 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// screen.c -- master for refresh, status bar, console, chat, notify, etc - -#include "quakedef.h" - -/* - -background clear -rendering -turtle/net/ram icons -sbar -centerprint / slow centerprint -notify lines -intermission / finale overlay -loading plaque -console -menu - -required background clears -required update regions - - -syncronous draw mode or async -One off screen buffer, with updates either copied or xblited -Need to double buffer? - - -async draw will require the refresh area to be cleared, because it will be -xblited, but sync draw can just ignore it. - -sync -draw - -CenterPrint () -SlowPrint () -Screen_Update (); -Con_Printf (); - -net -turn off messages option - -the refresh is always rendered, unless the console is full screen - - -console is: - notify lines - half - full - - -*/ - - -float scr_con_current; -float scr_conlines; // lines of console to display - -float oldscreensize, oldfov; -cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"}; -cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 10 - 170 -cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300 -cvar_t scr_centertime = {0, "scr_centertime","2"}; -cvar_t scr_showram = {CVAR_SAVE, "showram","1"}; -cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"}; -cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"}; -cvar_t scr_printspeed = {0, "scr_printspeed","8"}; -cvar_t r_render = {0, "r_render", "1"}; -cvar_t r_brightness = {CVAR_SAVE, "r_brightness", "1"}; // LordHavoc: a method of operating system independent color correction -cvar_t r_contrast = {CVAR_SAVE, "r_contrast", "1"}; // LordHavoc: a method of operating system independent color correction -cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering - -qboolean scr_initialized; // ready to draw - -int clearconsole; -int clearnotify; - -int lightscalebit; -float lightscale; - -qboolean scr_disabled_for_loading; -//qboolean scr_drawloading; -//float scr_disabled_time; - -void SCR_ScreenShot_f (void); - -/* -=============================================================================== - -CENTER PRINTING - -=============================================================================== -*/ - -char scr_centerstring[1024]; -float scr_centertime_start; // for slow victory printing -float scr_centertime_off; -int scr_center_lines; -int scr_erase_lines; -int scr_erase_center; - -/* -============== -SCR_CenterPrint - -Called for important messages that should stay in the center of the screen -for a few moments -============== -*/ -void SCR_CenterPrint (char *str) -{ - strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); - scr_centertime_off = scr_centertime.value; - scr_centertime_start = cl.time; - -// count the number of lines for centering - scr_center_lines = 1; - while (*str) - { - if (*str == '\n') - scr_center_lines++; - str++; - } -} - - -void SCR_DrawCenterString (void) -{ - char *start; - int l; - int x, y; - int remaining; - -// the finale prints the characters one at a time - if (cl.intermission) - remaining = scr_printspeed.value * (cl.time - scr_centertime_start); - else - remaining = 9999; - - scr_erase_center = 0; - start = scr_centerstring; - - if (scr_center_lines <= 4) - y = vid.conheight*0.35; - else - y = 48; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.conwidth - l*8)/2; - if (l > 0) - { - if (remaining < l) - l = remaining; - DrawQ_String(x, y, start, l, 8, 8, 1, 1, 1, 1, 0); - remaining -= l; - if (remaining <= 0) - return; - } - - y += 8; - - while (*start && *start != '\n') - start++; - - if (!*start) - break; - start++; // skip the \n - } while (1); -} - -void SCR_CheckDrawCenterString (void) -{ - if (scr_center_lines > scr_erase_lines) - scr_erase_lines = scr_center_lines; - - scr_centertime_off -= host_frametime; - - if (scr_centertime_off <= 0 && !cl.intermission) - return; - if (key_dest != key_game) - return; - - SCR_DrawCenterString (); -} - -//============================================================================= - -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) -{ - // calculate vision size and alter by aspect, then convert back to angle - return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI; -} - -/* -================= -SCR_CalcRefdef - -Must be called whenever vid changes -Internal use only -================= -*/ -static void SCR_CalcRefdef (void) -{ - float size; - -// vid.recalc_refdef = 0; - -//======================================== - -// bound viewsize - if (scr_viewsize.value < 30) - Cvar_Set ("viewsize","30"); - if (scr_viewsize.value > 120) - Cvar_Set ("viewsize","120"); - -// bound field of view - if (scr_fov.value < 10) - Cvar_Set ("fov","10"); - if (scr_fov.value > 170) - Cvar_Set ("fov","170"); - -// intermission is always full screen - if (cl.intermission) - { - size = 1; - sb_lines = 0; - } - else - { - if (scr_viewsize.value >= 120) - sb_lines = 0; // no status bar at all - else if (scr_viewsize.value >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - size = scr_viewsize.value * (1.0 / 100.0); - } - - if (size >= 1) - { - r_refdef.width = vid.realwidth; - r_refdef.height = vid.realheight; - r_refdef.x = 0; - r_refdef.y = 0; - } - else - { - r_refdef.width = vid.realwidth * size; - r_refdef.height = vid.realheight * size; - r_refdef.x = (vid.realwidth - r_refdef.width)/2; - r_refdef.y = (vid.realheight - r_refdef.height)/2; - } - - r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height); - - r_refdef.width = bound(0, r_refdef.width, vid.realwidth); - r_refdef.height = bound(0, r_refdef.height, vid.realheight); - r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx; - r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy; -} - - -/* -================= -SCR_SizeUp_f - -Keybinding command -================= -*/ -void SCR_SizeUp_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value+10); -} - - -/* -================= -SCR_SizeDown_f - -Keybinding command -================= -*/ -void SCR_SizeDown_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value-10); -} - -//============================================================================ - -void gl_screen_start(void) -{ -} - -void gl_screen_shutdown(void) -{ -} - -void gl_screen_newmap(void) -{ -} - -/* -================== -SCR_Init -================== -*/ -static void R_Envmap_f (void); -void GL_Screen_Init (void) -{ - Cvar_RegisterVariable (&scr_fov); - Cvar_RegisterVariable (&scr_viewsize); - Cvar_RegisterVariable (&scr_conspeed); - Cvar_RegisterVariable (&scr_showram); - Cvar_RegisterVariable (&scr_showturtle); - Cvar_RegisterVariable (&scr_showpause); - Cvar_RegisterVariable (&scr_centertime); - Cvar_RegisterVariable (&scr_printspeed); - Cvar_RegisterVariable (&r_render); - Cvar_RegisterVariable (&r_brightness); - Cvar_RegisterVariable (&r_contrast); - Cvar_RegisterVariable (&gl_dither); -#ifdef NORENDER - Cvar_SetValue("r_render", 0); -#endif - -// -// register our commands -// - Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddCommand ("envmap", R_Envmap_f); - Cmd_AddCommand ("sizeup",SCR_SizeUp_f); - Cmd_AddCommand ("sizedown",SCR_SizeDown_f); - - scr_initialized = true; - - R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown, gl_screen_newmap); -} - - - -/* -============== -SCR_DrawRam -============== -*/ -void SCR_DrawRam (void) -{ -// if (!scr_showram.integer) -// return; -// DrawQ_Pic (32, 0, "ram", 0, 0, 1, 1, 1, 1, 0); -} - -/* -============== -SCR_DrawTurtle -============== -*/ -void SCR_DrawTurtle (void) -{ - static int count; - - if (cls.state != ca_connected) - return; - - if (!scr_showturtle.integer) - return; - - if (host_frametime < 0.1) - { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0); -} - -/* -============== -SCR_DrawNet -============== -*/ -void SCR_DrawNet (void) -{ - if (cls.state != ca_connected) - return; - if (realtime - cl.last_received_message < 0.3) - return; - if (cls.demoplayback) - return; - - DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0); -} - -/* -============== -DrawPause -============== -*/ -void SCR_DrawPause (void) -{ - cachepic_t *pic; - - if (cls.state != ca_connected) - return; - - if (!scr_showpause.integer) // turn off for screenshots - return; - - if (!cl.paused) - return; - - pic = Draw_CachePic ("gfx/pause.lmp"); - DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/pause.lmp", 0, 0, 1, 1, 1, 1, 0); -} - - - -/* -============== -SCR_DrawLoading -============== -*/ -/* -void SCR_DrawLoading (void) -{ - cachepic_t *pic; - - if (!scr_drawloading) - return; - - pic = Draw_CachePic ("gfx/loading.lmp"); - DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0); -} -*/ - - - -//============================================================================= - - -/* -================== -SCR_SetUpToDrawConsole -================== -*/ -void SCR_SetUpToDrawConsole (void) -{ - Con_CheckResize (); - -// decide on the height of the console - con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; - - if (con_forcedup) - { - scr_conlines = vid.conheight; // full screen - scr_con_current = scr_conlines; - } - else if (key_dest == key_console) - scr_conlines = vid.conheight/2; // half screen - else - scr_conlines = 0; // none visible - - if (scr_conlines < scr_con_current) - { - scr_con_current -= scr_conspeed.value*host_realframetime; - if (scr_conlines > scr_con_current) - scr_con_current = scr_conlines; - - } - else if (scr_conlines > scr_con_current) - { - scr_con_current += scr_conspeed.value*host_realframetime; - if (scr_conlines < scr_con_current) - scr_con_current = scr_conlines; - } -} - -/* -================== -SCR_DrawConsole -================== -*/ -void SCR_DrawConsole (void) -{ - if (scr_con_current) - { - Con_DrawConsole (scr_con_current); - clearconsole = 0; - } - else - { - if (key_dest == key_game || key_dest == key_message) - Con_DrawNotify (); // only draw notify in game - } -} - - -/* -============================================================================== - - SCREEN SHOTS - -============================================================================== -*/ - -/* -================== -SCR_ScreenShot_f -================== -*/ -void SCR_ScreenShot_f (void) -{ - byte *buffer, gamma[256]; - char filename[80]; - char checkname[MAX_OSPATH]; - int i; -// -// find a file name to save it to -// - strcpy(filename,"dp0000.tga"); - - for (i=0 ; i<=9999 ; i++) - { - filename[2] = (i/1000)%10 + '0'; - filename[3] = (i/ 100)%10 + '0'; - filename[4] = (i/ 10)%10 + '0'; - filename[5] = (i/ 1)%10 + '0'; - sprintf (checkname, "%s/%s", com_gamedir, filename); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==10000) - { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); - return; - } - - buffer = Mem_Alloc(tempmempool, vid.realwidth*vid.realheight*3); - glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer); - CHECKGLERROR - - // apply hardware gamma to the image - BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma); - Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma); - - Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer); - - Mem_Free(buffer); - Con_Printf ("Wrote %s\n", filename); -} - -/* -=============== -R_Envmap_f - -Grab six views for environment mapping tests -=============== -*/ -float CalcFov (float fov_x, float width, float height); -struct -{ - float angles[3]; - char *name; -} -envmapinfo[6] = -{ - {{ 0, 0, 0}, "ft"}, - {{ 0, 90, 0}, "rt"}, - {{ 0, 180, 0}, "bk"}, - {{ 0, 270, 0}, "lf"}, - {{-90, 90, 0}, "up"}, - {{ 90, 90, 0}, "dn"} -}; -static void R_Envmap_f (void) -{ - int i, size; - char filename[256]; - char basename[256]; - byte *buffer, gamma[256]; - - if (Cmd_Argc() != 3) - { - Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); - return; - } - - if (!r_render.integer) - return; - - strcpy(basename, Cmd_Argv(1)); - size = atoi(Cmd_Argv(2)); - if (size != 128 && size != 256 && size != 512 && size != 1024) - { - Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); - return; - } - if (size > vid.realwidth || size > vid.realheight) - { - Con_Printf("envmap: your resolution is not big enough to render that size\n"); - return; - } - - buffer = Mem_Alloc(tempmempool, size*size*3); - if (buffer == NULL) - { - Con_Printf("envmap: unable to allocate memory for image\n"); - return; - } - - BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma); - -// glDrawBuffer (GL_FRONT); -// glReadBuffer (GL_FRONT); - glDrawBuffer (GL_BACK); - glReadBuffer (GL_BACK); - envmap = true; - - r_refdef.x = 0; - r_refdef.y = 0; - r_refdef.width = size; - r_refdef.height = size; - - r_refdef.fov_x = 90; - r_refdef.fov_y = 90; - - for (i = 0;i < 6;i++) - { - VectorCopy(envmapinfo[i].angles, r_refdef.viewangles); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) - R_RenderView (); - glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer); - sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name); - Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma); - Image_WriteTGARGB_preflipped(filename, size, size, buffer); - } - - envmap = false; - glDrawBuffer (GL_BACK); - glReadBuffer (GL_BACK); - - Mem_Free(buffer); - - // cause refdef to be fixed -// vid.recalc_refdef = 1; -} - -//============================================================================= - - -/* -=============== -SCR_BeginLoadingPlaque - -================ -*/ -/* -void SCR_BeginLoadingPlaque (void) -{ - S_StopAllSounds (true); - -// if (cls.state != ca_connected) -// return; -// if (cls.signon != SIGNONS) -// return; - -// redraw with no console and the loading plaque -// Con_ClearNotify (); -// scr_centertime_off = 0; -// scr_con_current = 0; - - scr_drawloading = true; - SCR_UpdateScreen (); - -// scr_disabled_for_loading = true; -// scr_disabled_time = realtime; -} -*/ - -/* -=============== -SCR_EndLoadingPlaque - -================ -*/ -/* -void SCR_EndLoadingPlaque (void) -{ -// scr_disabled_for_loading = false; - scr_drawloading = false; - Con_ClearNotify (); -} -*/ - -//============================================================================= - -char *scr_notifystring; - -void SCR_DrawNotifyString (void) -{ - char *start; - int l; - int x, y; - - start = scr_notifystring; - - y = vid.conheight*0.35; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.conwidth - l*8)/2; - DrawQ_String (x, y, start, l, 8, 8, 1, 1, 1, 1, 0); - - y += 8; - - while (*start && *start != '\n') - start++; - - if (!*start) - break; - start++; // skip the \n - } - while (1); -} - -//============================================================================= - -void DrawCrosshair(int num); - -char r_speeds_string[1024]; -int speedstringcount, r_timereport_active; -double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0; - -void R_TimeReport(char *desc) -{ - char tempbuf[256]; - int length; - int t; - - if (!r_timereport_active) - return; - - r_timereport_temp = r_timereport_current; - r_timereport_current = Sys_DoubleTime(); - t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0); - - sprintf(tempbuf, "%8i %s", t, desc); - length = strlen(tempbuf); - while (length < 20) - tempbuf[length++] = ' '; - tempbuf[length] = 0; - if (speedstringcount + length > (vid.conwidth / 8)) - { - strcat(r_speeds_string, "\n"); - speedstringcount = 0; - } - // skip the space at the beginning if it's the first on the line - if (speedstringcount == 0) - { - strcat(r_speeds_string, tempbuf + 1); - speedstringcount = length - 1; - } - else - { - strcat(r_speeds_string, tempbuf); - speedstringcount += length; - } -} - -void R_TimeReport_Start(void) -{ - r_timereport_active = r_speeds.integer && cl.worldmodel && cls.state == ca_connected; - r_speeds_string[0] = 0; - if (r_timereport_active) - { - speedstringcount = 0; - AngleVectors (r_refdef.viewangles, vpn, NULL, NULL); - //sprintf(r_speeds_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", - // r_refdef.vieworg[0] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[0]), r_refdef.vieworg[1] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[1]), r_refdef.vieworg[2] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[2]), - // r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), - // vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]), - sprintf(r_speeds_string, - "org:'%+8.2f %+8.2f %+8.2f' ang:'%+4.0f %+4.0f %+4.0f' dir:'%+2.3f %+2.3f %+2.3f'\n" - "world:%6i faces%6i nodes%6i leafs%6i walls%6i dlitwalls\n" - "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n" - "%6i modeltris%6i transmeshs%6i transtris%6i meshs%6i meshtris\n", - r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0], r_refdef.viewangles[1], r_refdef.viewangles[2], vpn[0], vpn[1], vpn[2], - c_faces, c_nodes, c_leafs, c_brush_polys, c_light_polys, - c_models, c_bmodels, c_sprites, c_particles, c_dlights, - c_alias_polys, c_transmeshs, c_transtris, c_meshs, c_meshtris); - - c_brush_polys = 0; - c_alias_polys = 0; - c_light_polys = 0; - c_faces = 0; - c_nodes = 0; - c_leafs = 0; - c_models = 0; - c_bmodels = 0; - c_sprites = 0; - c_particles = 0; - // c_dlights = 0; - - r_timereport_start = Sys_DoubleTime(); - } -} - -void R_TimeReport_End(void) -{ - r_timereport_current = r_timereport_start; - R_TimeReport("total"); - - if (r_timereport_active) - { - int i, j, lines, y; - lines = 1; - for (i = 0;r_speeds_string[i];i++) - if (r_speeds_string[i] == '\n') - lines++; - y = vid.conheight - sb_lines - lines * 8/* - 8*/; - i = j = 0; - DrawQ_Fill(0, y, vid.conwidth, lines * 8, 0, 0, 0, 0.5, 0); - while (r_speeds_string[i]) - { - j = i; - while (r_speeds_string[i] && r_speeds_string[i] != '\n') - i++; - if (i - j > 0) - DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0); - if (r_speeds_string[i] == '\n') - i++; - y += 8; - } - } -} - -/* -================== -SCR_UpdateScreen - -This is called every frame, and can also be called explicitly to flush -text to the screen. - -LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :) -================== -*/ -void SCR_UpdateScreen (void) -{ - VID_UpdateGamma(false); - - if (scr_disabled_for_loading) - return; - - if (!scr_initialized || !con_initialized) - return; // not initialized yet - - //Mem_CheckSentinelsGlobal(); - //R_TimeReport("memtest"); - - R_TimeReport("other"); - - glFinish (); - CHECKGLERROR - - GL_EndRendering (); - - R_TimeReport("finish"); - - GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight); - - if (gl_combine.integer && !gl_combine_extension) - Cvar_SetValue("gl_combine", 0); - - lighthalf = gl_lightmode.integer; - - lightscalebit = 0; - if (lighthalf) - lightscalebit += 1; - - if (gl_combine.integer && r_multitexture.integer) - lightscalebit += 2; - - lightscale = 1.0f / (float) (1 << lightscalebit); - - R_TimeReport("setup"); - - // determine size of refresh window - SCR_CalcRefdef(); - - R_TimeReport("calcrefdef"); - - if (r_render.integer) - { - glClearColor(0,0,0,0); - CHECKGLERROR - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) - CHECKGLERROR - if (gl_dither.integer) - glEnable(GL_DITHER); - else - glDisable(GL_DITHER); - CHECKGLERROR - } - - SCR_SetUpToDrawConsole(); - - R_TimeReport("clear"); - - if (scr_conlines < vid.conheight) - R_RenderView(); - - SCR_DrawRam(); - SCR_DrawNet(); - SCR_DrawTurtle(); - SCR_DrawPause(); - SCR_CheckDrawCenterString(); - Sbar_Draw(); - SHOWLMP_drawall(); - - SCR_DrawConsole(); - M_Draw(); - - ui_draw(); - - R_TimeReport("2d"); - - R_TimeReport_End(); - - // draw 2D stuff - R_DrawQueue(); - - R_TimeReport_Start(); -} diff --git a/glquake.h b/glquake.h index f510c1bf..8ddc2901 100644 --- a/glquake.h +++ b/glquake.h @@ -40,17 +40,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern qboolean isG200; extern qboolean isRagePro; -extern void GL_BeginRendering (int *x, int *y, int *width, int *height); -extern void GL_EndRendering (void); - -extern float gldepthmin, gldepthmax; +extern float gldepthmin, gldepthmax; //==================================================== -extern const char *gl_vendor; -extern const char *gl_renderer; -extern const char *gl_version; -extern const char *gl_extensions; +extern const char *gl_vendor; +extern const char *gl_renderer; +extern const char *gl_version; +extern const char *gl_extensions; #ifndef _WIN32 #define APIENTRY /* */ diff --git a/makefile b/makefile index 07e0eaa3..8cfd6929 100644 --- a/makefile +++ b/makefile @@ -9,7 +9,7 @@ SOUNDLIB=-lasound #SND=snd_oss.o #SOUNDLIB= -OBJECTS= builddate.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o gl_screen.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_particles.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o +OBJECTS= builddate.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_particles.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o #K6/athlon optimizations CPUOPTIMIZATIONS=-march=k6 diff --git a/menu.c b/menu.c index 0f42d577..0eb33215 100644 --- a/menu.c +++ b/menu.c @@ -117,7 +117,8 @@ void M_DrawBackground(void) menu_height = 200; menu_x = (vid.conwidth - menu_width) * 0.5; menu_y = (vid.conheight - menu_height) * 0.5; - DrawQ_Fill(menu_x, menu_y, menu_width, menu_height, 0, 0, 0, 0.5, 0); + //DrawQ_Fill(menu_x, menu_y, menu_width, menu_height, 0, 0, 0, 0.5, 0); + DrawQ_Fill(0, 0, vid.conwidth, vid.conheight, 0, 0, 0, 0.5, 0); } /* @@ -152,6 +153,21 @@ void M_PrintWhite (float cx, float cy, char *str) DrawQ_String(menu_x + cx, menu_y + cy, str, 0, 8, 8, 1, 1, 1, 1, 0); } +void M_ItemPrint (float cx, float cy, char *str, int unghosted) +{ + /* + while (*str) + { + M_DrawCharacter (cx, cy, (*str++)+128); + cx += 8; + } + */ + if (unghosted) + DrawQ_String(menu_x + cx, menu_y + cy, str, 0, 8, 8, 1, 1, 1, 1, 0); + else + DrawQ_String(menu_x + cx, menu_y + cy, str, 0, 8, 8, 0.7, 0.7, 0.7, 1, 0); +} + void M_DrawPic (float cx, float cy, char *picname) { DrawQ_Pic (menu_x + cx, menu_y + cy, picname, 0, 0, 1, 1, 1, 1, 0); @@ -1233,7 +1249,7 @@ again: //============================================================================= /* OPTIONS MENU */ -#define OPTIONS_ITEMS (vid_menudrawfn ? 25 : 24) +#define OPTIONS_ITEMS 26 #define SLIDER_RANGE 10 @@ -1253,58 +1269,56 @@ void M_AdjustSliders (int dir) switch (options_cursor) { - case 3: // screen size + case 4: + Cvar_SetValue ("scr_2dresolution", bound(0, scr_2dresolution.value + dir * 0.2, 1)); + break; + case 5: Cvar_SetValue ("viewsize", bound(30, scr_viewsize.value + dir * 10, 120)); break; - case 4: + case 6: + Cvar_SetValue ("r_skyquality", bound(0, r_skyquality.integer + dir, 2)); + break; + case 7: Cvar_SetValue ("r_ser", !r_ser.integer); break; - - case 5: // overbright rendering - Cvar_SetValue ("gl_lightmode", !gl_lightmode.integer); + case 8: + Cvar_SetValue ("v_overbrightbits", bound(0, v_overbrightbits.integer + dir, 4)); break; - - case 6: // dithering + case 9: Cvar_SetValue ("gl_dither", !gl_dither.integer); break; - - case 7: // sky quality - Cvar_SetValue ("r_skyquality", bound(0, r_skyquality.integer + dir, 2)); - break; - - case 8: // hardware gamma - Cvar_SetValue ("vid_gamma", bound(1, vid_gamma.value + dir * 0.25, 5)); - break; - - case 9: // hardware brightness - Cvar_SetValue ("vid_brightness", bound(1, vid_brightness.value + dir * 0.25, 5)); + case 10: + Cvar_SetValue ("v_hwgamma", !v_hwgamma.integer); break; - - case 10: // hardware contrast - Cvar_SetValue ("vid_contrast", bound(0.2, vid_contrast.value + dir * 0.08, 1)); + case 11: + Cvar_SetValue ("v_gamma", bound(1, v_gamma.value + dir * 0.25, 5)); break; - - case 11: // software brightness - Cvar_SetValue ("r_brightness", bound(1, r_brightness.value + dir * 0.25, 5)); + case 12: + Cvar_SetValue ("v_contrast", bound(0.5, v_contrast.value + dir * 0.25, 5)); break; - - case 12: // software base brightness - Cvar_SetValue ("r_contrast", bound(0.2, r_contrast.value + dir * 0.08, 1)); + case 13: + Cvar_SetValue ("v_brightness", bound(0, v_brightness.value + dir * 0.05, 0.8)); break; - - case 13: // music volume + case 14: // music volume #ifdef _WIN32 Cvar_SetValue ("bgmvolume", bound(0, bgmvolume.value + dir * 1.0, 1)); #else Cvar_SetValue ("bgmvolume", bound(0, bgmvolume.value + dir * 0.1, 1)); #endif break; - - case 14: // sfx volume + case 15: // sfx volume Cvar_SetValue ("volume", bound(0, volume.value + dir * 0.1, 1)); break; - - case 15: // always run + case 16: + Cvar_SetValue ("crosshair", bound(0, crosshair.integer + dir, 5)); + break; + case 17: + Cvar_SetValue ("crosshair_size", bound(1, crosshair_size.value + dir, 5)); + break; + case 18: // show framerate + Cvar_SetValue ("showfps", !showfps.integer); + break; + case 19: // always run if (cl_forwardspeed.value > 200) { Cvar_SetValue ("cl_forwardspeed", 200); @@ -1316,38 +1330,24 @@ void M_AdjustSliders (int dir) Cvar_SetValue ("cl_backspeed", 400); } break; - - case 16: // lookspring + case 20: // lookspring Cvar_SetValue ("lookspring", !lookspring.integer); break; - - case 17: // lookstrafe + case 21: // lookstrafe Cvar_SetValue ("lookstrafe", !lookstrafe.integer); break; - - case 18: // mouse speed + case 22: // mouse speed Cvar_SetValue ("sensitivity", bound(1, sensitivity.value + dir * 0.5, 50)); break; - - case 19: // mouse look + case 23: // mouse look Cvar_SetValue ("freelook", !freelook.integer); break; - - case 20: // invert mouse + case 24: // invert mouse Cvar_SetValue ("m_pitch", -m_pitch.value); break; - - case 21: // windowed mouse + case 25: // windowed mouse Cvar_SetValue ("vid_mouse", !vid_mouse.integer); break; - - case 22: - Cvar_SetValue ("crosshair", bound(0, crosshair.integer + dir, 5)); - break; - - case 23: // show framerate - Cvar_SetValue ("showfps", !showfps.integer); - break; } } @@ -1381,6 +1381,59 @@ void M_DrawCheckbox (int x, int y, int on) M_Print (x, y, "off"); } +/* +int m_2dres[] = +{ + 320, 200, + 320, 240, + 400, 300, + 512, 384, + 640, 480, + 800, 600, + 1024, 768, + 1280, 960, + 1600, 1200, + 2048, 1536 +}; + +int M_Num2DResolutions(void) +{ + return sizeof(m_2dres) / sizeof(int[2]); +}; + +float M_Classify2DResolution(void) +{ + int i, num, *res, best, bestdist, diff[3]; + num = M_Num2DResolutions(); + best = -1; + bestdist = 1000000000; + for (i = 0;i < num;i++) + { + res = m_2dres + i * 2; + diff[0] = res[0] - vid.conwidth; + diff[1] = res[1] - vid.conheight; + diff[2] = 0; + dist = DotProduct(diff, diff); + if (bestdist > dist) + { + bestdist = dist; + best = i; + } + } + return i; +} + +void M_Adjust2DResolution(int dir) +{ + int i, num; + i = M_Classify2DResolution() + dir; + num = M_Num2DResolutions() - 1; + i = bound(0, i, num); + Cvar_SetValue("v_2dwidth", m_2dres[i*2]); + Cvar_SetValue("v_2dheight", m_2dres[i*2+1]); +} +*/ + void M_Options_Draw (void) { float y; @@ -1394,18 +1447,22 @@ void M_Options_Draw (void) M_Print(16, y, " Customize controls");y += 8; M_Print(16, y, " Go to console");y += 8; M_Print(16, y, " Reset to defaults");y += 8; + M_ItemPrint(16, y, " Video Options", vid_menudrawfn != NULL);y += 8; + M_Print(16, y, " 2D Resolution");M_DrawSlider(220, y, scr_2dresolution.value);y += 8; M_Print(16, y, " Screen size");M_DrawSlider(220, y, (scr_viewsize.value - 30) /(120 - 30));y += 8; + M_Print(16, y, " Sky Quality");M_DrawSlider(220, y, r_skyquality.value / 2);y += 8; M_Print(16, y, "Hidden Surface Removal");M_DrawCheckbox(220, y, r_ser.integer);y += 8; - M_Print(16, y, " Overbright Rendering");M_DrawCheckbox(220, y, gl_lightmode.integer);y += 8; + M_Print(16, y, " Overbright Bits");M_DrawSlider(220, y, (v_overbrightbits.value) / 4);y += 8; M_Print(16, y, " Dithering");M_DrawCheckbox(220, y, gl_dither.integer);y += 8; - M_Print(16, y, " Sky Quality");M_DrawSlider(220, y, r_skyquality.value / 2);y += 8; - M_Print(16, y, " Hardware Gamma");M_DrawSlider(220, y, (vid_gamma.value - 1) / 4);y += 8; - M_Print(16, y, " Hardware Brightness");M_DrawSlider(220, y, (vid_brightness.value - 1) / 4);y += 8; - M_Print(16, y, " Hardware Contrast");M_DrawSlider(220, y, (vid_contrast.value - 0.2) / 0.8);y += 8; - M_Print(16, y, " Software Brightness");M_DrawSlider(220, y, (r_brightness.value - 1) / 4);y += 8; - M_Print(16, y, " Software Contrast");M_DrawSlider(220, y, (r_contrast.value - 0.2) / 0.8);y += 8; - M_Print(16, y, " CD Music Volume");M_DrawSlider(220, y, bgmvolume.value);y += 8; - M_Print(16, y, " Sound Volume");M_DrawSlider(220, y, volume.value);y += 8; + M_ItemPrint(16, y, "Hardware Gamma Control", hardwaregammasupported);M_DrawCheckbox(220, y, v_hwgamma.integer);y += 8; + M_ItemPrint(16, y, " Gamma", v_hwgamma.integer);M_DrawSlider(220, y, (v_gamma.value - 1) / 4);y += 8; + M_Print(16, y, " Contrast");M_DrawSlider(220, y, (v_contrast.value - 0.5) / (5 - 0.5));y += 8; + M_Print(16, y, " Brightness");M_DrawSlider(220, y, v_brightness.value / 0.8);y += 8; + M_ItemPrint(16, y, " CD Music Volume", Cvar_FindVar("bgmvolume") != NULL);M_DrawSlider(220, y, bgmvolume.value);y += 8; + M_ItemPrint(16, y, " Sound Volume", Cvar_FindVar("volume") != NULL);M_DrawSlider(220, y, volume.value);y += 8; + M_Print(16, y, " Crosshair");M_DrawSlider(220, y, crosshair.value / 5);y += 8; + M_Print(16, y, " Crosshair Size");M_DrawSlider(220, y, (crosshair_size.value - 1) / 4);y += 8; + M_Print(16, y, " Show Framerate");M_DrawCheckbox(220, y, showfps.integer);y += 8; M_Print(16, y, " Always Run");M_DrawCheckbox(220, y, cl_forwardspeed.value > 200);y += 8; M_Print(16, y, " Lookspring");M_DrawCheckbox(220, y, lookspring.integer);y += 8; M_Print(16, y, " Lookstrafe");M_DrawCheckbox(220, y, lookstrafe.integer);y += 8; @@ -1413,11 +1470,6 @@ void M_Options_Draw (void) M_Print(16, y, " Mouse Look");M_DrawCheckbox(220, y, freelook.integer);y += 8; M_Print(16, y, " Invert Mouse");M_DrawCheckbox(220, y, m_pitch.value < 0);y += 8; M_Print(16, y, " Use Mouse");M_DrawCheckbox(220, y, vid_mouse.integer);y += 8; - M_Print(16, y, " Crosshair");M_DrawSlider(220, y, crosshair.value / 5);y += 8; - M_Print(16, y, " Show Framerate");M_DrawCheckbox(220, y, showfps.integer);y += 8; - if (vid_menudrawfn) - M_Print(16, y, " Video Options"); - y += 8; // cursor M_DrawCharacter(200, 32 + options_cursor*8, 12+((int)(realtime*4)&1)); @@ -1446,12 +1498,12 @@ void M_Options_Key (int k) case 2: Cbuf_AddText ("exec default.cfg\n"); break; - default: - // this is really just another case, but since it is calculated... - if (vid_menudrawfn && options_cursor == (OPTIONS_ITEMS - 1)) + case 3: + if (vid_menudrawfn) M_Menu_Video_f (); - else - M_AdjustSliders (1); + break; + default: + M_AdjustSliders (1); break; } return; @@ -1522,11 +1574,9 @@ void M_FindKeysForCommand (char *command, int *twokeys) { int count; int j; - int l; char *b; twokeys[0] = twokeys[1] = -1; - l = strlen(command); count = 0; for (j=0 ; j<256 ; j++) @@ -1534,7 +1584,7 @@ void M_FindKeysForCommand (char *command, int *twokeys) b = keybindings[j]; if (!b) continue; - if (!strncmp (b, command, l) ) + if (!strcmp (b, command) ) { twokeys[count] = j; count++; @@ -1547,17 +1597,14 @@ void M_FindKeysForCommand (char *command, int *twokeys) void M_UnbindCommand (char *command) { int j; - int l; char *b; - l = strlen(command); - for (j=0 ; j<256 ; j++) { b = keybindings[j]; if (!b) continue; - if (!strncmp (b, command, l) ) + if (!strcmp (b, command)) Key_SetBinding (j, ""); } } diff --git a/model_brush.h b/model_brush.h index 21c6a7ee..d25f4858 100644 --- a/model_brush.h +++ b/model_brush.h @@ -176,7 +176,7 @@ typedef struct msurface_s unsigned short cached_light[MAXLIGHTMAPS]; // if lightmap was lit by dynamic lights, force update on next frame short cached_dlight; - // to cause lightmap to be rerendered when lighthalf changes + // to cause lightmap to be rerendered when v_overbrightbits changes short cached_lightscalebit; // rerender lightmaps when r_ambient changes float cached_ambient; diff --git a/palette.c b/palette.c index cdcbd1e7..76a2de55 100644 --- a/palette.c +++ b/palette.c @@ -6,9 +6,11 @@ unsigned int d_8to24table[256]; byte host_basepal[768]; byte texgamma[256]; -cvar_t vid_gamma = {CVAR_SAVE, "vid_gamma", "1"}; -cvar_t vid_brightness = {CVAR_SAVE, "vid_brightness", "1"}; -cvar_t vid_contrast = {CVAR_SAVE, "vid_contrast", "1"}; +cvar_t v_gamma = {CVAR_SAVE, "v_gamma", "1"}; +cvar_t v_contrast = {CVAR_SAVE, "v_contrast", "1"}; +cvar_t v_brightness = {CVAR_SAVE, "v_brightness", "0"}; +cvar_t v_overbrightbits = {CVAR_SAVE, "v_overbrightbits", "0"}; +cvar_t v_hwgamma = {0, "v_hwgamma", "1"}; void Palette_Setup8to24(void) { @@ -117,45 +119,57 @@ void BuildGammaTable16(float prescale, float gamma, float scale, float base, uns qboolean hardwaregammasupported = false; void VID_UpdateGamma(qboolean force) { - static float cachegamma = -1, cachebrightness = -1, cachecontrast = -1, cachelighthalf = -1; + static float cachegamma = -1, cachebrightness = -1, cachecontrast = -1; + static int cacheoverbrightbits = -1, cachehwgamma = -1; // LordHavoc: don't mess with gamma tables if running dedicated if (cls.state == ca_dedicated) return; - if (!force && vid_gamma.value == cachegamma && vid_brightness.value == cachebrightness && vid_contrast.value == cachecontrast && lighthalf == cachelighthalf) + if (!force + && v_gamma.value == cachegamma + && v_contrast.value == cachecontrast + && v_brightness.value == cachebrightness + && v_overbrightbits.integer == cacheoverbrightbits + && v_hwgamma.value == cachehwgamma) return; - if (vid_gamma.value < 0.1) - Cvar_SetValue("vid_gamma", 0.1); - if (vid_gamma.value > 5.0) - Cvar_SetValue("vid_gamma", 5.0); + if (v_gamma.value < 0.1) + Cvar_SetValue("v_gamma", 0.1); + if (v_gamma.value > 5.0) + Cvar_SetValue("v_gamma", 5.0); - if (vid_brightness.value < 1.0) - Cvar_SetValue("vid_brightness", 1.0); - if (vid_brightness.value > 5.0) - Cvar_SetValue("vid_brightness", 5.0); + if (v_contrast.value < 0.5) + Cvar_SetValue("v_contrast", 0.5); + if (v_contrast.value > 5.0) + Cvar_SetValue("v_contrast", 5.0); - if (vid_contrast.value < 0.2) - Cvar_SetValue("vid_contrast", 0.2); - if (vid_contrast.value > 1) - Cvar_SetValue("vid_contrast", 1); + if (v_brightness.value < 0) + Cvar_SetValue("v_brightness", 0); + if (v_brightness.value > 0.8) + Cvar_SetValue("v_brightness", 0.8); - cachegamma = vid_gamma.value; - cachebrightness = vid_brightness.value; - cachecontrast = vid_contrast.value; - cachelighthalf = lighthalf; + cachegamma = v_gamma.value; + cachecontrast = v_contrast.value; + cachebrightness = v_brightness.value; + cacheoverbrightbits = v_overbrightbits.integer; - hardwaregammasupported = VID_SetGamma((cachelighthalf ? 2.0f : 1.0f), cachegamma, cachebrightness * cachecontrast, 1 - cachecontrast); + hardwaregammasupported = VID_SetGamma((float) (1 << cacheoverbrightbits), cachegamma, cachecontrast, cachebrightness); if (!hardwaregammasupported) + { Con_Printf("Hardware gamma not supported.\n"); + Cvar_SetValue("v_hwgamma", 0); + } + cachehwgamma = v_hwgamma.integer; } void Gamma_Init(void) { - Cvar_RegisterVariable(&vid_gamma); - Cvar_RegisterVariable(&vid_brightness); - Cvar_RegisterVariable(&vid_contrast); + Cvar_RegisterVariable(&v_gamma); + Cvar_RegisterVariable(&v_brightness); + Cvar_RegisterVariable(&v_contrast); + Cvar_RegisterVariable(&v_hwgamma); + Cvar_RegisterVariable(&v_overbrightbits); } void Palette_Init(void) diff --git a/palette.h b/palette.h index d12c40a8..7e3ef152 100644 --- a/palette.h +++ b/palette.h @@ -1,7 +1,9 @@ -extern cvar_t vid_gamma; -extern cvar_t vid_brightness; -extern cvar_t vid_contrast; +extern cvar_t v_gamma; +extern cvar_t v_contrast; +extern cvar_t v_brightness; +extern cvar_t v_overbrightbits; +extern cvar_t v_hwgamma; extern unsigned int d_8to24table[256]; //extern byte d_15to8table[32768]; diff --git a/protocol.c b/protocol.c index 20cf850d..c2127571 100644 --- a/protocol.c +++ b/protocol.c @@ -19,3 +19,47 @@ void ClearStateToDefault(entity_state_t *s) s->active = 0; } +// (server) clears the database to contain no frames (thus delta compression compresses against nothing) +void EntityFrame_ClearDatabase(entity_database_t *d) +{ + memset(d, 0, sizeof(*d)); + d->ackframe = -1; +} + +// (server) acknowledge a frame as recieved by client (removes old frames from database, will use this new frame for delta compression) +void EntityFrame_AckFrame(entity_database_t *d, int frame) +{ +} + +// (server) clears frame, to prepare for adding entities +void EntityFrame_Clear(entity_frame_t *f) +{ + memset(f, 0, sizeof(*f)); +} + +// (server) allocates an entity slot in frame, returns NULL if full +entity_state_t *EntityFrame_NewEntity(entity_frame_t *f, int number) +{ + entity_state_t *e; + if (f->numentities >= MAX_ENTITY_DATABASE) + return NULL; + e = &f->entitydata[f->numentities++]; + e->active = true; + e->number = number; + return e; +} + +// (server) writes a frame to network stream +void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int deltaframe, int newframe, sizebuf_t *msg) +{ +} + +// (client) reads a frame from network stream +void EntityFrame_Read(entity_database_t *d, entity_frame_t *f) +{ +} + +// (client) fetchs an entity from the database, read with _Read, fills in structs for current and previous state +void EntityFrame_FetchEntity(entity_database_t *d, entity_state_t *previous, entity_state_t *current) +{ +} diff --git a/protocol.h b/protocol.h index d3b25a8e..22f18071 100644 --- a/protocol.h +++ b/protocol.h @@ -160,7 +160,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_stufftext 9 // [string] stuffed into client's console buffer // the string should be \n terminated #define svc_setangle 10 // [angle3] set the view angle to this absolute value - + #define svc_serverinfo 11 // [long] version // [string] signon string // [string]..[0]model cache @@ -173,11 +173,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_updatecolors 17 // [byte] [byte] #define svc_particle 18 // [vec3] #define svc_damage 19 - + #define svc_spawnstatic 20 // svc_spawnbinary 21 #define svc_spawnbaseline 22 - + #define svc_temp_entity 23 #define svc_setpause 24 // [byte] on / off @@ -209,7 +209,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_sound2 54 // short soundindex instead of byte #define svc_spawnbaseline2 55 // short modelindex instead of byte #define svc_spawnstatic2 56 // short modelindex instead of byte -#define svc_unusedlh2 57 +#define svc_entities 57 // [short] numentities [int] deltaframe [float vector] eye [variable length] entitydata #define svc_unusedlh3 58 #define svc_spawnstaticsound2 59 // [coord3] [short] samp [byte] vol [byte] aten @@ -275,12 +275,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct { double time; // time this state was built + vec3_t origin; + vec3_t angles; + int number; // entity number this state is for unsigned short active; // true if a valid state unsigned short modelindex; unsigned short frame; unsigned short effects; - vec3_t origin; - vec3_t angles; byte colormap; byte skin; byte alpha; @@ -288,7 +289,59 @@ typedef struct byte glowsize; byte glowcolor; byte flags; + byte padding[3]; } entity_state_t; +typedef struct +{ + int framenum; + int firstentity; // index into entitydata, modulo MAX_ENTITY_DATABASE + int endentity; // index into entitydata, firstentity + numentities +} +entity_frameinfo_t; + +#define MAX_ENTITY_HISTORY 64 +#define MAX_ENTITY_DATABASE 4096 + +typedef struct +{ + // note: these can be far out of range, modulo with MAX_ENTITY_DATABASE to get a valid range (which may wrap) + // start and end of used area, when adding a new update to database, store at endpos, and increment endpos + // when removing updates from database, nudge down frames array to only contain useful frames + // this logic should explain better: + // if (numframes >= MAX_ENTITY_HISTORY || (frames[numframes - 1].endentity - frames[0].firstentity) + entitiestoadd > MAX_ENTITY_DATABASE) + // flushdatabase(); + // note: if numframes == 0, insert at start (0 in entitydata) + // the only reason this system is used is to avoid copying memory when frames are removed + int numframes; + int ackframe; // server only: last acknowledged frame + entity_frameinfo_t frames[MAX_ENTITY_HISTORY]; + entity_state_t entitydata[MAX_ENTITY_DATABASE]; +} +entity_database_t; + +// build entity data in this, to pass to entity read/write functions +typedef struct +{ + int framenum; + int numentities; + entity_state_t entitydata[MAX_ENTITY_DATABASE]; +} +entity_frame_t; + void ClearStateToDefault(entity_state_t *s); +// (server) clears the database to contain no frames (thus delta compression compresses against nothing) +void EntityFrame_ClearDatabase(entity_database_t *d); +// (server) acknowledge a frame as recieved by client (removes old frames from database, will use this new frame for delta compression) +void EntityFrame_AckFrame(entity_database_t *d, int frame); +// (server) clears frame, to prepare for adding entities +void EntityFrame_Clear(entity_frame_t *f); +// (server) allocates an entity slot in frame, returns NULL if full +entity_state_t *EntityFrame_NewEntity(entity_frame_t *f, int number); +// (server) writes a frame to network stream +void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int deltaframe, int newframe, sizebuf_t *msg); +// (client) reads a frame from network stream +void EntityFrame_Read(entity_database_t *d, entity_frame_t *f); +// (client) fetchs an entity from the database, read with _Read, fills in structs for current and previous state +void EntityFrame_FetchEntity(entity_database_t *d, entity_state_t *previous, entity_state_t *current); diff --git a/r_crosshairs.c b/r_crosshairs.c index 6ab2619a..46585f98 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -1,9 +1,10 @@ #include "quakedef.h" -cvar_t crosshair_brightness = {CVAR_SAVE, "crosshair_brightness", "1.0"}; -cvar_t crosshair_alpha = {CVAR_SAVE, "crosshair_alpha", "1.0"}; +cvar_t crosshair_brightness = {CVAR_SAVE, "crosshair_brightness", "1"}; +cvar_t crosshair_alpha = {CVAR_SAVE, "crosshair_alpha", "1"}; cvar_t crosshair_flashspeed = {CVAR_SAVE, "crosshair_flashspeed", "2"}; cvar_t crosshair_flashrange = {CVAR_SAVE, "crosshair_flashrange", "0.1"}; +cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1"}; // must match NUMCROSSHAIRS in gl_draw.c #define NUMCROSSHAIRS 5 @@ -14,6 +15,7 @@ void R_Crosshairs_Init(void) Cvar_RegisterVariable(&crosshair_alpha); Cvar_RegisterVariable(&crosshair_flashspeed); Cvar_RegisterVariable(&crosshair_flashrange); + Cvar_RegisterVariable(&crosshair_size); } void DrawCrosshair(int num) @@ -21,6 +23,8 @@ void DrawCrosshair(int num) int i; byte *color; float scale, base; + char *picname; + cachepic_t *pic; if (num < 0 || num >= NUMCROSSHAIRS) num = 0; if (cl.viewentity) @@ -39,6 +43,9 @@ void DrawCrosshair(int num) else base = 0.0f; scale = crosshair_brightness.value * (1.0f / 255.0f); - DrawQ_Pic(vid.conwidth * 0.5f - 8.0f, vid.conheight * 0.5f - 8.0f, va("gfx/crosshair%i.tga", num + 1), 16.0f, 16.0f, color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, 0); + picname = va("gfx/crosshair%i.tga", num + 1); + pic = Draw_CachePic(picname); + if (pic) + DrawQ_Pic((vid.conwidth - pic->width * crosshair_size.value) * 0.5f, (vid.conheight - pic->height * crosshair_size.value) * 0.5f, picname, pic->width * crosshair_size.value, pic->height * crosshair_size.value, color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, 0); } diff --git a/render.h b/render.h index bd28ea5d..3fdbe0ff 100644 --- a/render.h +++ b/render.h @@ -146,7 +146,7 @@ extern vec_t fogdensity; #include "r_modules.h" -extern qboolean lighthalf; +extern float overbrightscale; #include "r_lerpanim.h" diff --git a/screen.h b/screen.h index 273436a3..f1fdd7fa 100644 --- a/screen.h +++ b/screen.h @@ -41,9 +41,7 @@ extern qboolean scr_disabled_for_loading; extern qboolean scr_skipupdate; extern cvar_t scr_viewsize; -extern cvar_t r_brightness; -extern cvar_t r_contrast; -extern cvar_t gl_lightmode; extern cvar_t scr_viewsize; extern cvar_t crosshair; +extern cvar_t crosshair_size; extern cvar_t showfps; diff --git a/vid.h b/vid.h index 60a659f1..2df5d6fc 100644 --- a/vid.h +++ b/vid.h @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct { - // these are set with GL_BeginRendering and can change from frame to frame + // these are set with VID_GetWindowSize and can change from frame to frame int realx; int realy; int realwidth; @@ -58,3 +58,7 @@ int VID_SetMode (int modenum); // sets hardware gamma correction, returns false if the device does not support gamma control int VID_SetGamma (float prescale, float gamma, float scale, float base); + +void VID_GetWindowSize (int *x, int *y, int *width, int *height); + +void VID_Finish (void); diff --git a/vid_3dfxsvga.c b/vid_3dfxsvga.c index 97124a1c..88a617f5 100644 --- a/vid_3dfxsvga.c +++ b/vid_3dfxsvga.c @@ -139,29 +139,23 @@ void VID_SetupDithering(void) /* ================= -GL_BeginRendering - +VID_GetWindowSize ================= */ -void GL_BeginRendering (int *x, int *y, int *width, int *height) +void VID_GetWindowSize (int *x, int *y, int *width, int *height) { *x = *y = 0; *width = scr_width; *height = scr_height; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); } - -void GL_EndRendering (void) +void VID_Finish (void) { - if (!r_render.integer) - return; - glFlush(); - fxMesaSwapBuffers(); + if (r_render.integer) + { + glFinish(); + fxMesaSwapBuffers(); + } } static int resolutions[][3]={ diff --git a/vid_glx.c b/vid_glx.c index 035e7014..3fc5efb1 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -478,27 +478,24 @@ void InitSig(void) /* ================= -GL_BeginRendering - +VID_GetWindowSize ================= */ -void GL_BeginRendering (int *x, int *y, int *width, int *height) +void VID_GetWindowSize (int *x, int *y, int *width, int *height) { *x = *y = 0; *width = scr_width; *height = scr_height; - -// glViewport (*x, *y, *width, *height); } - -void GL_EndRendering (void) +void VID_Finish (void) { int usemouse; - if (!r_render.integer) - return; - glFlush(); - glXSwapBuffers(vidx11_display, win); + if (r_render.integer) + { + glFinish(); + glXSwapBuffers(vidx11_display, win); + } // handle the mouse state when windowed if that's changed usemouse = false; diff --git a/vid_wgl.c b/vid_wgl.c index 6a78bb0b..9ce018a8 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -365,28 +365,25 @@ void VID_UpdateWindowStatus (void) /* ================= -GL_BeginRendering - +VID_GetWindowSize ================= */ -void GL_BeginRendering (int *x, int *y, int *width, int *height) +void VID_GetWindowSize (int *x, int *y, int *width, int *height) { *x = *y = 0; *width = WindowRect.right - WindowRect.left; *height = WindowRect.bottom - WindowRect.top; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); } -void GL_EndRendering (void) +void VID_Finish (void) { int usemouse; if (r_render.integer && !scr_skipupdate) + { + glFinish(); SwapBuffers(maindc); + } // handle the mouse state when windowed if that's changed usemouse = false; -- 2.39.2