// instantly hide console and deactivate it
key_dest = key_game;
- key_consoleactive = false;
+ key_consoleactive = 0;
scr_conlines = 0;
scr_con_current = 0;
}
}
+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;
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;
}
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);
}
}
}
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)
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 ();
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,
// 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
if (!NET_CanSendMessage (cls.netcon))
{
Con_DPrintf ("CL_WriteToServer: can't send\n");
+ if (developer.integer)
+ SZ_HexDumpToConsole(&cls.message);
return;
}
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++)
{
// 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 ();
}
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)
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)
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++)
// 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;
{
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;
{
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)
{
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;
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;
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);
}
{
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
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)
{
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;
{
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)
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);
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)
else
cl_avidemo_frame = 0;
- if (cl.worldmodel)
+ if (cls.signon == SIGNONS)
R_TimeReport("other");
CL_SetupScreenSize();
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)
{
}
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();
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;
void CL_Disconnect (void);
void CL_Disconnect_f (void);
+void CL_BoundingBoxForEntity(entity_render_t *ent);
+
//
// cl_input
//
return HULLCHECKSTATE_DONE;
}
-/*
// used if start and end are the same
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)
{
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)
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)
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);
}
void SZ_Print (sizebuf_t *buf, char *data)
{
int len;
-
+
len = strlen(data)+1;
// byte * cast to keep VC++ happy
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);
+ }
+}
+
//============================================================================
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)
*/
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));
}
R_TimeReport("clear");
- if (scr_conlines < vid.conheight)
+ if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
R_RenderView();
// draw 2D stuff
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;
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;
//
refdef_t r_refdef;
-mleaf_t *r_viewleaf, *r_oldviewleaf;
-
// 8.8 fraction of base light value
unsigned short d_lightstylevalue[256];
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;
{
}
+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;
}
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);
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;
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;
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;
return sky;
}
+void R_DrawNoModel(entity_render_t *ent);
void R_DrawModels (void)
{
int i;
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);
+ }
}
}
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
-// current viewleaf
- r_oldviewleaf = r_viewleaf;
- r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
-
R_AnimateLight ();
}
*/
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");
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);
+}
+
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;
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
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;
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
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)
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)
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++)
// 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;
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;
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;
{
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);
}
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
{
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);
}
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
{
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);
}
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
if (surf->currenttexture->fogtexture != NULL)
{
Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
}
}
-/*
-=============================================================
-
- 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};
texture_t *t;
model_t *model;
msurface_t *surf;
+ vec3_t modelorg;
for (i = 0;i < Cshader_count;i++)
Cshaders[i]->chain = NULL;
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)
}
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++)
{
}
}
-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);
}
}
+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
{
// 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);
}
/*
*/
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);
}
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)
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);
}
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);
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
{
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;
}
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];
#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)
*/
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);
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;
}
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;
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;
{
// 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;
// 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
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
vec3_t mins;
vec3_t maxs;
+ int pvsframe; // potentially visible if current (r_pvsframecount)
+
// node specific
mplane_t *plane;
struct mnode_s *children[2];
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;
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
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])
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])
*/
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");
if (mod_known[i].name[0])
Mod_UnloadModel(&mod_known[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);
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);
{
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);
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);
break;
if (!*check)
- PR_RunError ("no precache: %s\n", m);
+ Host_Error ("no precache: %s\n", m);
e->v.model = m - pr_strings;
*/
void PF_break (void)
{
- PR_RunError ("break statement");
+ Host_Error ("break statement");
}
/*
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)
{
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);
}
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;
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);
}
void PR_CheckEmptyString (char *s)
{
if (s[0] <= ' ')
- PR_RunError ("Bad string");
+ Host_Error ("Bad string");
}
void PF_precache_file (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);
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)
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])))
if (!strcmp(sv.model_precache[i], s))
return;
}
- PR_RunError ("PF_precache_model: overflow");
+ Host_Error ("PF_precache_model: overflow");
}
*/
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);
}
/*
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;
}
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:
return &sv.signon;
default:
- PR_RunError ("WriteDest: bad destination");
+ Host_Error ("WriteDest: bad destination");
break;
}
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);
}
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++];
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");
}
/*
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");
}
/*
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));
}
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)
}
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;
}
-/*
-============
-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++)
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");
}
/*
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];
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];
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);
}
}
void PR_Profile_f (void);
+void PR_Crash (void);
+
edict_t *ED_Alloc (void);
void ED_Free (edict_t *ed);
extern unsigned short pr_crc;
-void PR_RunError (char *error, ...);
void PR_Execute_ProgsLoaded(void);
void ED_PrintEdicts (void);
double sublerp, lerp, d;
animscene_t *scene;
frameblend_t *blend;
+
+ if (!r->model)
+ return;
+
blend = r->frameblend;
numframes = r->model->numframes;
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)
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;
r_numdlights = 0;
c_dlights = 0;
- if (!r_dynamic.integer)
+ if (!r_dynamic.integer || !cl_dlights)
return;
for (i = 0;i < MAX_DLIGHTS;i++)
{
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;
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);
// 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;
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];
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;
}
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;
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];
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;
}
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);
}
}
-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)
vec_t intensity;
}
nearlight[MAX_DLIGHTS], *nl;
- int modeldlightbits[8];
mlight_t *sl;
rdlight_t *rd;
a = ent->alpha;
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++)
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;
}
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;
}
}
}
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;
}
#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)
{
}
}
-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;
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);
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);
+}
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);
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;
//
{
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;
}
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);
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;
}
*/
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
{
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)
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;
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:
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)
void SV_World_Init(void)
{
Cvar_RegisterVariable(&sv_useareanodes);
+ Collision_Init ();
}
*/
void SV_ClearWorld (void)
{
- Collision_Init ();
-
memset (sv_areanodes, 0, sizeof(sv_areanodes));
sv_numareanodes = 0;
Mod_CheckLoaded(sv.worldmodel);
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])
{
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)
{