/* * ============== * R_DrawRect8 * ============== */ static void R_DrawRect8(vid.vrect_t prect, int rowbytes, int psrc, int transparent) { byte t; int i, j, srcdelta, destdelta; int pdest; pdest = (int)(/*vid.buffer + */ (prect.y * screen.vid.rowbytes) + prect.x); srcdelta = rowbytes - prect.width; destdelta = (int)(screen.vid.rowbytes - prect.width); if (transparent != 0) { for (i = 0; i < prect.height; i++) { for (j = 0; j < prect.width; j++) { t = r_rectdesc.ptexbytes[psrc]; if (t != TRANSPARENT_COLOR) { screen.vid.buffer[pdest] = t; } psrc++; pdest++; } psrc += srcdelta; pdest += destdelta; } } else { for (i = 0; i < prect.height; i++) { Buffer.BlockCopy(r_rectdesc.ptexbytes, psrc, screen.vid.buffer, pdest, prect.width); psrc += rowbytes; pdest += (int)screen.vid.rowbytes; } } }
/* * =============== * R_SetVrect * =============== */ public static void R_SetVrect(vid.vrect_t pvrectin, vid.vrect_t pvrect, int lineadj) { int h; double size; size = screen.scr_viewsize.value > 100 ? 100 : screen.scr_viewsize.value; if (client.cl.intermission != 0) { size = 100; lineadj = 0; } size /= 100; h = pvrectin.height - lineadj; pvrect.width = (int)(pvrectin.width * size); if (pvrect.width < 96) { size = 96.0 / pvrectin.width; pvrect.width = 96; // min for icons } pvrect.width &= ~7; pvrect.height = (int)(pvrectin.height * size); if (pvrect.height > pvrectin.height - lineadj) { pvrect.height = pvrectin.height - lineadj; } pvrect.height &= ~1; pvrect.x = (pvrectin.width - pvrect.width) / 2; pvrect.y = (h - pvrect.height) / 2; { if (view.lcd_x.value != 0) { pvrect.y >>= 1; pvrect.height >>= 1; } } }
/* ================= SCR_CalcRefdef Must be called whenever vid changes Internal use only ================= */ static void SCR_CalcRefdef() { vid.vrect_t vrect = new vid.vrect_t(); double size; scr_fullupdate = 0; // force a background redraw screen.vid.recalc_refdef = false; // force the status bar to redraw sbar.Sbar_Changed(); //======================================== // bound viewsize if (scr_viewsize.value < 30) cvar_t.Cvar_Set("viewsize", "30"); if (scr_viewsize.value > 120) cvar_t.Cvar_Set("viewsize", "120"); // bound field of view if (scr_fov.value < 10) cvar_t.Cvar_Set("fov", "10"); if (scr_fov.value > 170) cvar_t.Cvar_Set("fov", "170"); render.r_refdef.fov_x = scr_fov.value; render.r_refdef.fov_y = CalcFov(render.r_refdef.fov_x, render.r_refdef.vrect.width, render.r_refdef.vrect.height); // intermission is always full screen if (client.cl.intermission != 0) size = 120; else size = scr_viewsize.value; if (size >= 120) sbar.sb_lines = 0; // no status bar at all else if (size >= 110) sbar.sb_lines = 24; // no inventory else sbar.sb_lines = 24 + 16 + 8; // these calculations mirror those in R_Init() for r_refdef, but take no // account of water warping vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)screen.vid.height; render.R_SetVrect (vrect, scr_vrect, sbar.sb_lines); // guard against going from one mode to another that's less than half the // vertical resolution if (scr_con_current > screen.vid.height) scr_con_current = screen.vid.height; // notify the refresh of the change render.R_ViewChanged(vrect, sbar.sb_lines, screen.vid.aspect); }
public static void SCR_UpdateScreen() { vid.vrect_t vrect = new vid.vrect_t(); if (scr_skipupdate || block_drawing) return; scr_copytop = false; scr_copyeverything = false; if (scr_disabled_for_loading) { if (host.realtime - scr_disabled_time > 60) { scr_disabled_for_loading = false; console.Con_Printf("load failed.\n"); } else return; } if (client.cls.state == client.cactive_t.ca_dedicated) return; // stdout only if (!scr_initialized || !console.con_initialized) return; // not initialized yet if (scr_viewsize.value != oldscr_viewsize) { oldscr_viewsize = scr_viewsize.value; screen.vid.recalc_refdef = true; } // // check for vid changes // if (oldfov != scr_fov.value) { oldfov = scr_fov.value; vid.recalc_refdef = true; } if (oldscreensize != scr_viewsize.value) { oldscreensize = scr_viewsize.value; vid.recalc_refdef = true; } if (screen.vid.recalc_refdef) { // something changed, so reorder the screen SCR_CalcRefdef(); } if (scr_fullupdate++ < screen.vid.numpages) { // clear the entire screen scr_copyeverything = true; draw.Draw_TileClear(0, 0, (int)screen.vid.width, (int)screen.vid.height); sbar.Sbar_Changed(); } SCR_SetUpToDrawConsole (); SCR_EraseCenterString (); view.V_RenderView (); if (scr_drawdialog) { sbar.Sbar_Draw(); draw.Draw_FadeScreen(); SCR_DrawNotifyString(); scr_copyeverything = true; } else if (scr_drawloading) { SCR_DrawLoading(); sbar.Sbar_Draw (); } else if (client.cl.intermission == 1 && keys.key_dest == keys.keydest_t.key_game) { sbar.Sbar_IntermissionOverlay(); } else if (client.cl.intermission == 2 && keys.key_dest == keys.keydest_t.key_game) { sbar.Sbar_FinaleOverlay(); SCR_CheckDrawCenterString (); } else if (client.cl.intermission == 3 && keys.key_dest == keys.keydest_t.key_game) { SCR_CheckDrawCenterString (); } else { SCR_DrawRam(); SCR_DrawNet(); SCR_DrawTurtle(); SCR_DrawPause(); SCR_CheckDrawCenterString(); sbar.Sbar_Draw(); SCR_DrawConsole(); menu.M_Draw(); } view.V_UpdatePalette (); // // update one of three areas // if (scr_copyeverything) { vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)screen.vid.height; vrect.pnext = null; quake.vid.VID_Update(vrect); } else if (scr_copytop) { vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)(screen.vid.height - sbar.sb_lines); vrect.pnext = null; quake.vid.VID_Update(vrect); } else { vrect.x = scr_vrect.x; vrect.y = scr_vrect.y; vrect.width = scr_vrect.width; vrect.height = scr_vrect.height; vrect.pnext = null; quake.vid.VID_Update(vrect); } }
/* * =============== * R_ViewChanged * * Called every time the vid structure or r_refdef changes. * Guaranteed to be called before the first refresh * =============== */ public static void R_ViewChanged(vid.vrect_t pvrect, int lineadj, double aspect) { int i; double res_scale; r_viewchanged = true; R_SetVrect(pvrect, r_refdef.vrect, lineadj); r_refdef.horizontalFieldOfView = 2.0 * Math.Tan(r_refdef.fov_x / 360 * mathlib.M_PI); r_refdef.fvrectx = (double)r_refdef.vrect.x; r_refdef.fvrectx_adj = (double)r_refdef.vrect.x - 0.5; r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1; r_refdef.fvrecty = (double)r_refdef.vrect.y; r_refdef.fvrecty_adj = (double)r_refdef.vrect.y - 0.5; r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright << 20) + (1 << 19) - 1; r_refdef.fvrectright = (double)r_refdef.vrectright; r_refdef.fvrectright_adj = (double)r_refdef.vrectright - 0.5; r_refdef.vrectrightedge = (double)r_refdef.vrectright - 0.99; r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; r_refdef.fvrectbottom = (double)r_refdef.vrectbottom; r_refdef.fvrectbottom_adj = (double)r_refdef.vrectbottom - 0.5; r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); r_refdef.aliasvrectright = r_refdef.aliasvrect.x + r_refdef.aliasvrect.width; r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + r_refdef.aliasvrect.height; pixelAspect = aspect; xOrigin = r_refdef.xOrigin; yOrigin = r_refdef.yOrigin; screenAspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; // 320*200 1.0 pixelAspect = 1.6 screenAspect // 320*240 1.0 pixelAspect = 1.3333 screenAspect // proper 320*200 pixelAspect = 0.8333333 verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; // values for perspective projection // if math were exact, the values would range from 0.5 to to range+0.5 // hopefully they wll be in the 0.000001 to range+.999999 and truncate // the polygon rasterization will never render in the first row or column // but will definately render in the [range] row and column, so adjust the // buffer origin to get an exact edge to edge fill xcenter = ((double)r_refdef.vrect.width * XCENTERING) + r_refdef.vrect.x - 0.5; aliasxcenter = xcenter * r_aliasuvscale; ycenter = ((double)r_refdef.vrect.height * YCENTERING) + r_refdef.vrect.y - 0.5; aliasycenter = ycenter * r_aliasuvscale; xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; aliasxscale = xscale * r_aliasuvscale; xscaleinv = 1.0 / xscale; yscale = xscale * pixelAspect; aliasyscale = yscale * r_aliasuvscale; yscaleinv = 1.0 / yscale; xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView; yscaleshrink = xscaleshrink * pixelAspect; // left side clip screenedge[0].normal[0] = -1.0 / (xOrigin * r_refdef.horizontalFieldOfView); screenedge[0].normal[1] = 0; screenedge[0].normal[2] = 1; screenedge[0].type = bspfile.PLANE_ANYZ; // right side clip screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) * r_refdef.horizontalFieldOfView); screenedge[1].normal[1] = 0; screenedge[1].normal[2] = 1; screenedge[1].type = bspfile.PLANE_ANYZ; // top side clip screenedge[2].normal[0] = 0; screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView); screenedge[2].normal[2] = 1; screenedge[2].type = bspfile.PLANE_ANYZ; // bottom side clip screenedge[3].normal[0] = 0; screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView); screenedge[3].normal[2] = 1; screenedge[3].type = bspfile.PLANE_ANYZ; for (i = 0; i < 4; i++) { mathlib.VectorNormalize(ref screenedge[i].normal); } res_scale = Math.Sqrt((double)(r_refdef.vrect.width * r_refdef.vrect.height) / (320.0 * 152.0)) * (2.0 / r_refdef.horizontalFieldOfView); r_aliastransition = r_aliastransbase.value * res_scale; r_resfudge = r_aliastransadj.value * res_scale; if (screen.scr_fov.value <= 90.0) { r_fov_greater_than_90 = false; } else { r_fov_greater_than_90 = true; } draw.D_ViewChanged(); }
/* * ============= * Draw_TileClear * * This repeats a 64*64 tile graphic to fill the screen around a sized down * refresh window. * ============= */ public static void Draw_TileClear(int x, int y, int w, int h) { int width, height, tileoffsetx, tileoffsety; int psrc; vid.vrect_t vr = new vid.vrect_t(); r_rectdesc.rect.x = x; r_rectdesc.rect.y = y; r_rectdesc.rect.width = w; r_rectdesc.rect.height = h; vr.y = r_rectdesc.rect.y; height = r_rectdesc.rect.height; tileoffsety = vr.y % r_rectdesc.height; while (height > 0) { vr.x = r_rectdesc.rect.x; width = r_rectdesc.rect.width; if (tileoffsety != 0) { vr.height = r_rectdesc.height - tileoffsety; } else { vr.height = r_rectdesc.height; } if (vr.height > height) { vr.height = height; } tileoffsetx = vr.x % r_rectdesc.width; while (width > 0) { if (tileoffsetx != 0) { vr.width = r_rectdesc.width - tileoffsetx; } else { vr.width = r_rectdesc.width; } if (vr.width > width) { vr.width = width; } psrc = (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; if (render.r_pixbytes == 1) { R_DrawRect8(vr, r_rectdesc.rowbytes, psrc, 0); } vr.x += vr.width; width -= vr.width; tileoffsetx = 0; // only the left tile can be left-clipped } vr.y += vr.height; height -= vr.height; tileoffsety = 0; // only the top tile can be top-clipped } }
/* ============= Draw_TileClear This repeats a 64*64 tile graphic to fill the screen around a sized down refresh window. ============= */ public static void Draw_TileClear(int x, int y, int w, int h) { int width, height, tileoffsetx, tileoffsety; int psrc; vid.vrect_t vr = new vid.vrect_t(); r_rectdesc.rect.x = x; r_rectdesc.rect.y = y; r_rectdesc.rect.width = w; r_rectdesc.rect.height = h; vr.y = r_rectdesc.rect.y; height = r_rectdesc.rect.height; tileoffsety = vr.y % r_rectdesc.height; while (height > 0) { vr.x = r_rectdesc.rect.x; width = r_rectdesc.rect.width; if (tileoffsety != 0) vr.height = r_rectdesc.height - tileoffsety; else vr.height = r_rectdesc.height; if (vr.height > height) vr.height = height; tileoffsetx = vr.x % r_rectdesc.width; while (width > 0) { if (tileoffsetx != 0) vr.width = r_rectdesc.width - tileoffsetx; else vr.width = r_rectdesc.width; if (vr.width > width) vr.width = width; psrc = (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; if (render.r_pixbytes == 1) { R_DrawRect8 (vr, r_rectdesc.rowbytes, psrc, 0); } vr.x += vr.width; width -= vr.width; tileoffsetx = 0; // only the left tile can be left-clipped } vr.y += vr.height; height -= vr.height; tileoffsety = 0; // only the top tile can be top-clipped } }
public static void SCR_UpdateScreen() { vid.vrect_t vrect = new vid.vrect_t(); if (scr_skipupdate || block_drawing) { return; } scr_copytop = false; scr_copyeverything = false; if (scr_disabled_for_loading) { if (host.realtime - scr_disabled_time > 60) { scr_disabled_for_loading = false; console.Con_Printf("load failed.\n"); } else { return; } } if (client.cls.state == client.cactive_t.ca_dedicated) { return; // stdout only } if (!scr_initialized || !console.con_initialized) { return; // not initialized yet } if (scr_viewsize.value != oldscr_viewsize) { oldscr_viewsize = scr_viewsize.value; screen.vid.recalc_refdef = true; } // // check for vid changes // if (oldfov != scr_fov.value) { oldfov = scr_fov.value; vid.recalc_refdef = true; } if (oldscreensize != scr_viewsize.value) { oldscreensize = scr_viewsize.value; vid.recalc_refdef = true; } if (screen.vid.recalc_refdef) { // something changed, so reorder the screen SCR_CalcRefdef(); } if (scr_fullupdate++ < screen.vid.numpages) { // clear the entire screen scr_copyeverything = true; draw.Draw_TileClear(0, 0, (int)screen.vid.width, (int)screen.vid.height); sbar.Sbar_Changed(); } SCR_SetUpToDrawConsole(); SCR_EraseCenterString(); view.V_RenderView(); if (scr_drawdialog) { sbar.Sbar_Draw(); draw.Draw_FadeScreen(); SCR_DrawNotifyString(); scr_copyeverything = true; } else if (scr_drawloading) { SCR_DrawLoading(); sbar.Sbar_Draw(); } else if (client.cl.intermission == 1 && keys.key_dest == keys.keydest_t.key_game) { sbar.Sbar_IntermissionOverlay(); } else if (client.cl.intermission == 2 && keys.key_dest == keys.keydest_t.key_game) { sbar.Sbar_FinaleOverlay(); SCR_CheckDrawCenterString(); } else if (client.cl.intermission == 3 && keys.key_dest == keys.keydest_t.key_game) { SCR_CheckDrawCenterString(); } else { SCR_DrawRam(); SCR_DrawNet(); SCR_DrawTurtle(); SCR_DrawPause(); SCR_CheckDrawCenterString(); sbar.Sbar_Draw(); SCR_DrawConsole(); menu.M_Draw(); } view.V_UpdatePalette(); // // update one of three areas // if (scr_copyeverything) { vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)screen.vid.height; vrect.pnext = null; quake.vid.VID_Update(vrect); } else if (scr_copytop) { vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)(screen.vid.height - sbar.sb_lines); vrect.pnext = null; quake.vid.VID_Update(vrect); } else { vrect.x = scr_vrect.x; vrect.y = scr_vrect.y; vrect.width = scr_vrect.width; vrect.height = scr_vrect.height; vrect.pnext = null; quake.vid.VID_Update(vrect); } }
/* * ================= * SCR_CalcRefdef * * Must be called whenever vid changes * Internal use only * ================= */ static void SCR_CalcRefdef() { vid.vrect_t vrect = new vid.vrect_t(); double size; scr_fullupdate = 0; // force a background redraw screen.vid.recalc_refdef = false; // force the status bar to redraw sbar.Sbar_Changed(); //======================================== // bound viewsize if (scr_viewsize.value < 30) { cvar_t.Cvar_Set("viewsize", "30"); } if (scr_viewsize.value > 120) { cvar_t.Cvar_Set("viewsize", "120"); } // bound field of view if (scr_fov.value < 10) { cvar_t.Cvar_Set("fov", "10"); } if (scr_fov.value > 170) { cvar_t.Cvar_Set("fov", "170"); } render.r_refdef.fov_x = scr_fov.value; render.r_refdef.fov_y = CalcFov(render.r_refdef.fov_x, render.r_refdef.vrect.width, render.r_refdef.vrect.height); // intermission is always full screen if (client.cl.intermission != 0) { size = 120; } else { size = scr_viewsize.value; } if (size >= 120) { sbar.sb_lines = 0; // no status bar at all } else if (size >= 110) { sbar.sb_lines = 24; // no inventory } else { sbar.sb_lines = 24 + 16 + 8; } // these calculations mirror those in R_Init() for r_refdef, but take no // account of water warping vrect.x = 0; vrect.y = 0; vrect.width = (int)screen.vid.width; vrect.height = (int)screen.vid.height; render.R_SetVrect(vrect, scr_vrect, sbar.sb_lines); // guard against going from one mode to another that's less than half the // vertical resolution if (scr_con_current > screen.vid.height) { scr_con_current = screen.vid.height; } // notify the refresh of the change render.R_ViewChanged(vrect, sbar.sb_lines, screen.vid.aspect); }