From dbce962f09403fd5888d0bd858ceefc90bc3ea2b Mon Sep 17 00:00:00 2001 From: havoc Date: Thu, 5 Sep 2002 10:10:47 +0000 Subject: [PATCH] you can now (try to) play in maps you don't have, and models you don't have are shown as little multicolored things added CL_BoundingBoxForEntity to clean up the various mins/maxs calculations in the engine no longer spews clc_nops to server past the first signon stage the clc_nops sent to the server are now sent using unreliable packets (because queuing them up as reliable made no sense and spewed warnings when developer was on) failed client to server reliable messages now print a hexdump of the message contents when developer is on there is now Mod_PointContents (this is different than Mod_PointInLeaf because a lot of calls to Mod_PointInLeaf were just wanting the contents, and it's not convenient to check for NULL (no world model) in the caller r_speeds no longer reports a "walls" count, as it was often nearly identical to faces and simplified the code to remove it r_speeds faces count may count bmodels twice if some contain sky polygons (this is less technically correct, but more performance correct - it is processing the faces twice) DrawQ_Pic won't crash if given a NULL picname now (won't draw it either) r_cullsurfaces cvar added r_surfacesworldnode cvar added surface backface culling moved to PrepareSurfaces simplified a lot of worldnode related stuff surf->pvsframe and node->pvsframe and leaf->pvsframe simplified worldnode code, and only needs updating when leaf changes (this is partly how quake did things) leaf->visframe no longer exists, this meant changing/cleaning a lot of code leaf->dlightbits and leaf->dlightframe no longer exist, this meant doing TraceLine's to see if dlights should shine on models and such (but only if within radius of them) console is forced if there's nothing else to look at, this is tracked separately from whether the user wants a console (key_consoleactive is now bits, but most code should just check if it is non-zero) RecursiveHullCheckPoint has been enabled again, only invoked if trace length is exactly 0 SZ_GetSpace overflow warnings/errors have newlines at the end now R_VisibleCullBox is gone (it relied on leaf->visframe), uses R_CullBox instead move around some R_NewMap code into more suitable modules rearranged R_RenderView code a lot, to group things more appropriately dlights work correctly on bmodels now PR_Crash function added, to properly shutdown progs interpreter (reset it's stack) and print out a crash report PR_RunError went away, it has been replaced by Host_Error (which now calls PR_Crash incase it happend during progs execution) R_ResetQuakeSky and R_ResetSkyBox added, to clean up some sky related hacks in model loading various QC builtins added for getting info on surfaces from the engine git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2328 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_demo.c | 2 +- cl_main.c | 99 +++++---- cl_parse.c | 33 +-- cl_particles.c | 26 +-- cl_screen.c | 42 ++-- client.h | 4 +- collision.c | 14 +- common.c | 57 +++++- common.h | 1 + console.c | 3 +- gl_backend.c | 2 +- gl_backend.h | 3 +- gl_rmain.c | 298 +++++++++++++++------------ gl_rsurf.c | 518 +++++++++++++++++++++-------------------------- host.c | 9 +- keys.c | 30 ++- keys.h | 5 + makefile | 8 +- model_brush.c | 43 +++- model_brush.h | 20 +- model_shared.c | 13 +- model_shared.h | 3 - portals.c | 4 + pr_cmds.c | 219 ++++++++++++++++---- pr_exec.c | 38 ++-- pr_execprogram.h | 52 ++--- progs.h | 3 +- r_lerpanim.c | 4 + r_light.c | 237 ++++++++-------------- r_sky.c | 91 +++++---- render.h | 9 +- sv_move.c | 4 +- sv_phys.c | 12 +- view.c | 6 +- world.c | 11 +- 35 files changed, 1040 insertions(+), 883 deletions(-) diff --git a/cl_demo.c b/cl_demo.c index c0af9792..b38a2db5 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -399,7 +399,7 @@ void CL_TimeDemo_f (void) // instantly hide console and deactivate it key_dest = key_game; - key_consoleactive = false; + key_consoleactive = 0; scr_conlines = 0; scr_con_current = 0; diff --git a/cl_main.c b/cl_main.c index ae47246b..c4d450a9 100644 --- a/cl_main.c +++ b/cl_main.c @@ -259,6 +259,37 @@ static void CL_PrintEntities_f (void) } } +static const vec3_t nomodelmins = {-16, -16, -16}; +static const vec3_t nomodelmaxs = {16, 16, 16}; +void CL_BoundingBoxForEntity(entity_render_t *ent) +{ + if (ent->model) + { + if (ent->angles[0] || ent->angles[2]) + { + // pitch or roll + VectorAdd(ent->origin, ent->model->rotatedmins, ent->mins); + VectorAdd(ent->origin, ent->model->rotatedmaxs, ent->maxs); + } + else if (ent->angles[1]) + { + // yaw + VectorAdd(ent->origin, ent->model->yawmins, ent->mins); + VectorAdd(ent->origin, ent->model->yawmaxs, ent->maxs); + } + else + { + VectorAdd(ent->origin, ent->model->normalmins, ent->mins); + VectorAdd(ent->origin, ent->model->normalmaxs, ent->maxs); + } + } + else + { + VectorAdd(ent->origin, nomodelmins, ent->mins); + VectorAdd(ent->origin, nomodelmaxs, ent->maxs); + } +} + void CL_LerpUpdate(entity_t *e) { entity_persistent_t *p; @@ -605,35 +636,20 @@ static void CL_RelinkNetworkEntities() continue; } - if (ent->render.model == NULL) + // don't show entities with no modelindex (note: this still shows + // entities which have a modelindex that resolved to a NULL model) + if (!ent->state_current.modelindex) continue; if (effects & EF_NODRAW) continue; - if (ent->render.angles[0] || ent->render.angles[2]) - { - // pitch or roll - VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs); - } - else if (ent->render.angles[1]) - { - // yaw - VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs); - } - else - { - VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs); - } + CL_BoundingBoxForEntity(&ent->render); + if (ent->render.model && ent->render.model->name[0] == '*' && ent->render.model->type == mod_brush) + cl_brushmodel_entities[cl_num_brushmodel_entities++] = &ent->render; if (r_refdef.numentities < r_refdef.maxentities) r_refdef.entities[r_refdef.numentities++] = &ent->render; - if (ent->render.model->name[0] == '*' && ent->render.model->type == mod_brush) - cl_brushmodel_entities[cl_num_brushmodel_entities++] = &ent->render; - if (cl_num_entities < i + 1) cl_num_entities = i + 1; } @@ -746,23 +762,7 @@ static void CL_RelinkEffects() ent->render.scale = 1; ent->render.alpha = 1; - if (ent->render.angles[0] || ent->render.angles[2]) - { - // pitch or roll - VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs); - } - else if (ent->render.angles[1]) - { - // yaw - VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs); - } - else - { - VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs); - } + CL_BoundingBoxForEntity(&ent->render); } } } @@ -773,6 +773,7 @@ void CL_RelinkWorld (void) if (cl_num_entities < 1) cl_num_entities = 1; cl_brushmodel_entities[cl_num_brushmodel_entities++] = &cl_entities[0].render; + CL_BoundingBoxForEntity(&cl_entities[0].render); } void CL_RelinkEntities (void) @@ -834,7 +835,7 @@ int CL_ReadFromServer (void) cl_num_entities = 0; cl_num_brushmodel_entities = 0; - if (cls.state == ca_connected && cl.worldmodel) + if (cls.state == ca_connected && cls.signon == SIGNONS) { CL_RelinkEntities (); @@ -876,7 +877,7 @@ void CL_SendCmd (void) CL_SendMove (&cmd); } #ifndef NOROUTINGFIX - else + else if (cls.signon == 0 && !cls.demoplayback) { // LordHavoc: fix for NAT routing of netquake: // bounce back a clc_nop message to the newly allocated server port, @@ -884,9 +885,21 @@ void CL_SendCmd (void) // the server waits for this before sending anything if (realtime > cl.sendnoptime) { - Con_DPrintf("sending clc_nop to get server's attention\n"); cl.sendnoptime = realtime + 3; - MSG_WriteByte(&cls.message, clc_nop); + Con_DPrintf("sending clc_nop to get server's attention\n"); + { + sizebuf_t buf; + qbyte data[128]; + buf.maxsize = 128; + buf.cursize = 0; + buf.data = data; + MSG_WriteByte(&buf, clc_nop); + if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) + { + Con_Printf ("CL_SendCmd: lost server connection\n"); + CL_Disconnect (); + } + } } } #endif @@ -904,6 +917,8 @@ void CL_SendCmd (void) if (!NET_CanSendMessage (cls.netcon)) { Con_DPrintf ("CL_WriteToServer: can't send\n"); + if (developer.integer) + SZ_HexDumpToConsole(&cls.message); return; } diff --git a/cl_parse.c b/cl_parse.c index b33a23d7..0bb92223 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -388,6 +388,9 @@ void CL_ParseServerInfo (void) Mod_ClearUsed(); + // disable until we get textures for it + R_ResetSkyBox(); + // precache models memset (cl.model_precache, 0, sizeof(cl.model_precache)); for (nummodels=1 ; ; nummodels++) @@ -434,11 +437,10 @@ void CL_ParseServerInfo (void) { // LordHavoc: i == 1 means the first model is the world model cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1); - if (cl.model_precache[i] == NULL) { - Host_Error("Model %s not found\n", model_precache[i]); - return; + Con_Printf("Model %s not found\n", model_precache[i]); + //return; } CL_KeepaliveMessage (); } @@ -458,20 +460,19 @@ void CL_ParseServerInfo (void) ent->render.model = cl.worldmodel = cl.model_precache[1]; ent->render.scale = 1; ent->render.alpha = 1; - VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs); + CL_BoundingBoxForEntity(&ent->render); // clear entlife array memset(entlife, 0, MAX_EDICTS); cl_num_entities = 1; R_NewMap (); - CL_CGVM_Start(); + noclip_anglehack = false; // noclip is turned off at start + Mem_CheckSentinelsGlobal(); - noclip_anglehack = false; // noclip is turned off at start } void CL_ValidateState(entity_state_t *s) @@ -916,23 +917,7 @@ void CL_ParseStatic (int large) VectorCopy (ent->state_baseline.origin, ent->render.origin); VectorCopy (ent->state_baseline.angles, ent->render.angles); - if (ent->render.angles[0] || ent->render.angles[2]) - { - // pitch or roll - VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs); - } - else if (ent->render.angles[1]) - { - // yaw - VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs); - } - else - { - VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins); - VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs); - } + CL_BoundingBoxForEntity(&ent->render); // This is definitely cheating... if (ent->render.model == NULL) diff --git a/cl_particles.c b/cl_particles.c index 9a065549..11ed29f6 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -351,7 +351,7 @@ void CL_ParticleExplosion (vec3_t org, int smoke) if (cl_stainmaps.integer) R_Stain(org, 96, 80, 80, 80, 64, 176, 176, 176, 64); - i = Mod_PointInLeaf(org, cl.worldmodel)->contents; + i = Mod_PointContents(org, cl.worldmodel); if ((i == CONTENTS_SLIME || i == CONTENTS_WATER) && cl_particles.integer && cl_particles_bubbles.integer) { for (i = 0;i < 128;i++) @@ -717,7 +717,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) // if we skip out, leave it reset ent->persistent.trail_time = 0.0f; - contents = Mod_PointInLeaf(pos, cl.worldmodel)->contents; + contents = Mod_PointContents(pos, cl.worldmodel); if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA) return; @@ -880,7 +880,7 @@ void CL_MoveParticles (void) { f = p->friction * frametime; if (!content) - content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + content = Mod_PointContents(p->org, cl.worldmodel); if (content != CONTENTS_EMPTY) f *= 4; f = 1.0f - f; @@ -893,7 +893,7 @@ void CL_MoveParticles (void) { case pt_blood: if (!content) - content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + content = Mod_PointContents(p->org, cl.worldmodel); a = content; if (a != CONTENTS_EMPTY) { @@ -911,7 +911,7 @@ void CL_MoveParticles (void) break; case pt_bubble: if (!content) - content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + content = Mod_PointContents(p->org, cl.worldmodel); if (content != CONTENTS_WATER && content != CONTENTS_SLIME) { p->die = -1; @@ -928,7 +928,7 @@ void CL_MoveParticles (void) p->vel[2] = /*lhrandom(-32, 32) +*/ p->vel2[2]; } if (!content) - content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + content = Mod_PointContents(p->org, cl.worldmodel); a = content; if (a != CONTENTS_EMPTY && a != CONTENTS_SKY) p->die = -1; @@ -1305,17 +1305,9 @@ void R_DrawParticles (void) minparticledist = DotProduct(r_origin, vpn) + 16.0f; + // LordHavoc: only render if not too close for (i = 0, p = particles;i < cl_numparticles;i++, p++) - { - // LordHavoc: only render if not too close - if (DotProduct(p->org, vpn) < minparticledist) - continue; - - // LordHavoc: check if it's in a visible leaf - //if (Mod_PointInLeaf(p->org, cl.worldmodel)->visframe != r_framecount) - // continue; - - R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0); - } + if (DotProduct(p->org, vpn) >= minparticledist) + R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0); } diff --git a/cl_screen.c b/cl_screen.c index deceed22..16166631 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -237,11 +237,15 @@ void SCR_SetUpToDrawConsole (void) { Con_CheckResize (); - //if (key_dest == key_game && (!cl.worldmodel || cls.signon != SIGNONS)) - // key_dest = key_console; + if (key_dest == key_game && cls.signon != SIGNONS) + key_consoleactive |= KEY_CONSOLEACTIVE_FORCED; + else + key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED; // decide on the height of the console - if (key_consoleactive) + if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED) + scr_conlines = vid.conheight; // full screen + else if (key_consoleactive & KEY_CONSOLEACTIVE_USER) scr_conlines = vid.conheight/2; // half screen else scr_conlines = 0; // none visible @@ -348,7 +352,7 @@ void R_TimeReport(char *desc) void R_TimeReport_Start(void) { - r_timereport_active = r_speeds.integer && cl.worldmodel && cls.state == ca_connected; + r_timereport_active = r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected; r_speeds_string[0] = 0; if (r_timereport_active) { @@ -356,15 +360,14 @@ void R_TimeReport_Start(void) AngleVectors (r_refdef.viewangles, vpn, NULL, NULL); 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" + "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n" "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n" "%6i modeltris%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_faces, c_nodes, c_leafs, c_light_polys, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_alias_polys, c_meshs, c_meshtris); - c_brush_polys = 0; c_alias_polys = 0; c_light_polys = 0; c_faces = 0; @@ -478,7 +481,7 @@ void DrawQ_Pic(float x, float y, char *picname, float width, float height, float { int size; drawqueue_t *dq; - if (alpha < (1.0f / 255.0f)) + if (alpha < (1.0f / 255.0f) || !picname || !picname[0]) return; size = sizeof(*dq) + ((strlen(picname) + 1 + 3) & ~3); if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize) @@ -684,7 +687,7 @@ static void SCR_CalcRefdef (void) if (cl.worldmodel) { Mod_CheckLoaded(cl.worldmodel); - contents = Mod_PointInLeaf(r_refdef.vieworg, cl.worldmodel)->contents; + contents = Mod_PointContents(r_refdef.vieworg, cl.worldmodel); if (contents != CONTENTS_EMPTY && contents != CONTENTS_SOLID) { r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.015 + 0.985); @@ -880,10 +883,9 @@ void SHOWLMP_decodeshow(void) void SHOWLMP_drawall(void) { int i; - if (cl.worldmodel) - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive) - DrawQ_Pic(showlmp[i].x, showlmp[i].y, showlmp[i].pic, 0, 0, 1, 1, 1, 1, 0); + for (i = 0;i < SHOWLMP_MAXLABELS;i++) + if (showlmp[i].isactive) + DrawQ_Pic(showlmp[i].x, showlmp[i].y, showlmp[i].pic, 0, 0, 1, 1, 1, 1, 0); } void SHOWLMP_clear(void) @@ -939,7 +941,7 @@ void CL_UpdateScreen(void) else cl_avidemo_frame = 0; - if (cl.worldmodel) + if (cls.signon == SIGNONS) R_TimeReport("other"); CL_SetupScreenSize(); @@ -949,11 +951,11 @@ void CL_UpdateScreen(void) V_UpdateBlends(); V_CalcRefdef (); - if (cl.worldmodel) + if (cls.signon == SIGNONS) R_TimeReport("setup"); //FIXME: force menu if nothing else to look at? - //if (key_dest == key_game && !cl.worldmodel && cls.state == ca_disconnected) + //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected) if (scr_drawloading) { @@ -962,19 +964,19 @@ void CL_UpdateScreen(void) } else { - if (cl.worldmodel) + if (cls.signon == SIGNONS) { SCR_DrawNet (); SCR_DrawTurtle (); SCR_DrawPause (); Sbar_Draw(); + SHOWLMP_drawall(); + SCR_CheckDrawCenterString(); } - SCR_CheckDrawCenterString(); - SHOWLMP_drawall(); ui_draw(); CL_DrawVideo(); M_Draw(); - if (cl.worldmodel) + if (cls.signon == SIGNONS) { R_TimeReport("2d"); R_TimeReport_End(); diff --git a/client.h b/client.h index 02a6c558..cdd52556 100644 --- a/client.h +++ b/client.h @@ -483,7 +483,7 @@ extern cvar_t r_draweffects; extern cvar_t cl_explosions; extern cvar_t cl_stainmaps; -// these are updated by +// these are updated by CL_ClearState extern int cl_num_entities; extern int cl_num_static_entities; extern int cl_num_temp_entities; @@ -518,6 +518,8 @@ void CL_EstablishConnection (char *host); void CL_Disconnect (void); void CL_Disconnect_f (void); +void CL_BoundingBoxForEntity(entity_render_t *ent); + // // cl_input // diff --git a/collision.c b/collision.c index a22c8fb9..01904128 100644 --- a/collision.c +++ b/collision.c @@ -165,7 +165,6 @@ loc0: return HULLCHECKSTATE_DONE; } -/* // used if start and end are the same static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num) { @@ -204,7 +203,6 @@ static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num) } } } -*/ void Collision_RoundUpToHullSize(const model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs) { @@ -378,10 +376,10 @@ void Collision_ClipTrace (trace_t *trace, const void *cent, const model_t *cmode VectorCopy(endd, rhc.end); VectorCopy(rhc.end, rhc.trace->endpos); VectorSubtract(rhc.end, rhc.start, rhc.dist); - //if (DotProduct(rhc.dist, rhc.dist) > 0.00001) + if (rhc.dist[0] || rhc.dist[1] || rhc.dist[2]) RecursiveHullCheck (&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); - //else - // RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode); + else + RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode); // if we hit, unrotate endpos and normal, and store the entity we hit if (rhc.trace->fraction != 1) @@ -420,10 +418,10 @@ void Collision_ClipTrace (trace_t *trace, const void *cent, const model_t *cmode VectorSubtract(end, offset, rhc.end); VectorCopy(rhc.end, rhc.trace->endpos); VectorSubtract(rhc.end, rhc.start, rhc.dist); - //if (DotProduct(rhc.dist, rhc.dist) > 0.00001) + if (rhc.dist[0] || rhc.dist[1] || rhc.dist[2]) RecursiveHullCheck (&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); - //else - // RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode); + else + RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode); // if we hit, store the entity we hit if (rhc.trace->fraction != 1) diff --git a/common.c b/common.c index cbe05713..3dfcf6d5 100644 --- a/common.c +++ b/common.c @@ -434,13 +434,13 @@ void *SZ_GetSpace (sizebuf_t *buf, int length) if (buf->cursize + length > buf->maxsize) { if (!buf->allowoverflow) - Host_Error ("SZ_GetSpace: overflow without allowoverflow set"); + Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n"); if (length > buf->maxsize) - Host_Error ("SZ_GetSpace: %i is > full buffer size", length); + Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length); buf->overflowed = true; - Con_Printf ("SZ_GetSpace: overflow"); + Con_Printf ("SZ_GetSpace: overflow\n"); SZ_Clear (buf); } @@ -458,7 +458,7 @@ void SZ_Write (sizebuf_t *buf, void *data, int length) void SZ_Print (sizebuf_t *buf, char *data) { int len; - + len = strlen(data)+1; // byte * cast to keep VC++ happy @@ -468,6 +468,55 @@ void SZ_Print (sizebuf_t *buf, char *data) memcpy ((qbyte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0 } +static char *hexchar = "0123456789ABCDEF"; +void SZ_HexDumpToConsole(sizebuf_t *buf) +{ + int i; + char text[1024]; + char *cur, *flushpointer; + cur = text; + flushpointer = text + 512; + for (i = 0;i < buf->cursize;i++) + { + if ((i & 15) == 0) + { + *cur++ = hexchar[(i >> 12) & 15]; + *cur++ = hexchar[(i >> 8) & 15]; + *cur++ = hexchar[(i >> 4) & 15]; + *cur++ = hexchar[(i >> 0) & 15]; + *cur++ = ':'; + *cur++ = ' '; + } + else if ((i & 15) == 15) + *cur++ = '\n'; + else + *cur++ = ' '; + if (i & 1) + { + *cur++ = hexchar[(buf->data[i] >> 4) & 15] | 0x80; + *cur++ = hexchar[(buf->data[i] >> 0) & 15] | 0x80; + } + else + { + *cur++ = hexchar[(buf->data[i] >> 4) & 15]; + *cur++ = hexchar[(buf->data[i] >> 0) & 15]; + } + if (cur >= flushpointer) + { + *cur++ = 0; + Con_Printf("%s", text); + cur = text; + } + } + if ((i & 15) != 0) + *cur++ = '\n'; + if (cur > text) + { + *cur++ = 0; + Con_Printf("%s", text); + } +} + //============================================================================ diff --git a/common.h b/common.h index 3d2275f4..7ad25529 100644 --- a/common.h +++ b/common.h @@ -44,6 +44,7 @@ void SZ_Clear (sizebuf_t *buf); void *SZ_GetSpace (sizebuf_t *buf, int length); void SZ_Write (sizebuf_t *buf, void *data, int length); void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf +void SZ_HexDumpToConsole(sizebuf_t *buf); //============================================================================ #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG) diff --git a/console.c b/console.c index 66004911..93840d6d 100644 --- a/console.c +++ b/console.c @@ -78,7 +78,8 @@ Con_ToggleConsole_f */ void Con_ToggleConsole_f (void) { - key_consoleactive = !key_consoleactive; + // toggle the 'user wants console' bit + key_consoleactive ^= KEY_CONSOLEACTIVE_USER; memset (con_times, 0, sizeof(con_times)); } diff --git a/gl_backend.c b/gl_backend.c index 05ebc12b..4b8c0343 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -1044,7 +1044,7 @@ void SCR_UpdateScreen (void) R_TimeReport("clear"); - if (scr_conlines < vid.conheight) + if (scr_conlines < vid.conheight && cls.signon == SIGNONS) R_RenderView(); // draw 2D stuff diff --git a/gl_backend.h b/gl_backend.h index 3cbb6994..eac1e6d7 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -17,8 +17,7 @@ typedef struct int numverts; int tex[MAX_TEXTUREUNITS]; int texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present - // model to world transform matrix - matrix4x4_t matrix; + matrix4x4_t matrix; // model to world transform matrix // output int *index; diff --git a/gl_rmain.c b/gl_rmain.c index 82162e54..b16a2bda 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -26,7 +26,7 @@ int r_framecount; mplane_t frustum[4]; -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; +int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; // true during envmap command capture qboolean envmap; @@ -44,8 +44,6 @@ vec3_t vup; // refdef_t r_refdef; -mleaf_t *r_viewleaf, *r_oldviewleaf; - // 8.8 fraction of base light value unsigned short d_lightstylevalue[256]; @@ -125,50 +123,6 @@ static void R_TimeRefresh_f (void) extern cvar_t r_drawportals; -int R_VisibleCullBox (vec3_t mins, vec3_t maxs) -{ - int sides; - mnode_t *nodestack[8192], *node; - int stack = 0; - - if (R_CullBox(mins, maxs)) - return true; - - node = cl.worldmodel->nodes; -loc0: - if (node->contents < 0) - { - if (((mleaf_t *)node)->visframe == r_framecount) - return false; - if (!stack) - return true; - node = nodestack[--stack]; - goto loc0; - } - - sides = BOX_ON_PLANE_SIDE(mins, maxs, node->plane); - -// recurse down the contacted sides - if (sides & 1) - { - if (sides & 2) // 3 - { - // put second child on the stack for later examination - nodestack[stack++] = node->children[1]; - node = node->children[0]; - goto loc0; - } - else // 1 - { - node = node->children[0]; - goto loc0; - } - } - // 2 - node = node->children[1]; - goto loc0; -} - vec3_t fogcolor; vec_t fogdensity; float fog_density, fog_red, fog_green, fog_blue; @@ -248,8 +202,11 @@ void gl_main_shutdown(void) { } +extern void CL_ParseEntityLump(char *entitystring); void gl_main_newmap(void) { + if (cl.worldmodel && cl.worldmodel->entities) + CL_ParseEntityLump(cl.worldmodel->entities); r_framecount = 1; } @@ -313,20 +270,9 @@ float R_FarClip_Finish(void) R_NewMap =============== */ -void CL_ParseEntityLump(char *entitystring); void R_NewMap (void) { - int i; - - for (i = 0;i < 256;i++) - d_lightstylevalue[i] = 264; // normal light value - - r_viewleaf = NULL; - if (cl.worldmodel->entities) - CL_ParseEntityLump(cl.worldmodel->entities); R_Modules_NewMap(); - - r_farclip = 64.0f; } extern void R_Textures_Init(void); @@ -393,7 +339,8 @@ static void R_MarkEntities (void) Matrix4x4_CreateIdentity(&ent->matrix); Matrix4x4_CreateIdentity(&ent->inversematrix); - R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs); + if (cl.worldmodel) + R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs); if (!r_drawentities.integer) return; @@ -417,40 +364,23 @@ static void R_MarkEntities (void) VectorAdd(ent->angles, r_refdef.viewangles, ent->angles); } - if (ent->angles[0] || ent->angles[2]) - { - VectorMA(ent->origin, ent->scale, ent->model->rotatedmins, ent->mins); - VectorMA(ent->origin, ent->scale, ent->model->rotatedmaxs, ent->maxs); - } - else if (ent->angles[1]) - { - VectorMA(ent->origin, ent->scale, ent->model->yawmins, ent->mins); - VectorMA(ent->origin, ent->scale, ent->model->yawmaxs, ent->maxs); - } - else - { - VectorMA(ent->origin, ent->scale, ent->model->normalmins, ent->mins); - VectorMA(ent->origin, ent->scale, ent->model->normalmaxs, ent->maxs); - } - if (R_VisibleCullBox(ent->mins, ent->maxs)) + if (R_CullBox(ent->mins, ent->maxs)) continue; + ent->visframe = r_framecount; VectorCopy(ent->angles, v); - if (ent->model->type != mod_brush) + if (!ent->model || ent->model->type != mod_brush) v[0] = -v[0]; Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], v[0], v[1], v[2], ent->scale); Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix); R_LerpAnimation(ent); - ent->visframe = r_framecount; - - R_FarClip_Box(ent->mins, ent->maxs); - R_UpdateEntLights(ent); + R_FarClip_Box(ent->mins, ent->maxs); } } // only used if skyrendermasked, and normally returns false -int R_DrawBModelSky (void) +int R_DrawBrushModelsSky (void) { int i, sky; entity_render_t *ent; @@ -462,7 +392,7 @@ int R_DrawBModelSky (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - if (ent->visframe == r_framecount && ent->model->DrawSky) + if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky) { ent->model->DrawSky(ent); sky = true; @@ -471,6 +401,7 @@ int R_DrawBModelSky (void) return sky; } +void R_DrawNoModel(entity_render_t *ent); void R_DrawModels (void) { int i; @@ -482,8 +413,16 @@ void R_DrawModels (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - if (ent->visframe == r_framecount && ent->model->Draw) - ent->model->Draw(ent); + if (ent->visframe == r_framecount) + { + if (ent->model) + { + if (ent->model->Draw) + ent->model->Draw(ent); + } + else + R_DrawNoModel(ent); + } } } @@ -556,10 +495,6 @@ static void R_SetupFrame (void) AngleVectors (r_refdef.viewangles, vpn, vright, vup); -// current viewleaf - r_oldviewleaf = r_viewleaf; - r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); - R_AnimateLight (); } @@ -612,75 +547,63 @@ r_refdef must be set before the first call */ void R_RenderView (void) { - entity_render_t *world = &cl_entities[0].render; - if (!cl.worldmodel) + entity_render_t *world; + if (!r_refdef.entities/* || !cl.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); + world = &cl_entities[0].render; + // FIXME: move to client R_MoveExplosions(); R_TimeReport("mexplosion"); R_Textures_Frame(); - R_SetupFrame(); R_SetFrustum(); R_SetupFog(); R_SkyStartFrame(); R_BuildLightList(); - - R_FarClip_Start(r_origin, vpn, 768.0f); - R_TimeReport("setup"); - R_DrawWorld(world); - R_TimeReport("worldnode"); - + R_FarClip_Start(r_origin, vpn, 768.0f); R_MarkEntities(); - R_TimeReport("markentity"); - - R_SurfMarkLights(world); - R_TimeReport("marklights"); - r_farclip = R_FarClip_Finish() + 256.0f; + R_TimeReport("markentity"); R_Mesh_Start(r_farclip); - R_MeshQueue_BeginScene(); + if (R_DrawBrushModelsSky()) + R_TimeReport("bmodelsky"); - if (skyrendermasked) + if (world->model) { - if (R_DrawBModelSky()) - R_TimeReport("bmodelsky"); - } - else - { - R_DrawViewModel(); - R_TimeReport("viewmodel"); - } + R_DrawWorld(world); + R_TimeReport("worldnode"); - R_PrepareSurfaces(world); - R_TimeReport("surfprep"); + R_SurfMarkLights(world); + R_TimeReport("marklights"); - R_DrawSurfaces(world, SHADERSTAGE_SKY); - R_DrawSurfaces(world, SHADERSTAGE_NORMAL); - R_TimeReport("surfdraw"); + R_PrepareSurfaces(world); + R_TimeReport("surfprep"); - if (r_drawportals.integer) - { - R_DrawPortals(world); - R_TimeReport("portals"); + R_DrawSurfaces(world, SHADERSTAGE_SKY); + R_DrawSurfaces(world, SHADERSTAGE_NORMAL); + R_TimeReport("surfdraw"); + + if (r_drawportals.integer) + { + R_DrawPortals(world); + R_TimeReport("portals"); + } } // don't let sound skip if going slow if (!intimerefresh && !r_speeds.integer) S_ExtraUpdate (); - if (skyrendermasked) - { - R_DrawViewModel(); - R_TimeReport("viewmodel"); - } + R_DrawViewModel(); + R_TimeReport("viewmodel"); R_DrawModels(); R_TimeReport("models"); @@ -704,10 +627,129 @@ void R_RenderView (void) R_TimeReport("blendview"); R_MeshQueue_Render(); - R_MeshQueue_EndScene(); - R_Mesh_Finish(); R_TimeReport("meshfinish"); } +void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) +{ + int i; + float *v, *c, f1, f2, diff[3]; + rmeshbufferinfo_t m; + m.numtriangles = 12; + m.numverts = 8; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + Matrix4x4_CreateIdentity(&m.matrix); + if (R_Mesh_Draw_GetBuffer(&m, false)) + { + m.vertex[ 0] = mins[0];m.vertex[ 1] = mins[1];m.vertex[ 2] = mins[2]; + m.vertex[ 4] = maxs[0];m.vertex[ 5] = mins[1];m.vertex[ 6] = mins[2]; + m.vertex[ 8] = mins[0];m.vertex[ 9] = maxs[1];m.vertex[10] = mins[2]; + m.vertex[12] = maxs[0];m.vertex[13] = maxs[1];m.vertex[14] = mins[2]; + m.vertex[16] = mins[0];m.vertex[17] = mins[1];m.vertex[18] = maxs[2]; + m.vertex[20] = maxs[0];m.vertex[21] = mins[1];m.vertex[22] = maxs[2]; + m.vertex[24] = mins[0];m.vertex[25] = maxs[1];m.vertex[26] = maxs[2]; + m.vertex[28] = maxs[0];m.vertex[29] = maxs[1];m.vertex[30] = maxs[2]; + m.color[ 0] = m.color[ 4] = m.color[ 8] = m.color[12] = m.color[16] = m.color[20] = m.color[24] = m.color[28] = cr * m.colorscale; + m.color[ 1] = m.color[ 5] = m.color[ 9] = m.color[13] = m.color[17] = m.color[21] = m.color[25] = m.color[29] = cg * m.colorscale; + m.color[ 2] = m.color[ 6] = m.color[10] = m.color[14] = m.color[18] = m.color[22] = m.color[26] = m.color[30] = cb * m.colorscale; + m.color[ 3] = m.color[ 7] = m.color[11] = m.color[15] = m.color[19] = m.color[23] = m.color[27] = m.color[31] = ca; + if (fogenabled) + { + for (i = 0, v = m.vertex, c = m.color;i < m.numverts;i++, v += 4, c += 4) + { + VectorSubtract(v, r_origin, diff); + f2 = exp(fogdensity/DotProduct(diff, diff)); + f1 = 1 - f2; + f2 *= m.colorscale; + c[0] = c[0] * f1 + fogcolor[0] * f2; + c[1] = c[1] * f1 + fogcolor[1] * f2; + c[2] = c[2] * f1 + fogcolor[2] * f2; + } + } + R_Mesh_Render(); + } +} + +void R_DrawNoModelCallback(const void *calldata1, int calldata2) +{ + const entity_render_t *ent = calldata1; + int i; + float f1, f2, *c, diff[3]; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (ent->flags & EF_ADDITIVE) + { + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (ent->alpha < 1) + { + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.numtriangles = 8; + m.numverts = 6; + m.matrix = ent->matrix; + if (R_Mesh_Draw_GetBuffer(&m, false)) + { + m.index[ 0] = 5;m.index[ 1] = 2;m.index[ 2] = 0; + m.index[ 3] = 5;m.index[ 4] = 1;m.index[ 5] = 2; + m.index[ 6] = 5;m.index[ 7] = 0;m.index[ 8] = 3; + m.index[ 9] = 5;m.index[10] = 3;m.index[11] = 1; + m.index[12] = 0;m.index[13] = 2;m.index[14] = 4; + m.index[15] = 2;m.index[16] = 1;m.index[17] = 4; + m.index[18] = 3;m.index[19] = 0;m.index[20] = 4; + m.index[21] = 1;m.index[22] = 3;m.index[23] = 4; + m.vertex[ 0] = -16;m.vertex[ 1] = 0;m.vertex[ 2] = 0; + m.vertex[ 4] = 16;m.vertex[ 5] = 0;m.vertex[ 6] = 0; + m.vertex[ 8] = 0;m.vertex[ 9] = -16;m.vertex[10] = 0; + m.vertex[12] = 0;m.vertex[13] = 16;m.vertex[14] = 0; + m.vertex[16] = 0;m.vertex[17] = 0;m.vertex[18] = -16; + m.vertex[20] = 0;m.vertex[21] = 0;m.vertex[22] = 16; + m.color[ 0] = 0.00f;m.color[ 1] = 0.00f;m.color[ 2] = 0.50f;m.color[ 3] = ent->alpha; + m.color[ 4] = 0.00f;m.color[ 5] = 0.00f;m.color[ 6] = 0.50f;m.color[ 7] = ent->alpha; + m.color[ 8] = 0.00f;m.color[ 9] = 0.50f;m.color[10] = 0.00f;m.color[11] = ent->alpha; + m.color[12] = 0.00f;m.color[13] = 0.50f;m.color[14] = 0.00f;m.color[15] = ent->alpha; + m.color[16] = 0.50f;m.color[17] = 0.00f;m.color[18] = 0.00f;m.color[19] = ent->alpha; + m.color[20] = 0.50f;m.color[21] = 0.00f;m.color[22] = 0.00f;m.color[23] = ent->alpha; + if (fogenabled) + { + VectorSubtract(ent->origin, r_origin, diff); + f2 = exp(fogdensity/DotProduct(diff, diff)); + f1 = 1 - f2; + for (i = 0, c = m.color;i < m.numverts;i++, c += 4) + { + c[0] = (c[0] * f1 + fogcolor[0] * f2) * m.colorscale; + c[1] = (c[1] * f1 + fogcolor[1] * f2) * m.colorscale; + c[2] = (c[2] * f1 + fogcolor[2] * f2) * m.colorscale; + } + } + else + { + for (i = 0, c = m.color;i < m.numverts;i++, c += 4) + { + c[0] *= m.colorscale; + c[1] *= m.colorscale; + c[2] *= m.colorscale; + } + } + R_Mesh_Render(); + } +} + +void R_DrawNoModel(entity_render_t *ent) +{ + //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1)) + R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0); + //else + // R_DrawNoModelCallback(ent, 0); +} + diff --git a/gl_rsurf.c b/gl_rsurf.c index 86502d13..35701067 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -35,10 +35,17 @@ cvar_t r_drawportals = {0, "r_drawportals", "0"}; cvar_t r_testvis = {0, "r_testvis", "0"}; cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"}; cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"}; +cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"}; +cvar_t r_cullsurface = {0, "r_cullsurface", "0"}; static int dlightdivtable[32768]; -static int R_IntAddDynamicLights (msurface_t *surf) +// variables used by R_PVSUpdate +int r_pvsframecount = 0; +mleaf_t *r_viewleaf = NULL; +int r_viewleafnovis = 0; + +static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf) { int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract; unsigned int *bl; @@ -62,7 +69,7 @@ static int R_IntAddDynamicLights (msurface_t *surf) if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31)))) continue; // not lit by this light - softwareuntransform(r_dlight[lnum].origin, local); + Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; // for comparisons to minimum acceptable light @@ -139,7 +146,7 @@ static int R_IntAddDynamicLights (msurface_t *surf) return lit; } -static int R_FloatAddDynamicLights (msurface_t *surf) +static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf) { int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt; float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract; @@ -155,7 +162,7 @@ static int R_FloatAddDynamicLights (msurface_t *surf) if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31)))) continue; // not lit by this light - softwareuntransform(r_dlight[lnum].origin, local); + Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; // for comparisons to minimum acceptable light @@ -280,7 +287,7 @@ static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surf, int d if (surf->dlightframe == r_framecount && r_dlightmap.integer) { - surf->cached_dlight = R_IntAddDynamicLights(surf); + surf->cached_dlight = R_IntAddDynamicLights(&ent->inversematrix, surf); if (surf->cached_dlight) c_light_polys++; else if (dlightchanged) @@ -371,7 +378,7 @@ static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surf, int d if (surf->dlightframe == r_framecount && r_dlightmap.integer) { - surf->cached_dlight = R_FloatAddDynamicLights(surf); + surf->cached_dlight = R_FloatAddDynamicLights(&ent->inversematrix, surf); if (surf->cached_dlight) c_light_polys++; else if (dlightchanged) @@ -587,7 +594,8 @@ void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, i icolor[7] = ca2; model = cl.worldmodel; - R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor); + if (model) + R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor); // look for embedded bmodels for (n = 0;n < cl_num_brushmodel_entities;n++) @@ -795,7 +803,7 @@ static int RSurf_LightSeparate(const matrix4x4_t *matrix, const int *dlightbits, // note: this untransforms lights to do the checking, // and takes surf->mesh->vertex data -static int RSurf_LightCheck(const int *dlightbits, surfmesh_t *mesh) +static int RSurf_LightCheck(const matrix4x4_t *matrix, const int *dlightbits, surfmesh_t *mesh) { int i, l; rdlight_t *rd; @@ -806,7 +814,7 @@ static int RSurf_LightCheck(const int *dlightbits, surfmesh_t *mesh) if (dlightbits[l >> 5] & (1 << (l & 31))) { rd = &r_dlight[l]; - softwareuntransform(rd->origin, lightorigin); + Matrix4x4_Transform(matrix, rd->origin, lightorigin); for (i = 0, sv = mesh->vertex;i < mesh->numverts;i++, sv++) if (VectorDistance2(sv->v, lightorigin) < rd->cullradius2) return true; @@ -1230,7 +1238,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const m.matrix = ent->matrix; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - if (RSurf_LightCheck(surf->dlightbits, mesh)) + if (RSurf_LightCheck(&ent->inversematrix, surf->dlightbits, mesh)) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; @@ -1342,7 +1350,6 @@ static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const msurfa { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces); } @@ -1351,7 +1358,6 @@ static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const msurfa { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1390,7 +1396,6 @@ static void RSurfShader_Wall_Vertex(const entity_render_t *ent, const msurface_t { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces); } @@ -1399,7 +1404,6 @@ static void RSurfShader_Wall_Vertex(const entity_render_t *ent, const msurface_t { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1427,7 +1431,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces); } @@ -1436,7 +1439,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1462,7 +1464,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1476,7 +1477,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1495,7 +1495,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface { for (surf = firstsurf;surf;surf = surf->chain) { - c_brush_polys++; if (surf->currenttexture->fogtexture != NULL) { Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); @@ -1528,236 +1527,6 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface } } -/* -============================================================= - - WORLD MODEL - -============================================================= -*/ - -static void R_SolidWorldNode (entity_render_t *ent) -{ - if (r_viewleaf->contents != CONTENTS_SOLID) - { - int portalstack; - mportal_t *p, *pstack[8192]; - msurface_t *surf, **mark, **endmark; - mleaf_t *leaf; - // LordHavoc: portal-passage worldnode; follows portals leading - // outward from viewleaf, if a portal leads offscreen it is not - // followed, in indoor maps this can often cull a great deal of - // geometry away when pvs data is not present (useful with pvs as well) - - leaf = r_viewleaf; - leaf->worldnodeframe = r_framecount; - portalstack = 0; - loc0: - c_leafs++; - - leaf->visframe = r_framecount; - - 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(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } - } - while (mark < endmark); - } - - // follow portals into other leafs - p = leaf->portals; - for (;p;p = p->next) - { - if (DotProduct(r_origin, p->plane.normal) < p->plane.dist) - { - leaf = p->past; - if (leaf->worldnodeframe != r_framecount) - { - leaf->worldnodeframe = r_framecount; - if (leaf->contents != CONTENTS_SOLID) - { - if (R_NotCulledBox(leaf->mins, leaf->maxs)) - { - p->visframe = r_framecount; - pstack[portalstack++] = p; - goto loc0; - - loc1: - p = pstack[--portalstack]; - } - } - } - } - } - - if (portalstack) - goto loc1; - } - else - { - mnode_t *nodestack[8192], *node = cl.worldmodel->nodes; - int nodestackpos = 0; - // LordHavoc: recursive descending worldnode; if portals are not - // available, this is a good last resort, can cull large amounts of - // geometry, but is more time consuming than portal-passage and renders - // things behind walls - -loc2: - if (R_NotCulledBox(node->mins, node->maxs)) - { - if (node->numsurfaces) - { - msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces; - if (PlaneDiff (r_origin, node->plane) < 0) - { - for (;surf < surfend;surf++) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - } - else - { - for (;surf < surfend;surf++) - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } - } - } - - // recurse down the children - if (node->children[0]->contents >= 0) - { - if (node->children[1]->contents >= 0) - { - if (nodestackpos < 8192) - nodestack[nodestackpos++] = node->children[1]; - node = node->children[0]; - goto loc2; - } - else - ((mleaf_t *)node->children[1])->visframe = r_framecount; - node = node->children[0]; - goto loc2; - } - else - { - ((mleaf_t *)node->children[0])->visframe = r_framecount; - if (node->children[1]->contents >= 0) - { - node = node->children[1]; - goto loc2; - } - else if (nodestackpos > 0) - { - ((mleaf_t *)node->children[1])->visframe = r_framecount; - node = nodestack[--nodestackpos]; - goto loc2; - } - } - } - else if (nodestackpos > 0) - { - node = nodestack[--nodestackpos]; - goto loc2; - } - } -} - -static void R_PVSWorldNode() -{ - int portalstack, i; - mportal_t *p, *pstack[8192]; - msurface_t *surf, **mark, **endmark; - mleaf_t *leaf; - qbyte *worldvis; - - worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - - leaf = r_viewleaf; - leaf->worldnodeframe = r_framecount; - portalstack = 0; -loc0: - c_leafs++; - - leaf->visframe = r_framecount; - - 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(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } - } - while (mark < endmark); - } - - // follow portals into other leafs - for (p = leaf->portals;p;p = p->next) - { - if (DotProduct(r_origin, p->plane.normal) < p->plane.dist) - { - leaf = p->past; - if (leaf->worldnodeframe != r_framecount) - { - leaf->worldnodeframe = r_framecount; - if (leaf->contents != CONTENTS_SOLID) - { - i = (leaf - cl.worldmodel->leafs) - 1; - if (worldvis[i>>3] & (1<<(i&7))) - { - if (R_NotCulledBox(leaf->mins, leaf->maxs)) - { - pstack[portalstack++] = p; - goto loc0; - -loc1: - p = pstack[--portalstack]; - } - } - } - } - } - } - - if (portalstack) - goto loc1; -} - Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex}, NULL}; Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, NULL}; Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, NULL}; @@ -1780,6 +1549,7 @@ void R_PrepareSurfaces(entity_render_t *ent) texture_t *t; model_t *model; msurface_t *surf; + vec3_t modelorg; for (i = 0;i < Cshader_count;i++) Cshaders[i]->chain = NULL; @@ -1788,14 +1558,25 @@ void R_PrepareSurfaces(entity_render_t *ent) alttextures = ent->frame != 0; texframe = (int)(cl.time * 5.0f); + Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); for (i = 0;i < model->nummodelsurfaces;i++) { surf = model->modelsortedsurfaces[i]; if (surf->visframe == r_framecount) { - if (surf->insertframe != r_framecount) + // mark any backface surfaces as not visible + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) + { + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = -1; + } + else + { + if (surf->flags & SURF_PLANEBACK) + surf->visframe = -1; + } + if (surf->visframe == r_framecount) { - surf->insertframe = r_framecount; c_faces++; t = surf->texinfo->texture; if (t->animated) @@ -1808,18 +1589,18 @@ void R_PrepareSurfaces(entity_render_t *ent) } else surf->currenttexture = t; - } - surf->chain = surf->shader->chain; - surf->shader->chain = surf; + surf->chain = surf->shader->chain; + surf->shader->chain = surf; + } } } } void R_DrawSurfaces (entity_render_t *ent, int type) { - int i; - Cshader_t *shader; + int i; + Cshader_t *shader; for (i = 0;i < Cshader_count;i++) { @@ -1892,37 +1673,36 @@ void R_DrawPortals(entity_render_t *ent) } } -void R_SetupForBModelRendering(entity_render_t *ent) +void R_SetupForBrushModelRendering(entity_render_t *ent) { - int i; - msurface_t *surf; - model_t *model; - vec3_t modelorg; + int i; + msurface_t *surf; + model_t *model; + vec3_t modelorg; // because bmodels can be reused, we have to decide which things to render // from scratch every time - model = ent->model; - Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); for (i = 0;i < model->nummodelsurfaces;i++) { - surf = model->modelsortedsurfaces[i]; - if (((surf->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, surf->plane) >= 0)) - surf->visframe = r_framecount; - else - surf->visframe = -1; + surf = model->surfaces + model->firstmodelsurface + i; + surf->visframe = r_framecount; + surf->pvsframe = -1; surf->worldnodeframe = -1; surf->lightframe = -1; surf->dlightframe = -1; - surf->insertframe = -1; } + R_PrepareSurfaces(ent); } void R_SurfMarkLights (entity_render_t *ent) { - int i; - msurface_t *surf; + int i; + msurface_t *surf; + + if (!ent->model) + return; if (r_dynamic.integer) R_MarkLights(ent); @@ -1952,6 +1732,171 @@ void R_SurfMarkLights (entity_render_t *ent) } } +void R_SurfaceWorldNode (entity_render_t *ent) +{ + int i; + msurface_t *surf; + model_t *model; + model = ent->model; + // FIXME: R_NotCulledBox is absolute, should be done relative + for (i = 0, surf = model->surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surf++) + if (surf->pvsframe == r_pvsframecount && (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs))) + surf->visframe = r_framecount; +} + +/* +static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf) +{ + int portalstack, i; + mportal_t *p, *pstack[8192]; + msurface_t *surf, **mark, **endmark; + mleaf_t *leaf; + // LordHavoc: portal-passage worldnode with PVS; + // follows portals leading outward from viewleaf, does not venture + // offscreen or into leafs that are not visible, faster than Quake's + // RecursiveWorldNode + leaf = viewleaf; + leaf->worldnodeframe = r_framecount; + portalstack = 0; +loc0: + c_leafs++; + if (leaf->nummarksurfaces) + { + for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--) + { + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe != r_framecount) + { + surf->worldnodeframe = r_framecount; + if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) + { + if (surf->flags & SURF_PLANEBACK) + surf->visframe = r_framecount; + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = r_framecount; + } + } + } + } + // follow portals into other leafs + for (p = leaf->portals;p;p = p->next) + { + leaf = p->past; + if (leaf->worldnodeframe != r_framecount) + { + leaf->worldnodeframe = r_framecount; + // FIXME: R_NotCulledBox is absolute, should be done relative + if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs)) + { + p->visframe = r_framecount; + pstack[portalstack++] = p; + goto loc0; +loc1: + p = pstack[--portalstack]; + } + } + } + if (portalstack) + goto loc1; +} +*/ + +static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf) +{ + int c, leafstackpos; + mleaf_t *leaf, *leafstack[8192]; + mportal_t *p; + msurface_t *surf, **mark; + vec3_t modelorg; + // LordHavoc: portal-passage worldnode with PVS; + // follows portals leading outward from viewleaf, does not venture + // offscreen or into leafs that are not visible, faster than Quake's + // RecursiveWorldNode + Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg); + viewleaf->worldnodeframe = r_framecount; + leafstack[0] = viewleaf; + leafstackpos = 1; + while (leafstackpos) + { + c_leafs++; + leaf = leafstack[--leafstackpos]; + // only useful for drawing portals + //leaf->visframe = r_framecount; + // draw any surfaces bounding this leaf + if (leaf->nummarksurfaces) + { + for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--) + { + surf = *mark++; + if (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs)) + surf->visframe = r_framecount; + } + } + // follow portals into other leafs + for (p = leaf->portals;p;p = p->next) + { + leaf = p->past; + if (leaf->worldnodeframe != r_framecount) + { + leaf->worldnodeframe = r_framecount; + // FIXME: R_NotCulledBox is absolute, should be done relative + if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs)) + leafstack[leafstackpos++] = leaf; + } + } + } +} + + +void R_PVSUpdate (mleaf_t *viewleaf) +{ + int i, j, l, c, bits; + mnode_t *node; + mleaf_t *leaf; + qbyte *vis; + msurface_t **mark; + + if (r_viewleaf == viewleaf && r_viewleafnovis == r_novis.integer) + return; + + r_pvsframecount++; + r_viewleaf = viewleaf; + r_viewleafnovis = r_novis.integer; + + if (viewleaf) + { + vis = Mod_LeafPVS (viewleaf, cl.worldmodel); + for (j = 0;j < cl.worldmodel->numleafs;j += 8) + { + bits = *vis++; + if (bits) + { + l = cl.worldmodel->numleafs - j; + if (l > 8) + l = 8; + for (i = 0;i < l;i++) + { + if (bits & (1 << i)) + { + leaf = &cl.worldmodel->leafs[j + i + 1]; + // mark surfaces bounding this leaf as visible + for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--) + (*mark++)->pvsframe = r_pvsframecount; + // mark parents as visible until we hit an already + // marked parent (which is usually very soon) + for (node = (mnode_t *)leaf;node && node->pvsframe != r_pvsframecount;node = node->parent) + node->pvsframe = r_pvsframecount; + } + } + } + } + } +} + /* ============= R_DrawWorld @@ -1961,10 +1906,15 @@ void R_DrawWorld (entity_render_t *ent) { // there is only one instance of the world, but it can be rendered in // multiple stages - if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.integer || r_viewleaf->compressed_vis == NULL) - R_SolidWorldNode (ent); + mleaf_t *viewleaf; + viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + R_PVSUpdate(viewleaf); + if (!viewleaf) + return; + if (r_surfaceworldnode.integer || viewleaf->contents == CONTENTS_SOLID) + R_SurfaceWorldNode (ent); else - R_PVSWorldNode (ent); + R_PortalWorldNode (ent, viewleaf); } /* @@ -1974,27 +1924,17 @@ R_DrawBrushModel */ void R_DrawBrushModelSky (entity_render_t *ent) { - R_SetupForBModelRendering(ent); - - R_PrepareSurfaces(ent); + R_SetupForBrushModelRendering(ent); R_DrawSurfaces(ent, SHADERSTAGE_SKY); } void R_DrawBrushModelNormal (entity_render_t *ent) { c_bmodels++; - // have to flush queue because of possible lightmap reuse R_Mesh_Render(); - - R_SetupForBModelRendering(ent); - + R_SetupForBrushModelRendering(ent); R_SurfMarkLights(ent); - - R_PrepareSurfaces(ent); - - if (!skyrendermasked) - R_DrawSurfaces(ent, SHADERSTAGE_SKY); R_DrawSurfaces(ent, SHADERSTAGE_NORMAL); } @@ -2008,6 +1948,10 @@ static void gl_surf_shutdown(void) static void gl_surf_newmap(void) { + // reset pvs visibility variables so it will update on first frame + r_pvsframecount = 1; + r_viewleaf = NULL; + r_viewleafnovis = false; } void GL_Surf_Init(void) @@ -2024,6 +1968,8 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&r_testvis); Cvar_RegisterVariable(&r_floatbuildlightmap); Cvar_RegisterVariable(&r_detailtextures); + Cvar_RegisterVariable(&r_surfaceworldnode); + Cvar_RegisterVariable(&r_cullsurface); R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } diff --git a/host.c b/host.c index ef402120..2816a121 100644 --- a/host.c +++ b/host.c @@ -143,12 +143,14 @@ void Host_Error (char *error, ...) Sys_Error ("Host_Error: recursively entered (original error was: %s new error is: %s)", hosterrorstring, string); } inerror = true; - + va_start (argptr,error); vsprintf (hosterrorstring,error,argptr); va_end (argptr); Con_Printf ("Host_Error: %s\n",hosterrorstring); - + + PR_Crash(); + if (sv.active) Host_ShutdownServer (false); @@ -449,6 +451,9 @@ void Host_ShutdownServer(qboolean crash) if (!sv.active) return; + // print out where the crash happened, if it was caused by QC + PR_Crash(); + sv.active = false; // stop all client sounds immediately diff --git a/keys.c b/keys.c index ff098d5f..9b4380a9 100644 --- a/keys.c +++ b/keys.c @@ -703,25 +703,19 @@ void Key_Event (int key, qboolean down) { if (!down) return; - if (key_consoleactive) - M_ToggleMenu_f (); - else + switch (key_dest) { - switch (key_dest) - { - case key_message: - Key_Message (key); - break; - case key_menu: - M_Keydown (key); - break; - case key_game: - //case key_console: - M_ToggleMenu_f (); - break; - default: - Sys_Error ("Bad key_dest"); - } + case key_message: + Key_Message (key); + break; + case key_menu: + M_Keydown (key); + break; + case key_game: + M_ToggleMenu_f (); + break; + default: + Sys_Error ("Bad key_dest"); } return; } diff --git a/keys.h b/keys.h index 4447faf4..57d32eed 100644 --- a/keys.h +++ b/keys.h @@ -149,6 +149,11 @@ typedef enum { typedef enum {key_game, key_message, key_menu} keydest_t; +// key_consoleactive bits +// user wants console (halfscreen) +#define KEY_CONSOLEACTIVE_USER 1 +// console forced because there's nothing else active (fullscreen) +#define KEY_CONSOLEACTIVE_FORCED 2 extern int key_consoleactive; extern keydest_t key_dest; extern char *keybindings[256]; diff --git a/makefile b/makefile index fff672e4..ec3105c2 100644 --- a/makefile +++ b/makefile @@ -50,11 +50,11 @@ NOPROFILEOPTIMIZATIONS= #this is used to ensure that all released versions are free of warnings. #normal compile -OPTIMIZATIONS= -O6 -fno-strict-aliasing -ffast-math -funroll-loops $(NOPROFILEOPTIMIZATIONS) -fexpensive-optimizations $(CPUOPTIMIZATIONS) -CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include $(OPTIMIZATIONS) $(PROFILEOPTION) +#OPTIMIZATIONS= -O6 -fno-strict-aliasing -ffast-math -funroll-loops $(NOPROFILEOPTIMIZATIONS) -fexpensive-optimizations $(CPUOPTIMIZATIONS) +#CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include $(OPTIMIZATIONS) $(PROFILEOPTION) #debug compile -#OPTIMIZATIONS= -#CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -ggdb $(OPTIMIZATIONS) $(PROFILEOPTION) +OPTIMIZATIONS= +CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -ggdb $(OPTIMIZATIONS) $(PROFILEOPTION) LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXxf86dga -lXxf86vm -ldl $(SOUNDLIB) $(PROFILEOPTION) diff --git a/model_brush.c b/model_brush.c index 92244c45..4eec6da8 100644 --- a/model_brush.c +++ b/model_brush.c @@ -111,7 +111,10 @@ Mod_PointInLeaf */ mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) { - mnode_t *node; + mnode_t *node; + + if (model == NULL) + return NULL; Mod_CheckLoaded(model); @@ -124,17 +127,35 @@ mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) return (mleaf_t *)node; } +int Mod_PointContents (const vec3_t p, model_t *model) +{ + mnode_t *node; + + if (model == NULL) + return CONTENTS_EMPTY; + + Mod_CheckLoaded(model); + + // LordHavoc: modified to start at first clip node, + // in other words: first node of the (sub)model + node = model->nodes + model->hulls[0].firstclipnode; + while (node->contents == 0) + node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist]; + + return ((mleaf_t *)node)->contents; +} + void Mod_FindNonSolidLocation(vec3_t pos, model_t *mod) { - if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[0]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[0]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[0]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[0]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; pos[0]-=1; - pos[1]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[1]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + pos[1]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[1]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; pos[1]-=1; - pos[2]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[2]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + pos[2]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[2]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; pos[2]-=1; } @@ -1275,6 +1296,8 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2]; vert += 3; } + VectorCopy(mins, surf->poly_mins); + VectorCopy(maxs, surf->poly_maxs); surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f; surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f; surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f; @@ -2485,7 +2508,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i (Quake) or 30 (HalfLife))", mod->name, i, BSPVERSION); mod->ishlbsp = i == 30; if (loadmodel->isworldmodel) + { Cvar_SetValue("halflifebsp", mod->ishlbsp); + // until we get a texture for it... + R_ResetQuakeSky(); + } // swap all the lumps mod_base = (qbyte *)header; diff --git a/model_brush.h b/model_brush.h index fdc69165..6f24b259 100644 --- a/model_brush.h +++ b/model_brush.h @@ -139,6 +139,8 @@ typedef struct msurface_s { // should be drawn if visframe == r_framecount (set by WorldNode functions) int visframe; + // should be drawn if onscreen and not a backface (used for setting visframe) + int pvsframe; // the node plane this is on, backwards if SURF_PLANEBACK flag set mplane_t *plane; @@ -176,8 +178,8 @@ typedef struct msurface_s // no texcoord info (that can be generated from these) int poly_numverts; float *poly_verts; - // the center is useful for sorting - float poly_center[3]; + // bounding box for onscreen checks, and center for sorting + vec3_t poly_mins, poly_maxs, poly_center; // these are regenerated every frame // lighting info @@ -187,8 +189,6 @@ typedef struct msurface_s int lightframe; // only render each surface once int worldnodeframe; - // marked when surface is prepared for the frame - int insertframe; // these cause lightmap updates if regenerated // values currently used in lightmap @@ -235,6 +235,8 @@ typedef struct mnode_s vec3_t mins; vec3_t maxs; + int pvsframe; // potentially visible if current (r_pvsframecount) + // node specific mplane_t *plane; struct mnode_s *children[2]; @@ -256,15 +258,13 @@ typedef struct mleaf_s vec3_t mins; vec3_t maxs; + int pvsframe; // potentially visible if current (r_pvsframecount) + // leaf specific int visframe; // visible if current (r_framecount) int worldnodeframe; // used by certain worldnode variants to avoid processing the same leaf twice in a frame int portalmarkid; // used by polygon-through-portals visibility checker - // LordHavoc: leaf based dynamic lighting - int dlightbits[8]; - int dlightframe; - qbyte *compressed_vis; msurface_t **firstmarksurface; @@ -317,7 +317,11 @@ extern texture_t r_notexture_mip; struct model_s; void Mod_LoadBrushModel (struct model_s *mod, void *buffer); void Mod_BrushInit(void); + void Mod_FindNonSolidLocation(vec3_t pos, struct model_s *mod); +mleaf_t *Mod_PointInLeaf (const float *p, struct model_s *model); +int Mod_PointContents (const float *p, struct model_s *model); +qbyte *Mod_LeafPVS (mleaf_t *leaf, struct model_s *model); #endif diff --git a/model_shared.c b/model_shared.c index adbe9348..4ece6a32 100644 --- a/model_shared.c +++ b/model_shared.c @@ -251,8 +251,8 @@ void Mod_ClearAll (void) void Mod_ClearUsed(void) { - int i; - model_t *mod; + int i; + model_t *mod; for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) if (mod->name[0]) @@ -261,8 +261,8 @@ void Mod_ClearUsed(void) void Mod_PurgeUnused(void) { - int i; - model_t *mod; + int i; + model_t *mod; for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) if (mod->name[0]) @@ -278,8 +278,8 @@ Mod_FindName */ model_t *Mod_FindName (char *name) { - int i; - model_t *mod, *freemod; + int i; + model_t *mod, *freemod; if (!name[0]) Host_Error ("Mod_ForName: NULL name"); @@ -369,4 +369,3 @@ static void Mod_Flush (void) if (mod_known[i].name[0]) Mod_UnloadModel(&mod_known[i]); } - diff --git a/model_shared.h b/model_shared.h index f6a6bdc9..d970b84f 100644 --- a/model_shared.h +++ b/model_shared.h @@ -226,9 +226,6 @@ model_t *Mod_ForName (char *name, qboolean crash, qboolean checkdisk, qboolean i void Mod_TouchModel (char *name); void Mod_UnloadModel (model_t *mod); -mleaf_t *Mod_PointInLeaf (const float *p, model_t *model); -qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); - void Mod_ClearUsed(void); void Mod_PurgeUnused(void); diff --git a/portals.c b/portals.c index 0343e9de..554177ad 100644 --- a/portals.c +++ b/portals.c @@ -187,6 +187,10 @@ int Portal_CheckPolygon(model_t *model, vec3_t eye, float *polypoints, int numpo mleaf_t *eyeleaf; vec3_t center, v1, v2; + // if there is no model, it can not block visibility + if (model == NULL) + return true; + portal_markid++; Mod_CheckLoaded(model); diff --git a/pr_cmds.c b/pr_cmds.c index 14cc2934..2c1c8ce6 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -166,7 +166,7 @@ void PF_objerror (void) { char *s; edict_t *ed; - + s = PF_VarString(0); Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); ed = PROG_TO_EDICT(pr_global_struct->self); @@ -229,7 +229,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) for (i=0 ; i<3 ; i++) if (min[i] > max[i]) - PR_RunError ("backwards mins/maxs"); + Host_Error ("backwards mins/maxs"); // set derived values VectorCopy (min, e->v.mins); @@ -284,7 +284,7 @@ void PF_setmodel (void) break; if (!*check) - PR_RunError ("no precache: %s\n", m); + Host_Error ("no precache: %s\n", m); e->v.model = m - pr_strings; @@ -646,7 +646,7 @@ break() */ void PF_break (void) { - PR_RunError ("break statement"); + Host_Error ("break statement"); } /* @@ -849,15 +849,15 @@ void PF_checkclient (void) mleaf_t *leaf; int l; vec3_t view; - -// find a new check if on a new frame + + // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { sv.lastcheck = PF_newcheckclient (sv.lastcheck); sv.lastchecktime = sv.time; } -// return check if it might be visible + // return check if it might be visible ent = EDICT_NUM(sv.lastcheck); if (ent->free || ent->v.health <= 0) { @@ -865,20 +865,23 @@ void PF_checkclient (void) return; } -// if current entity can't possibly see the check entity, return 0 + // if current entity can't possibly see the check entity, return 0 self = PROG_TO_EDICT(pr_global_struct->self); VectorAdd (self->v.origin, self->v.view_ofs, view); leaf = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) + if (leaf) { -c_notvis++; - RETURN_EDICT(sv.edicts); - return; + l = (leaf - sv.worldmodel->leafs) - 1; + if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) + { + c_notvis++; + RETURN_EDICT(sv.edicts); + return; + } } -// might be able to see it -c_invis++; + // might be able to see it + c_invis++; RETURN_EDICT(ent); } @@ -902,7 +905,7 @@ void PF_stuffcmd (void) entnum = G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("Parm 0 not a client"); + Host_Error ("Parm 0 not a client"); str = G_STRING(OFS_PARM1); old = host_client; @@ -1081,9 +1084,9 @@ void PF_Remove (void) ed = G_EDICT(OFS_PARM0); if (ed == sv.edicts) - PR_RunError("remove: tried to remove world\n"); + Host_Error("remove: tried to remove world\n"); if (NUM_FOR_EDICT(ed) <= svs.maxclients) - PR_RunError("remove: tried to remove a client\n"); + Host_Error("remove: tried to remove a client\n"); ED_Free (ed); } @@ -1219,7 +1222,7 @@ void PF_findchainfloat (void) void PR_CheckEmptyString (char *s) { if (s[0] <= ' ') - PR_RunError ("Bad string"); + Host_Error ("Bad string"); } void PF_precache_file (void) @@ -1233,7 +1236,7 @@ void PF_precache_sound (void) int i; if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); + Host_Error ("PF_Precache_*: Precache can only be done in spawn functions"); s = G_STRING(OFS_PARM0); G_INT(OFS_RETURN) = G_INT(OFS_PARM0); @@ -1249,7 +1252,7 @@ void PF_precache_sound (void) if (!strcmp(sv.sound_precache[i], s)) return; } - PR_RunError ("PF_precache_sound: overflow"); + Host_Error ("PF_precache_sound: overflow"); } void PF_precache_model (void) @@ -1258,7 +1261,7 @@ void PF_precache_model (void) int i; if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); + Host_Error ("PF_Precache_*: Precache can only be done in spawn functions"); s = G_STRING(OFS_PARM0); if (sv.worldmodel->ishlbsp && ((!s) || (!s[0]))) @@ -1277,7 +1280,7 @@ void PF_precache_model (void) if (!strcmp(sv.model_precache[i], s)) return; } - PR_RunError ("PF_precache_model: overflow"); + Host_Error ("PF_precache_model: overflow"); } @@ -1447,7 +1450,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = Mod_PointInLeaf(G_VECTOR(OFS_PARM0), sv.worldmodel)->contents; + G_FLOAT(OFS_RETURN) = Mod_PointContents(G_VECTOR(OFS_PARM0), sv.worldmodel); } /* @@ -1621,14 +1624,14 @@ void PF_changepitch (void) ideal = val->_float; else { - PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); return; } if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed))) speed = val->_float; else { - PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); return; } @@ -1688,7 +1691,7 @@ sizebuf_t *WriteDest (void) ent = PROG_TO_EDICT(pr_global_struct->msg_entity); entnum = NUM_FOR_EDICT(ent); if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("WriteDest: not a client"); + Host_Error ("WriteDest: not a client"); return &svs.clients[entnum-1].message; case MSG_ALL: @@ -1698,7 +1701,7 @@ sizebuf_t *WriteDest (void) return &sv.signon; default: - PR_RunError ("WriteDest: bad destination"); + Host_Error ("WriteDest: bad destination"); break; } @@ -1802,7 +1805,7 @@ void PF_setspawnparms (void) ent = G_EDICT(OFS_PARM0); i = NUM_FOR_EDICT(ent); if (i < 1 || i > svs.maxclients) - PR_RunError ("Entity is not a client"); + Host_Error ("Entity is not a client"); // copy spawn parms out of the client_t client = svs.clients + (i-1); @@ -1911,7 +1914,7 @@ void PF_registercvar (void) } if (currentqc_cvar >= MAX_QC_CVARS) - PR_RunError ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS); + Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS); // copy the name and value variable = &qc_cvar[currentqc_cvar++]; @@ -1949,7 +1952,7 @@ void PF_min (void) G_FLOAT(OFS_RETURN) = f; } else - PR_RunError("min: must supply at least 2 floats\n"); + Host_Error("min: must supply at least 2 floats\n"); } /* @@ -1976,7 +1979,7 @@ void PF_max (void) G_FLOAT(OFS_RETURN) = f; } else - PR_RunError("max: must supply at least 2 floats\n"); + Host_Error("max: must supply at least 2 floats\n"); } /* @@ -2068,7 +2071,7 @@ void PF_effect (void) char *s; s = G_STRING(OFS_PARM1); if (!s || !s[0]) - PR_RunError("effect: no model specified\n"); + Host_Error("effect: no model specified\n"); SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4)); } @@ -2464,9 +2467,152 @@ void PF_te_plasmaburn (void) MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } +static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out) +{ + int i, j; + vec3_t v1, clipplanenormal, normal; + vec_t clipplanedist, clipdist; + VectorCopy(p, out); + if (surf->flags & SURF_PLANEBACK) + VectorNegate(surf->plane->normal, normal); + else + VectorCopy(surf->plane->normal, normal); + for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++) + { + VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1); + VectorNormalizeFast(v1); + CrossProduct(v1, normal, clipplanenormal); + clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal); + clipdist = DotProduct(out, clipplanenormal) - clipplanedist; + if (clipdist > 0) + { + clipdist = -clipdist; + VectorMA(out, clipdist, clipplanenormal, out); + } + } +} + +static msurface_t *getsurface(edict_t *ed, int surfnum) +{ + int modelindex; + model_t *model; + if (!ed || ed->free) + return NULL; + modelindex = ed->v.modelindex; + if (modelindex < 1 || modelindex >= MAX_MODELS) + return NULL; + model = sv.models[modelindex]; + if (model->type != mod_brush) + return NULL; + if (surfnum < 0 || surfnum >= model->nummodelsurfaces) + return NULL; + return model->surfaces + surfnum + model->firstmodelsurface; +} + + +//PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; +void PF_getsurfacenumpoints(void) +{ + msurface_t *surf; + // return 0 if no such surface + if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + { + G_FLOAT(OFS_RETURN) = 0; + return; + } + + G_FLOAT(OFS_RETURN) = surf->poly_numverts; +} +//PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435; +void PF_getsurfacepoint(void) +{ + edict_t *ed; + msurface_t *surf; + int pointnum; + VectorClear(G_VECTOR(OFS_RETURN)); + ed = G_EDICT(OFS_PARM0); + if (!ed || ed->free) + return; + if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) + return; + pointnum = G_FLOAT(OFS_PARM2); + if (pointnum < 0 || pointnum >= surf->poly_numverts) + return; + // FIXME: implement rotation/scaling + VectorAdd(&surf->poly_verts[pointnum * 3], ed->v.origin, G_VECTOR(OFS_RETURN)); +} +//PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; +void PF_getsurfacenormal(void) +{ + msurface_t *surf; + VectorClear(G_VECTOR(OFS_RETURN)); + if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + return; + // FIXME: implement rotation/scaling + if (surf->flags & SURF_PLANEBACK) + VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN)); + else + VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN)); +} +//PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; +void PF_getsurfacetexture(void) +{ + msurface_t *surf; + G_INT(OFS_RETURN) = 0; + if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + return; + G_INT(OFS_RETURN) = surf->texinfo->texture->name - pr_strings; +} +//PF_getsurfacenearpoint, // #438 void(entity e, vector p) getsurfacenearpoint = #438; +void PF_getsurfacenearpoint(void) +{ + int surfnum, best, modelindex; + vec3_t clipped, p; + vec_t dist, bestdist; + edict_t *ed; + model_t *model; + msurface_t *surf; + vec_t *point; + G_FLOAT(OFS_RETURN) = -1; + ed = G_EDICT(OFS_PARM0); + point = G_VECTOR(OFS_PARM1); + + if (!ed || ed->free) + return; + modelindex = ed->v.modelindex; + if (modelindex < 1 || modelindex >= MAX_MODELS) + return; + model = sv.models[modelindex]; + if (model->type != mod_brush) + return; + + // FIXME: implement rotation/scaling + VectorSubtract(point, ed->v.origin, p); + best = -1; + bestdist = 1000000000; + for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++) + { + surf = model->surfaces + surfnum + model->firstmodelsurface; + dist = PlaneDiff(p, surf->plane); + dist = dist * dist; + if (dist < bestdist) + { + clippointtosurface(surf, p, clipped); + VectorSubtract(clipped, p, clipped); + dist += DotProduct(clipped, clipped); + if (dist < bestdist) + { + best = surfnum; + bestdist = dist; + } + } + } + G_FLOAT(OFS_RETURN) = best; +} + void PF_Fixme (void) { - PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin) + Host_Error ("unimplemented QC builtin"); // LordHavoc: was misspelled (bulitin) } @@ -2622,6 +2768,11 @@ PF_te_lightning3, // #430 PF_te_beam, // #431 PF_vectorvectors, // #432 PF_te_plasmaburn, // #433 +PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; +PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435; +PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; +PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; +PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; }; builtin_t *pr_builtins = pr_builtin; diff --git a/pr_exec.c b/pr_exec.c index eda7404f..368f485b 100644 --- a/pr_exec.c +++ b/pr_exec.c @@ -240,23 +240,18 @@ void PR_Profile_f (void) } -/* -============ -PR_RunError - -Aborts the currently executing function -============ -*/ -void PR_RunError (char *error, ...) +void PR_Crash(void) { - int i; - va_list argptr; - char string[1024]; - - va_start (argptr,error); - vsprintf (string,error,argptr); - va_end (argptr); + int i; + if (!pr_depth) + { + // kill the stack just to be sure + pr_depth = 0; + localstack_used = 0; + return; + } + Con_Printf("QuakeC crash report:\n"); if (pr_xfunction) { for (i = -4;i <= 0;i++) @@ -266,13 +261,10 @@ void PR_RunError (char *error, ...) else Con_Printf("null function executing??\n"); PR_StackTrace (); - Con_Printf ("%s\n", string); // dump the stack so host_error can shutdown functions pr_depth = 0; localstack_used = 0; - - Host_Error ("Program error"); } /* @@ -295,18 +287,18 @@ int PR_EnterFunction (dfunction_t *f) int i, j, c, o; if (!f) - PR_RunError ("PR_EnterFunction: NULL function\n"); + Host_Error ("PR_EnterFunction: NULL function\n"); pr_stack[pr_depth].s = pr_xstatement; pr_stack[pr_depth].f = pr_xfunction; pr_depth++; if (pr_depth >= MAX_STACK_DEPTH) - PR_RunError ("stack overflow"); + Host_Error ("stack overflow"); // save off any locals that the new function steps on c = f->locals; if (localstack_used + c > LOCALSTACK_SIZE) - PR_RunError ("PR_ExecuteProgram: locals stack overflow\n"); + Host_Error ("PR_ExecuteProgram: locals stack overflow\n"); for (i=0 ; i < c ; i++) localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; @@ -340,12 +332,12 @@ int PR_LeaveFunction (void) Host_Error ("prog stack underflow"); if (!pr_xfunction) - PR_RunError ("PR_LeaveFunction: NULL function\n"); + Host_Error ("PR_LeaveFunction: NULL function\n"); // restore locals from the stack c = pr_xfunction->locals; localstack_used -= c; if (localstack_used < 0) - PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); + Host_Error ("PR_ExecuteProgram: locals stack underflow\n"); for (i=0 ; i < c ; i++) ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i]; diff --git a/pr_execprogram.h b/pr_execprogram.h index fd306cf2..05e86103 100644 --- a/pr_execprogram.h +++ b/pr_execprogram.h @@ -7,7 +7,7 @@ if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x { pr_xstatement = st - pr_statements; - PR_RunError ("runaway loop error"); + Host_Error ("runaway loop error"); } #if PRTRACE @@ -144,13 +144,13 @@ if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an out of bounds edict\n"); + Host_Error("Progs attempted to write to an out of bounds edict\n"); return; } if (OPB->_int % pr_edict_size < ((qbyte *)&sv.edicts->v - (qbyte *)sv.edicts)) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an engine edict field\n"); + Host_Error("Progs attempted to write to an engine edict field\n"); return; } #endif @@ -162,7 +162,7 @@ if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an out of bounds edict\n"); + Host_Error("Progs attempted to write to an out of bounds edict\n"); return; } #endif @@ -179,33 +179,33 @@ if (OPA->edict == 0 && sv.state == ss_active) { pr_xstatement = st - pr_statements; - PR_RunError ("assignment to world entity"); + Host_Error ("assignment to world entity"); return; } else { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to address an out of bounds edict\n"); + Host_Error("Progs attempted to address an out of bounds edict\n"); return; } } else if (OPA->edict >= pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to address an out of bounds edict\n"); + Host_Error("Progs attempted to address an out of bounds edict\n"); return; } if (OPB->_int < 0 || OPB->_int >= progs->entityfields) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to address an invalid field in an edict\n"); + Host_Error("Progs attempted to address an invalid field in an edict\n"); return; } #else if (OPA->edict == 0 && sv.state == ss_active) { pr_xstatement = st - pr_statements; - PR_RunError ("assignment to world entity"); + Host_Error ("assignment to world entity"); return; } #endif @@ -222,13 +222,13 @@ if (OPA->edict < 0 || OPA->edict >= pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an out of bounds edict number\n"); + Host_Error("Progs attempted to read an out of bounds edict number\n"); return; } if (OPB->_int < 0 || OPB->_int >= progs->entityfields) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an invalid field in an edict\n"); + Host_Error("Progs attempted to read an invalid field in an edict\n"); return; } #endif @@ -241,13 +241,13 @@ if (OPA->edict < 0 || OPA->edict >= pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an out of bounds edict number\n"); + Host_Error("Progs attempted to read an out of bounds edict number\n"); return; } if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an invalid field in an edict\n"); + Host_Error("Progs attempted to read an invalid field in an edict\n"); return; } #endif @@ -287,7 +287,7 @@ pr_xstatement = st - pr_statements; pr_argc = st->op - OP_CALL0; if (!OPA->function) - PR_RunError ("NULL function"); + Host_Error ("NULL function"); newf = &pr_functions[OPA->function]; @@ -295,7 +295,7 @@ { // negative statements are built in functions if ((-newf->first_statement) >= pr_numbuiltins) - PR_RunError ("Bad builtin call number"); + Host_Error ("Bad builtin call number"); pr_builtins[-newf->first_statement] (); } else @@ -480,13 +480,13 @@ if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an out of bounds edict\n"); + Host_Error("Progs attempted to write to an out of bounds edict\n"); return; } if (OPB->_int % pr_edict_size < ((qbyte *)&sv.edicts->v - (qbyte *)sv.edicts)) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an engine edict field\n"); + Host_Error("Progs attempted to write to an engine edict field\n"); return; } #endif @@ -498,13 +498,13 @@ if (OPA->edict < 0 || OPA->edict >= pr_edictareasize) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an out of bounds edict number\n"); + Host_Error("Progs attempted to read an out of bounds edict number\n"); return; } if (OPB->_int < 0 || OPB->_int >= progs->entityfields) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an invalid field in an edict\n"); + Host_Error("Progs attempted to read an invalid field in an edict\n"); return; } #endif @@ -522,7 +522,7 @@ if (OPB->_int < 0 || OPB->_int >= pr_globaldefs) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an invalid indexed global\n"); + Host_Error("Progs attempted to write to an invalid indexed global\n"); return; } #endif @@ -533,7 +533,7 @@ if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to write to an invalid indexed global\n"); + Host_Error("Progs attempted to write to an invalid indexed global\n"); return; } #endif @@ -548,7 +548,7 @@ if (i < 0 || i >= pr_globaldefs) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to address an out of bounds global\n"); + Host_Error("Progs attempted to address an out of bounds global\n"); return; } #endif @@ -565,7 +565,7 @@ if (OPA->_int < 0 || OPA->_int >= pr_globaldefs) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an invalid indexed global\n"); + Host_Error("Progs attempted to read an invalid indexed global\n"); return; } #endif @@ -577,7 +577,7 @@ if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs) { pr_xstatement = st - pr_statements; - PR_RunError("Progs attempted to read an invalid indexed global\n"); + Host_Error("Progs attempted to read an invalid indexed global\n"); return; } #endif @@ -590,7 +590,7 @@ if (OPA->_int < 0 || OPA->_int >= st->b) { pr_xstatement = st - pr_statements; - PR_RunError("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c); + Host_Error("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c); return; } break; @@ -599,7 +599,7 @@ default: pr_xstatement = st - pr_statements; - PR_RunError ("Bad opcode %i", st->op); + Host_Error ("Bad opcode %i", st->op); } } diff --git a/progs.h b/progs.h index c456c894..874ba9f9 100644 --- a/progs.h +++ b/progs.h @@ -122,6 +122,8 @@ void PR_LoadProgs (void); void PR_Profile_f (void); +void PR_Crash (void); + edict_t *ED_Alloc (void); void ED_Free (edict_t *ed); @@ -176,7 +178,6 @@ extern int pr_xstatement; extern unsigned short pr_crc; -void PR_RunError (char *error, ...); void PR_Execute_ProgsLoaded(void); void ED_PrintEdicts (void); diff --git a/r_lerpanim.c b/r_lerpanim.c index fe8f2495..753e4af2 100644 --- a/r_lerpanim.c +++ b/r_lerpanim.c @@ -10,6 +10,10 @@ void R_LerpAnimation(entity_render_t *r) double sublerp, lerp, d; animscene_t *scene; frameblend_t *blend; + + if (!r->model) + return; + blend = r->frameblend; numframes = r->model->numframes; diff --git a/r_light.c b/r_light.c index f6b8d480..754685ae 100644 --- a/r_light.c +++ b/r_light.c @@ -64,6 +64,9 @@ void r_light_shutdown(void) void r_light_newmap(void) { + int i; + for (i = 0;i < 256;i++) + d_lightstylevalue[i] = 264; // normal light value } void R_Light_Init(void) @@ -90,7 +93,7 @@ void R_AnimateLight (void) i = (int)(cl.time * 10); for (j = 0;j < MAX_LIGHTSTYLES;j++) { - if (!cl_lightstyle[j].length) + if (!cl_lightstyle || !cl_lightstyle[j].length) { d_lightstylevalue[j] = 256; continue; @@ -112,7 +115,7 @@ void R_BuildLightList(void) r_numdlights = 0; c_dlights = 0; - if (!r_dynamic.integer) + if (!r_dynamic.integer || !cl_dlights) return; for (i = 0;i < MAX_DLIGHTS;i++) @@ -226,8 +229,9 @@ static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t { float ndist, maxdist; msurface_t *surf; - mleaf_t *leaf; int i; + int d, impacts, impactt; + float dist, dist2, impact[3]; if (!r_dynamic.integer) return; @@ -237,19 +241,7 @@ static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t loc0: if (node->contents < 0) - { - if (node->contents != CONTENTS_SOLID) - { - leaf = (mleaf_t *)node; - if (leaf->dlightframe != r_framecount) // not dynamic until now - { - leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0; - leaf->dlightframe = r_framecount; - } - leaf->dlightbits[bitindex] |= bit; - } return; - } ndist = PlaneDiff(lightorigin, node->plane); @@ -266,10 +258,8 @@ loc0: // mark the polygons surf = ent->model->surfaces + node->firstsurface; - for (i=0 ; inumsurfaces ; i++, surf++) + for (i = 0;i < node->numsurfaces;i++, surf++) { - int d, impacts, impactt; - float dist, dist2, impact[3]; if (surf->visframe != r_framecount) continue; dist = ndist; @@ -285,14 +275,14 @@ loc0: if (node->plane->type < 3) { - VectorCopy(rd->origin, impact); + VectorCopy(lightorigin, impact); impact[node->plane->type] -= dist; } else { - impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; - impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; - impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; + impact[0] = lightorigin[0] - surf->plane->normal[0] * dist; + impact[1] = lightorigin[1] - surf->plane->normal[1] * dist; + impact[2] = lightorigin[2] - surf->plane->normal[2] * dist; } impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; @@ -355,28 +345,17 @@ static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int b if (!r_dynamic.integer) return; - model = ent->model; - //softwareuntransform(rd->origin, lightorigin); Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin); - if (!r_vismarklights.integer) - { - R_OldMarkLights(ent, lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode); - return; - } - + model = ent->model; pvsleaf = Mod_PointInLeaf (lightorigin, model); if (pvsleaf == NULL) - { - Con_Printf("R_VisMarkLights: NULL leaf??\n"); - R_OldMarkLights(ent, lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode); return; - } in = pvsleaf->compressed_vis; - if (!in) + if (!r_vismarklights.integer || !in) { - // no vis info, so make all visible + // told not to use pvs, or there's no pvs to use R_OldMarkLights(ent, lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode); return; } @@ -406,19 +385,10 @@ static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int b if (leafnum > model->numleafs) return; leaf = &model->leafs[leafnum]; - if (leaf->visframe != r_framecount - || leaf->contents == CONTENTS_SOLID - || leaf->mins[0] > high[0] || leaf->maxs[0] < low[0] + if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0] || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1] || leaf->mins[2] > high[2] || leaf->maxs[2] < low[2]) continue; - if (leaf->dlightframe != r_framecount) - { - // not dynamic until now - leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0; - leaf->dlightframe = r_framecount; - } - leaf->dlightbits[bitindex] |= bit; if ((m = leaf->nummarksurfaces)) { mark = leaf->firstmarksurface; @@ -445,14 +415,14 @@ static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int b if (surf->plane->type < 3) { - VectorCopy(rd->origin, impact); + VectorCopy(lightorigin, impact); impact[surf->plane->type] -= dist; } else { - impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; - impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; - impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; + impact[0] = lightorigin[0] - surf->plane->normal[0] * dist; + impact[1] = lightorigin[1] - surf->plane->normal[1] * dist; + impact[2] = lightorigin[2] - surf->plane->normal[2] * dist; } impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; @@ -646,23 +616,15 @@ middle sample (the one which was requested) void R_CompleteLightPoint (vec3_t color, const vec3_t p, int dynamic, const mleaf_t *leaf) { int i; - const int *dlightbits; vec3_t v; float f; rdlight_t *rd; mlight_t *sl; if (leaf == NULL) leaf = Mod_PointInLeaf(p, cl.worldmodel); - - if (leaf->contents == CONTENTS_SOLID) + if (!leaf || leaf->contents == CONTENTS_SOLID || r_fullbright.integer || !cl.worldmodel->lightdata) { - color[0] = color[1] = color[2] = 0; - return; - } - - if (r_fullbright.integer || !cl.worldmodel->lightdata) - { - color[0] = color[1] = color[2] = 2; + color[0] = color[1] = color[2] = 1; return; } @@ -687,17 +649,14 @@ void R_CompleteLightPoint (vec3_t color, const vec3_t p, int dynamic, const mlea else RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); - if (dynamic && leaf->dlightframe == r_framecount) + if (dynamic) { - dlightbits = leaf->dlightbits; for (i = 0;i < r_numdlights;i++) { - if (!(dlightbits[i >> 5] & (1 << (i & 31)))) - continue; rd = r_dlight + i; VectorSubtract (p, rd->origin, v); f = DotProduct(v, v); - if (f < rd->cullradius2) + if (f < rd->cullradius2 && CL_TraceLine(p, rd->origin, NULL, NULL, 0, false) == 1) { f = (1.0f / (f + LIGHTOFFSET)) - rd->subtract; VectorMA(color, f, rd->light, color); @@ -706,41 +665,19 @@ void R_CompleteLightPoint (vec3_t color, const vec3_t p, int dynamic, const mlea } } -void R_ModelLightPoint (const entity_render_t *ent, vec3_t color, const vec3_t p, int *dlightbits) +void R_ModelLightPoint (const entity_render_t *ent, vec3_t color, const vec3_t p) { mleaf_t *leaf; leaf = Mod_PointInLeaf(p, cl.worldmodel); - if (leaf->contents == CONTENTS_SOLID) + if (!leaf || leaf->contents == CONTENTS_SOLID || r_fullbright.integer || !cl.worldmodel->lightdata || ent->effects & EF_FULLBRIGHT) { - color[0] = color[1] = color[2] = 0; - dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; - return; - } - - if (r_fullbright.integer || !cl.worldmodel->lightdata || ent->effects & EF_FULLBRIGHT) - { - color[0] = color[1] = color[2] = 2; - dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; + color[0] = color[1] = color[2] = 1; return; } color[0] = color[1] = color[2] = r_ambient.value * (2.0f / 128.0f); if (!cl.worldmodel->numlights) RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); - - if (leaf->dlightframe == r_framecount) - { - dlightbits[0] = leaf->dlightbits[0]; - dlightbits[1] = leaf->dlightbits[1]; - dlightbits[2] = leaf->dlightbits[2]; - dlightbits[3] = leaf->dlightbits[3]; - dlightbits[4] = leaf->dlightbits[4]; - dlightbits[5] = leaf->dlightbits[5]; - dlightbits[6] = leaf->dlightbits[6]; - dlightbits[7] = leaf->dlightbits[7]; - } - else - dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; } void R_LightModel(const entity_render_t *ent, int numverts, float colorr, float colorg, float colorb, int worldcoords) @@ -761,7 +698,6 @@ void R_LightModel(const entity_render_t *ent, int numverts, float colorr, float vec_t intensity; } nearlight[MAX_DLIGHTS], *nl; - int modeldlightbits[8]; mlight_t *sl; rdlight_t *rd; a = ent->alpha; @@ -770,7 +706,7 @@ void R_LightModel(const entity_render_t *ent, int numverts, float colorr, float mscale = ent->scale * ent->scale; if ((maxnearlights != 0) && !r_fullbright.integer && !(ent->effects & EF_FULLBRIGHT)) { - R_ModelLightPoint(ent, basecolor, ent->origin, modeldlightbits); + R_ModelLightPoint(ent, basecolor, ent->origin); nl = &nearlight[0]; for (i = 0;i < ent->numentlights;i++) @@ -812,7 +748,6 @@ void R_LightModel(const entity_render_t *ent, int numverts, float colorr, float if (worldcoords) VectorCopy(sl->origin, nl->origin); else - //softwareuntransform(sl->origin, nl->origin); Matrix4x4_Transform(&ent->inversematrix, sl->origin, nl->origin); // integrate mscale into falloff, for maximum speed nl->falloff = sl->falloff * mscale; @@ -826,66 +761,73 @@ void R_LightModel(const entity_render_t *ent, int numverts, float colorr, float } for (i = 0;i < r_numdlights;i++) { - if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) - continue; rd = r_dlight + i; - VectorSubtract (ent->origin, rd->origin, v); - f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); - VectorScale(rd->light, f, ambientcolor); - intensity = DotProduct(ambientcolor, ambientcolor); - if (f < 0) - intensity *= -1.0f; - if (nearlights < maxnearlights) - j = nearlights++; - else + VectorCopy(rd->origin, v); + if (v[0] < ent->mins[0]) v[0] = ent->mins[0];if (v[0] > ent->maxs[0]) v[0] = ent->maxs[0]; + if (v[1] < ent->mins[1]) v[1] = ent->mins[1];if (v[1] > ent->maxs[1]) v[1] = ent->maxs[1]; + if (v[2] < ent->mins[2]) v[2] = ent->mins[2];if (v[2] > ent->maxs[2]) v[2] = ent->maxs[2]; + VectorSubtract (v, rd->origin, v); + if (DotProduct(v, v) < rd->cullradius2) { - for (j = 0;j < maxnearlights;j++) + if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, 0, false) != 1) + continue; + VectorSubtract (ent->origin, rd->origin, v); + f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); + VectorScale(rd->light, f, ambientcolor); + intensity = DotProduct(ambientcolor, ambientcolor); + if (f < 0) + intensity *= -1.0f; + if (nearlights < maxnearlights) + j = nearlights++; + else { - if (nearlight[j].intensity < intensity) + for (j = 0;j < maxnearlights;j++) { - if (nearlight[j].intensity > 0) - VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); - break; + if (nearlight[j].intensity < intensity) + { + if (nearlight[j].intensity > 0) + VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); + break; + } } } - } - if (j >= maxnearlights) - { - // this light is less significant than all others, - // add it to ambient - if (intensity > 0) - VectorAdd(basecolor, ambientcolor, basecolor); - } - else - { - nl = nearlight + j; - nl->intensity = intensity; - // transform the light into the model's coordinate system - if (worldcoords) - VectorCopy(rd->origin, nl->origin); + if (j >= maxnearlights) + { + // this light is less significant than all others, + // add it to ambient + if (intensity > 0) + VectorAdd(basecolor, ambientcolor, basecolor); + } else { - //softwareuntransform(rd->origin, nl->origin); - Matrix4x4_Transform(&ent->inversematrix, rd->origin, nl->origin); - /* - Con_Printf("%i %s : %f %f %f : %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n" - , rd - r_dlight, ent->model->name - , rd->origin[0], rd->origin[1], rd->origin[2] - , nl->origin[0], nl->origin[1], nl->origin[2] - , ent->inversematrix.m[0][0], ent->inversematrix.m[0][1], ent->inversematrix.m[0][2], ent->inversematrix.m[0][3] - , ent->inversematrix.m[1][0], ent->inversematrix.m[1][1], ent->inversematrix.m[1][2], ent->inversematrix.m[1][3] - , ent->inversematrix.m[2][0], ent->inversematrix.m[2][1], ent->inversematrix.m[2][2], ent->inversematrix.m[2][3] - , ent->inversematrix.m[3][0], ent->inversematrix.m[3][1], ent->inversematrix.m[3][2], ent->inversematrix.m[3][3]); - */ + nl = nearlight + j; + nl->intensity = intensity; + // transform the light into the model's coordinate system + if (worldcoords) + VectorCopy(rd->origin, nl->origin); + else + { + Matrix4x4_Transform(&ent->inversematrix, rd->origin, nl->origin); + /* + Con_Printf("%i %s : %f %f %f : %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n" + , rd - r_dlight, ent->model->name + , rd->origin[0], rd->origin[1], rd->origin[2] + , nl->origin[0], nl->origin[1], nl->origin[2] + , ent->inversematrix.m[0][0], ent->inversematrix.m[0][1], ent->inversematrix.m[0][2], ent->inversematrix.m[0][3] + , ent->inversematrix.m[1][0], ent->inversematrix.m[1][1], ent->inversematrix.m[1][2], ent->inversematrix.m[1][3] + , ent->inversematrix.m[2][0], ent->inversematrix.m[2][1], ent->inversematrix.m[2][2], ent->inversematrix.m[2][3] + , ent->inversematrix.m[3][0], ent->inversematrix.m[3][1], ent->inversematrix.m[3][2], ent->inversematrix.m[3][3]); + */ + } + // integrate mscale into falloff, for maximum speed + nl->falloff = mscale; + VectorCopy(ambientcolor, nl->ambientlight); + nl->light[0] = rd->light[0] * colorr * 4.0f; + nl->light[1] = rd->light[1] * colorg * 4.0f; + nl->light[2] = rd->light[2] * colorb * 4.0f; + nl->subtract = rd->subtract; + nl->offset = LIGHTOFFSET; } - // integrate mscale into falloff, for maximum speed - nl->falloff = mscale; - VectorCopy(ambientcolor, nl->ambientlight); - nl->light[0] = rd->light[0] * colorr * 4.0f; - nl->light[1] = rd->light[1] * colorg * 4.0f; - nl->light[2] = rd->light[2] * colorb * 4.0f; - nl->subtract = rd->subtract; - nl->offset = LIGHTOFFSET; } } } @@ -967,9 +909,10 @@ void R_UpdateEntLights(entity_render_t *ent) ent->entlightstime = realtime + 0.1; VectorCopy(ent->origin, ent->entlightsorigin); ent->numentlights = 0; - for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && ent->numentlights < MAXENTLIGHTS;i++, sl++) - if (CL_TraceLine(ent->origin, sl->origin, NULL, NULL, 0, false) == 1) - ent->entlights[ent->numentlights++] = i; + if (cl.worldmodel) + for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && ent->numentlights < MAXENTLIGHTS;i++, sl++) + if (CL_TraceLine(ent->origin, sl->origin, NULL, NULL, 0, false) == 1) + ent->entlights[ent->numentlights++] = i; } ent->entlightsframe = r_framecount; } diff --git a/r_sky.c b/r_sky.c index 364818a8..8b3d697a 100644 --- a/r_sky.c +++ b/r_sky.c @@ -1,52 +1,21 @@ #include "quakedef.h" -void LoadSky_f(void); - cvar_t r_sky = {CVAR_SAVE, "r_sky", "1"}; - -static char skyworldname[1024]; -rtexture_t *solidskytexture; -rtexture_t *alphaskytexture; -static qboolean skyavailable_quake; -static qboolean skyavailable_box; -static rtexturepool_t *skytexturepool; - +qboolean skyavailable_quake; +qboolean skyavailable_box; int skyrendernow; int skyrendermasked; -static void r_sky_start(void) -{ - skytexturepool = R_AllocTexturePool(); - solidskytexture = NULL; - alphaskytexture = NULL; -} - -static void r_sky_shutdown(void) -{ - R_FreeTexturePool(&skytexturepool); - solidskytexture = NULL; - alphaskytexture = NULL; -} - -int R_SetSkyBox(char *sky); - -static void r_sky_newmap(void) -{ - skyavailable_quake = false; - if (!strcmp(skyworldname, cl.worldmodel->name)) - skyavailable_quake = true; -} - -void R_Sky_Init(void) -{ - Cmd_AddCommand ("loadsky", &LoadSky_f); - Cvar_RegisterVariable (&r_sky); - R_RegisterModule("R_Sky", r_sky_start, r_sky_shutdown, r_sky_newmap); -} - +static rtexture_t *solidskytexture; +static rtexture_t *alphaskytexture; static int skyrendersphere; static int skyrenderbox; +static rtexturepool_t *skytexturepool; +static char skyname[256]; +static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; +static rtexture_t *skyboxside[6]; +int R_SetSkyBox(char *sky); void R_SkyStartFrame(void) { @@ -66,15 +35,11 @@ void R_SkyStartFrame(void) } } -static char skyname[256]; - /* ================== R_SetSkyBox ================== */ -static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; -static rtexture_t *skyboxside[6]; int R_SetSkyBox(char *sky) { int i; @@ -405,7 +370,7 @@ void R_InitSky (qbyte *src, int bytesperpixel) qbyte skyupperlayerpixels[128*128*4], skylowerlayerpixels[128*128*4]; unsigned trans[128*128], transpix, *rgba; - strcpy(skyworldname, loadmodel->name); + skyavailable_quake = true; // flush skytexturepool so we won't build up a leak from uploading textures multiple times R_FreeTexturePool(&skytexturepool); @@ -473,3 +438,39 @@ void R_InitSky (qbyte *src, int bytesperpixel) alphaskytexture = R_LoadTexture (skytexturepool, "sky_alphatexture", 128, 128, (qbyte *) trans, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE); } +void R_ResetQuakeSky(void) +{ + skyavailable_quake = false; +} + +void R_ResetSkyBox(void) +{ + skyboxside[0] = skyboxside[1] = skyboxside[2] = skyboxside[3] = skyboxside[4] = skyboxside[5] = NULL; + skyname[0] = 0; + skyavailable_box = false; +} + +static void r_sky_start(void) +{ + skytexturepool = R_AllocTexturePool(); + solidskytexture = NULL; + alphaskytexture = NULL; +} + +static void r_sky_shutdown(void) +{ + R_FreeTexturePool(&skytexturepool); + solidskytexture = NULL; + alphaskytexture = NULL; +} + +static void r_sky_newmap(void) +{ +} + +void R_Sky_Init(void) +{ + Cmd_AddCommand ("loadsky", &LoadSky_f); + Cvar_RegisterVariable (&r_sky); + R_RegisterModule("R_Sky", r_sky_start, r_sky_shutdown, r_sky_newmap); +} diff --git a/render.h b/render.h index a22cad76..195c0cac 100644 --- a/render.h +++ b/render.h @@ -32,14 +32,13 @@ extern void FOG_clear(void); extern float fog_density, fog_red, fog_green, fog_blue; // sky stuff -extern int R_SetSkyBox(char* sky); extern cvar_t r_sky; -// these are exposed because surface rendering uses them -extern rtexture_t *solidskytexture; -extern rtexture_t *alphaskytexture; extern int skyrendernow, skyrendermasked; +extern int R_SetSkyBox(char* sky); extern void R_SkyStartFrame(void); extern void R_Sky(void); +extern void R_ResetQuakeSky(void); +extern void R_ResetSkyBox(void); // SHOWLMP stuff (Nehahra) extern void SHOWLMP_decodehide(void); @@ -79,7 +78,7 @@ void R_FillColors(float *out, int verts, float r, float g, float b, float a); extern int r_framecount; extern mplane_t frustum[4]; -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; +extern int 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/sv_move.c b/sv_move.c index dd710970..5645c540 100644 --- a/sv_move.c +++ b/sv_move.c @@ -51,7 +51,7 @@ qboolean SV_CheckBottom (edict_t *ent) { start[0] = x ? maxs[0] : mins[0]; start[1] = y ? maxs[1] : mins[1]; - if (Mod_PointInLeaf(start, sv.worldmodel)->contents != CONTENTS_SOLID) + if (Mod_PointContents(start, sv.worldmodel) != CONTENTS_SOLID) goto realcheck; } @@ -138,7 +138,7 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) if (trace.fraction == 1) { VectorCopy(trace.endpos, traceendpos); - if ( ((int)ent->v.flags & FL_SWIM) && Mod_PointInLeaf(traceendpos, sv.worldmodel)->contents == CONTENTS_EMPTY ) + if ( ((int)ent->v.flags & FL_SWIM) && Mod_PointContents(traceendpos, sv.worldmodel) == CONTENTS_EMPTY ) return false; // swim monster left water VectorCopy (traceendpos, ent->v.origin); diff --git a/sv_phys.c b/sv_phys.c index 94f2bdf0..b89e114d 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -771,18 +771,18 @@ qboolean SV_CheckWater (edict_t *ent) ent->v.waterlevel = 0; ent->v.watertype = CONTENTS_EMPTY; - cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; + cont = Mod_PointContents(point, sv.worldmodel); if (cont <= CONTENTS_WATER) { ent->v.watertype = cont; ent->v.waterlevel = 1; point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; - cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; + cont = Mod_PointContents(point, sv.worldmodel); if (cont <= CONTENTS_WATER) { ent->v.waterlevel = 2; point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; - cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; + cont = Mod_PointContents(point, sv.worldmodel); if (cont <= CONTENTS_WATER) ent->v.waterlevel = 3; } @@ -1135,8 +1135,8 @@ SV_CheckWaterTransition */ void SV_CheckWaterTransition (edict_t *ent) { - int cont; - cont = Mod_PointInLeaf(ent->v.origin, sv.worldmodel)->contents; + int cont; + cont = Mod_PointContents(ent->v.origin, sv.worldmodel); if (!ent->v.watertype) { // just spawned here @@ -1291,7 +1291,7 @@ void SV_Physics_Step (edict_t *ent) { if (flags & FL_FLY) fall = false; - else if ((flags & FL_SWIM) && Mod_PointInLeaf(ent->v.origin, sv.worldmodel)->contents != CONTENTS_EMPTY) + else if ((flags & FL_SWIM) && Mod_PointContents(ent->v.origin, sv.worldmodel) != CONTENTS_EMPTY) fall = false; } if (fall && (flags & FL_ONGROUND) && ent->v.groundentity == 0) diff --git a/view.c b/view.c index 4839e64e..e50d4ce7 100644 --- a/view.c +++ b/view.c @@ -324,7 +324,7 @@ void V_UpdateBlends (void) float r, g, b, a, a2; int j; - if (cl.worldmodel == NULL) + if (cls.signon != SIGNONS) { cl.cshifts[CSHIFT_DAMAGE].percent = 0; cl.cshifts[CSHIFT_BONUS].percent = 0; @@ -348,7 +348,7 @@ void V_UpdateBlends (void) cl.cshifts[CSHIFT_BONUS].percent = 0; // set contents color - switch (Mod_PointInLeaf (r_refdef.vieworg, cl.worldmodel)->contents) + switch (Mod_PointContents (r_refdef.vieworg, cl.worldmodel)) { case CONTENTS_EMPTY: case CONTENTS_SOLID: @@ -478,7 +478,7 @@ void V_CalcRefdef (void) float bob; float side; - if (cls.state != ca_connected || !cl.worldmodel) + if (cls.state != ca_connected || cls.signon != SIGNONS) return; // ent is the player model (visible when out of body) diff --git a/world.c b/world.c index a970bdd0..0dbcb29f 100644 --- a/world.c +++ b/world.c @@ -34,6 +34,7 @@ cvar_t sv_useareanodes = {CVAR_NOTIFY, "sv_useareanodes", "1"}; void SV_World_Init(void) { Cvar_RegisterVariable(&sv_useareanodes); + Collision_Init (); } @@ -179,8 +180,6 @@ SV_ClearWorld */ void SV_ClearWorld (void) { - Collision_Init (); - memset (sv_areanodes, 0, sizeof(sv_areanodes)); sv_numareanodes = 0; Mod_CheckLoaded(sv.worldmodel); @@ -290,12 +289,12 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) if (ent->v.solid == SOLID_BSP) { if (ent->v.modelindex < 0 || ent->v.modelindex > MAX_MODELS) - PR_RunError("SOLID_BSP with invalid modelindex!\n"); + Host_Error("SOLID_BSP with invalid modelindex!\n"); model = sv.models[(int) ent->v.modelindex]; if (model != NULL) { if (model->type != mod_brush) - PR_RunError("SOLID_BSP with non-BSP model\n"); + Host_Error("SOLID_BSP with non-BSP model\n"); if (ent->v.angles[0] || ent->v.angles[2] || ent->v.avelocity[0] || ent->v.avelocity[2]) { @@ -427,10 +426,10 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max i = ent->v.modelindex; if ((unsigned int) i >= MAX_MODELS) - PR_RunError("SV_ClipMoveToEntity: invalid modelindex\n"); + Host_Error("SV_ClipMoveToEntity: invalid modelindex\n"); model = sv.models[i]; if (i != 0 && model == NULL) - PR_RunError("SV_ClipMoveToEntity: invalid modelindex\n"); + Host_Error("SV_ClipMoveToEntity: invalid modelindex\n"); if ((int) ent->v.solid == SOLID_BSP) { -- 2.39.2