you can now (try to) play in maps you don't have, and models you don't have are shown...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 5 Sep 2002 10:10:47 +0000 (10:10 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 5 Sep 2002 10:10:47 +0000 (10:10 +0000)
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

35 files changed:
cl_demo.c
cl_main.c
cl_parse.c
cl_particles.c
cl_screen.c
client.h
collision.c
common.c
common.h
console.c
gl_backend.c
gl_backend.h
gl_rmain.c
gl_rsurf.c
host.c
keys.c
keys.h
makefile
model_brush.c
model_brush.h
model_shared.c
model_shared.h
portals.c
pr_cmds.c
pr_exec.c
pr_execprogram.h
progs.h
r_lerpanim.c
r_light.c
r_sky.c
render.h
sv_move.c
sv_phys.c
view.c
world.c

index c0af979..b38a2db 100644 (file)
--- 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;
 
index ae47246..c4d450a 100644 (file)
--- 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;
        }
 
index b33a23d..0bb9222 100644 (file)
@@ -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)
index 9a06554..11ed29f 100644 (file)
@@ -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);
 }
 
index deceed2..1616663 100644 (file)
@@ -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();
index 02a6c55..cdd5255 100644 (file)
--- 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
 //
index a22c8fb..0190412 100644 (file)
@@ -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)
index cbe0571..3dfcf6d 100644 (file)
--- 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);
+       }
+}
+
 
 //============================================================================
 
index 3d2275f..7ad2552 100644 (file)
--- 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)
index 6600491..93840d6 100644 (file)
--- 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));
 }
 
index 05ebc12..4b8c034 100644 (file)
@@ -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
index 3cbb699..eac1e6d 100644 (file)
@@ -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;
index 82162e5..b16a2bd 100644 (file)
@@ -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);
+}
+
index 86502d1..3570106 100644 (file)
@@ -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 ef40212..2816a12 100644 (file)
--- 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 ff098d5..9b4380a 100644 (file)
--- 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 4447faf..57d32ee 100644 (file)
--- 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];
index fff672e..ec3105c 100644 (file)
--- 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)
 
index 92244c4..4eec6da 100644 (file)
@@ -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;
index fdc6916..6f24b25 100644 (file)
@@ -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
 
index adbe934..4ece6a3 100644 (file)
@@ -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]);
 }
-
index f6a6bdc..d970b84 100644 (file)
@@ -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);
 
index 0343e9d..554177a 100644 (file)
--- 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);
index 14cc293..2c1c8ce 100644 (file)
--- 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;
index eda7404..368f485 100644 (file)
--- 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];
index fd306cf..05e8610 100644 (file)
@@ -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
                                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
                                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
                                        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
                                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
                                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
                                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];
 
                                {
                                        // 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
                                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
                                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
                                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
                                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
                                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
                                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
                                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
                                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;
 
                        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 c456c89..874ba9f 100644 (file)
--- 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);
index fe8f249..753e4af 100644 (file)
@@ -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;
index f6b8d48..754685a 100644 (file)
--- 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 ; i<node->numsurfaces ; 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 364818a..8b3d697 100644 (file)
--- 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);
+}
index a22cad7..195c0ca 100644 (file)
--- 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;
 
 
 //
index dd71097..5645c54 100644 (file)
--- 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);
index 94f2bdf..b89e114 100644 (file)
--- 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 4839e64..e50d4ce 100644 (file)
--- 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 a970bdd..0dbcb29 100644 (file)
--- 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)
        {