From 6a384398c93b7e2bc1936427797909eb60094160 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Fri, 9 Feb 2001 12:11:11 +0000 Subject: [PATCH] added back r_speeds2, with masses of information (6 lines high), and made it print to the screen rather than console print changed fps reading to be integer, no fraction (is this desirable?) and moved it to bottom right corner changed rendering order yet again made sky and waterripple speed dependent on cl.time rather than realtime (undecided if this is desirable) made console scrolling not subject to slowmo time scaling some whitespace changes/cleanup moved some registervariable definitions around optional new worldnode function (r_newworldnode, defaults to off), very different approach, minimal speed differences... sigh added backface culling on surfaces (r_nobacks, defaults to off), barely a gain in worldnode, made 'trivial inclusion' case for all children nodes of a completely successful CullBox test, defaults to off because it was no speed gain even on the most complex maps I could find readability cleanup and minor speedup in lightmap conversion added host_minfps (if framerate drops below this it will be slowmo, this replaces quake's hardcoded 10fps limit) added host_maxfps (limit your framerate if desired, defaults to 1000, this does affect timedemo) improved slowmo behavior optimized out most vec3_origin uses (created VectorNegate and VectorClear for this reason) fixed VectorDistance (old definition didn't work correctly, but never got used anyway) darkened blood trails a bit split R_DrawParticles into R_MoveParticles and R_DrawParticles (for speed profiling reasons) fix for extremely rare and probably unnoticable bug in particle compacter fixed a number of prediction issues, prediction does not occur in local games anymore, prediction also made optional (sv_predict cvar) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@147 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 4 +- gl_models.c | 2 + gl_poly.c | 4 +- gl_refrag.c | 9 +-- gl_rmain.c | 84 +++++++++++++++++------ gl_rmisc.c | 12 +--- gl_rsurf.c | 184 +++++++++++++++++++++++++++++++++++++++++--------- gl_screen.c | 24 +++++-- gl_warp.c | 4 +- glquake.h | 3 +- host.c | 32 ++++++--- mathlib.h | 5 +- model_brush.h | 1 + pr_edict.c | 4 +- quakedef.h | 1 + r_part.c | 167 ++++++++++++++++++++++++--------------------- r_sprites.c | 3 + render.h | 4 ++ sv_main.c | 7 +- sv_phys.c | 24 ++++--- sv_user.c | 6 +- world.c | 14 +--- 22 files changed, 404 insertions(+), 194 deletions(-) diff --git a/cl_main.c b/cl_main.c index 77321663..56d77abb 100644 --- a/cl_main.c +++ b/cl_main.c @@ -350,7 +350,9 @@ void CL_DecayLights (void) { if (dl->die < cl.time || !dl->radius) continue; - + + c_dlights++; // count every dlight in use + dl->radius -= time*dl->decay; if (dl->radius < 0) dl->radius = 0; diff --git a/gl_models.c b/gl_models.c index 87adbe99..8b2d2823 100644 --- a/gl_models.c +++ b/gl_models.c @@ -650,6 +650,8 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i if (cull && R_CullBox (mins, maxs)) return; + c_models++; + leaf = Mod_PointInLeaf (org, cl.worldmodel); if (leaf->dlightframe == r_dlightframecount) for (i = 0;i < 8;i++) diff --git a/gl_poly.c b/gl_poly.c index 4252170e..2631e352 100644 --- a/gl_poly.c +++ b/gl_poly.c @@ -813,7 +813,7 @@ void skypolyrender() glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, solidskytexture); // upper clouds - speedscale = realtime*8; + speedscale = cl.time*8; speedscale -= (int)speedscale & ~127 ; for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++) { @@ -836,7 +836,7 @@ void skypolyrender() glEnable(GL_BLEND); glDepthMask(0); glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds - speedscale = realtime*16; + speedscale = cl.time*16; speedscale -= (int)speedscale & ~127 ; for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++) { diff --git a/gl_refrag.c b/gl_refrag.c index 1a85e7c6..224899f8 100644 --- a/gl_refrag.c +++ b/gl_refrag.c @@ -229,20 +229,17 @@ void R_StoreEfrags (efrag_t **ppefrag) case mod_sprite: pent = pefrag->entity; - if ((pent->visframe != r_framecount) && - (cl_numvisedicts < MAX_VISEDICTS)) + if ((pent->visframe != r_framecount) && (cl_numvisedicts < MAX_VISEDICTS)) { cl_visedicts[cl_numvisedicts++] = pent; - - // mark that we've recorded this entity for this frame - pent->visframe = r_framecount; + pent->visframe = r_framecount; // render each entity only once per frame } ppefrag = &pefrag->leafnext; break; default: - Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); + Host_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); } } } diff --git a/gl_rmain.c b/gl_rmain.c index 1575fc03..907822e1 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -33,7 +33,7 @@ int r_framecount; // used for dlight push checking mplane_t frustum[4]; -int c_brush_polys, c_alias_polys, c_light_polys, c_nodes, c_leafs; +int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; qboolean envmap; // true during envmap command capture @@ -223,6 +223,10 @@ void glmain_shutdown() void GL_Main_Init() { FOG_registercvars(); + Cvar_RegisterVariable (&r_drawentities); + Cvar_RegisterVariable (&r_drawviewmodel); + Cvar_RegisterVariable (&r_shadows); + Cvar_RegisterVariable (&r_speeds); Cvar_RegisterVariable (&r_speeds2); Cvar_RegisterVariable (&contrast); Cvar_RegisterVariable (&brightness); @@ -230,6 +234,10 @@ void GL_Main_Init() // Cvar_RegisterVariable (&r_dynamicwater); // Cvar_RegisterVariable (&r_dynamicbothsides); Cvar_RegisterVariable (&r_fullbrights); + Cvar_RegisterVariable (&r_wateralpha); + Cvar_RegisterVariable (&r_dynamic); + Cvar_RegisterVariable (&r_novis); + Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple if (nehahra) Cvar_SetValue("r_fullbrights", 0); // if (gl_vendor && strstr(gl_vendor, "3Dfx")) @@ -484,8 +492,14 @@ void R_SetupFrame (void) 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; } @@ -586,10 +600,6 @@ void R_SetupGL (void) glShadeModel(GL_SMOOTH); } -void R_DrawWorld (void); -//void R_RenderDlights (void); -void R_DrawParticles (void); - /* ============= R_Clear @@ -680,6 +690,7 @@ void GL_BlendView() glEnable(GL_TEXTURE_2D); } +/* #define TIMEREPORT(DESC) \ if (r_speeds2.value)\ {\ @@ -688,6 +699,14 @@ void GL_BlendView() temptime += currtime;\ Con_Printf(DESC " %.4fms ", temptime * 1000.0);\ } +*/ +#define TIMEREPORT(VAR) \ + if (r_speeds2.value)\ + {\ + temptime = currtime;\ + currtime = Sys_FloatTime();\ + VAR = (int) ((currtime - temptime) * 1000000.0);\ + } /* ================ @@ -700,8 +719,11 @@ extern qboolean intimerefresh; extern qboolean skyisvisible; extern void R_Sky(); extern void UploadLightmaps(); +char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81]; void R_RenderView (void) { + double starttime, currtime, temptime; + int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_transpoly, time_blend, time_total; // double currtime, temptime; // if (r_norefresh.value) // return; @@ -713,47 +735,71 @@ void R_RenderView (void) FOG_framebegin(); -// if (r_speeds2.value) -// { -// currtime = Sys_FloatTime(); + if (r_speeds2.value) + { + starttime = currtime = Sys_FloatTime(); // Con_Printf("render time: "); -// } + } R_Clear(); -// TIMEREPORT("R_Clear") + skypolyclear(); + wallpolyclear(); + transpolyclear(); + skyisvisible = false; + TIMEREPORT(time_clear) // render normal view R_SetupFrame (); R_SetFrustum (); R_SetupGL (); - - skypolyclear(); - wallpolyclear(); - transpolyclear(); - skyisvisible = false; + TIMEREPORT(time_setup) R_MarkLeaves (); // done here so we know if we're in water R_DrawWorld (); // adds static entities to the list - if (!intimerefresh) - S_ExtraUpdate (); // don't let sound get messed up if going slow + TIMEREPORT(time_world) R_DrawEntitiesOnList1 (); // BSP models + TIMEREPORT(time_bmodels) + + UploadLightmaps(); + TIMEREPORT(time_upload) skypolyrender(); // fogged sky polys, affects depth + if (skyname[0] && skyisvisible && !fogenabled) R_Sky(); // does not affect depth, draws over the sky polys + TIMEREPORT(time_sky) - UploadLightmaps(); wallpolyrender(); + TIMEREPORT(time_wall) + +// if (!intimerefresh) +// S_ExtraUpdate (); // don't let sound get messed up if going slow R_DrawEntitiesOnList2 (); // other models // R_RenderDlights (); R_DrawViewModel (); + TIMEREPORT(time_models) + R_MoveParticles (); + TIMEREPORT(time_moveparticles) R_DrawParticles (); + TIMEREPORT(time_drawparticles) transpolyrender(); + TIMEREPORT(time_transpoly) FOG_frameend(); + GL_BlendView(); -// if (r_speeds2.value) + TIMEREPORT(time_blend) + if (r_speeds2.value) + { + time_total = (int) ((Sys_FloatTime() - starttime) * 1000000.0); // Con_Printf("\n"); + sprintf(r_speeds2_string1, "%6i walls %6i dlitwalls %7i modeltris %7i transpoly\n", c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly); + sprintf(r_speeds2_string2, "BSP: %6i faces %6i nodes %6i leafs\n", c_faces, c_nodes, c_leafs); + sprintf(r_speeds2_string3, "%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights); + sprintf(r_speeds2_string4, "%6ius clear %6ius setup %6ius world %6ius bmodel %6ius upload", time_clear, time_setup, time_world, time_bmodels, time_upload); + sprintf(r_speeds2_string5, "%6ius sky %6ius wall %6ius models %6ius mpart %6ius dpart ", time_sky, time_wall, time_models, time_moveparticles, time_drawparticles); + sprintf(r_speeds2_string6, "%6ius trans %6ius blend %6ius total %6ius permdl", time_transpoly, time_blend, time_total, time_models / max(c_models, 1)); + } } diff --git a/gl_rmisc.c b/gl_rmisc.c index 0d9df636..2a07083b 100644 --- a/gl_rmisc.c +++ b/gl_rmisc.c @@ -143,18 +143,8 @@ R_Init */ void GL_Misc_Init (void) { - Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); Cmd_AddCommand ("envmap", R_Envmap_f); - Cmd_AddCommand ("pointfile", R_ReadPointFile_f); - - Cvar_RegisterVariable (&r_drawentities); - Cvar_RegisterVariable (&r_drawviewmodel); - Cvar_RegisterVariable (&r_shadows); - Cvar_RegisterVariable (&r_wateralpha); - Cvar_RegisterVariable (&r_dynamic); - Cvar_RegisterVariable (&r_novis); - Cvar_RegisterVariable (&r_speeds); - Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 70afc094..6ab30c4d 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -48,6 +48,8 @@ cvar_t r_ambient = {"r_ambient", "0"}; cvar_t gl_vertex = {"gl_vertex", "0"}; cvar_t gl_texsort = {"gl_texsort", "1"}; //cvar_t gl_funnywalls = {"gl_funnywalls", "0"}; // LordHavoc: see BuildSurfaceDisplayList +cvar_t r_newworldnode = {"r_newworldnode", "0"}; +cvar_t r_oldclip = {"r_oldclip", "1"}; qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible; int lightmapbytes; @@ -77,6 +79,8 @@ void GL_Surf_Init() // Cvar_RegisterVariable(&gl_funnywalls); Cvar_RegisterVariable(&gl_vertex); Cvar_RegisterVariable(&gl_texsort); + Cvar_RegisterVariable(&r_newworldnode); + Cvar_RegisterVariable(&r_oldclip); // check if it's the glquake minigl driver if (strncasecmp(gl_vendor,"3Dfx",4)==0) if (!gl_arrays) @@ -99,7 +103,6 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) { int smax, tmax; - int t; int i, j, size; byte *lightmap; int scale; @@ -139,6 +142,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) // add all the lightmaps if (lightmap) + { for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) { scale = d_lightstylevalue[surf->styles[maps]]; @@ -151,6 +155,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) *bl++ += *lightmap++ * scale; } } + } } stride -= (smax*lightmapbytes); bl = blocklights; @@ -160,26 +165,26 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) // the image is brightened as a processing pass if (lightmaprgba) { - for (i=0 ; i> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - *dest++ = 255; + dest[0] = min(bl[0] >> 8, 255); + dest[1] = min(bl[1] >> 8, 255); + dest[2] = min(bl[2] >> 8, 255); + dest[3] = 255; } } } else { - for (i=0 ; i> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; + dest[0] = min(bl[0] >> 8, 255); + dest[1] = min(bl[1] >> 8, 255); + dest[2] = min(bl[2] >> 8, 255); } } } @@ -188,26 +193,26 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) { if (lightmaprgba) { - for (i=0 ; i> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - *dest++ = 255; + dest[0] = min(bl[0] >> 7, 255); + dest[1] = min(bl[1] >> 7, 255); + dest[2] = min(bl[2] >> 7, 255); + dest[3] = 255; } } } else { - for (i=0 ; i> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; - t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t; + dest[0] = min(bl[0] >> 7, 255); + dest[1] = min(bl[1] >> 7, 255); + dest[2] = min(bl[2] >> 7, 255); } } } @@ -441,7 +446,7 @@ int RSurf_Light(int *dlightbits, glpoly_t *polys) void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) { int i; - float os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(realtime * TURBSCALE + 96.0) & 255]; + float os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(cl.time * TURBSCALE + 96.0) & 255]; glpoly_t *p; float *wv, *v; wv = wvert; @@ -454,7 +459,7 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) else VectorCopy(v, wv); if (r_waterripple.value) - wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f); + wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f); wv[3] = wv[4] = wv[5] = 128.0f; wv += 6; } @@ -732,6 +737,8 @@ void R_DrawBrushModel (entity_t *e) if (R_CullBox (mins, maxs)) return; + c_bmodels++; + VectorSubtract (r_refdef.vieworg, e->origin, modelorg); if (rotated) { @@ -799,10 +806,78 @@ e->angles[0] = -e->angles[0]; // stupid quake bug void R_StoreEfrags (efrag_t **ppefrag); +void R_NewWorldNode () +{ + int l, texsort = gl_texsort.value, vertex = gl_vertex.value; + mleaf_t *leaf; + msurface_t *surf, **mark, **endmark; + + for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++) + { + if ((leaf->visframe == r_visframecount) && (leaf->efrags || leaf->nummarksurfaces)) + { + if (R_CullBox(leaf->minmaxs, leaf->minmaxs+3)) + continue; + + c_leafs++; + + // deal with model fragments in this leaf + if (leaf->efrags) + R_StoreEfrags (&leaf->efrags); + + if (leaf->nummarksurfaces) + { + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + do + { + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) + { + if ( (surf->flags & SURF_PLANEBACK)) + { + surf->visframe = r_framecount; + c_faces++; + if (texsort) + { + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } + else + R_DrawSurf(surf, false, vertex); + } + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + { + surf->visframe = r_framecount; + c_faces++; + if (texsort) + { + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } + else + R_DrawSurf(surf, false, vertex); + } + } + } + while (mark < endmark); + } + } + } +} + struct nodestack_s { int side; mnode_t *node; + int noclipping; } nodestack[8192]; /* @@ -812,20 +887,43 @@ R_WorldNode */ void R_WorldNode () { - int side, texsort, vertex; + int side, texsort = gl_texsort.value, vertex = gl_vertex.value, ca, cb, cc, cd, noclipping = false, oldclip = r_oldclip.value; struct nodestack_s *nstack; mnode_t *node; mleaf_t *pleaf; msurface_t *surf, *endsurf, **mark, **endmark; nstack = nodestack; - texsort = gl_texsort.value; - vertex = gl_vertex.value; if (!(node = cl.worldmodel->nodes)) return; while(1) { + if (oldclip) + { + if (R_CullBox(node->minmaxs, node->minmaxs+3)) + { +backupstack: + if (nstack <= nodestack) + break; + nstack--; + node = nstack->node; + side = nstack->side; + noclipping = nstack->noclipping; + goto loc0; + } + } + else + if (!noclipping) + { + ca = frustum[0].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[0]);if (ca == 2) goto backupstack; // completely clipped away + cb = frustum[1].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[1]);if (cb == 2) goto backupstack; // completely clipped away + cc = frustum[2].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[2]);if (cc == 2) goto backupstack; // completely clipped away + cd = frustum[3].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[3]);if (cd == 2) goto backupstack; // completely clipped away + if (ca == 0 && cb == 0 && cc == 0 && cd == 0) + noclipping = true; // not clipped at all, no need to clip any children of this node + // partially clipped node + } // if a leaf node, draw stuff if (node->contents < 0) { @@ -856,6 +954,7 @@ void R_WorldNode () nstack--; node = nstack->node; side = nstack->side; + noclipping = nstack->noclipping; goto loc0; } @@ -867,10 +966,11 @@ void R_WorldNode () side = PlaneDist(modelorg, node->plane) < node->plane->dist; // recurse down the children, front side first - if (node->children[side]->visframe == r_visframecount && R_NotCulledBox(node->children[side]->minmaxs, node->children[side]->minmaxs+3)) + if (node->children[side]->visframe == r_visframecount) { nstack->node = node; nstack->side = !side; // go down back side when we come back up + nstack->noclipping = noclipping; nstack++; node = node->children[side]; continue; @@ -892,9 +992,12 @@ loc0: { if (surf->visframe == r_framecount && !(surf->flags & SURF_PLANEBACK)) { + c_faces++; surf->texturechain = surf->texinfo->texture->texturechain; surf->texinfo->texture->texturechain = surf; } + else + surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it surf++; } while (surf < endsurf); @@ -905,9 +1008,12 @@ loc0: { if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK)) { + c_faces++; surf->texturechain = surf->texinfo->texture->texturechain; surf->texinfo->texture->texturechain = surf; } + else + surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it surf++; } while (surf < endsurf); @@ -920,7 +1026,12 @@ loc0: do { if (surf->visframe == r_framecount && !(surf->flags & SURF_PLANEBACK)) + { + c_faces++; R_DrawSurf(surf, false, vertex); + } + else + surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it surf++; } while (surf < endsurf); @@ -930,7 +1041,12 @@ loc0: do { if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK)) + { + c_faces++; R_DrawSurf(surf, false, vertex); + } + else + surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it surf++; } while (surf < endsurf); @@ -939,7 +1055,7 @@ loc0: } // recurse down the back side - if (node->children[side]->visframe == r_visframecount && R_NotCulledBox(node->children[side]->minmaxs, node->children[side]->minmaxs+3)) + if (node->children[side]->visframe == r_visframecount) { node = node->children[side]; continue; @@ -950,6 +1066,7 @@ loc0: nstack--; node = nstack->node; side = nstack->side; + noclipping = nstack->noclipping; goto loc0; } } @@ -977,7 +1094,12 @@ void R_DrawWorld (void) softwaretransformidentity(); // LordHavoc: clear transform if (cl.worldmodel) - R_WorldNode (); + { + if (r_newworldnode.value) + R_NewWorldNode (); + else + R_WorldNode (); + } R_PushDlights (); // now mark the lit surfaces diff --git a/gl_screen.c b/gl_screen.c index ab123c0c..0e593950 100644 --- a/gl_screen.c +++ b/gl_screen.c @@ -541,14 +541,14 @@ void SCR_SetUpToDrawConsole (void) if (scr_conlines < scr_con_current) { - scr_con_current -= scr_conspeed.value*host_frametime; + 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_frametime; + scr_con_current += scr_conspeed.value*host_realframetime; if (scr_conlines < scr_con_current) scr_con_current = scr_conlines; } @@ -772,6 +772,7 @@ extern void SHOWLMP_drawall(); extern cvar_t contrast; extern cvar_t brightness; extern cvar_t gl_lightmode; +extern cvar_t r_speeds2; void GL_BrightenScreen() { @@ -936,10 +937,21 @@ void SCR_UpdateScreen (void) char temp[32]; int calc; newtime = Sys_FloatTime(); - calc = (int) (100.0 / (newtime - currtime)); - sprintf(temp, "% 4i.%02i fps", calc / 100, calc % 100); + calc = (int) ((1.0 / (newtime - currtime)) + 0.5); + sprintf(temp, "%4i fps", calc); currtime = newtime; - Draw_String(vid.width - (12*8), 0, temp, 9999); + Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999); + } + + if (r_speeds2.value) + { + extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81]; + Draw_String(0, vid.height - sb_lines - 48, r_speeds2_string1, 80); + Draw_String(0, vid.height - sb_lines - 40, r_speeds2_string2, 80); + Draw_String(0, vid.height - sb_lines - 32, r_speeds2_string3, 80); + Draw_String(0, vid.height - sb_lines - 24, r_speeds2_string4, 80); + Draw_String(0, vid.height - sb_lines - 16, r_speeds2_string5, 80); + Draw_String(0, vid.height - sb_lines - 8, r_speeds2_string6, 80); } V_UpdateBlends (); @@ -951,7 +963,7 @@ void SCR_UpdateScreen (void) if (r_speeds.value) { time2 = Sys_FloatTime (); - Con_Printf ("%3i ms %4i wpoly %4i epoly %4i transpoly %4i lightpoly %4i BSPnodes %4i BSPleafs\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, currenttranspoly, c_light_polys, c_nodes, c_leafs); + Con_Printf ("%3i ms %4i wpoly %4i epoly %4i transpoly %4i lightpoly %4i BSPnodes %4i BSPleafs %4i BSPfaces %4i models %4i bmodels %4i sprites %4i particles %3i dlights\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, currenttranspoly, c_light_polys, c_nodes, c_leafs, c_faces, c_models, c_bmodels, c_sprites, c_particles, c_dlights); } GL_EndRendering (); } diff --git a/gl_warp.c b/gl_warp.c index 296da186..8f35afba 100644 --- a/gl_warp.c +++ b/gl_warp.c @@ -391,12 +391,12 @@ void R_SkyDome() skydomecalc(skydomeouter, 1024, 1024, 256); skydomecalc(skydomeinner, 512, 512, 128); } - speedscale = realtime*8.0/256.0; + speedscale = cl.time*8.0/256.0; speedscale -= (int)speedscale; skydome(skydomeouter, speedscale, 1.0 / 256.0); glEnable (GL_BLEND); glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds - speedscale = realtime*8.0/128.0; + speedscale = cl.time*8.0/128.0; speedscale -= (int)speedscale; skydome(skydomeinner, speedscale, 1.0 / 128.0); glDisable (GL_BLEND); diff --git a/glquake.h b/glquake.h index c7830ee8..89dc8c25 100644 --- a/glquake.h +++ b/glquake.h @@ -71,7 +71,6 @@ extern int glx, gly, glwidth, glheight; extern void R_TimeRefresh_f (void); -extern void R_ReadPointFile_f (void); //==================================================== @@ -83,7 +82,7 @@ extern entity_t *currententity; extern int r_visframecount; // ??? what difs? extern int r_framecount; extern mplane_t frustum[4]; -extern int c_brush_polys, c_alias_polys, c_light_polys, c_nodes, c_leafs; +extern int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; // diff --git a/host.c b/host.c index 8ca544a4..25240ec3 100644 --- a/host.c +++ b/host.c @@ -37,6 +37,7 @@ quakeparms_t host_parms; qboolean host_initialized; // true if into command execution double host_frametime; +double host_realframetime; // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling) double host_time; double realtime; // without any filtering or bounding double oldrealtime; // last frame run @@ -55,6 +56,8 @@ jmp_buf host_abortserver; cvar_t host_framerate = {"host_framerate","0"}; // set for slow motion cvar_t host_speeds = {"host_speeds","0"}; // set for running times cvar_t slowmo = {"slowmo", "1.0"}; // LordHavoc: framerate independent slowmo +cvar_t host_minfps = {"host_minfps", "10"}; // LordHavoc: game logic lower cap on framerate (if framerate is below this is, it pretends it is this, so game logic will run normally) +cvar_t host_maxfps = {"host_maxfps", "1000"}; // LordHavoc: framerate upper cap cvar_t sys_ticrate = {"sys_ticrate","0.05"}; cvar_t serverprofile = {"serverprofile","0"}; @@ -216,6 +219,8 @@ void Host_InitLocal (void) Cvar_RegisterVariable (&host_framerate); Cvar_RegisterVariable (&host_speeds); Cvar_RegisterVariable (&slowmo); + Cvar_RegisterVariable (&host_minfps); + Cvar_RegisterVariable (&host_maxfps); Cvar_RegisterVariable (&sys_ticrate); Cvar_RegisterVariable (&serverprofile); @@ -507,21 +512,32 @@ qboolean Host_FilterTime (float time) { realtime += time; -// if (!cls.timedemo && realtime - oldrealtime < (1.0 / 72.0)) -// return false; // framerate is too high + if (slowmo.value < 0.0f) + Cvar_SetValue("slowmo", 0.0f); + if (host_minfps.value < 10.0f) + Cvar_SetValue("host_minfps", 10.0f); + if (host_maxfps.value < host_minfps.value) + Cvar_SetValue("host_maxfps", host_minfps.value); - host_frametime = (realtime - oldrealtime) * slowmo.value; // LordHavoc: slowmo cvar + if ((!cls.timedemo) && ((realtime - oldrealtime) < (1.0 / host_maxfps.value))) + return false; // framerate is too high + + host_realframetime = host_frametime = realtime - oldrealtime; // LordHavoc: copy into host_realframetime as well oldrealtime = realtime; + if (cls.timedemo) + return true; // disable time effects + if (host_framerate.value > 0) host_frametime = host_framerate.value; else - { // don't allow really long or short frames - if (host_frametime > 0.1) - host_frametime = 0.1; - if (host_frametime < 0.001) - host_frametime = 0.001; + { + // don't allow really short frames + if (host_frametime > (1.0 / host_minfps.value)) + host_frametime = (1.0 / host_minfps.value); } + + host_frametime *= slowmo.value; return true; } diff --git a/mathlib.h b/mathlib.h index 42c76ea8..3b669e90 100644 --- a/mathlib.h +++ b/mathlib.h @@ -40,6 +40,9 @@ extern int nanmask; #define bound(min,num,max) (num >= min ? (num < max ? num : max) : min) +#define VectorNegate(a,b) {b[0] = -(a[0]);b[1] = -(a[1]);b[2] = -(a[2]);} +#define VectorSet(a,b,c,d) {d[0]=(a);d[1]=(b);d[2]=(c);} +#define VectorClear(a) {a[0]=a[1]=a[2]=0;} #define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) #define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} #define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} @@ -48,7 +51,7 @@ extern int nanmask; #define VectorNormalize(v) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;} #define VectorNormalize2(v,dest) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;} #define VectorDistance2(a, b) ((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2])) -#define VectorDistance(a, b) sqrt(VectorDistance(a,b)) +#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b))) #define VectorLength(a) sqrt(DotProduct(a, a)) diff --git a/model_brush.h b/model_brush.h index ec31becd..172ae413 100644 --- a/model_brush.h +++ b/model_brush.h @@ -130,6 +130,7 @@ typedef struct msurface_s int dlightbits[8]; int lightframe; // avoid redundent addition of dlights + int worldnodeframe; // only render each surface once int lightmaptexturenum; byte styles[MAXLIGHTMAPS]; diff --git a/pr_edict.c b/pr_edict.c index f816537d..0bb47d99 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -235,8 +235,8 @@ void ED_Free (edict_t *ed) ed->v.colormap = 0; ed->v.skin = 0; ed->v.frame = 0; - VectorCopy (vec3_origin, ed->v.origin); - VectorCopy (vec3_origin, ed->v.angles); + VectorClear(ed->v.origin); + VectorClear(ed->v.angles); ed->v.nextthink = -1; ed->v.solid = 0; diff --git a/quakedef.h b/quakedef.h index e49cc204..3aee5075 100644 --- a/quakedef.h +++ b/quakedef.h @@ -266,6 +266,7 @@ extern cvar_t developer; extern qboolean host_initialized; // true if into command execution extern double host_frametime; +extern double host_realframetime; // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling) extern int host_framecount; // incremented every frame, never reset extern double realtime; // not bounded in any way, changed at // start of every frame, never reset diff --git a/r_part.c b/r_part.c index 03980806..7f8627c9 100644 --- a/r_part.c +++ b/r_part.c @@ -205,6 +205,7 @@ void r_part_shutdown() R_InitParticles =============== */ +void R_ReadPointFile_f (void); void R_Particles_Init (void) { int i; @@ -222,6 +223,8 @@ void R_Particles_Init (void) r_numparticles = MAX_PARTICLES; } + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + Cvar_RegisterVariable (&r_particles); Cvar_RegisterVariable (&r_dynamicparticles); @@ -887,7 +890,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) p->texnum = smokeparticletexture[rand()&7]; p->scale = lhrandom(4, 6); p->alpha = type == 4 ? 192 : 255; - p->color = 251; //(rand()&3)+68; + p->color = 247; //(rand()&3)+68; p->type = pt_bloodcloud; p->die = cl.time + 9999; for (j=0 ; j<3 ; j++) @@ -967,84 +970,37 @@ R_DrawParticles =============== */ extern cvar_t sv_gravity; -void R_CompleteLightPoint (vec3_t color, vec3_t p); void TraceLine (vec3_t start, vec3_t end, vec3_t impact); -void R_DrawParticles (void) +void R_MoveParticles (void) { particle_t *p; - int i, r,g,b,a; - float gravity, dvel, frametime, scale, scale2, minparticledist; - byte *color24; - vec3_t up, right, uprightangles, forward2, up2, right2, tempcolor, v; - int activeparticles, maxparticle, j, k; + int i, activeparticles, maxparticle, j, a; + vec3_t v; + float gravity, dvel, frametime; // LordHavoc: early out condition if (!numparticles) return; - VectorScale (vup, 1.5, up); - VectorScale (vright, 1.5, right); - - uprightangles[0] = 0; - uprightangles[1] = r_refdef.viewangles[1]; - uprightangles[2] = 0; - AngleVectors (uprightangles, forward2, right2, up2); - frametime = cl.time - cl.oldtime; gravity = frametime * sv_gravity.value; dvel = 1+4*frametime; - minparticledist = DotProduct(r_refdef.vieworg, vpn) + 16.0f; - activeparticles = 0; maxparticle = -1; j = 0; - for (k = 0, p = particles;k < numparticles;k++, p++) + for (i = 0, p = particles;i < numparticles;i++, p++) { if (p->die < cl.time) { freeparticles[j++] = p; continue; } - maxparticle = k; + maxparticle = i; activeparticles++; - // LordHavoc: only render if not too close - if (DotProduct(p->org, vpn) >= minparticledist) - { - color24 = (byte *) &d_8to24table[(int)p->color]; - r = color24[0]; - g = color24[1]; - b = color24[2]; - a = p->alpha; - if (r_dynamicparticles.value) - { - R_CompleteLightPoint(tempcolor, p->org); - r = (r * (int) tempcolor[0]) >> 7; - g = (g * (int) tempcolor[1]) >> 7; - b = (b * (int) tempcolor[2]) >> 7; - } - transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA); - scale = p->scale * -0.5;scale2 = p->scale * 0.5; - if (p->texnum == rainparticletexture) // rain streak - { - transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale , p->org[1] + up2[1]*scale + right2[1]*scale , p->org[2] + up2[2]*scale + right2[2]*scale , 0,1,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale , p->org[1] + up2[1]*scale2 + right2[1]*scale , p->org[2] + up2[2]*scale2 + right2[2]*scale , 0,0,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale2, p->org[1] + up2[1]*scale2 + right2[1]*scale2, p->org[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale2, p->org[1] + up2[1]*scale + right2[1]*scale2, p->org[2] + up2[2]*scale + right2[2]*scale2, 1,1,r,g,b,a); - } - else - { - transpolyvert(p->org[0] + up[0]*scale + right[0]*scale , p->org[1] + up[1]*scale + right[1]*scale , p->org[2] + up[2]*scale + right[2]*scale , 0,1,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 0,0,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale2, p->org[1] + up[1]*scale2 + right[1]*scale2, p->org[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale + right[0]*scale2, p->org[1] + up[1]*scale + right[1]*scale2, p->org[2] + up[2]*scale + right[2]*scale2, 1,1,r,g,b,a); - } - transpolyend(); - } - VectorCopy(p->org, p->oldorg); p->org[0] += p->vel[0]*frametime; p->org[1] += p->vel[1]*frametime; @@ -1055,14 +1011,12 @@ void R_DrawParticles (void) case pt_static: break; + // LordHavoc: drop-through because of shared code case pt_blob: - for (i=0 ; i<3 ; i++) - p->vel[i] *= dvel; - break; - + p->vel[2] *= dvel; case pt_blob2: - for (i=0 ; i<2 ; i++) - p->vel[i] *= dvel; + p->vel[0] *= dvel; + p->vel[1] *= dvel; break; case pt_grav: @@ -1085,19 +1039,13 @@ void R_DrawParticles (void) // } p->scale += frametime * 16; p->alpha -= frametime * 512; - if (p->alpha < 1 || p->scale < 1) - p->die = -1; break; case pt_fallfadespark: p->alpha -= frametime * 256; p->vel[2] -= gravity; - if (p->alpha < 1) - p->die = -1; break; case pt_fade: p->alpha -= frametime * 512; - if (p->alpha < 1) - p->die = -1; break; case pt_bubble: a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; @@ -1123,27 +1071,19 @@ void R_DrawParticles (void) p->vel[2] += lhrandom(-32,32); } p->alpha -= frametime * 64; - if (p->alpha < 1) - p->die = -1; break; // LordHavoc: for smoke trails case pt_smoke: p->scale += frametime * 16; - p->alpha -= frametime * 384; - if (p->alpha < 16) - p->die = -1; + p->alpha -= frametime * 256; break; case pt_smokecloud: p->scale += frametime * 64; - p->alpha -= frametime * 384; - if (p->alpha < 16) - p->die = -1; + p->alpha -= frametime * 256; break; case pt_splash: p->scale += frametime * 24; p->alpha -= frametime * 512; - if (p->alpha < 1) - p->die = -1; break; case pt_rain: a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; @@ -1185,6 +1125,14 @@ void R_DrawParticles (void) } break; } + + // LordHavoc: most particles did this check anyway, consistency... + if (p->alpha < 1) + p->die = -1; + + // LordHavoc: immediate removal of unnecessary particles (must be done to ensure compactor below operates properly in all cases) + if (p->die < cl.time) + freeparticles[j++] = p; } // fill in gaps to compact the array i = 0; @@ -1197,3 +1145,70 @@ void R_DrawParticles (void) numparticles = activeparticles; } +void R_CompleteLightPoint (vec3_t color, vec3_t p); + +void R_DrawParticles (void) +{ + particle_t *p; + int i, r,g,b,a; + float scale, scale2, minparticledist; + byte *color24; + vec3_t up, right, uprightangles, forward2, up2, right2, tempcolor; + + // LordHavoc: early out condition + if (!numparticles) + return; + + c_particles += numparticles; + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); + + uprightangles[0] = 0; + uprightangles[1] = r_refdef.viewangles[1]; + uprightangles[2] = 0; + AngleVectors (uprightangles, forward2, right2, up2); + + minparticledist = DotProduct(r_refdef.vieworg, vpn) + 16.0f; + + for (i = 0, p = particles;i < numparticles;i++, p++) + { + // LordHavoc: unnecessary (array was already compacted) +// if (p->die < cl.time) +// continue; + + // LordHavoc: only render if not too close + if (DotProduct(p->org, vpn) < minparticledist) + continue; + + color24 = (byte *) &d_8to24table[(int)p->color]; + r = color24[0]; + g = color24[1]; + b = color24[2]; + a = p->alpha; + if (r_dynamicparticles.value) + { + R_CompleteLightPoint(tempcolor, p->org); + r = (r * (int) tempcolor[0]) >> 7; + g = (g * (int) tempcolor[1]) >> 7; + b = (b * (int) tempcolor[2]) >> 7; + } + transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA); + scale = p->scale * -0.5;scale2 = p->scale * 0.5; + if (p->texnum == rainparticletexture) // rain streak + { + transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale , p->org[1] + up2[1]*scale + right2[1]*scale , p->org[2] + up2[2]*scale + right2[2]*scale , 0,1,r,g,b,a); + transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale , p->org[1] + up2[1]*scale2 + right2[1]*scale , p->org[2] + up2[2]*scale2 + right2[2]*scale , 0,0,r,g,b,a); + transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale2, p->org[1] + up2[1]*scale2 + right2[1]*scale2, p->org[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a); + transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale2, p->org[1] + up2[1]*scale + right2[1]*scale2, p->org[2] + up2[2]*scale + right2[2]*scale2, 1,1,r,g,b,a); + } + else + { + transpolyvert(p->org[0] + up[0]*scale + right[0]*scale , p->org[1] + up[1]*scale + right[1]*scale , p->org[2] + up[2]*scale + right[2]*scale , 0,1,r,g,b,a); + transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 0,0,r,g,b,a); + transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale2, p->org[1] + up[1]*scale2 + right[1]*scale2, p->org[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a); + transpolyvert(p->org[0] + up[0]*scale + right[0]*scale2, p->org[1] + up[1]*scale + right[1]*scale2, p->org[2] + up[2]*scale + right[2]*scale2, 1,1,r,g,b,a); + } + transpolyend(); + } +} diff --git a/r_sprites.c b/r_sprites.c index 512dad12..ef054901 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -100,6 +100,9 @@ void R_DrawSpriteModel (entity_t *e) // don't even bother culling, because it's just a single // polygon without a surface cache + + c_sprites++; + R_GetSpriteFrame (e, &oldframe, &newframe, &lerp); if (lerp < 0) lerp = 0; if (lerp > 1) lerp = 1; diff --git a/render.h b/render.h index 5bc09aff..c713eb40 100644 --- a/render.h +++ b/render.h @@ -157,6 +157,10 @@ extern void R_LavaSplash (vec3_t org); extern void R_TeleportSplash (vec3_t org); extern void R_PushDlights (void); +extern void R_DrawWorld (void); +//extern void R_RenderDlights (void); +extern void R_DrawParticles (void); +extern void R_MoveParticles (void); extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits); extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org); diff --git a/sv_main.c b/sv_main.c index 27ed2e5b..8bf174b6 100644 --- a/sv_main.c +++ b/sv_main.c @@ -46,6 +46,7 @@ void SV_Init (void) extern cvar_t sv_accelerate; extern cvar_t sv_idealpitchscale; extern cvar_t sv_aim; + extern cvar_t sv_predict; Cvar_RegisterVariable (&sv_maxvelocity); Cvar_RegisterVariable (&sv_gravity); @@ -57,6 +58,7 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_idealpitchscale); Cvar_RegisterVariable (&sv_aim); Cvar_RegisterVariable (&sv_nostep); + Cvar_RegisterVariable (&sv_predict); for (i=0 ; istepoldangles[0]; angles[1] = angles[1] * movelerp + ent->stepoldangles[1]; angles[2] = angles[2] * movelerp + ent->stepoldangles[2]; - VectorMA(origin, host_client->ping, ent->v.velocity, origin); + VectorMA(origin, host_client->latency, ent->v.velocity, origin); } else // copy as they are { @@ -1015,8 +1017,7 @@ void SV_SendClientMessages (void) SV_DropClient (false); // went to another level else { - if (NET_SendMessage (host_client->netconnection - , &host_client->message) == -1) + if (NET_SendMessage (host_client->netconnection, &host_client->message) == -1) SV_DropClient (true); // if the message couldn't send, kick off SZ_Clear (&host_client->message); host_client->last_message = realtime; diff --git a/sv_phys.c b/sv_phys.c index 06e1f40e..48af07c4 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -270,7 +270,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) if (trace.allsolid) { // entity is trapped in another solid - VectorCopy (vec3_origin, ent->v.velocity); + VectorClear(ent->v.velocity); return 3; } @@ -316,7 +316,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen - VectorCopy (vec3_origin, ent->v.velocity); + VectorClear(ent->v.velocity); return 3; } @@ -348,7 +348,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) if (numplanes != 2) { // Con_Printf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy (vec3_origin, ent->v.velocity); + VectorClear(ent->v.velocity); return 7; } CrossProduct (planes[0], planes[1], dir); @@ -362,7 +362,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) // if (DotProduct (ent->v.velocity, primal_velocity) <= 0) { - VectorCopy (vec3_origin, ent->v.velocity); + VectorClear(ent->v.velocity); return blocked; } } @@ -625,7 +625,7 @@ void SV_PushRotate (edict_t *pusher, float movetime) for (i=0 ; i<3 ; i++) amove[i] = pusher->v.avelocity[i] * movetime; - VectorSubtract (vec3_origin, amove, a); + VectorNegate (amove, a); AngleVectors (a, forward, right, up); VectorCopy (pusher->v.origin, pushorigin); @@ -923,7 +923,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) trace_t steptrace; VectorCopy (ent->v.origin, oldorg); - VectorCopy (vec3_origin, dir); + VectorClear (dir); for (i=0 ; i<8 ; i++) { @@ -959,7 +959,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) VectorCopy (oldorg, ent->v.origin); } - VectorCopy (vec3_origin, ent->v.velocity); + VectorClear (ent->v.velocity); return 7; // still not moving } @@ -1014,8 +1014,8 @@ void SV_WalkMove (edict_t *ent) // VectorCopy (oldorg, ent->v.origin); // back to start pos - VectorCopy (vec3_origin, upmove); - VectorCopy (vec3_origin, downmove); + VectorClear (upmove); + VectorClear (downmove); upmove[2] = STEPSIZE; downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; @@ -1116,12 +1116,14 @@ void SV_Physics_Client (edict_t *ent, int num) case MOVETYPE_FLY: if (!SV_RunThink (ent)) return; + SV_CheckWater (ent); SV_FlyMove (ent, host_frametime, NULL); break; case MOVETYPE_NOCLIP: if (!SV_RunThink (ent)) return; + SV_CheckWater (ent); VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); break; @@ -1314,8 +1316,8 @@ void SV_Physics_Toss (edict_t *ent) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, ent->v.velocity); - VectorCopy (vec3_origin, ent->v.avelocity); + VectorClear (ent->v.velocity); + VectorClear (ent->v.avelocity); } } diff --git a/sv_user.c b/sv_user.c index 12ef6157..8ddff994 100644 --- a/sv_user.c +++ b/sv_user.c @@ -25,6 +25,7 @@ edict_t *sv_player; extern cvar_t sv_friction; cvar_t sv_edgefriction = {"edgefriction", "2"}; +cvar_t sv_predict = {"sv_predict", "1"}; extern cvar_t sv_stopspeed; static vec3_t forward, right, up; @@ -459,8 +460,9 @@ void SV_ReadClientMove (usercmd_t *move) for (i=0, total = 0;i < NUM_PING_TIMES;i++) total += host_client->ping_times[i]; host_client->ping = total / NUM_PING_TIMES; // can be used for prediction - if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) // if paused for any reason, don't predict - host_client->latency = host_client->ping + sv_frametime; // push ahead by ticrate + host_client->latency = 0; + if (sv_predict.value && (svs.maxclients > 1) && (!sv.paused)) // if paused or a local game, don't predict + host_client->latency = host_client->ping; if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_ping))) val->_float = host_client->ping * 1000.0; diff --git a/world.c b/world.c index a37612bf..ec9942e4 100644 --- a/world.c +++ b/world.c @@ -692,11 +692,7 @@ loc0: } else { - // LordHavoc: unrolled vector operation because the compiler can't be sure vec3_origin is 0 -// VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); - trace->plane.normal[0] = -plane->normal[0]; - trace->plane.normal[1] = -plane->normal[1]; - trace->plane.normal[2] = -plane->normal[2]; + VectorNegate (plane->normal, trace->plane.normal); trace->plane.dist = -plane->dist; } @@ -824,11 +820,7 @@ loc0: } else { - // LordHavoc: vec3_origin is evil; the compiler can not rely on it being '0 0 0' -// VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); - trace->plane.normal[0] = -plane->normal[0]; - trace->plane.normal[1] = -plane->normal[1]; - trace->plane.normal[2] = -plane->normal[2]; + VectorNegate (plane->normal, trace->plane.normal); trace->plane.dist = -plane->dist; } @@ -974,7 +966,7 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max if (trace.fraction != 1) { - VectorSubtract (vec3_origin, ent->v.angles, a); + VectorNegate (ent->v.angles, a); AngleVectors (a, forward, right, up); VectorCopy (trace.endpos, temp); -- 2.39.2