-#define BUILDNUMBER 103
+#define BUILDNUMBER 104
int buildnumber = BUILDNUMBER;
//==========================================================================
-cvar_t cl_upspeed = {"cl_upspeed","200"};
-cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true};
-cvar_t cl_backspeed = {"cl_backspeed","200", true};
-cvar_t cl_sidespeed = {"cl_sidespeed","350"};
+cvar_t cl_upspeed = {"cl_upspeed","400"};
+cvar_t cl_forwardspeed = {"cl_forwardspeed","400", true};
+cvar_t cl_backspeed = {"cl_backspeed","400", true};
+cvar_t cl_sidespeed = {"cl_sidespeed","350", true};
cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"};
CL_AllocDlight (ent, ent->render.origin, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0);
}
- if (!chase_active.value && ((i == cl.viewentity) || (ent->render.flags & RENDER_EXTERIORMODEL)))
- continue;
+ if (chase_active.value)
+ {
+ if (ent->render.flags & RENDER_VIEWMODEL)
+ continue;
+ }
+ else
+ {
+ if (i == cl.viewentity || (ent->render.flags & RENDER_EXTERIORMODEL))
+ continue;
+ }
if (ent->render.model == NULL)
continue;
"svc_cutscene",
"svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
"svc_hidelmp", // [string] iconlabel
- "", // 37
+ "svc_skybox", // [string] skyname
"", // 38
"", // 39
"", // 40
char wadname[128];
int i, j, k;
FOG_clear(); // LordHavoc: no fog until set
- R_SetSkyBox(""); // LordHavoc: no enviroment mapped sky until set
+ R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
r_farclip.value = 6144; // LordHavoc: default farclip distance
data = entdata;
if (!data)
case svc_showlmp:
SHOWLMP_decodeshow();
break;
+ case svc_skybox:
+ R_SetSkyBox(MSG_ReadString());
+ break;
}
}
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
-int Cmd_CompleteAliasCountPossible (char *partial);
-char **Cmd_CompleteAliasBuildList (char *partial);
-int Cmd_CompleteCountPossible (char *partial);
-char **Cmd_CompleteBuildList (char *partial);
-char *Cmd_CompleteAlias (char *partial);
-// Enhanced console completion by Fett erich@heintz.com
-// Added by EvilTypeGuy eviltypeguy@qeradiant.com
-
int Cmd_Argc (void);
char *Cmd_Argv (int arg);
char *Cmd_Args (void);
void COM_InitFilesystem (void);
-// if a packfile directory differs from this, it is assumed to be hacked
-#define PAK0_COUNT 339
-#define PAK0_CRC 32981
-
char com_token[1024];
int com_argc;
char **com_argv;
qboolean standard_quake = true, rogue = false, hipnotic = false, nehahra = false;
-// this graphic needs to be in the pak file to use registered features
-unsigned short pop[] =
-{
- 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
-,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
-,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
-,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
-,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
-,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
-,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
-,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
-,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
-,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
-,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
-,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
-,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
-,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
-,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
-,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
-};
-
/*
FIXME:
The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line.
-
+
*/
//============================================================================
-// ClearLink is used for new headnodes
-void ClearLink (link_t *l)
-{
- l->prev = l->next = l;
-}
-
-void RemoveLink (link_t *l)
-{
- l->next->prev = l->prev;
- l->prev->next = l->next;
-}
-
-void InsertLinkBefore (link_t *l, link_t *before)
-{
- l->next = before;
- l->prev = before->prev;
- l->prev->next = l;
- l->next->prev = l;
-}
-void InsertLinkAfter (link_t *l, link_t *after)
-{
- l->next = after->next;
- l->prev = after;
- l->prev->next = l;
- l->next->prev = l;
-}
-
/*
============================================================================
void Q_memset (void *dest, int fill, int count)
{
int i;
-
+
if ( (((long)dest | count) & 3) == 0)
{
count >>= 2;
int Q_strncasecmp (char *s1, char *s2, int n)
{
int c1, c2;
-
+
while (1)
{
c1 = *s1++;
val /= 10;
total--;
}
-
+
return val*sign;
}
*/
============================================================================
*/
-#ifndef WIN32
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
short (*BigShort) (short l);
short (*LittleShort) (short l);
int (*BigLong) (int l);
msg_badread = true;
return -1;
}
-
+
c = net_message.data[msg_readcount]
+ (net_message.data[msg_readcount+1]<<8)
+ (net_message.data[msg_readcount+2]<<16)
COM_StripExtension
============
*/
+// LordHavoc: replacement for severely broken COM_StripExtension that was used in original quake.
void COM_StripExtension (char *in, char *out)
{
- while (*in && *in != '.')
+ char *last = NULL;
+ while (*in)
+ {
+ if (*in == '.')
+ last = in;
+ if ((*in == '/') || (*in == '\\') || (*in == ':'))
+ last = NULL;
*out++ = *in++;
- *out = 0;
+ }
+ if (last)
+ *last = 0;
}
/*
*/
void COM_CheckRegistered (void)
{
- QFile *h;
- unsigned short check[128];
- int i;
-
Cvar_Set ("cmdline", com_cmdline);
- COM_FOpenFile("gfx/pop.lmp", &h, false, true);
static_registered = 0;
- if (!h)
+ if (!Sys_FileTime("gfx/pop.lmp"))
{
if (com_modified)
Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
// Sys_Error ("You must have the registered version to use modified games");
return;
}
-
- Qread (h, check, sizeof(check));
- Qclose (h);
-
- for (i=0 ; i<128 ; i++)
- if (pop[i] != (unsigned short)BigShort (check[i]))
- Sys_Error ("Corrupted data file.");
// Cvar_Set ("cmdline", com_cmdline);
Cvar_Set ("registered", "1");
*/
void COM_Init (char *basedir)
{
-#ifndef WIN32
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
byte swaptest[2] = {1,0};
// set the byte swapping variables in a portable manner
void COM_CreatePath (char *path)
{
char *ofs, save;
-
+
for (ofs = path+1 ; *ofs ; ofs++)
{
if (*ofs == '/' || *ofs == '\\' || *ofs == ':')
findtime = Sys_FileTime (netpath);
if (findtime == -1)
- {
- sprintf (netpath, "%s/%s",search->filename, gzfilename);
- findtime = Sys_FileTime (netpath);
- if (findtime == -1)
- continue;
- }
+ continue;
#if CACHEENABLE
// see if the file needs to be updated in the cache
*/
pack_t *COM_LoadPackFile (char *packfile)
{
- dpackheader_t header;
- int i;
- packfile_t *newfiles;
- int numpackfiles;
- pack_t *pack;
- int packhandle;
+ dpackheader_t header;
+ int i;
+ packfile_t *newfiles;
+ int numpackfiles;
+ pack_t *pack;
+ int packhandle;
// LordHavoc: changed from stack array to temporary malloc, allowing huge pack directories
- dpackfile_t *info;
- unsigned short crc;
+ dpackfile_t *info;
if (Sys_FileOpenRead (packfile, &packhandle) == -1)
{
if (numpackfiles > MAX_FILES_IN_PACK)
Sys_Error ("%s has %i files", packfile, numpackfiles);
- if (numpackfiles != PAK0_COUNT)
- com_modified = true; // not the original file
-
newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "pack file-table");
info = qmalloc(sizeof(*info)*MAX_FILES_IN_PACK);
Sys_FileSeek (packhandle, header.dirofs);
Sys_FileRead (packhandle, (void *)info, header.dirlen);
-// crc the directory to check for modifications
- CRC_Init (&crc);
- // LordHavoc: speedup
- CRC_ProcessBytes(&crc, (byte *)info, header.dirlen);
-// for (i=0 ; i<header.dirlen ; i++)
-// CRC_ProcessByte (&crc, ((byte *)info)[i]);
- if (crc != PAK0_CRC)
- com_modified = true;
-
// parse the directory
for (i=0 ; i<numpackfiles ; i++)
{
//============================================================================
-typedef struct link_s
-{
- struct link_s *prev, *next;
-} link_t;
-
-
-void ClearLink (link_t *l);
-void RemoveLink (link_t *l);
-void InsertLinkBefore (link_t *l, link_t *before);
-void InsertLinkAfter (link_t *l, link_t *after);
-
-// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
-// ent = STRUCT_FROM_LINK(link,entity_t,order)
-// FIXME: remove this mess!
-#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
-
-//============================================================================
-
#ifndef NULL
#define NULL ((void *)0)
#endif
-#define Q_MAXCHAR ((char)0x7f)
-#define Q_MAXSHORT ((short)0x7fff)
-#define Q_MAXINT ((int)0x7fffffff)
-#define Q_MAXLONG ((int)0x7fffffff)
-#define Q_MAXFLOAT ((int)0x7fffffff)
-
-#define Q_MINCHAR ((char)0x80)
-#define Q_MINSHORT ((short)0x8000)
-#define Q_MININT ((int)0x80000000)
-#define Q_MINLONG ((int)0x80000000)
-#define Q_MINFLOAT ((int)0x7fffffff)
-
//============================================================================
-#ifdef WIN32
-short ShortSwap (short l);
-int LongSwap (int l);
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
+#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || (defined(__alpha__) || defined(__alpha)) || defined(__arm__) || (defined(__mips__) && defined(__MIPSEL__)) || defined(__LITTLE_ENDIAN__)
+#define ENDIAN_LITTLE
+#else
+#define ENDIAN_BIG
+#endif
+#endif
+
+short ShortSwap (short l);
+int LongSwap (int l);
float FloatSwap (float f);
+
+#ifdef ENDIAN_LITTLE
+// little endian
#define BigShort(l) ShortSwap(l)
#define LittleShort(l) (l)
#define BigLong(l) LongSwap(l)
#define LittleLong(l) (l)
#define BigFloat(l) FloatSwap(l)
#define LittleFloat(l) (l)
+#elif ENDIAN_BIG
+// big endian
+#define BigShort(l) (l)
+#define LittleShort(l) ShortSwap(l)
+#define BigLong(l) (l)
+#define LittleLong(l) LongSwap(l)
+#define BigFloat(l) (l)
+#define LittleFloat(l) FloatSwap(l)
#else
-extern short (*BigShort) (short l);
-extern short (*LittleShort) (short l);
-extern int (*BigLong) (int l);
-extern int (*LittleLong) (int l);
-extern float (*BigFloat) (float l);
-extern float (*LittleFloat) (float l);
+// figure it out at runtime
+extern short (*BigShort) (short l);
+extern short (*LittleShort) (short l);
+extern int (*BigLong) (int l);
+extern int (*LittleLong) (int l);
+extern float (*BigFloat) (float l);
+extern float (*LittleFloat) (float l);
#endif
//============================================================================
float *av, *avn;
av = aliasvert;
avn = aliasvertnorm;
- VectorScaleQuick(fscale1, lerp1, scale1);
+ VectorScale(fscale1, lerp1, scale1);
if (lerp2)
{
- VectorScaleQuick(fscale2, lerp2, scale2);
+ VectorScale(fscale2, lerp2, scale2);
if (lerp3)
{
- VectorScaleQuick(fscale3, lerp3, scale3);
+ VectorScale(fscale3, lerp3, scale3);
if (lerp4)
{
- VectorScaleQuick(fscale4, lerp4, scale4);
+ VectorScale(fscale4, lerp4, scale4);
translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3 + translate4[0] * lerp4;
translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3 + translate4[1] * lerp4;
translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3 + translate4[2] * lerp4;
{
float lerp1, lerp2, lerp3, lerp4;
zymbonematrix *out, rootmatrix, m, *bone1, *bone2, *bone3, *bone4;
- lerp1 = 1 - lerp2;
out = zymbonepose;
AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]);
VectorScale(rootmatrix.m[0], rootscale, rootmatrix.m[0]);
}
}
-float ixtable[4096];
-
void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist)
{
int a, b, c, d;
float *out, v1[3], v2[3], normal[3];
int *u;
- if (!ixtable[1])
- {
- ixtable[0] = 0;
- for (a = 1;a < 4096;a++)
- ixtable[a] = 1.0f / a;
- }
// clear normals
memset(aliasvertnorm, 0, sizeof(float[3]) * vertcount);
memset(aliasvertusage, 0, sizeof(int) * vertcount);
VectorAdd (org, clmodel->mins, mins);
VectorAdd (org, clmodel->maxs, maxs);
- if (cull && R_VisibleCullBox (mins, maxs))
- return;
+// if (cull && R_CullBox (mins, maxs))
+// return;
c_models++;
#include "quakedef.h"
-entity_t r_worldentity;
-
qboolean r_cache_thrash; // compatability
vec3_t modelorg, r_entorigin;
unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
+float ixtable[4096];
void R_MarkLeaves (void);
cvar_t gl_fogend = {"gl_fogend","0"};
cvar_t glfog = {"glfog", "0"};
+/*
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)
+ {
+ if (R_CullBox(mins, maxs))
+ return true;
return false;
+ }
if (!stack)
return true;
node = nodestack[--stack];
node = node->children[1];
goto loc0;
}
+*/
qboolean lighthalf;
void GL_Main_Init(void)
{
+ int a;
FOG_registercvars();
+ // LordHavoc: setup 1.0f / N table for quick recipricols of integers
+ ixtable[0] = 0;
+ for (a = 1;a < 4096;a++)
+ ixtable[a] = 1.0f / a;
Cvar_RegisterVariable (&r_drawentities);
Cvar_RegisterVariable (&r_drawviewmodel);
Cvar_RegisterVariable (&r_speeds);
extern void R_Particles_Init(void);
extern void R_Explosion_Init(void);
extern void CL_Effects_Init(void);
+extern void R_Clip_Init(void);
void Render_Init(void)
{
R_Modules_Shutdown();
+ R_Clip_Init();
GL_Draw_Init();
GL_Main_Init();
GL_Models_Init();
//==================================================================================
-void R_DrawBrushModel (entity_t *e);
-void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
-
void R_LerpUpdate(entity_t *ent)
{
int frame;
}
}
+void R_Entity_Callback(void *data, void *junk)
+{
+ ((entity_t *)data)->render.visframe = r_framecount;
+}
+
+void R_AddModelEntities (void)
+{
+ int i;
+ vec3_t mins, maxs;
+ frameblend_t blend[4];
+
+ if (!r_drawentities.value)
+ return;
+
+ for (i = 0;i < cl_numvisedicts;i++)
+ {
+ currententity = cl_visedicts[i];
+ if (currententity->render.model->type == mod_brush)
+ {
+ modelalpha = currententity->render.alpha;
+ R_DrawBrushModel (currententity);
+ }
+ else if (currententity->render.model->type == mod_alias)
+ {
+ VectorAdd(currententity->render.origin, currententity->render.model->mins, mins);
+ VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs);
+ R_Clip_AddBox(mins, maxs, R_Entity_Callback, currententity, NULL);
+ }
+ else if (currententity->render.model->type == mod_sprite)
+ {
+ R_LerpUpdate(currententity);
+ R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
+ R_ClipSprite(currententity, blend);
+ }
+ }
+}
+
/*
=============
R_DrawEntitiesOnList
=============
*/
-// LordHavoc: split so bmodels are rendered before any other objects
+/*
void R_DrawEntitiesOnList1 (void)
{
int i;
for (i = 0;i < cl_numvisedicts;i++)
{
+ if (cl_visedicts[i]->render.visframe != r_framecount)
+ continue;
if (cl_visedicts[i]->render.model->type != mod_brush)
continue;
currententity = cl_visedicts[i];
R_DrawBrushModel (currententity);
}
}
+*/
-void R_DrawEntitiesOnList2 (void)
+void R_DrawModels (void)
{
int i;
frameblend_t blend[4];
+// vec3_t mins, maxs;
if (!r_drawentities.value)
return;
for (i = 0;i < cl_numvisedicts;i++)
{
+ if (cl_visedicts[i]->render.visframe != r_framecount)
+ continue;
currententity = cl_visedicts[i];
+ if (currententity->render.model->type != mod_alias && currententity->render.model->type != mod_sprite)
+ continue;
+
modelalpha = currententity->render.alpha;
- switch (currententity->render.model->type)
+ if (currententity->render.model->type == mod_alias)
{
- case mod_alias:
+ // only lerp models here because sprites were already lerped for their clip polygon
R_LerpUpdate(currententity);
R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
- break;
-
- case mod_sprite:
- R_LerpUpdate(currententity);
+ }
+ else //if (currententity->render.model->type == mod_sprite)
+ {
+ // build blend array
R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
R_DrawSpriteModel (currententity, blend);
- break;
+ }
- default:
+ /*
+ VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->mins, mins);
+ VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->maxs, maxs);
+
+ switch (cl_visedicts[i]->render.model->type)
+ {
+ case mod_alias:
+ R_Clip_AddBox(mins, maxs, R_DrawModelCallback, cl_visedicts[i], NULL);
+ break;
+ case mod_sprite:
+ R_Clip_AddBox(mins, maxs, R_DrawSpriteCallback, cl_visedicts[i], NULL);
break;
}
+ */
}
}
{
int i;
- if (r_refdef.fov_x == 90)
+ // LordHavoc: note to all quake engine coders, this code was making the
+ // view frustum taller than it should have been (it assumed the view is
+ // square; it is not square), so I disabled it
+ /*
+ if (r_refdef.fov_x == 90)
{
// front side is visible
}
else
{
+ */
// rotate VPN right by FOV_X/2 degrees
RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
// rotate VPN left by FOV_X/2 degrees
RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
// rotate VPN down by FOV_X/2 degrees
RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
- }
+ //}
for (i=0 ; i<4 ; i++)
{
frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
// frustum[i].signbits = SignbitsForPlane (&frustum[i]);
- BoxOnPlaneSideClassify(&frustum[i]);
+ PlaneClassify(&frustum[i]);
}
}
glEnable(GL_TEXTURE_2D);
}
-#define TIMEREPORT(VAR) \
- if (r_speeds2.value)\
- {\
- temptime = currtime;\
- currtime = Sys_DoubleTime();\
- VAR = (int) ((currtime - temptime) * 1000000.0);\
- }\
- else\
- VAR = 0;
-
/*
================
R_RenderView
*/
extern void R_Sky(void);
extern void UploadLightmaps(void);
-char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81];
+extern void R_DrawSurfaces(void);
+extern void R_DrawPortals(void);
+char r_speeds2_string[1024];
+int speedstringcount;
+
+void timestring(int t, char *desc)
+{
+ char tempbuf[256];
+ int length;
+ if (t < 1000000)
+ sprintf(tempbuf, " %6ius %s", t, desc);
+ else
+ sprintf(tempbuf, " %6ims %s", t / 1000, desc);
+ length = strlen(tempbuf);
+// while (length < 20)
+// tempbuf[length++] = ' ';
+// tempbuf[length] = 0;
+ if (speedstringcount + length > 80)
+ {
+ strcat(r_speeds2_string, "\n");
+ speedstringcount = 0;
+ }
+ // skip the space at the beginning if it's the first on the line
+ if (speedstringcount == 0)
+ {
+ strcat(r_speeds2_string, tempbuf + 1);
+ speedstringcount = length - 1;
+ }
+ else
+ {
+ strcat(r_speeds2_string, tempbuf);
+ speedstringcount += length;
+ }
+}
+
+#define TIMEREPORT(NAME) \
+ if (r_speeds2.value)\
+ {\
+ temptime = currtime;\
+ currtime = Sys_DoubleTime();\
+ timestring((int) ((currtime - temptime) * 1000000.0), NAME);\
+ }
+
void R_RenderView (void)
{
double starttime, currtime, temptime;
- int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend, time_total;
// if (r_norefresh.value)
// return;
- if (!r_worldentity.render.model || !cl.worldmodel)
+ if (!cl.worldmodel)
Host_Error ("R_RenderView: NULL worldmodel");
- lighthalf = gl_lightmode.value;
-
- FOG_framebegin();
-
if (r_speeds2.value)
+ {
starttime = currtime = Sys_DoubleTime();
+
+ speedstringcount = 0;
+ sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i transpoly\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
+ r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
+ c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly,
+ c_faces, c_nodes, c_leafs,
+ c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+ }
else
starttime = currtime = 0;
+
+ R_MoveParticles ();
+ R_MoveExplosions();
+
+ lighthalf = gl_lightmode.value;
+
+ FOG_framebegin();
+
R_Clear();
- TIMEREPORT(time_clear)
+ TIMEREPORT("clear ")
// render normal view
R_SetupFrame ();
R_SetFrustum ();
R_SetupGL ();
+ R_Clip_StartFrame();
R_PrepareEntities();
wallpolyclear();
transpolyclear();
- TIMEREPORT(time_setup)
+ TIMEREPORT("setup ")
R_DrawWorld ();
- TIMEREPORT(time_world)
- R_DrawEntitiesOnList1 (); // BSP models
- TIMEREPORT(time_bmodels)
+ TIMEREPORT("world ")
+
+ R_AddModelEntities();
+ TIMEREPORT("addmodels")
+
+ R_Clip_EndFrame();
+ TIMEREPORT("scanedge ")
+
+ // now mark the lit surfaces
+ R_PushDlights ();
+ // yes this does add the world surfaces after the brush models
+ R_DrawSurfaces ();
+ R_DrawPortals ();
+ TIMEREPORT("surfaces ");
UploadLightmaps();
- TIMEREPORT(time_upload)
+ TIMEREPORT("uploadlmap")
- skypolyrender(); // fogged sky polys, affects depth
+ // fogged sky polys, affects depth
+ skypolyrender();
+ // does not affect depth, draws over the sky polys
if (currentskypoly)
- R_Sky(); // does not affect depth, draws over the sky polys
- TIMEREPORT(time_sky)
+ R_Sky();
+ TIMEREPORT("skypoly ")
wallpolyrender();
- TIMEREPORT(time_wall)
+ TIMEREPORT("wallpoly ")
GL_DrawDecals();
- TIMEREPORT(time_drawdecals)
+ TIMEREPORT("ddecal ")
+ // don't let sound skip if going slow
if (!intimerefresh && !r_speeds2.value)
- S_ExtraUpdate (); // don't let sound get messed up if going slow
+ S_ExtraUpdate ();
- R_DrawEntitiesOnList2 (); // other models
-// R_RenderDlights ();
R_DrawViewModel ();
- TIMEREPORT(time_models)
- R_MoveParticles ();
- TIMEREPORT(time_moveparticles)
+ R_DrawModels ();
+ TIMEREPORT("models ")
+
R_DrawParticles ();
- TIMEREPORT(time_drawparticles)
- R_MoveExplosions();
- TIMEREPORT(time_moveexplosions)
+ TIMEREPORT("dparticles")
R_DrawExplosions();
- TIMEREPORT(time_drawexplosions)
+ TIMEREPORT("dexplosion")
transpolyrender();
- TIMEREPORT(time_transpoly)
+ TIMEREPORT("transpoly ")
FOG_frameend();
GL_BlendView();
- TIMEREPORT(time_blend)
+ TIMEREPORT("blend ")
+
if (r_speeds2.value)
- {
- time_total = (int) ((Sys_DoubleTime() - starttime) * 1000000.0);
- sprintf(r_speeds2_string1, "%6i walls %6i dlitwalls %7i modeltris %7i transpoly\n", c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly);
- sprintf(r_speeds2_string2, "BSP: %6i faces %6i nodes %6i leafs\n", c_faces, c_nodes, c_leafs);
- sprintf(r_speeds2_string3, "%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights);
- sprintf(r_speeds2_string4, "%6ius clear %6ius setup %6ius world %6ius bmodel %6ius upload", time_clear, time_setup, time_world, time_bmodels, time_upload);
- sprintf(r_speeds2_string5, "%6ius sky %6ius wall %6ius models %6ius mpart %6ius dpart ", time_sky, time_wall, time_models, time_moveparticles, time_drawparticles);
- sprintf(r_speeds2_string6, "%6ius mexplo %6ius dexplo %6ius decals %6ius trans %6ius blend ", time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend);
- sprintf(r_speeds2_string7, "%6ius permdl %6ius total ", time_models / max(c_models, 1), time_total);
- }
+ timestring((int) ((Sys_DoubleTime() - starttime) * 1000000.0), "total ");
}
r_refdef.viewangles[0] = 0;
r_refdef.viewangles[1] = 0;
r_refdef.viewangles[2] = 0;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[1] = 90;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[1] = 180;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[0] = -90;
r_refdef.viewangles[1] = 0;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[0] = 90;
r_refdef.viewangles[1] = 0;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));
for (i=0 ; i<256 ; i++)
d_lightstylevalue[i] = 264; // normal light value
- memset (&r_worldentity, 0, sizeof(r_worldentity));
- r_worldentity.render.model = cl.worldmodel;
- currententity = &r_worldentity;
-
r_viewleaf = NULL;
R_Modules_NewMap();
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
int lightmap_textures;
-// LordHavoc: skinny but tall lightmaps for quicker subimage uploads
#define BLOCK_WIDTH 256
#define BLOCK_HEIGHT 256
// LordHavoc: increased lightmap limit from 64 to 1024
cvar_t gl_vertex = {"gl_vertex", "0"};
cvar_t r_dlightmap = {"r_dlightmap", "1"};
cvar_t r_drawportals = {"r_drawportals", "0"};
+cvar_t r_testvis = {"r_testvis", "0"};
+cvar_t r_solidworldnode = {"r_solidworldnode", "1"};
qboolean lightmaprgba, nosubimagefragments, nosubimage;
int lightmapbytes;
Cvar_RegisterVariable(&gl_vertex);
Cvar_RegisterVariable(&r_dlightmap);
Cvar_RegisterVariable(&r_drawportals);
+ Cvar_RegisterVariable(&r_testvis);
+ Cvar_RegisterVariable(&r_solidworldnode);
R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
}
-int dlightdivtable[32768];
+int dlightdivtable[32768];
/*
R_AddDynamicLights
*/
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
{
- int smax, tmax;
- int i, j, size, size3;
- byte *lightmap;
- int scale;
- int maps;
- int *bl;
+ int smax, tmax;
+ int i, j, size, size3;
+ byte *lightmap;
+ int scale;
+ int maps;
+ int *bl;
surf->cached_dlight = 0;
surf->cached_lighthalf = lighthalf;
|| (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2])
|| (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3]))))
R_UpdateLightmap(s, s->lightmaptexturenum);
- if (r_dlightmap.value || s->dlightframe != r_framecount)
+ if (s->dlightframe != r_framecount || r_dlightmap.value)
{
// LordHavoc: fast path version for no vertex lighting cases
wp = &wallpoly[currentwallpoly];
wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture);
wp->firstvert = currentwallvert;
wp->numverts = p->numverts;
- wp->lit = lit;
+ wp->lit = false;
wp++;
currentwallpoly++;
currentwallvert += p->numverts;
void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model);
+float bmverts[256*3];
+
+int vertexworld;
+
+/*
+void RBrushModelSurf_DoVisible(msurface_t *surf)
+{
+// float *v, *bmv, *endbmv;
+// glpoly_t *p;
+// for (p = surf->polys;p;p = p->next)
+// {
+// for (v = p->verts[0], bmv = bmpoints, endbmv = bmv + p->numverts * 3;bmv < endbmv;v += VERTEXSIZE, bmv += 3)
+// softwaretransform(v, bmv);
+// if (R_Clip_Polygon(bmpoints, p->numverts, sizeof(float) * 3, surf->flags & SURF_CLIPSOLID))
+ surf->visframe = r_framecount;
+// }
+}
+*/
+
+void RBrushModelSurf_Callback(void *data, void *data2)
+{
+ entity_t *ent = data2;
+ msurface_t *surf = data;
+ texture_t *t;
+
+ /*
+ // FIXME: implement better dupe prevention in AddPolygon callback code
+ if (ent->render.model->firstmodelsurface != 0)
+ {
+ // it's not an instanced model, so we already rely on there being only one of it (usually a valid assumption, but QC can break this)
+ if (surf->visframe == r_framecount)
+ return;
+ }
+ */
+ surf->visframe = r_framecount;
+
+ c_faces++;
+
+ currententity = ent;
+ modelalpha = ent->render.alpha;
+
+ softwaretransformforbrushentity (ent);
+
+ if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
+ {
+ // sky and liquid don't need sorting (skypoly/transpoly)
+ if (surf->flags & SURF_DRAWSKY)
+ RSurf_DrawSky(surf, true);
+ else
+ RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), true, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+ }
+ else
+ {
+ t = R_TextureAnimation(surf->texinfo->texture);
+ if (surf->texinfo->texture->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1)
+ RSurf_DrawWallVertex(surf, t, true, true);
+ else
+ RSurf_DrawWall(surf, t, true);
+ }
+}
+
/*
=================
R_DrawBrushModel
*/
void R_DrawBrushModel (entity_t *e)
{
- int i;
+ int i, j;
vec3_t mins, maxs;
msurface_t *s;
model_t *clmodel;
- int rotated, vertexlit = false;
+ int rotated;
vec3_t org;
+ glpoly_t *p;
currententity = e;
VectorAdd (e->render.origin, clmodel->maxs, maxs);
}
- if (R_VisibleCullBox (mins, maxs))
+ if (R_CullBox (mins, maxs))
return;
c_bmodels++;
modelorg[2] = DotProduct (temp, up);
}
+ softwaretransformforbrushentity (e);
+
for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
{
+ s->visframe = -1;
if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0))
s->visframe = r_framecount;
- else
- s->visframe = -1;
}
-// calculate dynamic lighting for bmodel if it's not an
-// instanced model
+// calculate dynamic lighting for bmodel if it's not an instanced model
for (i = 0;i < MAX_DLIGHTS;i++)
{
if (!cl_dlights[i].radius)
VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org);
R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel);
}
- vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1;
-
- e->render.angles[0] = -e->render.angles[0]; // stupid quake bug
- softwaretransformforentity (e);
- e->render.angles[0] = -e->render.angles[0]; // stupid quake bug
+// vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1;
// draw texture
for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
if (s->visframe == r_framecount)
{
// R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent);
+ for (p = s->polys;p;p = p->next)
+ {
+ for (j = 0;j < p->numverts;j++)
+ softwaretransform(&p->verts[j][0], bmverts + j * 3);
+ R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && modelalpha == 1, RBrushModelSurf_Callback, s, e, NULL);
+ }
+ /*
if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
// sky and liquid don't need sorting (skypoly/transpoly)
else
RSurf_DrawWall(s, t, true);
}
+ */
}
}
UploadLightmaps();
=============================================================
*/
+/*
static byte *worldvis;
void R_MarkLeaves (void)
worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
}
+*/
-void R_SolidWorldNode (void)
+void RSurf_Callback(void *data, void *junk)
+{
+ ((msurface_t *)data)->visframe = r_framecount;
+}
+
+/*
+void RSurf_Callback(void *data, void *junk)
+{
+ msurface_t *surf = data;
+ texture_t *t;
+
+// if (surf->visframe == r_framecount)
+// return;
+
+ surf->visframe = r_framecount;
+
+ c_faces++;
+
+ if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
+ {
+ // sky and liquid don't need sorting (skypoly/transpoly)
+ if (surf->flags & SURF_DRAWSKY)
+ RSurf_DrawSky(surf, false);
+ else
+ RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+ }
+ else
+ {
+ t = R_TextureAnimation(surf->texinfo->texture);
+ if (vertexworld)
+ RSurf_DrawWallVertex(surf, t, false, false);
+ else
+ RSurf_DrawWall(surf, t, false);
+ }
+}
+*/
+
+/*
+mleaf_t *r_oldviewleaf;
+int r_markvisframecount = 0;
+
+void R_MarkLeaves (void)
{
- int l;
+ static float noviscache;
+ int i, l, k, c;
mleaf_t *leaf;
msurface_t *surf, **mark, **endmark;
+ model_t *model = cl.worldmodel;
+// mportal_t *portal;
+ glpoly_t *p;
+ byte *in;
+ int row;
+
+ // ignore testvis if the map just changed
+ if (r_testvis.value && model->nodes->markvisframe == r_markvisframecount)
+ return;
+
+ if (r_oldviewleaf == r_viewleaf && noviscache == r_novis.value)
+ return;
+
+ r_oldviewleaf = r_viewleaf;
+ noviscache = r_novis.value;
- for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++)
+ if ((in = r_viewleaf->compressed_vis))
{
- if (leaf->nummarksurfaces)
+ row = (model->numleafs+7)>>3;
+
+ if (!r_testvis.value)
+ r_markvisframecount++;
+
+ // LordHavoc: mark the root node as visible, it will terminate all other ascensions
+ model->nodes->markvisframe = r_markvisframecount;
+
+ k = 0;
+ while (k < row)
{
- if (R_CullBox(leaf->mins, leaf->maxs))
- continue;
+ c = *in++;
+ if (c)
+ {
+ l = model->numleafs - (k << 3);
+ if (l > 8)
+ l = 8;
+ for (i=0 ; i<l ; i++)
+ {
+ if (c & (1<<i))
+ {
+ leaf = &model->leafs[(k << 3)+i+1];
+ node = (mnode_t *)leaf;
+ do
+ {
+ node->markvisframe = r_markvisframecount;
+ node = node->parent;
+ }
+ while (node->markvisframecount != r_markvisframecount);
+ }
+ }
+ k++;
+ }
+ else
+ k += *in++;
+ }
+ }
+ else
+ {
+ // LordHavoc: no vis data, mark everything as visible
+ model->nodes->markvisframe = r_markvisframecount;
- c_leafs++;
+ for (i = 1;i < model->numleafs;i++)
+ {
+ node = (mnode_t *)&model->leafs[i];
+ do
+ {
+ node->markvisframe = r_markvisframecount;
+ node = node->parent;
+ }
+ while (node->markvisframecount != r_markvisframecount);
+ }
+ }
+}
+*/
- leaf->visframe = r_framecount;
+void R_SolidWorldNode (void)
+{
+ if ((int) r_solidworldnode.value == 2)
+ {
+ mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
+ int nodestackpos = 0;
+ glpoly_t *p;
- if (leaf->nummarksurfaces)
+loc0:
+ if (node->numsurfaces)
+ {
+ msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
+ tinyplane_t plane;
+ if (PlaneDiff (r_origin, node->plane) < 0)
{
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- do
+ for (;surf < surfend;surf++)
{
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
+ if (surf->flags & SURF_PLANEBACK)
{
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
+ VectorNegate(surf->plane->normal, plane.normal);
+ plane.dist = -surf->plane->dist;
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, &plane);
}
- else
+ }
+ }
+ else
+ {
+ for (;surf < surfend;surf++)
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
+ }
+ }
+ }
+
+ // 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 loc0;
+ }
+ node = node->children[0];
+ goto loc0;
+ }
+ else if (node->children[1]->contents >= 0)
+ {
+ node = node->children[1];
+ goto loc0;
+ }
+ else if (nodestackpos > 0)
+ {
+ node = nodestack[--nodestackpos];
+ goto loc0;
+ }
+ }
+ else if ((int) r_solidworldnode.value == 1)
+ {
+ glpoly_t *p;
+ msurface_t *surf, *endsurf;
+ tinyplane_t plane;
+
+
+ surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
+ endsurf = surf + cl.worldmodel->nummodelsurfaces;
+ for (;surf < endsurf;surf++)
+ {
+ if (PlaneDiff(r_origin, surf->plane) < 0)
+ {
+ if (surf->flags & SURF_PLANEBACK)
+ {
+ VectorNegate(surf->plane->normal, plane.normal);
+ plane.dist = -surf->plane->dist;
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
+ }
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)&surf->plane);
+ }
+ }
+ }
+ else
+ {
+ int l;
+ mleaf_t *leaf;
+ msurface_t *surf, **mark, **endmark;
+ glpoly_t *p;
+ tinyplane_t plane;
+
+ for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++)
+ {
+ if (R_CullBox(leaf->mins, leaf->maxs))
+ continue;
+// leaf->visframe = r_framecount;
+ c_leafs++;
+ if (leaf->nummarksurfaces)
+ {
+// if (R_CullBox(leaf->mins, leaf->maxs))
+// continue;
+
+ if (leaf->nummarksurfaces)
+ {
+ mark = leaf->firstmarksurface;
+ endmark = mark + leaf->nummarksurfaces;
+ do
{
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
+ 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)
+ {
+ VectorNegate(surf->plane->normal, plane.normal);
+ plane.dist = -surf->plane->dist;
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
+ }
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
+ }
}
+ while (mark < endmark);
+ }
+ }
+ }
+ }
+}
+
+/*
+void RSurf_Callback(void *data, void *junk)
+{
+ ((msurface_t *)data)->visframe = r_framecount;
+}
+
+int R_FrustumTestPolygon(float *points, int numpoints, int stride);
+
+void RSurf_DoVisible(msurface_t *surf)
+{
+ glpoly_t *p;
+ for (p = surf->polys;p;p = p->next)
+ if (R_FrustumTestPolygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float)) >= 3)
+// R_Clip_Polygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float), true, RSurf_Callback, surf, 1);
+// if (R_Clip_Polygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID))
+ surf->visframe = r_framecount;
+}
+*/
+
+//mleaf_t *llistbuffer[32768], *l, **llist;
+
+/*
+void RSurfLeaf_Callback(void *data)
+{
+ int portalstackpos = 0;
+ mleaf_t *leaf;
+ mportal_t *p, *portalstack[32768];
+ msurface_t *surf, **mark, **endmark;
+ do
+ {
+
+ leaf = data;
+ if (leaf->visframe == r_framecount)
+ return;
+ leaf->visframe = r_framecount;
+
+ c_leafs++;
+
+ if (leaf->nummarksurfaces)
+ {
+ mark = leaf->firstmarksurface;
+ endmark = mark + leaf->nummarksurfaces;
+ do
+ {
+ surf = *mark++;
+ // make sure surfaces are only processed once
+ if (surf->worldnodeframe == r_framecount)
+ continue;
+ surf->worldnodeframe = r_framecount;
+ if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
+ {
+ if (surf->flags & SURF_PLANEBACK)
+ RSurf_DoVisible(surf);
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ RSurf_DoVisible(surf);
}
- while (mark < endmark);
+ }
+ while (mark < endmark);
+ }
+
+ // follow portals into other leafs
+ for (p = leaf->portals;p;p = p->next)
+ {
+ if (p->past->visframe != r_framecount && DotProduct(r_origin, p->plane.normal) < p->plane.dist)
+ {
+ // R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3, RSurfLeaf_Callback, p->past, 1);
+ if (R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3))
+ portalstack[portalstackpos++] = p;
}
}
}
+ while(portalstackpos);
+ RSurfLeaf_Callback(p->past);
+ // upon returning, R_ProcessSpans will notice that the spans have changed and restart the line, this is ok because we're not adding any polygons that aren't already behind the portal
}
+*/
/*
// experimental and inferior to the other in recursion depth allowances
void R_PortalWorldNode (void)
{
- int i, j;
+// int i, j;
mportal_t *p;
msurface_t *surf, **mark, **endmark;
- mleaf_t *leaf, *llistbuffer[8192], **l, **llist;
+ mleaf_t *leaf, *llistbuffer[32768], **l, **llist;
leaf = r_viewleaf;
- leaf->worldnodeframe = r_framecount;
+ leaf->visframe = r_framecount;
l = llist = &llistbuffer[0];
*llist++ = r_viewleaf;
while (l < llist)
c_leafs++;
- leaf->visframe = r_framecount;
-
if (leaf->nummarksurfaces)
{
mark = leaf->firstmarksurface;
if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
{
if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
+ RSurf_DoVisible(surf);
}
else
{
if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
+ RSurf_DoVisible(surf);
}
}
while (mark < endmark);
}
// follow portals into other leafs
- p = leaf->portals;
- for (;p;p = p->next)
+ for (p = leaf->portals;p;p = p->next)
{
- leaf = p->past;
- if (leaf->worldnodeframe != r_framecount)
+ if (p->past->visframe != r_framecount)
{
- leaf->worldnodeframe = r_framecount;
- i = (leaf - cl.worldmodel->leafs) - 1;
- if ((worldvis[i>>3] & (1<<(i&7))) && R_NotCulledBox(leaf->mins, leaf->maxs))
- *llist++ = leaf;
+ if (R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3))
+ {
+ p->past->visframe = r_framecount;
+ *llist++ = p->past;
+ }
}
}
+
+// for (p = leaf->portals;p;p = p->next)
+// {
+// leaf = p->past;
+// if (leaf->worldnodeframe != r_framecount)
+// {
+// leaf->worldnodeframe = r_framecount;
+// i = (leaf - cl.worldmodel->leafs) - 1;
+// if ((worldvis[i>>3] & (1<<(i&7))) && R_NotCulledBox(leaf->mins, leaf->maxs))
+// *llist++ = leaf;
+// }
+// }
}
+// i = 0;
+// j = 0;
+// p = r_viewleaf->portals;
+// for (;p;p = p->next)
+// {
+// j++;
+// if (p->past->worldnodeframe != r_framecount)
+// i++;
+// }
+// if (i)
+// Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, j);
+}
+*/
+
+/*
+#define MAXRECURSIVEPORTALPLANES 1024
+#define MAXRECURSIVEPORTALS 256
+
+tinyplane_t portalplanes[MAXRECURSIVEPORTALPLANES];
+int portalplanestack[MAXRECURSIVEPORTALS];
+int portalplanecount;
+int ranoutofportalplanes;
+int ranoutofportals;
+int ranoutofleafs;
+int portalcantseeself;
+int portalrecursion;
+
+int R_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p)
+{
+ int i, outpoints, prevside, side;
+ float *prevpoint, prevdist, dist, dot;
+
+ if (inpoints < 3)
+ return inpoints;
+ // begin with the last point, then enter the loop with the first point as current
+ prevpoint = in + 3 * (inpoints - 1);
+ prevdist = DotProduct(prevpoint, p->normal) - p->dist;
+ prevside = prevdist >= 0 ? SIDE_FRONT : SIDE_BACK;
i = 0;
- j = 0;
- p = r_viewleaf->portals;
- for (;p;p = p->next)
+ outpoints = 0;
+ goto begin;
+ for (;i < inpoints;i++)
{
- j++;
- if (p->past->worldnodeframe != r_framecount)
- i++;
+ prevpoint = in;
+ prevdist = dist;
+ prevside = side;
+ in += 3;
+
+begin:
+ dist = DotProduct(in, p->normal) - p->dist;
+ side = dist >= 0 ? SIDE_FRONT : SIDE_BACK;
+
+ if (prevside == SIDE_FRONT)
+ {
+ if (outpoints >= maxoutpoints)
+ return -1;
+ VectorCopy(prevpoint, out);
+ out += 3;
+ outpoints++;
+ if (side == SIDE_FRONT)
+ continue;
+ }
+ else if (side == SIDE_BACK)
+ continue;
+
+ // generate a split point
+ if (outpoints >= maxoutpoints)
+ return -1;
+ dot = prevdist / (prevdist - dist);
+ out[0] = prevpoint[0] + dot * (in[0] - prevpoint[0]);
+ out[1] = prevpoint[1] + dot * (in[1] - prevpoint[1]);
+ out[2] = prevpoint[2] + dot * (in[2] - prevpoint[2]);
+ out += 3;
+ outpoints++;
+ }
+
+ return outpoints;
+}
+
+float portaltemppoints[2][256][3];
+float portaltemppoints2[256][3];
+
+int R_FrustumTestPolygon(float *points, int numpoints, int stride)
+{
+ int i;
+ float *out;
+ if (numpoints < 3)
+ return numpoints;
+ out = &portaltemppoints[0][0][0];
+ for (i = 0;i < numpoints;i++)
+ {
+ VectorCopy(points, portaltemppoints[0][i]);
+ (byte *)points += stride;
+ }
+ numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, (tinyplane_t *)&frustum[0]);
+ if (numpoints < 3)
+ return numpoints;
+ numpoints = R_ClipPolygonToPlane(&portaltemppoints[1][0][0], &portaltemppoints[0][0][0], numpoints, 256, (tinyplane_t *)&frustum[1]);
+ if (numpoints < 3)
+ return numpoints;
+ numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, (tinyplane_t *)&frustum[2]);
+ if (numpoints < 3)
+ return numpoints;
+ return R_ClipPolygonToPlane(&portaltemppoints[1][0][0], &portaltemppoints[0][0][0], numpoints, 256, (tinyplane_t *)&frustum[3]);
+}
+
+void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
+{
+ vec3_t v1, v2;
+ VectorSubtract(point1, point2, v1);
+ VectorSubtract(point3, point2, v2);
+ CrossProduct(v1, v2, p->normal);
+// VectorNormalize(p->normal);
+ VectorNormalizeFast(p->normal);
+ p->dist = DotProduct(point1, p->normal);
+}
+
+int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints)
+{
+ int numpoints, i;
+ if (targnumpoints < 3)
+ return targnumpoints;
+ if (maxpoints < 3)
+ return -1;
+ numpoints = targnumpoints;
+ memcpy(&portaltemppoints[0][0][0], targpoints, numpoints * 3 * sizeof(float));
+ for (i = 0;i < clipnumplanes;i++)
+ {
+ numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i);
+ if (numpoints < 3)
+ return numpoints;
+ memcpy(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float));
+ }
+ if (numpoints > maxpoints)
+ return -1;
+ memcpy(out, &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float));
+ return numpoints;
+}
+
+#define MAXRECURSIVEPORTALLEAFS 256
+
+//mleaf_t *leafstack[MAXRECURSIVEPORTALLEAFS];
+//int leafstackpos;
+int r_portalframecount;
+
+void R_RecursivePortalWorldNode (mleaf_t *leaf, int firstclipplane, int numclipplanes)
+{
+ mportal_t *p;
+
+// if (leafstackpos >= MAXRECURSIVEPORTALLEAFS)
+// {
+// ranoutofleafs = true;
+// return;
+// }
+
+// leafstack[leafstackpos++] = leaf;
+
+ if (leaf->visframe != r_framecount)
+ {
+ c_leafs++;
+ leaf->visframe = r_framecount;
+ if (leaf->nummarksurfaces)
+ {
+ msurface_t *surf, **mark, **endmark;
+ mark = leaf->firstmarksurface;
+ endmark = mark + leaf->nummarksurfaces;
+ do
+ {
+ surf = *mark++;
+ // make sure surfaces are only processed once
+ if (surf->worldnodeframe == r_framecount)
+ continue;
+ surf->worldnodeframe = r_framecount;
+ if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
+ {
+ if (surf->flags & SURF_PLANEBACK)
+ RSurf_DoVisible(surf);
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ RSurf_DoVisible(surf);
+ }
+ }
+ while (mark < endmark);
+ }
+ }
+
+ // follow portals into other leafs
+ for (p = leaf->portals;p;p = p->next)
+ {
+ int newpoints, i, prev;
+ vec3_t center;
+ vec3_t v1, v2;
+ tinyplane_t *newplanes;
+ // only flow through portals facing away from the viewer
+ if (PlaneDiff(r_origin, (&p->plane)) < 0)
+ {
+*/
+ /*
+ for (i = 0;i < leafstackpos;i++)
+ if (leafstack[i] == p->past)
+ break;
+ if (i < leafstackpos)
+ {
+ portalrecursion = true;
+ continue;
+ }
+ */
+/*
+ newpoints = R_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256);
+ if (newpoints < 3)
+ continue;
+ else if (firstclipplane + numclipplanes + newpoints > MAXRECURSIVEPORTALPLANES)
+ ranoutofportalplanes = true;
+ else
+ {
+ // go ahead and mark the leaf early, nothing can abort here
+ if (!r_testvis.value)
+ p->visframe = r_portalframecount;
+
+ // find the center by averaging
+ VectorClear(center);
+ for (i = 0;i < newpoints;i++)
+ VectorAdd(center, portaltemppoints2[i], center);
+ // ixtable is a 1.0f / N table
+ VectorScale(center, ixtable[newpoints], center);
+ // calculate the planes, and make sure the polygon can see it's own center
+ newplanes = &portalplanes[firstclipplane + numclipplanes];
+ for (prev = newpoints - 1, i = 0;i < newpoints;prev = i, i++)
+ {
+// R_TriangleToPlane(r_origin, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
+ VectorSubtract(r_origin, portaltemppoints2[i], v1);
+ VectorSubtract(portaltemppoints2[prev], portaltemppoints2[i], v2);
+ CrossProduct(v1, v2, newplanes[i].normal);
+ VectorNormalizeFast(newplanes[i].normal);
+ newplanes[i].dist = DotProduct(r_origin, newplanes[i].normal);
+ if (DotProduct(newplanes[i].normal, center) <= newplanes[i].dist)
+ {
+ // polygon can't see it's own center, discard and use parent portal
+ break;
+ }
+ }
+ if (i == newpoints)
+ R_RecursivePortalWorldNode(p->past, firstclipplane + numclipplanes, newpoints);
+ else
+ R_RecursivePortalWorldNode(p->past, firstclipplane, numclipplanes);
+ }
+ }
+ }
+// leafstackpos--;
+}
+
+//float viewportalpoints[16*3];
+
+*/
+
+int r_portalframecount = 0;
+
+/*
+void R_Portal_Callback(void *data, void *data2)
+{
+ mleaf_t *leaf = data;
+ if (!r_testvis.value)
+ ((mportal_t *)data2)->visframe = r_portalframecount;
+ if (leaf->visframe != r_framecount)
+ {
+ c_leafs++;
+ leaf->visframe = r_framecount;
}
- if (i)
- Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, j);
}
*/
-void R_PortalWorldNode (void)
+void R_PVSWorldNode()
+{
+ int i/*, l*/, k, c, row, numbits, bit, leafnum, numleafs;
+ mleaf_t *leaf;
+ msurface_t *surf, **mark, **endmark;
+ model_t *model = cl.worldmodel;
+ byte *in;
+// mportal_t *portal;
+ glpoly_t *p;
+ tinyplane_t plane;
+
+// c_leafs++;
+// r_viewleaf->visframe = r_framecount;
+ if (!r_testvis.value)
+ r_portalframecount++;
+
+ numleafs = model->numleafs;
+ numbits = numleafs - 1;
+ k = 0;
+ in = r_viewleaf->compressed_vis;
+ row = (numbits + 7) >> 3;
+ while (k < row)
+ {
+ c = *in++;
+ if (c)
+ {
+ for (i = 0, bit = 1;c;i++, bit <<= 1)
+ {
+ if (c & bit)
+ {
+ leafnum = (k << 3)+i+1;
+ if (leafnum >= numleafs)
+ return;
+ c -= bit;
+ leaf = &model->leafs[leafnum];
+ if (R_NotCulledBox(leaf->mins, leaf->maxs))
+ {
+ //for (portal = leaf->portals;portal;portal = portal->next)
+ // if (DotProduct(r_origin, portal->plane.normal) > portal->plane.dist)
+ // R_Clip_AddPolygon((float *)portal->points, portal->numpoints, sizeof(mvertex_t), false, R_Portal_Callback, leaf, portal, portal->plane);
+ //leaf->visframe = r_framecount;
+ c_leafs++;
+ 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)
+ {
+ VectorNegate(surf->plane->normal, plane.normal);
+ plane.dist = -surf->plane->dist;
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
+ }
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ for (p = surf->polys;p;p = p->next)
+ R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
+ }
+ }
+ while (mark < endmark);
+ }
+ }
+ }
+ }
+ k++;
+ }
+ else
+ k += *in++;
+ }
+}
+
+ /*
+ if (!r_testvis.value)
+ r_portalframecount = r_framecount;
+ portalplanecount = 0;
+// leafstackpos = 0;
+ ranoutofportalplanes = false;
+ ranoutofportals = false;
+ ranoutofleafs = false;
+ portalcantseeself = 0;
+ portalrecursion = false;
+ memcpy(&portalplanes[0], &frustum[0], sizeof(tinyplane_t));
+ memcpy(&portalplanes[1], &frustum[1], sizeof(tinyplane_t));
+ memcpy(&portalplanes[2], &frustum[2], sizeof(tinyplane_t));
+ memcpy(&portalplanes[3], &frustum[3], sizeof(tinyplane_t));
+ R_RecursivePortalWorldNode(r_viewleaf, 0, 4);
+ if (ranoutofportalplanes)
+ Con_Printf("R_RecursivePortalWorldNode: ran out of %d plane stack when recursing through portals\n", MAXRECURSIVEPORTALPLANES);
+ if (ranoutofportals)
+ Con_Printf("R_RecursivePortalWorldNode: ran out of %d portal stack when recursing through portals\n", MAXRECURSIVEPORTALS);
+ if (ranoutofleafs)
+ Con_Printf("R_RecursivePortalWorldNode: ran out of %d leaf stack when recursing through portals\n", MAXRECURSIVEPORTALLEAFS);
+// if (portalcantseeself)
+// Con_Printf("R_RecursivePortalWorldNode: %d portals could not see themself during clipping\n", portalcantseeself);
+ if (portalrecursion)
+ Con_Printf("R_RecursivePortalWorldNode: portal saw into previously encountered leaf??\n");
+ */
+
+/*
+void R_OldPortalWorldNode (void)
{
int portalstack, i;
mportal_t *p, *pstack[8192];
if (i)
Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, portalstack);
}
+*/
+
+entity_t clworldent;
void R_DrawSurfaces (void)
{
msurface_t *surf, *endsurf;
- texture_t *t;
+ texture_t *t, *currentt;
int vertex = gl_vertex.value;
+ currententity = &clworldent;
+ modelalpha = 1;
+ softwaretransformidentity();
surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
endsurf = surf + cl.worldmodel->nummodelsurfaces;
+ t = currentt = NULL;
for (;surf < endsurf;surf++)
{
if (surf->visframe == r_framecount)
if (surf->flags & SURF_DRAWSKY)
RSurf_DrawSky(surf, false);
else
- RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+ {
+ if (currentt != surf->texinfo->texture)
+ {
+ currentt = surf->texinfo->texture;
+ t = R_TextureAnimation(surf->texinfo->texture);
+ }
+ RSurf_DrawWater(surf, t, false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+ }
}
else
{
- t = R_TextureAnimation(surf->texinfo->texture);
+ if (currentt != surf->texinfo->texture)
+ {
+ currentt = surf->texinfo->texture;
+ t = R_TextureAnimation(surf->texinfo->texture);
+ }
if (vertex)
RSurf_DrawWallVertex(surf, t, false, false);
else
void R_DrawPortals(void)
{
int drawportals, i, r, g, b;
- mleaf_t *leaf, *endleaf;
- mportal_t *portal;
- mvertex_t *point, *endpoint;
+// mleaf_t *leaf, *endleaf;
+ mportal_t *portal, *endportal;
+ mvertex_t *point/*, *endpoint*/;
drawportals = (int)r_drawportals.value;
if (drawportals < 1)
return;
+ /*
leaf = cl.worldmodel->leafs;
endleaf = leaf + cl.worldmodel->numleafs;
for (;leaf < endleaf;leaf++)
}
}
}
+ */
+ portal = cl.worldmodel->portals;
+ endportal = portal + cl.worldmodel->numportals;
+ for (;portal < endportal;portal++)
+ {
+ if (portal->visframe == r_portalframecount)
+ {
+ i = portal - cl.worldmodel->portals;
+ r = (i & 0x0007) << 5;
+ g = (i & 0x0038) << 2;
+ b = (i & 0x01C0) >> 1;
+ transpolybegin(0, 0, 0, TPOLYTYPE_ALPHA);
+ point = portal->points;
+ if (PlaneDiff(r_origin, (&portal->plane)) > 0)
+ {
+ for (i = portal->numpoints - 1;i >= 0;i--)
+ transpolyvertub(point[i].position[0], point[i].position[1], point[i].position[2], 0, 0, r, g, b, 32);
+ }
+ else
+ {
+ for (i = 0;i < portal->numpoints;i++)
+ transpolyvertub(point[i].position[0], point[i].position[1], point[i].position[2], 0, 0, r, g, b, 32);
+ }
+ transpolyend();
+ }
+ }
}
/*
*/
void R_DrawWorld (void)
{
- entity_t ent;
-
wateralpha = bound(0, r_wateralpha.value*255.0f, 255);
+ vertexworld = gl_vertex.value;
- memset (&ent, 0, sizeof(ent));
- ent.render.model = cl.worldmodel;
- ent.render.colormod[0] = ent.render.colormod[1] = ent.render.colormod[2] = 1;
- modelalpha = ent.render.alpha = 1;
- ent.render.scale = 1;
+ memset (&clworldent, 0, sizeof(clworldent));
+ clworldent.render.model = cl.worldmodel;
+ clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1;
+ modelalpha = clworldent.render.alpha = 1;
+ clworldent.render.scale = 1;
VectorCopy (r_origin, modelorg);
- currententity = &ent;
+ currententity = &clworldent;
softwaretransformidentity(); // LordHavoc: clear transform
if (cl.worldmodel)
{
- if (r_viewleaf->contents == CONTENTS_SOLID)
+ if (r_novis.value || r_viewleaf->compressed_vis == NULL)
R_SolidWorldNode ();
else
{
- R_MarkLeaves ();
- R_PortalWorldNode ();
+// R_MarkLeaves ();
+ R_PVSWorldNode ();
}
}
-
- R_PushDlights (); // now mark the lit surfaces
-
- R_DrawSurfaces ();
-
- R_DrawPortals ();
}
/*
}
-mvertex_t *r_pcurrentvertbase;
-model_t *currentmodel;
-
-int nColinElim;
+//int nColinElim;
/*
================
BuildSurfaceDisplayList
================
*/
-void BuildSurfaceDisplayList (msurface_t *fa)
+void BuildSurfaceDisplayList (model_t *model, mvertex_t *vertices, msurface_t *fa)
{
int i, j, lindex, lnumverts;
- medge_t *pedges, *r_pedge;
- int vertpage;
+ medge_t *pedges;
float *vec;
float s, t;
glpoly_t *poly;
// reconstruct the polygon
- pedges = currentmodel->edges;
+ pedges = model->edges;
lnumverts = fa->numedges;
- vertpage = 0;
//
// draw texture
//
- poly = Hunk_AllocName (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float), "surfaces");
+ poly = Hunk_AllocName (sizeof(glpolysizeof_t) + lnumverts * sizeof(float[VERTEXSIZE]), "surfaces");
poly->next = fa->polys;
- poly->flags = fa->flags;
fa->polys = poly;
+// poly->flags = fa->flags;
poly->numverts = lnumverts;
for (i=0 ; i<lnumverts ; i++)
{
- lindex = currentmodel->surfedges[fa->firstedge + i];
+ lindex = model->surfedges[fa->firstedge + i];
if (lindex > 0)
- {
- r_pedge = &pedges[lindex];
- vec = r_pcurrentvertbase[r_pedge->v[0]].position;
- }
+ vec = vertices[pedges[lindex].v[0]].position;
else
- {
- r_pedge = &pedges[-lindex];
- vec = r_pcurrentvertbase[r_pedge->v[1]].position;
- }
+ vec = vertices[pedges[-lindex].v[1]].position;
+
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
// skip co-linear points
#define COLINEAR_EPSILON 0.001
if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
- (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
+ (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
(fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
{
int j;
--i;
}
}
+ poly->numverts = lnumverts;
}
*/
- poly->numverts = lnumverts;
}
/*
break;
if (m->name[0] == '*')
continue;
- r_pcurrentvertbase = m->vertexes;
- currentmodel = m;
for (i=0 ; i<m->numsurfaces ; i++)
{
if ( m->surfaces[i].flags & SURF_DRAWTURB )
if ( m->surfaces[i].flags & SURF_DRAWSKY )
continue;
GL_CreateSurfaceLightmap (m->surfaces + i);
- BuildSurfaceDisplayList (m->surfaces + i);
+ BuildSurfaceDisplayList (m, m->vertexes, m->surfaces + i);
}
}
// intermission is always full screen
if (cl.intermission)
- size = 120;
- else
- size = scr_viewsize.value;
-
- if (size >= 120)
- sb_lines = 0; // no status bar at all
- else if (size >= 110)
- sb_lines = 24; // no inventory
- else
- sb_lines = 24+16+8;
-
- if (scr_viewsize.value >= 100.0)
{
full = true;
- size = 100.0;
+ size = 1;
+ sb_lines = 0;
}
else
- size = scr_viewsize.value;
- if (cl.intermission)
{
- full = true;
- size = 100;
- sb_lines = 0;
+ if (scr_viewsize.value >= 120)
+ sb_lines = 0; // no status bar at all
+ else if (scr_viewsize.value >= 110)
+ sb_lines = 24; // no inventory
+ else
+ sb_lines = 24+16+8;
+
+ if (scr_viewsize.value >= 100.0)
+ {
+ full = true;
+ size = 1.0f;
+ }
+ else
+ size = scr_viewsize.value * (1.0f / 100.0f);
}
- size /= 100.0;
- // LordHavoc: always fullyscreen rendering
+ // LordHavoc: always fullscreen rendering
h = vid.height/* - sb_lines*/;
r_refdef.vrect.width = vid.width * size;
filename[2] = (i/1000)%10 + '0';
filename[3] = (i/ 100)%10 + '0';
filename[4] = (i/ 10)%10 + '0';
- filename[5] = (i/ 1)%10 + '0';
+ filename[5] = (i/ 1)%10 + '0';
sprintf (checkname, "%s/%s", com_gamedir, filename);
if (Sys_FileTime(checkname) == -1)
break; // file doesn't exist
// for (j=0 ; j<l ; j++, x+=8)
// Draw_Character (x, y, start[j]);
Draw_String (x, y, start, l);
-
+
y += 8;
while (*start && *start != '\n')
==================
*/
void GL_Finish(void);
+void R_Clip_DisplayBuffer(void);
void SCR_UpdateScreen (void)
{
double time1 = 0, time2;
GL_Set2D();
+ R_Clip_DisplayBuffer();
+
SCR_DrawRam();
SCR_DrawNet();
SCR_DrawTurtle();
Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999);
}
- if (r_speeds2.value)
+ // LordHavoc: only print info if renderer is being used
+ if (r_speeds2.value && cl.worldmodel != NULL)
{
- Draw_String(0, vid.height - sb_lines - 56, r_speeds2_string1, 80);
- Draw_String(0, vid.height - sb_lines - 48, r_speeds2_string2, 80);
- Draw_String(0, vid.height - sb_lines - 40, r_speeds2_string3, 80);
- Draw_String(0, vid.height - sb_lines - 32, r_speeds2_string4, 80);
- Draw_String(0, vid.height - sb_lines - 24, r_speeds2_string5, 80);
- Draw_String(0, vid.height - sb_lines - 16, r_speeds2_string6, 80);
- Draw_String(0, vid.height - sb_lines - 8, r_speeds2_string7, 80);
+ int i, j, lines, y;
+ lines = 1;
+ for (i = 0;r_speeds2_string[i];i++)
+ if (r_speeds2_string[i] == '\n')
+ lines++;
+ y = vid.height - sb_lines - lines * 8 - 8;
+ i = j = 0;
+ while (r_speeds2_string[i])
+ {
+ j = i;
+ while (r_speeds2_string[i] && r_speeds2_string[i] != '\n')
+ i++;
+ if (i - j > 0)
+ Draw_String(0, y, r_speeds2_string + j, i - j);
+ if (r_speeds2_string[i] == '\n')
+ i++;
+ y += 8;
+ }
}
V_UpdateBlends();
inrow = (int *)indata + inwidth*(i*inheight/outheight);
frac = fracstep >> 1;
j = outwidth - 4;
- while(j >= 0)
+ while (j >= 0)
{
out[0] = inrow[frac >> 16];frac += fracstep;
out[1] = inrow[frac >> 16];frac += fracstep;
out[2] = inrow[frac >> 16];frac += fracstep;
out[3] = inrow[frac >> 16];frac += fracstep;
out += 4;
- j--;
+ j -= 4;
}
if (j & 2)
{
if (!identifier[0])
Host_Error("R_LoadTexture: no identifier\n");
+ if (data == NULL)
+ Host_Error("R_LoadTexture: \"%s\" has no data\n", identifier);
// clear the alpha flag if the texture has no transparent pixels
if (flags & TEXF_ALPHA)
//====================================================
-extern entity_t r_worldentity;
extern qboolean r_cache_thrash; // compatability
extern vec3_t modelorg, r_entorigin;
extern entity_t *currententity;
//#endif
#endif
-
-// LordHavoc: vertex transform
-#include "transform.h"
-
-// LordHavoc: transparent polygon system
-#include "gl_poly.h"
-
-#define gl_solid_format 3
-#define gl_alpha_format 4
-
-//#define PARANOID
-
-// LordHavoc: was a major time waster
-#define R_CullBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) == 2 || frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) == 2 || frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) == 2 || frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) == 2)
-#define R_NotCulledBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) != 2 && frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) != 2 && frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) != 2 && frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) != 2)
-
-extern qboolean fogenabled;
-extern vec3_t fogcolor;
-extern vec_t fogdensity;
-//#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2]))))
-#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0])*((v)[0] - r_origin[0])+((v)[1] - r_origin[1])*((v)[1] - r_origin[1])+((v)[2] - r_origin[2])*((v)[2] - r_origin[2])))))
-#define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255)))
-
-#include "r_modules.h"
-
-extern qboolean lighthalf;
-
-#include "r_lerpanim.h"
-
-void GL_LockArray(int first, int count);
-void GL_UnlockArray(void);
-
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap);
-
-extern cvar_t r_render;
-extern cvar_t r_upload;
-#include "image.h"
return false;
}
- host_realframetime = host_frametime = realtime - oldrealtime; // LordHavoc: copy into host_realframetime as well
+ // LordHavoc: copy into host_realframetime as well
+ host_realframetime = host_frametime = realtime - oldrealtime;
oldrealtime = realtime;
if (cls.timedemo)
- return true; // disable time effects
+ {
+ // disable time effects
+ cl.frametime = host_frametime;
+ return true;
+ }
if (host_framerate.value > 0)
host_frametime = host_framerate.value;
str = Qgetline (f);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++) {
str = Qgetline (f);
- sscanf (str, "%f", &spawn_parms[i]);
+ sscanf (str, "%f\n", &spawn_parms[i]);
}
// this silliness is so we can load 1.06 save files, which have float skill values
str = Qgetline (f);
Cvar_SetValue ("skill", (float)current_skill);
strcpy (mapname, Qgetline (f));
- mapname[strlen (mapname) -1] = 0; // strip trailing \n
str = Qgetline (f);
sscanf (str, "%f\n",&time);
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
str = Qgetline (f);
- str[strlen (str) -1] = 0; // strip trailing \n
sv.lightstyles[i] = Hunk_AllocName (strlen(str)+1, "lightstyles");
strcpy (sv.lightstyles[i], str);
}
}
}
outofdata:;
-
+
image_width = columns;
image_height = rows;
- free(f);
+ qfree(f);
return image_rgba;
}
{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
-{0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
+{0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
{-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
-{-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
+{-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
VectorClear(n) // FIXME: complain?
}
+float Q_RSqrt(float number)
+{
+ float y;
+
+ if (number == 0.0f)
+ return 0.0f;
+
+ *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
+ return y * (1.5f - (number * 0.5f * y * y));
+}
+
+void _VectorNormalizeFast(vec3_t v)
+{
+ float y, number;
+
+ number = DotProduct(v, v);
+
+ if (number != 0.0)
+ {
+ *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
+ y = y * (1.5f - (number * 0.5f * y * y));
+
+ VectorScale(v, y, v);
+ }
+}
+
#if 0
// LordHavoc: no longer used at all
void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
}
}
+void PlaneClassify(mplane_t *p)
+{
+ if (p->normal[0] == 1)
+ p->type = 0;
+ else if (p->normal[1] == 1)
+ p->type = 1;
+ else if (p->normal[2] == 1)
+ p->type = 2;
+ else
+ p->type = 3;
+ BoxOnPlaneSideClassify(p);
+}
+
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
{
float angle;
{
int i;
float length;
-
+
length = 0;
for (i=0 ; i< 3 ; i++)
length += v[i]*v[i];
}
-void VectorInverse (vec3_t v)
+void _VectorInverse (vec3_t v)
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
-void VectorScale (vec3_t in, vec_t scale, vec3_t out)
+void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
{
out[0] = in[0]*scale;
out[1] = in[1]*scale;
#define VectorDistance2(a, b) ((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2]))
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
#define VectorLength(a) sqrt(DotProduct(a, a))
-#define VectorScaleQuick(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);}
+#define VectorScale(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);}
#define VectorMAQuick(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];}
+#define VectorNormalizeFast(_v)\
+{\
+ float _y, _number;\
+ _number = DotProduct(_v, _v);\
+ if (_number != 0.0)\
+ {\
+ *((long *)&_y) = 0x5f3759df - ((* (long *) &_number) >> 1);\
+ _y = _y * (1.5f - (_number * 0.5f * _y * _y));\
+ VectorScale(_v, _y, _v);\
+ }\
+}\
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
vec_t Length (vec3_t v);
float VectorNormalizeLength (vec3_t v); // returns vector length
float VectorNormalizeLength2 (vec3_t v, vec3_t dest); // returns vector length
-void VectorInverse (vec3_t v);
-void VectorScale (vec3_t in, vec_t scale, vec3_t out);
+void _VectorInverse (vec3_t v);
+void _VectorScale (vec3_t in, vec_t scale, vec3_t out);
int Q_log2(int val);
+void _VectorNormalizeFast (vec3_t v);
+
+float Q_RSqrt(float number);
#define NUMVERTEXNORMALS 162
extern float m_bytenormals[NUMVERTEXNORMALS][3];
// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up);
-void BoxOnPlaneSideClassify(struct mplane_s *p);
+void PlaneClassify(struct mplane_s *p);
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \
#define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal))
#define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
+//#define PlaneDist(point,plane) (DotProduct((point), (plane)->normal))
+//#define PlaneDiff(point,plane) (DotProduct((point), (plane)->normal) - (plane)->dist)
#define lhrandom(MIN,MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN))
#define min(A,B) (A < B ? A : B)
#define max(A,B) (A > B ? A : B)
#endif
+
+// LordHavoc: minimal plane structure
+typedef struct
+{
+ float normal[3], dist;
+} tinyplane_t;
+
+typedef struct
+{
+ double normal[3], dist;
+} tinydoubleplane_t;
//=============================================================================
/* OPTIONS MENU */
-#define OPTIONS_ITEMS 23
+#define OPTIONS_ITEMS (vid_menudrawfn ? 23 : 22)
#define SLIDER_RANGE 10
M_Print(16, y, " Use Mouse");M_DrawCheckbox(220, y, vid_mouse.value);y += 8;
M_Print(16, y, " Crosshair");M_DrawSlider(220, y, crosshair.value / 5);y += 8;
M_Print(16, y, " Show Framerate");M_DrawCheckbox(220, y, showfps.value);y += 8;
- M_Print(16, y, " Video Options");y += 8;
+ if (vid_menudrawfn)
+ M_Print(16, y, " Video Options");
+ y += 8;
// cursor
M_DrawCharacter(200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
Cbuf_AddText ("exec default.cfg\n");
break;
case 22:
- M_Menu_Video_f ();
+ if (vid_menudrawfn)
+ M_Menu_Video_f ();
break;
default:
M_AdjustSliders (1);
&& (out->texinfo->texture->name[2] == 'y' || out->texinfo->texture->name[2] == 'Y'))
{
// LordHavoc: for consistency reasons, mark sky as fullbright and solid as well
- out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+ out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
+
+ out->flags |= SURF_CLIPSOLID;
}
}
mplane_t *out;
dplane_t *in;
int count;
- int bits;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
for ( i=0 ; i<count ; i++, in++, out++)
{
- bits = 0;
for (j=0 ; j<3 ; j++)
- {
out->normal[j] = LittleFloat (in->normal[j]);
-// if (out->normal[j] < 0)
-// bits |= 1<<j;
- }
out->dist = LittleFloat (in->dist);
- out->type = LittleLong (in->type);
-// out->signbits = bits;
- BoxOnPlaneSideClassify(out);
+ // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal?
+// out->type = LittleLong (in->type);
+ PlaneClassify(out);
}
}
VectorCopy(p->winding->points[j], point->position);
point++;
}
+ PlaneClassify(&portal->plane);
// link into leaf's portal chain
portal->next = portal->here->portals;
VectorCopy(p->winding->points[j], point->position);
point++;
}
+ PlaneClassify(&portal->plane);
// link into leaf's portal chain
portal->next = portal->here->portals;
#define SURF_DRAWTILED 0x20
#define SURF_DRAWBACKGROUND 0x40
//#define SURF_UNDERWATER 0x80
-// LordHavoc: added these for lava and teleport textures
#define SURF_DRAWNOALPHA 0x100
#define SURF_DRAWFULLBRIGHT 0x200
-// LordHavoc: light both sides
-#define SURF_LIGHTBOTHSIDES 0x400
+#define SURF_LIGHTBOTHSIDES 0x400
+#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons
typedef struct
{
} mtexinfo_t;
// LordHavoc: was 7, I added one more for raw lightmap position
+// (xyz st uv l)
#define VERTEXSIZE 8
typedef struct glpoly_s
{
struct glpoly_s *next;
- struct glpoly_s *chain;
int numverts;
- int flags; // for SURF_UNDERWATER
- float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
+ float verts[4][VERTEXSIZE]; // variable sized
} glpoly_t;
+typedef struct glpolysizeof_s
+{
+ struct glpoly_s *next;
+ int numverts;
+ int flags; // for SURF_UNDERWATER
+} glpolysizeof_t;
+
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
-
+
short texturemins[2];
short extents[2];
glpoly_t *polys; // multiple if warped
mtexinfo_t *texinfo;
-
+
// lighting info
int dlightframe;
int dlightbits[8];
// node specific
mplane_t *plane;
- struct mnode_s *children[2];
+ struct mnode_s *children[2];
unsigned short firstsurface;
unsigned short numsurfaces;
struct mportal_s *portals;
// 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 visframe; // visible if current (r_framecount)
+// int worldnodeframe; // used by certain worldnode variants to avoid processing the same leaf twice in a frame
// for bounding box culling
vec3_t mins;
mvertex_t *points;
int numpoints;
mplane_t plane;
+ int visframe; // is this portal visible this frame?
}
mportal_t;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
func_t function;
int _int;
int edict;
-} eval_t;
+} eval_t;
+
+typedef struct link_s
+{
+ struct link_s *prev, *next;
+} link_t;
// LordHavoc: increased number of leafs per entity limit from 16 to 256
#define MAX_ENT_LEAFS 256
typedef struct edict_s
{
qboolean free;
- link_t area; // linked to a division node or leaf
-
+ link_t area;
+
int num_leafs;
short leafnums[MAX_ENT_LEAFS];
entity_state_t baseline;
entity_state_t deltabaseline; // LordHavoc: previous frame
-
+
float freetime; // sv.time when the object was freed
// LordHavoc: for MOVETYPE_STEP interpolation
vec3_t steporigin;
entvars_t v; // C exported fields from progs
// other fields from progs come immediately after
} edict_t;
-#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
+//#define EDICT_FROM_AREA(l) ((edict_t *)((byte *)l - (int)&(((edict_t *)0)->area)))
+//#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
// LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... see pr_edict.c for the functions which use these.
extern int eval_gravity;
#define svc_showlmp 35 // [string] slotname [string] lmpfilename [short] x [short] y
#define svc_hidelmp 36 // [string] slotname
+#define svc_skybox 37 // [string] skyname
#define svc_unusedlh1
#define svc_fog 51 // unfinished
return 0;
len = strlen (buf);
- while (buf[len - 1] != '\n') {
+ while (buf[len - 1] != '\n' && buf[len - 1] != '\r') {
char *t = realloc (buf, size + 256);
if (!t)
- return 0;
+ Host_Error("Qgetline: realloc failed, out of memory?\n");
buf = t;
size += 256;
if (!Qgets (file, buf + len, size - len))
break;
len = strlen (buf);
}
+ while ((len = strlen(buf)) && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
+ buf[len - 1] = 0;
return buf;
}
#ifndef __quakeio_h
#define __quakeio_h
-#define HAVE_ZLIB
+//#define HAVE_ZLIB
#ifdef HAVE_CONFIG_H
# include "config.h"
--- /dev/null
+
+#include "quakedef.h"
+
+typedef struct clipsurf_s
+{
+ struct clipsurf_s *next, *prev;
+ int state;
+ int visible;
+ int solid;
+ int removed;
+ void (*callback)(void *nativedata, void *nativedata2);
+ void *nativedata;
+ void *nativedata2;
+ float wstepx, wstepy, w00;
+ // wcurrent is a cached copy of w00 + wstepy * y,
+ // updated each time the surface is added to the stack,
+ // for quicker comparisons.
+ float wcurrent;
+ // this is a linked list of all edges belonging to this surface,
+ // used to remove them if this is a non-solid surface that is
+ // marked visible (it can not hide anything, so it is useless)
+// struct clipedge_s *edgechain;
+}
+clipsurf_t;
+
+typedef struct clipedge_s
+{
+ float x, realx, realxstep;
+ struct clipedge_s *next, *prev, *nextremove;
+ clipsurf_t *psurf;
+ int leading;
+ int pad;
+}
+clipedge_t;
+
+clipsurf_t *pavailsurf, *clipsurfs, *clipsurfsend;
+clipedge_t *pavailedge, *clipedges, *clipedgesend, *newedges, **removeedges;
+
+clipsurf_t surfstack;
+clipedge_t edgehead, edgetail;
+clipedge_t maxedge = {2000000000.0f};
+
+cvar_t r_clipwidth = {"r_clipwidth", "800"};
+cvar_t r_clipheight = {"r_clipheight", "600"};
+cvar_t r_clipedges = {"r_clipedges", "32768", true};
+cvar_t r_clipsurfaces = {"r_clipsurfaces", "8192", true};
+
+int clipwidth = 0, clipheight = 0;
+int maxclipsurfs = 0, maxclipedges = 0;
+int needededges, neededsurfs;
+
+#if CLIPTEST
+typedef struct
+{
+ float w; // inverse depth (1/z)
+}
+clippixel_t;
+
+clippixel_t *clipbuffer;
+#endif
+
+float r_clip_viewmatrix[3][3], r_clip_viewmulx, r_clip_viewmuly, r_clip_viewcenterx, r_clip_viewcentery;
+// REMOVELATER
+//float xscale, yscale, xscaleinv, yscaleinv;
+//float r_clip_nearclipdist, r_clip_nearclipdist2;
+tinyplane_t r_clip_viewplane[5];
+
+void R_Clip_MakeViewMatrix(void)
+{
+ float pixelaspect, screenaspect, horizontalfieldofview, verticalfieldofview;
+ pixelaspect = (float) clipheight / (float) clipwidth * 320 / 240.0;
+ horizontalfieldofview = 2.0 * tan (r_refdef.fov_x/360*M_PI);
+ screenaspect = clipwidth * pixelaspect / clipheight;
+ verticalfieldofview = horizontalfieldofview / screenaspect;
+ r_clip_viewcenterx = clipwidth * 0.5 - 0.5;
+ r_clip_viewcentery = clipheight * 0.5 - 0.5;
+ r_clip_viewmulx = clipwidth / horizontalfieldofview;
+ r_clip_viewmuly = r_clip_viewmulx * pixelaspect;
+ // this constructs a transposed rotation matrix for the view (transposed matrices do the opposite of their normal behavior)
+ VectorCopy (vright, r_clip_viewmatrix[0]);
+ VectorNegate (vup, r_clip_viewmatrix[1]);
+ VectorCopy (vpn, r_clip_viewmatrix[2]);
+// r_clip_nearclipdist = DotProduct(r_origin, vpn) + 4.0f;
+// r_clip_nearclipdist2 = r_clip_nearclipdist - 8.0f;
+ VectorCopy (vpn, r_clip_viewplane[0].normal);
+ r_clip_viewplane[0].dist = DotProduct(r_origin, vpn);
+ memcpy(&r_clip_viewplane[1], &frustum[0], sizeof(tinyplane_t));
+ memcpy(&r_clip_viewplane[2], &frustum[1], sizeof(tinyplane_t));
+ memcpy(&r_clip_viewplane[3], &frustum[2], sizeof(tinyplane_t));
+ memcpy(&r_clip_viewplane[4], &frustum[3], sizeof(tinyplane_t));
+// REMOVELATER
+// maxscreenscaleinv = (1.0f / max(clipwidth, clipheight)) * horizontalfieldofview * 0.5f;
+// xscale = clipwidth / horizontalfieldofview;
+// xscaleinv = 1.0 / xscale;
+// yscale = xscale * pixelaspect;
+// yscaleinv = 1.0 / yscale;
+}
+
+void R_Clip_StartFrame(void)
+{
+ int i;
+ int newwidth, newheight, newmaxedges, newmaxsurfs;
+ newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2);
+ newheight = bound(60, (int) r_clipheight.value, vid.height * 2);
+ newmaxedges = bound(128, (int) r_clipedges.value, 262144);
+ newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536);
+ if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs)
+ {
+#if CLIPTEST
+ if (clipbuffer)
+ qfree(clipbuffer);
+#endif
+ if (clipedges)
+ qfree(clipedges);
+ if (clipsurfs)
+ qfree(clipsurfs);
+ if (newedges)
+ qfree(newedges);
+ if (removeedges)
+ qfree(removeedges);
+ clipwidth = newwidth;
+ clipheight = newheight;
+ maxclipedges = newmaxedges;
+ maxclipsurfs = newmaxsurfs;
+#if CLIPTEST
+ clipbuffer = qmalloc(clipwidth * clipheight * sizeof(clippixel_t));
+#endif
+ clipedges = qmalloc(maxclipedges * sizeof(clipedge_t));
+ clipsurfs = qmalloc(maxclipsurfs * sizeof(clipsurf_t));
+ newedges = qmalloc(clipheight * sizeof(clipedge_t));
+ removeedges = qmalloc(clipheight * sizeof(clipedge_t *));
+ clipedgesend = clipedges + maxclipedges;
+ clipsurfsend = clipsurfs + maxclipsurfs;
+ }
+#if CLIPTEST
+ memset(clipbuffer, 0, clipwidth * clipheight * sizeof(clippixel_t));
+#endif
+ pavailedge = clipedges;
+ pavailsurf = clipsurfs;
+ // Clear the lists of edges to add and remove on each scan line.
+
+ needededges = 0;
+ neededsurfs = 0;
+ for (i = 0;i < clipheight;i++)
+ {
+ newedges[i].next = &maxedge;
+ removeedges[i] = NULL;
+ }
+
+ R_Clip_MakeViewMatrix();
+}
+
+void ScanEdges (void);
+
+void R_Clip_EndFrame(void)
+{
+ ScanEdges();
+ if (maxclipedges < needededges)
+ {
+ Con_Printf("R_Clip: ran out of edges, increasing limit from %d to %d\n", maxclipedges, needededges);
+ Cvar_SetValue("r_clipedges", needededges);
+ }
+ if (maxclipsurfs < neededsurfs)
+ {
+ Con_Printf("R_Clip: ran out of surfaces, increasing limit from %d to %d\n", maxclipsurfs, neededsurfs);
+ Cvar_SetValue("r_clipsurfaces", neededsurfs);
+ }
+}
+
+void r_clip_start(void)
+{
+}
+
+void r_clip_shutdown(void)
+{
+#if CLIPTEST
+ if (clipbuffer)
+ qfree(clipbuffer);
+ clipbuffer = NULL;
+#endif
+ if (clipsurfs)
+ qfree(clipsurfs);
+ clipsurfs = NULL;
+ if (clipedges)
+ qfree(clipedges);
+ clipedges = NULL;
+ if (newedges)
+ qfree(newedges);
+ newedges = NULL;
+ if (removeedges)
+ qfree(removeedges);
+ removeedges = NULL;
+ clipwidth = -1;
+ clipheight = -1;
+}
+
+void r_clip_newmap(void)
+{
+}
+
+void R_Clip_Init(void)
+{
+ Cvar_RegisterVariable(&r_clipwidth);
+ Cvar_RegisterVariable(&r_clipheight);
+ Cvar_RegisterVariable(&r_clipedges);
+ Cvar_RegisterVariable(&r_clipsurfaces);
+ R_RegisterModule("R_Clip", r_clip_start, r_clip_shutdown, r_clip_newmap);
+}
+
+int R_Clip_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
+{
+ float y, number;
+ vec3_t v1, v2;
+ VectorSubtract(point1, point2, v1);
+ VectorSubtract(point3, point2, v2);
+ CrossProduct(v1, v2, p->normal);
+ number = DotProduct(p->normal, p->normal);
+ if (number >= 0.1f)
+ {
+ *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
+ y = y * (1.5f - (number * 0.5f * y * y));
+ VectorScale(p->normal, y, p->normal);
+ p->dist = DotProduct(point1, p->normal);
+ return true;
+ }
+ else
+ return false;
+}
+
+/*
+int R_Clip_TriangleToDoublePlane(double *point1, double *point2, double *point3, tinydoubleplane_t *p)
+{
+ double y, number;
+ double v1[3], v2[3];
+ VectorSubtract(point1, point2, v1);
+ VectorSubtract(point3, point2, v2);
+ CrossProduct(v1, v2, p->normal);
+ number = DotProduct(p->normal, p->normal);
+ if (number >= 0.1)
+ {
+ y = 1.0 / sqrt(number);
+ VectorScale(p->normal, y, p->normal);
+ p->dist = DotProduct(point1, p->normal);
+ return true;
+ }
+ else
+ return false;
+}
+*/
+
+int R_Clip_ClipPolygonToPlane(float *in, float *out, int inpoints, int stride, tinyplane_t *plane)
+{
+ int i, outpoints, prevside, side;
+ float *prevpoint, prevdist, dist, dot;
+
+ // begin with the last point, then enter the loop with the first point as current
+ prevpoint = (float *) ((byte *)in + stride * (inpoints - 1));
+ prevdist = DotProduct(prevpoint, plane->normal) - plane->dist;
+ prevside = prevdist >= 0 ? SIDE_FRONT : SIDE_BACK;
+ i = 0;
+ outpoints = 0;
+ goto begin;
+ for (;i < inpoints;i++)
+ {
+ prevpoint = in;
+ prevdist = dist;
+ prevside = side;
+ (byte *)in += stride;
+
+begin:
+ dist = DotProduct(in, plane->normal) - plane->dist;
+ side = dist >= 0 ? SIDE_FRONT : SIDE_BACK;
+
+ if (prevside == SIDE_FRONT)
+ {
+ VectorCopy(prevpoint, out);
+ out += 3;
+ outpoints++;
+ if (side == SIDE_FRONT)
+ continue;
+ }
+ else if (side == SIDE_BACK)
+ continue;
+
+ // generate a split point
+ dot = prevdist / (prevdist - dist);
+ out[0] = prevpoint[0] + dot * (in[0] - prevpoint[0]);
+ out[1] = prevpoint[1] + dot * (in[1] - prevpoint[1]);
+ out[2] = prevpoint[2] + dot * (in[2] - prevpoint[2]);
+ out += 3;
+ outpoints++;
+ }
+
+ return outpoints;
+}
+
+float tempverts[256][3];
+float tempverts2[256][3];
+float screenverts[256][3];
+
+// LordHavoc: this code is based primarily on the ddjzsort code
+
+// Clips polygon to view frustum and nearclip, transforms polygon to viewspace, perspective projects polygon to screenspace,
+// and adds polygon's edges to the global edge table.
+void R_Clip_AddPolygon (vec_t *points, int numverts, int stride, int solid, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2, tinyplane_t *polyplane)
+{
+ float deltax, deltay, vx, vy, vz, fx;
+ int i, j, k, nextvert, temp, topy, bottomy, height, addededges;
+ clipedge_t *pedge;
+// tinydoubleplane_t plane;
+ tinyplane_t localplane;
+// tinyplane_t testplane;
+ float distinv;
+
+// if (!solid)
+// return;
+
+ if (polyplane == NULL)
+ {
+ polyplane = &localplane;
+ // calculate the plane for the polygon
+ if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), polyplane))
+ {
+ for (i = 0;i < numverts;i++)
+ for (j = i + 1;j < numverts;j++)
+ for (k = j + 1;k < numverts;k++)
+ if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), polyplane))
+ goto valid1;
+ return; // gave up
+ valid1:;
+ }
+
+ // caller hasn't checked if this polygon faces the view, so we have to check
+ if (DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f))
+ return;
+ }
+#if 0 // debugging (validates planes passed in)
+ else
+ {
+ // calculate the plane for the polygon
+ if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), &localplane))
+ {
+ for (i = 0;i < numverts;i++)
+ for (j = i + 1;j < numverts;j++)
+ for (k = j + 1;k < numverts;k++)
+ if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), &localplane))
+ goto valid4;
+ return; // gave up
+ valid4:;
+ }
+
+// if ((DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f)) != (DotProduct(r_origin, localplane.normal) < (localplane.dist + 0.5f)))
+ if (DotProduct(polyplane->normal, localplane.normal) < 0.9f)
+ {
+ Con_Printf("*\n");
+ return;
+ }
+ }
+#endif
+
+ // for adaptive limits
+ needededges += numverts;
+ neededsurfs++;
+
+ if (pavailsurf >= clipsurfsend)
+ return;
+
+ // clip to view frustum and nearclip
+ if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(points , tempverts2[0], numverts, stride, &r_clip_viewplane[0]);
+ if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[1]);
+ if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[2]);
+ if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[3]);
+ if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[4]);
+ if (numverts < 3)
+ return;
+ if (numverts > 256)
+ Sys_Error("R_Clip_AddPolygon: polygon exceeded 256 vertex buffer\n");
+
+ // it survived the clipping, transform to viewspace and project to screenspace
+
+ if (pavailedge + numverts > clipedgesend)
+ return;
+
+#if 1
+ for (i = 0;i < numverts;i++)
+ {
+ vx = tempverts2[i][0] - r_origin[0];
+ vy = tempverts2[i][1] - r_origin[1];
+ vz = tempverts2[i][2] - r_origin[2];
+ screenverts[i][2] = 1.0f / (r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz);
+ screenverts[i][0] = (r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz) * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx;
+ screenverts[i][1] = (r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz) * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery;
+ }
+
+ /*
+ if (polyplane != NULL)
+ {
+ */
+ /*
+ distinv = 1.0f / (polyplane->dist - DotProduct(r_origin, polyplane->normal));
+ pavailsurf->wstepx = DotProduct(r_clip_viewmatrix[0], polyplane->normal) * xscaleinv * distinv;
+ pavailsurf->wstepy = DotProduct(r_clip_viewmatrix[1], polyplane->normal) * yscaleinv * distinv;
+ pavailsurf->w00 = DotProduct(r_clip_viewmatrix[2], polyplane->normal) * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy;
+ */
+ /*
+ }
+ else
+ {
+ */
+ // calculate the plane for the polygon
+ if (!R_Clip_TriangleToPlane(screenverts[0], screenverts[1], screenverts[2], &localplane))
+ {
+ for (i = 0;i < numverts;i++)
+ for (j = i + 1;j < numverts;j++)
+ for (k = j + 1;k < numverts;k++)
+ if (R_Clip_TriangleToPlane(screenverts[i], screenverts[j], screenverts[k], &localplane))
+ goto valid;
+ return; // gave up
+ valid:;
+ }
+
+ // Set up the 1/z gradients from the polygon, calculating the
+ // base value at screen coordinate 0,0 so we can use screen
+ // coordinates directly when calculating 1/z from the gradients
+ distinv = 1.0f / localplane.normal[2];
+ pavailsurf->wstepx = -(localplane.normal[0] * distinv);
+ pavailsurf->wstepy = -(localplane.normal[1] * distinv);
+ pavailsurf->w00 = localplane.dist * distinv;
+ /*
+ }
+ */
+ // REMOVELATER
+ /*
+ prevdist = z1 * plane.normal[2] - plane.dist;
+ dist = z2 * plane.normal[2] - plane.dist;
+ d = prevdist / (prevdist - dist);
+ zc = z1 + d * (z2 - z1);
+
+ prevdist = plane.normal[0] + z1 * plane.normal[2] - plane.dist;
+ dist = plane.normal[0] + z2 * plane.normal[2] - plane.dist;
+ d = prevdist / (prevdist - dist);
+ zx = (z1 + d * (z2 - z1)) - zc;
+
+ prevdist = plane.normal[1] + z1 * plane.normal[2] - plane.dist;
+ dist = plane.normal[1] + z2 * plane.normal[2] - plane.dist;
+ d = prevdist / (prevdist - dist);
+ zy = (z1 + d * (z2 - z1)) - zc;
+ */
+
+ /*
+ zc = (-plane.dist) / ((-plane.dist) - (plane.normal[2] - plane.dist));
+ zx = ((plane.normal[0] - plane.dist) / ((plane.normal[0] - plane.dist) - (plane.normal[0] + plane.normal[2] - plane.dist))) - zc;
+ zy = ((plane.normal[1] - plane.dist) / ((plane.normal[1] - plane.dist) - (plane.normal[1] + plane.normal[2] - plane.dist))) - zc;
+ */
+
+// zc = (plane.dist / plane.normal[2]);
+// zx = -(plane.normal[0] / plane.normal[2]);
+// zy = -(plane.normal[1] / plane.normal[2]);
+// zy = ((plane.normal[1] - plane.dist) / (-plane.normal[2])) + ((plane.dist) / (-plane.normal[2]));
+#else // REMOVELATER
+ for (i = 0;i < numverts;i++)
+ {
+ vx = tempverts2[i][0] - r_origin[0];
+ vy = tempverts2[i][1] - r_origin[1];
+ vz = tempverts2[i][2] - r_origin[2];
+ screenverts[i][0] = r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz;
+ screenverts[i][1] = r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz;
+ screenverts[i][2] = r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz;
+ }
+
+ // REMOVELATER
+ // calculate the plane for the polygon
+ for (i = 0;i < numverts;i++)
+ for (j = i + 1;j < numverts;j++)
+ for (k = j + 1;k < numverts;k++)
+ if (R_Clip_TriangleToDoublePlane(screenverts[i], screenverts[j], screenverts[k], &plane))
+ goto valid2;
+ return; // gave up
+valid2:;
+
+ distinv = 1.0f / plane.dist;
+ pavailsurf->d_zistepx = plane.normal[0] * xscaleinv * distinv;
+ pavailsurf->d_zistepy = -plane.normal[1] * yscaleinv * distinv;
+ pavailsurf->d_ziorigin = plane.normal[2] * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy;
+
+ for (i = 0;i < numverts;i++)
+ {
+ screenverts[i][2] = 1.0f / (screenverts[i][2]);
+ screenverts[i][0] = screenverts[i][0] * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx;
+ screenverts[i][1] = screenverts[i][1] * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery;
+ // REMOVELATER
+// if (screenverts[i][0] < -0.5)
+// screenverts[i][0] = -0.5;
+// if (screenverts[i][0] > (clipwidth - 0.5))
+// screenverts[i][0] = clipwidth - 0.5;
+// if (screenverts[i][1] < -0.5)
+// screenverts[i][1] = -0.5;
+// if (screenverts[i][1] > (clipheight - 0.5))
+// screenverts[i][1] = clipheight - 0.5;
+// if (screenverts[i][2] <= 0.0)
+// Con_Printf("R_Clip_AddPolygon: vertex z <= 0!\n");
+ }
+#endif
+
+ addededges = false;
+
+ // Add each edge in turn
+ for (i = 0;i < numverts;i++)
+ {
+ nextvert = i + 1;
+ if (nextvert >= numverts)
+ nextvert = 0;
+
+ topy = (int)ceil(screenverts[i][1]);
+ bottomy = (int)ceil(screenverts[nextvert][1]);
+ height = bottomy - topy;
+ if (height == 0)
+ continue; // doesn't cross any scan lines
+ if (height < 0)
+ {
+ // Leading edge
+ temp = topy;
+ topy = bottomy;
+ bottomy = temp;
+ if (topy < 0)
+ topy = 0;
+ if (bottomy > clipheight)
+ bottomy = clipheight;
+ if (topy >= bottomy)
+ continue;
+
+ pavailedge->leading = 1;
+
+ deltax = screenverts[i][0] - screenverts[nextvert][0];
+ deltay = screenverts[i][1] - screenverts[nextvert][1];
+
+ pavailedge->realxstep = deltax / deltay;
+ pavailedge->realx = screenverts[nextvert][0] + ((float)topy - screenverts[nextvert][1]) * pavailedge->realxstep;
+ }
+ else
+ {
+ // Trailing edge
+ if (topy < 0)
+ topy = 0;
+ if (bottomy > clipheight)
+ bottomy = clipheight;
+ if (topy >= bottomy)
+ continue;
+
+ pavailedge->leading = 0;
+
+ deltax = screenverts[nextvert][0] - screenverts[i][0];
+ deltay = screenverts[nextvert][1] - screenverts[i][1];
+
+ pavailedge->realxstep = deltax / deltay;
+ pavailedge->realx = screenverts[i][0] + ((float)topy - screenverts[i][1]) * pavailedge->realxstep;
+ }
+
+ // Put the edge on the list to be added on top scan
+ fx = pavailedge->x = bound(0.0f, pavailedge->realx, clipwidth - 0.5f);
+ pedge = &newedges[topy];
+ while (fx > pedge->next->x)
+ pedge = pedge->next;
+ pavailedge->next = pedge->next;
+ pedge->next = pavailedge;
+
+ // Put the edge on the list to be removed after final scan
+ pavailedge->nextremove = removeedges[bottomy - 1];
+ removeedges[bottomy - 1] = pavailedge;
+
+ // Associate the edge with the surface
+ pavailedge->psurf = pavailsurf;
+
+ pavailedge++;
+
+ addededges = true;
+ }
+
+ if (!addededges)
+ return;
+
+ // Create the surface, so we'll know how to sort and draw from the edges
+ pavailsurf->next = NULL;
+ pavailsurf->prev = NULL;
+ pavailsurf->state = 0;
+ pavailsurf->visible = false;
+ pavailsurf->callback = callback;
+ pavailsurf->nativedata = nativedata;
+ pavailsurf->nativedata2 = nativedata2;
+ pavailsurf->solid = solid;
+ pavailsurf->removed = false;
+ pavailsurf++;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Scan all the edges in the global edge table into spans.
+/////////////////////////////////////////////////////////////////////
+void ScanEdges (void)
+{
+ int y, rescan;
+ float fx, fy, w, w2, clipwidthf = clipwidth - 0.5f;
+ clipedge_t *pedge, *pedge2, *ptemp;
+ clipsurf_t *psurf, *psurf2;
+#if CLIPTEST
+ int x, x2;
+ float zi;
+ clippixel_t *cb;
+#endif
+ float cx;
+
+ // Set up the active edge list as initially empty, containing
+ // only the sentinels (which are also the background fill). Most
+ // of these fields could be set up just once at start-up
+ edgehead.next = &edgetail;
+ edgehead.prev = NULL;
+ edgehead.x = edgehead.realx = -0.9999f; // left edge of screen
+ edgehead.realxstep = 0;
+ edgehead.leading = 1;
+ edgehead.psurf = &surfstack;
+
+ edgetail.next = NULL; // mark end of list
+ edgetail.prev = &edgehead;
+ edgetail.x = edgetail.realx = clipwidth + 0.5f; // right edge of screen
+ edgetail.realxstep = 0;
+ edgetail.leading = 0;
+ edgetail.psurf = &surfstack;
+
+ // The background surface is the entire stack initially, and
+ // is infinitely far away, so everything sorts in front of it.
+ // This could be set just once at start-up
+ surfstack.solid = true;
+ surfstack.visible = true; // no callback
+ surfstack.next = surfstack.prev = &surfstack;
+ surfstack.wcurrent = surfstack.w00 = -999999.0;
+ surfstack.wstepx = surfstack.wstepy = 0.0;
+ surfstack.removed = false;
+
+ // rescan causes the edges to be compared at the span level
+ // it is false if the scanline will be identical to the previous
+ rescan = true;
+ for (y = 0;y < clipheight;y++)
+ {
+ fy = y;
+#if CLIPTEST
+ cb = clipbuffer + y * clipwidth;
+#endif
+
+ // Sort in any edges that start on this scan
+ if (newedges[y].next != &maxedge)
+ {
+ rescan = true;
+ pedge = newedges[y].next;
+ pedge2 = &edgehead;
+ while (pedge != &maxedge)
+ {
+ if (pedge->psurf->removed)
+ {
+ pedge = pedge->next;
+ continue;
+ }
+
+ while (pedge->x > pedge2->next->x)
+ pedge2 = pedge2->next;
+
+ ptemp = pedge->next;
+ pedge->next = pedge2->next;
+ pedge->prev = pedge2;
+ pedge2->next->prev = pedge;
+ pedge2->next = pedge;
+
+ pedge2 = pedge;
+ pedge = ptemp;
+ }
+ }
+
+ // Scan out the active edges into spans
+
+ // Start out with the left background edge already inserted, and the surface stack containing only the background
+ surfstack.state = 1;
+ cx = 0;
+
+ // must always rescan if rendering to wbuffer
+#ifndef CLIPTEST
+// if (rescan)
+#endif
+ {
+ for (pedge = edgehead.next;pedge;pedge = pedge->next)
+ {
+ edgeremoved:
+ psurf = pedge->psurf;
+ if (psurf->removed)
+ {
+ pedge2 = pedge->next;
+ pedge->prev->next = pedge->next;
+ pedge->next->prev = pedge->prev;
+ pedge->next = pedge->prev = pedge;
+ pedge = pedge2;
+ if (pedge)
+ goto edgeremoved;
+ else
+ break;
+ }
+
+ if (pedge->leading)
+ {
+ // It's a leading edge. Figure out where it is
+ // relative to the current surfaces and insert in
+ // the surface stack; if it's on top, emit the span
+ // for the current top.
+ // First, make sure the edges don't cross
+ if (++psurf->state == 1)
+ {
+ fx = pedge->x;
+ // Calculate the surface's 1/z value at this pixel, and cache the y depth for quick compares later
+ w = (psurf->wcurrent = psurf->w00 + psurf->wstepy * fy) + psurf->wstepx * fx;
+// if (w < 0)
+// w = 0;
+
+ // See if that makes it a new top surface
+ psurf2 = surfstack.next;
+ w2 = psurf2->wcurrent + psurf2->wstepx * fx;
+// if (w2 < 0 && psurf2 != &surfstack)
+// w2 = 0;
+
+ if (w >= w2)
+ {
+ // It's a new top surface
+ // emit the span for the current top
+ if (fx > cx && !psurf2->visible)
+ {
+ psurf2->visible = true;
+ psurf2->callback(psurf2->nativedata, psurf2->nativedata2);
+ }
+
+#if CLIPTEST
+ for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf2->wcurrent + psurf2->wstepx * x;x < x2;x++, zi += psurf2->wstepx)
+ cb[x].w = zi;
+#endif
+
+ cx = fx;
+
+ // Add the edge to the stack
+ psurf->next = psurf2;
+ psurf2->prev = psurf;
+ surfstack.next = psurf;
+ psurf->prev = &surfstack;
+ }
+ else
+ {
+ // Not a new top; sort into the surface stack.
+ // Guaranteed to terminate due to sentinel background surface
+ do
+ {
+ psurf2 = psurf2->next;
+ w2 = psurf2->wcurrent + psurf2->wstepx * fx;
+// if (w2 < 0 && psurf2 != &surfstack)
+// w2 = 0;
+ }
+ while (w < w2);
+
+ // Insert the surface into the stack
+ psurf->next = psurf2;
+ psurf->prev = psurf2->prev;
+ psurf2->prev->next = psurf;
+ psurf2->prev = psurf;
+ }
+ }
+ }
+ else
+ {
+ // It's a trailing edge; if this was the top surface,
+ // emit the span and remove it.
+ // First, make sure the edges didn't cross
+ if (--psurf->state == 0)
+ {
+ if (surfstack.next == psurf)
+ {
+ fx = pedge->x;
+
+ // It's on top, emit the span
+ if (fx > cx && !psurf->visible)
+ {
+ psurf->visible = true;
+ psurf->callback(psurf->nativedata, psurf->nativedata2);
+ }
+
+#if CLIPTEST
+ fx = pedge->x;
+ for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf->w00 + psurf->wstepx * x + psurf->wstepy * fy;x < x2;x++, zi += psurf->wstepx)
+ cb[x].w = zi;
+#endif
+
+ cx = fx;
+ }
+
+ // Remove the surface from the stack
+ psurf->next->prev = psurf->prev;
+ psurf->prev->next = psurf->next;
+ }
+ }
+
+ // mark and remove all non-solid surfaces that are ontop
+ while (!surfstack.next->solid)
+ {
+ psurf = surfstack.next;
+ if (!psurf->visible)
+ {
+ psurf->visible = true;
+ psurf->callback(psurf->nativedata, psurf->nativedata2);
+ }
+ psurf->removed = true;
+ psurf->next->prev = psurf->prev;
+ psurf->prev->next = psurf->next;
+ // isolate the surface
+ psurf->next = psurf->prev = psurf;
+ }
+ }
+ rescan = false;
+ }
+
+ // Remove edges that are done
+ pedge = removeedges[y];
+ if (pedge)
+ {
+ while (pedge)
+ {
+ if (!pedge->psurf->removed)
+ {
+ pedge->prev->next = pedge->next;
+ pedge->next->prev = pedge->prev;
+ if (pedge->psurf->visible)
+ rescan = true;
+ }
+ pedge = pedge->nextremove;
+ }
+ }
+
+ // Step the remaining edges one scan line, and re-sort
+ for (pedge = edgehead.next;pedge != &edgetail;)
+ {
+ ptemp = pedge->next;
+ if (pedge->psurf->removed)
+ {
+ pedge->next->prev = pedge->prev;
+ pedge->prev->next = pedge->next;
+ pedge->next = pedge->prev = pedge;
+ pedge = ptemp;
+ continue;
+ }
+
+ // Step the edge
+ if (pedge->realxstep)
+ {
+ pedge->realx += pedge->realxstep;
+ pedge->x = bound(0.0f, pedge->realx, clipwidthf);
+ }
+ fx = pedge->x;
+
+ // Move the edge back to the proper sorted location, if necessary
+ while (fx < pedge->prev->x)
+ {
+ if (!rescan && (pedge->psurf->solid || pedge->prev->psurf->solid))
+ rescan = true;
+ pedge2 = pedge->prev;
+ pedge2->next = pedge->next;
+ pedge->next->prev = pedge2;
+ pedge2->prev->next = pedge;
+ pedge->prev = pedge2->prev;
+ pedge->next = pedge2;
+ pedge2->prev = pedge;
+ }
+
+ pedge = ptemp;
+ }
+ }
+}
+
+void R_Clip_DisplayBuffer(void)
+{
+#if CLIPTEST
+ int i;
+ static int firstupload = true;
+ byte clipbuffertex[256*256], *b;
+ if (!r_render.value)
+ return;
+ if (clipwidth > 256 || clipheight > 256)
+ return;
+ glBlendFunc(GL_ONE, GL_ONE);
+ glBindTexture(GL_TEXTURE_2D, 8000);
+ if (firstupload)
+ {
+ memset(clipbuffertex, 0, sizeof(clipbuffertex));
+ glTexImage2D(GL_TEXTURE_2D, 0, 1, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
+ }
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ if (lighthalf)
+ glColor3f(0.5, 0.5, 0.5);
+ else
+ glColor3f(1, 1, 1);
+ firstupload = false;
+ b = clipbuffertex;
+ for (i = 0;i < clipwidth*clipheight;i++)
+ {
+ if (clipbuffer[i].w > 0)
+ *b++ = bound(0, (int) (clipbuffer[i].w * 4096.0f), 255);
+ else
+ *b++ = 0;
+ }
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
+ glBegin (GL_QUADS);
+ glTexCoord2f (0 , 0 );glVertex2f (0 , 0 );
+ glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.width, 0 );
+ glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height);
+ glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.height);
+ glEnd ();
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+}
+
+float boxpoints[4*3];
+
+#define R_Clip_MinsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \
+{\
+ if (r_origin[(axis)] < ((axisvalue) - 0.5f))\
+ {\
+ (plane)->dist = -axisvalue;\
+ boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\
+ boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\
+ boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\
+ boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\
+ R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\
+ }\
+}
+
+#define R_Clip_MaxsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \
+{\
+ if (r_origin[(axis)] > ((axisvalue) + 0.5f))\
+ {\
+ (plane)->dist = axisvalue;\
+ boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\
+ boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\
+ boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\
+ boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\
+ R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\
+ }\
+}
+
+tinyplane_t clipboxplane[6] =
+{
+ {{-1, 0, 0}, 0},
+ {{ 1, 0, 0}, 0},
+ {{ 0, -1, 0}, 0},
+ {{ 0, 1, 0}, 0},
+ {{ 0, 0, -1}, 0},
+ {{ 0, 0, 1}, 0},
+};
+
+void R_Clip_AddBox(float *a, float *b, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2)
+{
+ if (r_origin[0] >= (a[0] - 5.0f) && r_origin[0] < (b[0] + 5.0f)
+ && r_origin[1] >= (a[1] - 5.0f) && r_origin[1] < (b[1] + 5.0f)
+ && r_origin[2] >= (a[2] - 5.0f) && r_origin[2] < (b[2] + 5.0f))
+ {
+ callback(nativedata, nativedata2);
+ return;
+ }
+
+ if (R_CullBox(a, b))
+ return;
+
+ R_Clip_MinsBoxPolygon
+ (
+ 0, a[0],
+ a[0], a[1], a[2],
+ a[0], b[1], a[2],
+ a[0], b[1], b[2],
+ a[0], a[1], b[2],
+ callback, nativedata, nativedata2, &clipboxplane[0]
+ );
+ R_Clip_MaxsBoxPolygon
+ (
+ 0, b[0],
+ b[0], b[1], a[2],
+ b[0], a[1], a[2],
+ b[0], a[1], b[2],
+ b[0], b[1], b[2],
+ callback, nativedata, nativedata2, &clipboxplane[1]
+ );
+ R_Clip_MinsBoxPolygon
+ (
+ 1, a[1],
+ b[0], a[1], a[2],
+ a[0], a[1], a[2],
+ a[0], a[1], b[2],
+ b[0], a[1], b[2],
+ callback, nativedata, nativedata2, &clipboxplane[2]
+ );
+ R_Clip_MaxsBoxPolygon
+ (
+ 1, b[1],
+ a[0], b[1], a[2],
+ b[0], b[1], a[2],
+ b[0], b[1], b[2],
+ a[0], b[1], b[2],
+ callback, nativedata, nativedata2, &clipboxplane[3]
+ );
+ R_Clip_MinsBoxPolygon
+ (
+ 2, a[2],
+ a[0], a[1], a[2],
+ b[0], a[1], a[2],
+ b[0], b[1], a[2],
+ a[0], b[1], a[2],
+ callback, nativedata, nativedata2, &clipboxplane[4]
+ );
+ R_Clip_MaxsBoxPolygon
+ (
+ 2, b[2],
+ b[0], a[1], b[2],
+ a[0], a[1], b[2],
+ a[0], b[1], b[2],
+ b[0], b[1], b[2],
+ callback, nativedata, nativedata2, &clipboxplane[5]
+ );
+}
--- /dev/null
+
+void R_Clip_StartFrame(void);
+void R_Clip_EndFrame(void);
+//int R_Clip_Polygon(float *inv, int numpoints, int stride, int solid);
+//int R_Clip_Portal(float *inv, int numpoints, int stride);
+// This takes a polygon in the form of vec_t triplets, at a caller specified
+// stride (structure size), it can be solid (obscures other geometry) or not,
+// a callback and two parameters must be provided (will be called if it is
+// determined visible), and a plane can be provided (this also indicates that
+// the surface is not a backface, so if a plane is provided, the caller must
+// check that it is not a backface, it is not likely to be fatal if the caller
+// does not, but it is inadvisable)
+void R_Clip_AddPolygon (vec_t *points, int numverts, int stride, int solid, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2, tinyplane_t *polyplane);
+void R_Clip_AddBox(float *mins, float *maxs, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2);
R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
}
-int lightframe = 0;
void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
{
+ static int lightframe = 0;
mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
if (!r_dynamic.value)
lightframe++;
- radius = light->radius * 2;
+ radius = light->radius * 3;
// clamp radius to avoid exceeding 32768 entry division table
if (radius > 2048)
if (c & (1<<i))
{
leaf = &model->leafs[(k << 3)+i+1];
- if (leaf->visframe != r_framecount)
- continue;
- if (leaf->contents == CONTENTS_SOLID)
- continue;
+// if (leaf->visframe != r_framecount)
+// continue;
+// if (leaf->contents == CONTENTS_SOLID)
+// continue;
// if out of the light radius, skip
if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0]
|| leaf->mins[1] > high[1] || leaf->maxs[1] < low[1]
do
{
surf = *mark++;
- if (surf->visframe != r_framecount || surf->lightframe == lightframe)
+ // if not visible in current frame, or already marked because it was in another leaf we passed, skip
+ if (surf->lightframe == lightframe)
continue;
surf->lightframe = lightframe;
+ if (surf->visframe != r_framecount)
+ continue;
dist = PlaneDiff(lightorigin, surf->plane);
if (surf->flags & SURF_PLANEBACK)
dist = -dist;
// LordHavoc: make sure it is infront of the surface and not too far away
- if ((dist >= -0.25f || (surf->flags & SURF_LIGHTBOTHSIDES)) && dist < radius)
+ if (dist < radius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -radius)))
{
int d;
float dist2, impact[3];
// R_MarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel->nodes );
R_VisMarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel);
}
+
+
}
lightmap += size3;
}
+ /*
+ // LordHavoc: here's the readable version of the interpolation
+ // code, not quite as easy for the compiler to optimize...
+
+ // dsfrac is the X position in the lightmap pixel, * 16
+ // dtfrac is the Y position in the lightmap pixel, * 16
+ // r00 is top left corner, r01 is top right corner
+ // r10 is bottom left corner, r11 is bottom right corner
+ // g and b are the same layout.
+ // r0 and r1 are the top and bottom intermediate results
+
+ // first we interpolate the top two points, to get the top
+ // edge sample
+ r0 = (((r01-r00) * dsfrac) >> 4) + r00;
+ g0 = (((g01-g00) * dsfrac) >> 4) + g00;
+ b0 = (((b01-b00) * dsfrac) >> 4) + b00;
+ // then we interpolate the bottom two points, to get the
+ // bottom edge sample
+ r1 = (((r11-r10) * dsfrac) >> 4) + r10;
+ g1 = (((g11-g10) * dsfrac) >> 4) + g10;
+ b1 = (((b11-b10) * dsfrac) >> 4) + b10;
+ // then we interpolate the top and bottom samples to get the
+ // middle sample (the one which was requested)
+ r = (((r1-r0) * dtfrac) >> 4) + r0;
+ g = (((g1-g0) * dtfrac) >> 4) + g0;
+ b = (((b1-b0) * dtfrac) >> 4) + b0;
+ */
+
color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f);
color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f);
color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f);
float scale, scale2, minparticledist;
byte *color24;
vec3_t uprightangles, up2, right2, tempcolor, corner;
- mleaf_t *leaf;
+// mleaf_t *leaf;
// LordHavoc: early out condition
if ((!numparticles) || (!r_drawparticles.value))
continue;
// LordHavoc: check if it's in a visible leaf
- leaf = Mod_PointInLeaf(p->org, cl.worldmodel);
- if (leaf->visframe != r_framecount)
- continue;
+// leaf = Mod_PointInLeaf(p->org, cl.worldmodel);
+// if (leaf->visframe != r_framecount)
+// continue;
/*
if (p->type == pt_decal)
#include "quakedef.h"
+void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, vec3_t origin, vec3_t up, vec3_t right)
+{
+ int i;
+ mspriteframe_t *frame;
+ vec3_t points[4];
+ float fleft, fright, fdown, fup;
+ frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame;
+ fleft = frame->left;
+ fdown = frame->down;
+ fright = frame->right;
+ fup = frame->up;
+ for (i = 1;i < 4 && blend[i].lerp;i++)
+ {
+ frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[i].frame;
+ fleft = min(fleft , frame->left );
+ fdown = min(fdown , frame->down );
+ fright = max(fright, frame->right);
+ fup = max(fup , frame->up );
+ }
+ points[0][0] = origin[0] + fdown * up[0] + fleft * right[0];points[0][1] = origin[1] + fdown * up[1] + fleft * right[1];points[0][2] = origin[2] + fdown * up[2] + fleft * right[2];
+ points[1][0] = origin[0] + fup * up[0] + fleft * right[0];points[1][1] = origin[1] + fup * up[1] + fleft * right[1];points[1][2] = origin[2] + fup * up[2] + fleft * right[2];
+ points[2][0] = origin[0] + fup * up[0] + fright * right[0];points[2][1] = origin[1] + fup * up[1] + fright * right[1];points[2][2] = origin[2] + fup * up[2] + fright * right[2];
+ points[3][0] = origin[0] + fdown * up[0] + fright * right[0];points[3][1] = origin[1] + fdown * up[1] + fright * right[1];points[3][2] = origin[2] + fdown * up[2] + fright * right[2];
+ R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, e, NULL, NULL);
+}
+
+void R_ClipSprite (entity_t *e, frameblend_t *blend)
+{
+ vec3_t right, up, org;
+ msprite_t *psprite;
+
+ if (!blend[0].lerp)
+ return;
+
+ psprite = Mod_Extradata(e->render.model);
+
+ if (psprite->type == SPR_ORIENTED)
+ {
+ // bullet marks on walls
+ vec3_t forward;
+ AngleVectors (e->render.angles, forward, right, up);
+ // nudge it toward the view, so it will be infront of the wall
+ VectorSubtract(e->render.origin, vpn, org);
+ // don't draw if it's a backface
+ if (DotProduct(r_origin, forward) < (DotProduct(org, forward) + 1.0f))
+ return;
+ }
+ else
+ {
+ // normal sprite
+ VectorCopy(vup, up);
+ VectorCopy(vright, right);
+ VectorCopy(e->render.origin, org);
+ // don't draw if it's a backface
+ if (DotProduct(org, vpn) < (DotProduct(r_origin, vpn) + 1.0f))
+ return;
+ }
+
+
+ if (e->render.scale != 1)
+ {
+ VectorScale(up, e->render.scale, up);
+ VectorScale(right, e->render.scale, right);
+ }
+
+ // LordHavoc: interpolated sprite rendering
+ R_ClipSpriteImage(e, psprite, blend, org, up, right);
+}
+
void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha)
{
byte alphaub;
alphaub = bound(0, alpha, 255);
transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
- transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub);
- transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub);
- transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
+ transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub);
+ transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub);
+ transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
transpolyvertub(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alphaub);
transpolyend();
}
/*
=================
R_DrawSpriteModel
-
=================
*/
void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
{
- vec3_t right, up, org, color, mins, maxs;
- byte colorub[4];
- msprite_t *psprite;
+ vec3_t right, up, org, color, mins, maxs;
+ byte colorub[4];
+ msprite_t *psprite;
+
+ if (!blend[0].lerp)
+ return;
VectorAdd (e->render.origin, e->render.model->mins, mins);
VectorAdd (e->render.origin, e->render.model->maxs, maxs);
- if (R_VisibleCullBox (mins, maxs))
- return;
+// if (R_CullBox (mins, maxs))
+// return;
c_sprites++;
if (psprite->type == SPR_ORIENTED)
{ // bullet marks on walls
- AngleVectors (e->render.angles, NULL, right, up);
+ vec3_t forward;
+ AngleVectors (e->render.angles, forward, right, up);
VectorSubtract(e->render.origin, vpn, org);
+ if (DotProduct(r_origin, forward) < DotProduct(e->render.origin, forward))
+ return; // backface
}
else
{ // normal sprite
VectorCopy(vright, right);
VectorCopy(e->render.origin, org);
}
+
if (e->render.scale != 1)
{
VectorScale(up, e->render.scale, up);
// render profiling stuff
extern qboolean intimerefresh;
extern cvar_t r_speeds2;
-extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81];
+extern char r_speeds2_string[1024];
// lighting stuff
extern vec3_t lightspot;
// model transform stuff
extern cvar_t gl_transform;
+// LordHavoc: 1.0f / N table
+extern float ixtable[4096];
+
#define TOP_RANGE 16 // soldier uniform colors
#define BOTTOM_RANGE 96
// LordHavoc: changed this for sake of GLQuake
void R_InitSky (byte *src, int bytesperpixel); // called at level load
-int R_VisibleCullBox (vec3_t mins, vec3_t maxs);
+//int R_VisibleCullBox (vec3_t mins, vec3_t maxs);
void R_NewMap (void);
void R_MoveParticles (void);
void R_DrawExplosions (void);
void R_MoveExplosions (void);
+
+#include "r_clip.h"
+
+// LordHavoc: vertex transform
+#include "transform.h"
+
+// LordHavoc: transparent polygon system
+#include "gl_poly.h"
+
+#define gl_solid_format 3
+#define gl_alpha_format 4
+
+//#define PARANOID
+
+// LordHavoc: was a major time waster
+#define R_CullBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) == 2 || frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) == 2 || frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) == 2 || frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) == 2)
+#define R_NotCulledBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) != 2 && frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) != 2 && frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) != 2 && frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) != 2)
+
+extern qboolean fogenabled;
+extern vec3_t fogcolor;
+extern vec_t fogdensity;
+//#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2]))))
+#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0])*((v)[0] - r_origin[0])+((v)[1] - r_origin[1])*((v)[1] - r_origin[1])+((v)[2] - r_origin[2])*((v)[2] - r_origin[2])))))
+#define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255)))
+
+#include "r_modules.h"
+
+extern qboolean lighthalf;
+
+#include "r_lerpanim.h"
+
+void GL_LockArray(int first, int count);
+void GL_UnlockArray(void);
+
+void R_DrawBrushModel (entity_t *e);
+void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap);
+void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
+
+void R_ClipSprite (entity_t *e, frameblend_t *blend);
+void R_Entity_Callback(void *data, void *junk);
+
+extern cvar_t r_render;
+extern cvar_t r_upload;
+#include "image.h"
switch (mmap_control->status.status) {
case SND_PCM_STATUS_PREPARED:
if ((rc=snd_pcm_channel_go(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) {
- Qprintf(stderr, "unable to start playback. %s\n",
+ fprintf(stderr, "unable to start playback. %s\n",
snd_strerror(rc));
exit(1);
}
break;
case SND_PCM_STATUS_UNDERRUN:
if ((rc=snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) {
- Qprintf(stderr, "underrun: playback channel prepare error. %s\n",
+ fprintf(stderr, "underrun: playback channel prepare error. %s\n",
snd_strerror(rc));
exit(1);
}
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
- ent->v.angles[0] = ent->v.angles[1] = ent->v.angles[2] = 0;
if (coop.value)
pr_global_struct->coop = coop.value;
ED_LoadFromFile (sv.worldmodel->entities);
// LordHavoc: clear world angles (to fix e3m3.bsp)
- sv.edicts->v.angles[0] = sv.edicts->v.angles[1] = sv.edicts->v.angles[2] = 0;
+ VectorClear(sv.edicts->v.angles);
sv.active = true;
{
int i;
vec3_t wishvel;
- float speed, newspeed, wishspeed, addspeed, accelspeed;
+ float speed, newspeed, wishspeed, addspeed, accelspeed, temp;
//
// user intentions
wishspeed = Length(wishvel);
if (wishspeed > sv_maxspeed.value)
{
- VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
+ temp = sv_maxspeed.value/wishspeed;
+ VectorScale (wishvel, temp, wishvel);
wishspeed = sv_maxspeed.value;
}
wishspeed *= 0.7;
{
newspeed = speed - sv.frametime * speed * sv_friction.value;
if (newspeed < 0)
- newspeed = 0;
- VectorScale (velocity, newspeed/speed, velocity);
+ newspeed = 0;
+ temp = newspeed/speed;
+ VectorScale (velocity, temp, velocity);
}
else
newspeed = 0;
{
int i;
vec3_t wishvel;
- float fmove, smove;
+ float fmove, smove, temp;
// LordHavoc: correct quake movement speed bug when looking up/down
wishvel[0] = wishvel[2] = 0;
wishspeed = VectorNormalizeLength(wishdir);
if (wishspeed > sv_maxspeed.value)
{
- VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
+ temp = sv_maxspeed.value/wishspeed;
+ VectorScale (wishvel, temp, wishvel);
wishspeed = sv_maxspeed.value;
}
umask (0);
- handle = open(path,O_RDWR | O_CREAT | O_TRUNC
- , 0666);
+ handle = open(path,O_RDWR | O_CREAT | O_TRUNC, 0666);
if (handle == -1)
- Sys_Error ("Error opening %s: %s", path,strerror(errno));
+ {
+ Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno));
+ return 0;
+ }
return handle;
}
f = Qopen(path, "wb");
if (!f)
- Host_Error ("Error opening %s: %s", path,strerror(errno));
+ {
+ Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno));
+ return 0;
+ }
sys_handles[i] = f;
return i;
static double oldtime = 0.0, basetime = 0.0, old = 0.0;
double newtime, now;
- now = (double) timeGetTime () - basetime;
+ now = (double) timeGetTime () + basetime;
if (first)
{
if (now < old)
{
// wrapped
- basetime -= (65536.0 * 65536.0);
+ basetime += (65536.0 * 65536.0);
now += (65536.0 * 65536.0);
}
old = now;
angles[2] = e->render.angles[2];
softwaretransformset(e->render.origin, angles, e->render.scale);
}
+
+// brush entities are not backwards like models and sprites are
+void softwaretransformforbrushentity (entity_t *e)
+{
+ softwaretransformset(e->render.origin, e->render.angles, e->render.scale);
+}
extern int softwaretransform_type;
extern void softwaretransformforentity (entity_t *e);
+extern void softwaretransformforbrushentity (entity_t *e);
extern void softwaretransformidentity (void);
extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale);
extern void (*softwaretransform) (vec3_t in, vec3_t out);
*/
// vid.h -- video driver defs
-#define VID_CBITS 6
-#define VID_GRADES (1 << VID_CBITS)
-
-// a pixel can be one, two, or four bytes
-typedef byte pixel_t;
-
typedef struct vrect_s
{
int x,y,width,height;
typedef struct
{
- unsigned width;
- unsigned height;
- float aspect; // width / height -- < 0 is taller than wide
- int recalc_refdef; // if true, recalc vid-based stuff
- unsigned conwidth;
- unsigned conheight;
+ int width;
+ int height;
+ int recalc_refdef; // if true, recalc vid-based stuff
+ int conwidth;
+ int conheight;
} viddef_t;
extern viddef_t vid; // global video state
vid.width = vid.conwidth;
vid.height = vid.conheight;
- vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
-
InitSig(); // trap evil signals
GL_Init();
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
viddef_t vid; // global video state
static qboolean mouse_avail = true;
-static qboolean mouse_active = false;
+static qboolean mouse_active = false, usingmouse = false;
// static qboolean dga_active;
static float mouse_x, mouse_y;
static float old_mouse_x, old_mouse_y;
static int p_mouse_x, p_mouse_y;
-static cvar_t in_mouse = {"in_mouse", "1", false};
-static cvar_t in_dga = {"in_dga", "1", false};
-static cvar_t in_dga_mouseaccel = {"in_dga_mouseaccel", "1", false};
-static cvar_t m_filter = {"m_filter", "0"};
+cvar_t vid_dga = {"vid_dga", "1", true};
+cvar_t vid_dga_mouseaccel = {"vid_dga_mouseaccel", "1", false};
+cvar_t m_filter = {"m_filter", "0"};
qboolean vidmode_ext = false;
keysym = XLookupKeysym(ev, 0);
- switch(keysym) {
+ switch(keysym)
+ {
case XK_KP_Page_Up: key = KP_PGUP; break;
case XK_Page_Up: key = K_PGUP; break;
case XK_F35: key = K_PGDN; break;
default:
- if (keysym < 128) {
+ if (keysym < 128)
+ {
/* ASCII keys */
key = keysym;
- if (/*!modified && */((key >= 'A') && (key <= 'Z'))) {
+ if (/*!modified && */((key >= 'A') && (key <= 'Z')))
key = key + ('a' - 'A');
- }
}
break;
}
static Cursor CreateNullCursor(Display *display, Window root)
{
- Pixmap cursormask;
- XGCValues xgc;
- GC gc;
- XColor dummycolour;
- Cursor cursor;
-
- cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
- xgc.function = GXclear;
- gc = XCreateGC(display, cursormask, GCFunction, &xgc);
- XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
- dummycolour.pixel = 0;
- dummycolour.red = 0;
- dummycolour.flags = 04;
- cursor = XCreatePixmapCursor(display, cursormask, cursormask,
- &dummycolour,&dummycolour, 0,0);
- XFreePixmap(display,cursormask);
- XFreeGC(display,gc);
- return cursor;
+ Pixmap cursormask;
+ XGCValues xgc;
+ GC gc;
+ XColor dummycolour;
+ Cursor cursor;
+
+ cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
+ xgc.function = GXclear;
+ gc = XCreateGC(display, cursormask, GCFunction, &xgc);
+ XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
+ dummycolour.pixel = 0;
+ dummycolour.red = 0;
+ dummycolour.flags = 04;
+ cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0);
+ XFreePixmap(display,cursormask);
+ XFreeGC(display,gc);
+ return cursor;
}
static void install_grabs(void)
{
- XWindowAttributes attribs_1;
- XSetWindowAttributes attribs_2;
+ XWindowAttributes attribs_1;
+ XSetWindowAttributes attribs_2;
- XGetWindowAttributes(dpy, win, &attribs_1);
- attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
- XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2);
+ XGetWindowAttributes(dpy, win, &attribs_1);
+ attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
+ XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2);
// inviso cursor
XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
- XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync,
- win, None, CurrentTime);
+ XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
- if (in_dga.value) {
+ if (vid_dga.value)
+ {
int MajorVersion, MinorVersion;
- if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
+ if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion))
+ {
// unable to query, probalby not supported
Con_Printf( "Failed to detect XF86DGA Mouse\n" );
- in_dga.value = 0;
- } else {
- in_dga.value = 1;
+ vid_dga.value = 0;
+ }
+ else
+ {
+ vid_dga.value = 1;
XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
}
- } else {
- XWarpPointer(dpy, None, win,
- 0, 0, 0, 0,
- vid.width / 2, vid.height / 2);
}
+ else
+ XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
if (!dpy || !win)
return;
- if (in_dga.value == 1) {
+ if (vid_dga.value == 1)
XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
- }
XUngrabPointer(dpy, CurrentTime);
XUngrabKeyboard(dpy, CurrentTime);
{
XEvent event;
// KeySym ks;
- int b;
qboolean dowarp = false;
if (!dpy)
return;
- while (XPending(dpy)) {
+ while (XPending(dpy))
+ {
XNextEvent(dpy, &event);
- switch (event.type) {
+ switch (event.type)
+ {
case KeyPress:
case KeyRelease:
Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
break;
case MotionNotify:
- if (in_dga.value == 1) {
- mouse_x += event.xmotion.x_root * in_dga_mouseaccel.value;
- mouse_y += event.xmotion.y_root * in_dga_mouseaccel.value;
- } else {
- if (!p_mouse_x && !p_mouse_y) {
- Con_Printf("event->xmotion.x: %d\n", event.xmotion.x);
- Con_Printf("event->xmotion.y: %d\n", event.xmotion.y);
+ if (usingmouse)
+ {
+ if (vid_dga.value == 1)
+ {
+ mouse_x += event.xmotion.x_root * vid_dga_mouseaccel.value;
+ mouse_y += event.xmotion.y_root * vid_dga_mouseaccel.value;
}
- if (vid_fullscreen.value || vid_mouse.value) {
- if (!event.xmotion.send_event) {
+ else
+ {
+ /*
+ if (!p_mouse_x && !p_mouse_y)
+ {
+ Con_Printf("event->xmotion.x: %d\n", event.xmotion.x);
+ Con_Printf("event->xmotion.y: %d\n", event.xmotion.y);
+ }
+ */
+ //if (usingmouse)
+ {
+ if (!event.xmotion.send_event)
+ {
+ mouse_x += (event.xmotion.x - p_mouse_x);
+ mouse_y += (event.xmotion.y - p_mouse_y);
+ if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4)
+ dowarp = true;
+ }
+ }
+ /*
+ else
+ {
mouse_x += (event.xmotion.x - p_mouse_x);
mouse_y += (event.xmotion.y - p_mouse_y);
- if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4
- || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) {
- dowarp = true;
- }
}
- } else {
- mouse_x += (event.xmotion.x - p_mouse_x);
- mouse_y += (event.xmotion.y - p_mouse_y);
+ */
+ p_mouse_x = event.xmotion.x;
+ p_mouse_y = event.xmotion.y;
}
- p_mouse_x = event.xmotion.x;
- p_mouse_y = event.xmotion.y;
}
break;
case ButtonPress:
- b=-1;
- if (event.xbutton.button == 1)
- b = 0;
- else if (event.xbutton.button == 2)
- b = 2;
- else if (event.xbutton.button == 3)
- b = 1;
- if (b>=0)
- Key_Event(K_MOUSE1 + b, true);
+ switch(event.xbutton.button)
+ {
+ case 1:
+ Key_Event(K_MOUSE1, true);
+ break;
+ case 2:
+ Key_Event(K_MOUSE3, true);
+ break;
+ case 3:
+ Key_Event(K_MOUSE2, true);
+ break;
+ case 4:
+ Key_Event(K_MWHEELUP, true);
+ break;
+ case 5:
+ Key_Event(K_MWHEELDOWN, true);
+ break;
+ default:
+ Con_Printf("HandleEvents: ButtonPress gave value %d, 1-5 expected\n", event.xbutton.button);
+ break;
+ }
break;
case ButtonRelease:
- b=-1;
- if (event.xbutton.button == 1)
- b = 0;
- else if (event.xbutton.button == 2)
- b = 2;
- else if (event.xbutton.button == 3)
- b = 1;
- if (b>=0)
- Key_Event(K_MOUSE1 + b, false);
+ switch(event.xbutton.button)
+ {
+ case 1:
+ Key_Event(K_MOUSE1, false);
+ break;
+ case 2:
+ Key_Event(K_MOUSE3, false);
+ break;
+ case 3:
+ Key_Event(K_MOUSE2, false);
+ break;
+ case 4:
+ Key_Event(K_MWHEELUP, false);
+ break;
+ case 5:
+ Key_Event(K_MWHEELDOWN, false);
+ break;
+ default:
+ Con_Printf("HandleEvents: ButtonRelease gave value %d, 1-5 expected\n", event.xbutton.button);
+ break;
+ }
break;
case CreateNotify :
}
}
- if (dowarp) {
+ if (dowarp)
+ {
/* move the mouse to the window center again */
p_mouse_x = vid.width / 2;
p_mouse_y = vid.height / 2;
}
-static void IN_DeactivateMouse( void )
+static void IN_DeactivateMouse( void )
{
if (!mouse_avail || !dpy || !win)
return;
- if (mouse_active) {
+ if (mouse_active)
+ {
uninstall_grabs();
mouse_active = false;
}
}
-static void IN_ActivateMouse( void )
+static void IN_ActivateMouse( void )
{
if (!mouse_avail || !dpy || !win)
return;
- if (!mouse_active) {
+ if (!mouse_active)
+ {
mouse_x = mouse_y = 0; // don't spazz
install_grabs();
mouse_active = true;
if (!ctx || !dpy)
return;
- if (dpy) {
+ if (dpy)
+ {
uninstall_grabs();
if (vidmode_active)
signal(SIGTERM, signal_handler);
}
-void VID_CheckMultitexture(void)
+void VID_CheckMultitexture(void)
{
void *prjobj;
qglMTexCoord2f = NULL;
void GL_EndRendering (void)
{
+ int usemouse;
if (!r_render.value)
return;
glFlush();
glXSwapBuffers(dpy, win);
+
+// handle the mouse state when windowed if that's changed
+ usemouse = false;
+ if (vid_mouse.value && key_dest == key_game)
+ usemouse = true;
+ if (vidmode_active)
+ usemouse = true;
+ if (usemouse)
+ {
+ if (!usingmouse)
+ {
+ usingmouse = true;
+ IN_ActivateMouse ();
+ }
+ }
+ else
+ {
+ if (usingmouse)
+ {
+ usingmouse = false;
+ IN_DeactivateMouse ();
+ }
+ }
}
int VID_SetGamma(float prescale, float gamma, float scale, float base)
void VID_Init(void)
{
int i;
- int attrib[] = {
+ int attrib[] =
+ {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
int MajorVersion, MinorVersion;
int actualWidth, actualHeight;
- Cvar_RegisterVariable (&in_mouse);
- Cvar_RegisterVariable (&in_dga);
- Cvar_RegisterVariable (&in_dga_mouseaccel);
+ Cvar_RegisterVariable (&vid_mouse);
+ Cvar_RegisterVariable (&vid_dga);
+ Cvar_RegisterVariable (&vid_dga_mouseaccel);
Cvar_RegisterVariable (&m_filter);
-
+
// interpret command-line params
// set vid parameters
if (vid.conheight < 200)
vid.conheight = 200;
- if (!(dpy = XOpenDisplay(NULL))) {
+ if (!(dpy = XOpenDisplay(NULL)))
+ {
fprintf(stderr, "Error couldn't open the X display\n");
exit(1);
}
// Get video mode list
MajorVersion = MinorVersion = 0;
- if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
+ if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion))
vidmode_ext = false;
- } else {
+ else
+ {
Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion);
vidmode_ext = true;
}
visinfo = glXChooseVisual(dpy, scrnum, attrib);
- if (!visinfo) {
+ if (!visinfo)
+ {
fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
exit(1);
}
- if (vidmode_ext) {
+ if (vidmode_ext)
+ {
int best_fit, best_dist, dist, x, y;
-
+
XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
// Are we going fullscreen? If so, let's change video mode
- if (fullscreen) {
+ if (fullscreen)
+ {
best_dist = 9999999;
best_fit = -1;
- for (i = 0; i < num_vidmodes; i++) {
- if (width > vidmodes[i]->hdisplay ||
- height > vidmodes[i]->vdisplay)
+ for (i = 0; i < num_vidmodes; i++)
+ {
+ if (width > vidmodes[i]->hdisplay || height > vidmodes[i]->vdisplay)
continue;
x = width - vidmodes[i]->hdisplay;
y = height - vidmodes[i]->vdisplay;
dist = (x * x) + (y * y);
- if (dist < best_dist) {
+ if (dist < best_dist)
+ {
best_dist = dist;
best_fit = i;
}
}
- if (best_fit != -1) {
+ if (best_fit != -1)
+ {
actualWidth = vidmodes[best_fit]->hdisplay;
actualHeight = vidmodes[best_fit]->vdisplay;
// Move the viewport to top left
XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
- } else
+ }
+ else
fullscreen = 0;
}
}
attr.border_pixel = 0;
attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
attr.event_mask = X_MASK;
- if (vidmode_active) {
- mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore |
- CWEventMask | CWOverrideRedirect;
+ if (vidmode_active)
+ {
+ mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect;
attr.override_redirect = True;
attr.backing_store = NotUseful;
attr.save_under = False;
- } else
+ }
+ else
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- win = XCreateWindow(dpy, root, 0, 0, width, height,
- 0, visinfo->depth, InputOutput,
- visinfo->visual, mask, &attr);
+ win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
+ XStoreName(dpy, win, "DarkPlaces-GLX");
XMapWindow(dpy, win);
- if (vidmode_active) {
+ if (vidmode_active)
+ {
XMoveWindow(dpy, win, 0, 0);
XRaiseWindow(dpy, win);
XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
vid.width = vid.conwidth;
vid.height = vid.conheight;
- vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
-
InitSig(); // trap evil signals
GL_Init();
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
- vid.recalc_refdef = 1; // force a surface cache flush
-
- install_grabs();
+ // force a surface cache flush
+ vid.recalc_refdef = 1;
}
void Sys_SendKeyEvents(void)
*/
void IN_Commands (void)
{
- if (!dpy || !win)
- return;
-
- if (vidmode_active || key_dest == key_game)
- IN_ActivateMouse();
- else
- IN_DeactivateMouse ();
}
/*
if (!mouse_avail)
return;
- if (!mouse_avail)
- return;
-
- if (m_filter.value) {
- mouse_x = (mouse_x + old_mouse_x) * 0.5;
- mouse_y = (mouse_y + old_mouse_y) * 0.5;
-
- old_mouse_x = mouse_x;
- old_mouse_y = mouse_y;
- }
-
- mouse_x *= sensitivity.value;
- mouse_y *= sensitivity.value;
-
- if (in_strafe.state & 1)
- cmd->sidemove += m_side.value * mouse_x;
- else
- cl.viewangles[YAW] -= m_yaw.value * mouse_x;
-
-/* if (freelook)*/
- V_StopPitchDrift ();
-
- if (/*freelook && */!(in_strafe.state & 1)) {
- cl.viewangles[PITCH] += m_pitch.value * mouse_y;
- cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80);
- } else {
- if ((in_strafe.state & 1) && noclip_anglehack)
- cmd->upmove -= m_forward.value * mouse_y;
- else
- cmd->forwardmove -= m_forward.value * mouse_y;
- }
- mouse_x = mouse_y = 0.0;
+ if (m_filter.value)
+ {
+ mouse_x = (mouse_x + old_mouse_x) * 0.5;
+ mouse_y = (mouse_y + old_mouse_y) * 0.5;
+
+ old_mouse_x = mouse_x;
+ old_mouse_y = mouse_y;
+ }
+
+ mouse_x *= sensitivity.value;
+ mouse_y *= sensitivity.value;
+
+ if (in_strafe.state & 1)
+ cmd->sidemove += m_side.value * mouse_x;
+ else
+ cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+
+ //if (freelook)
+ V_StopPitchDrift ();
+
+ if (/*freelook && */!(in_strafe.state & 1))
+ {
+ cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+ cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80);
+ }
+ else
+ {
+ if ((in_strafe.state & 1) && noclip_anglehack)
+ cmd->upmove -= m_forward.value * mouse_y;
+ else
+ cmd->forwardmove -= m_forward.value * mouse_y;
+ }
+ mouse_x = mouse_y = 0.0;
}
void IN_Move (usercmd_t *cmd)
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
ent = &cl_entities[cl.viewentity];
// view is the weapon model (only visible from inside body)
view = &cl.viewent;
-
-// transform the view offset by the model's matrix to get the offset from model origin for the view
- if (!chase_active.value) // LordHavoc: get rid of angle problems in chase_active mode
+
+ if (chase_active.value)
{
- ent->render.angles[YAW] = cl.viewangles[YAW]; // the model should face the view dir
- ent->render.angles[PITCH] = -cl.viewangles[PITCH]; // the model should face the view dir
+ VectorCopy (ent->render.origin, r_refdef.vieworg);
+ VectorCopy (cl.viewangles, r_refdef.viewangles);
+ Chase_Update ();
+ V_AddIdle ();
}
-
-
- bob = V_CalcBob ();
-
-// refresh position
- VectorCopy (ent->render.origin, r_refdef.vieworg);
- r_refdef.vieworg[2] += cl.viewheight + bob;
+ else
+ {
+ // transform the view offset by the model's matrix to get the offset from model origin for the view
+ // if (!chase_active.value) // LordHavoc: get rid of angle problems in chase_active mode
+ // {
+ // ent->render.angles[YAW] = cl.viewangles[YAW]; // the model should face the view dir
+ // ent->render.angles[PITCH] = -cl.viewangles[PITCH]; // the model should face the view dir
+ // }
- // LordHavoc: the protocol has changed... so this is an obsolete approach
-// never let it sit exactly on a node line, because a water plane can
-// dissapear when viewed with the eye exactly on it.
-// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
-// r_refdef.vieworg[0] += 1.0/32;
-// r_refdef.vieworg[1] += 1.0/32;
-// r_refdef.vieworg[2] += 1.0/32;
+ bob = V_CalcBob ();
- if (!intimerefresh)
- VectorCopy (cl.viewangles, r_refdef.viewangles);
- V_CalcViewRoll ();
- V_AddIdle ();
+ // refresh position
+ VectorCopy (ent->render.origin, r_refdef.vieworg);
+ r_refdef.vieworg[2] += cl.viewheight + bob;
-// offsets
- angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward
- angles[YAW] = ent->render.angles[YAW];
- angles[ROLL] = ent->render.angles[ROLL];
+ // LordHavoc: the protocol has changed... so this is an obsolete approach
+ // never let it sit exactly on a node line, because a water plane can
+ // dissapear when viewed with the eye exactly on it.
+ // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
+ // r_refdef.vieworg[0] += 1.0/32;
+ // r_refdef.vieworg[1] += 1.0/32;
+ // r_refdef.vieworg[2] += 1.0/32;
- AngleVectors (angles, forward, NULL, NULL);
+ if (!intimerefresh)
+ VectorCopy (cl.viewangles, r_refdef.viewangles);
+ V_CalcViewRoll ();
+ V_AddIdle ();
- V_BoundOffsets ();
-
-// set up gun position
- VectorCopy (cl.viewangles, view->render.angles);
-
- CalcGunAngle ();
+ // offsets
+ angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward
+ angles[YAW] = ent->render.angles[YAW];
+ angles[ROLL] = ent->render.angles[ROLL];
- VectorCopy (ent->render.origin, view->render.origin);
- view->render.origin[2] += cl.viewheight;
+ AngleVectors (angles, forward, NULL, NULL);
- for (i=0 ; i<3 ; i++)
- {
- view->render.origin[i] += forward[i]*bob*0.4;
-// view->render.origin[i] += right[i]*bob*0.4;
-// view->render.origin[i] += up[i]*bob*0.8;
- }
- view->render.origin[2] += bob;
+ V_BoundOffsets ();
- view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]];
- view->render.frame = cl.stats[STAT_WEAPONFRAME];
- view->render.colormap = -1; // no special coloring
+ // set up gun position
+ VectorCopy (cl.viewangles, view->render.angles);
-// set up the refresh position
+ CalcGunAngle ();
- // LordHavoc: this never looked all that good to begin with...
- /*
-// smooth out stair step ups
-if (cl.onground && ent->render.origin[2] - oldz > 0)
-{
- float steptime;
-
- steptime = cl.time - cl.oldtime;
- if (steptime < 0)
-//FIXME I_Error ("steptime < 0");
- steptime = 0;
+ VectorCopy (ent->render.origin, view->render.origin);
+ view->render.origin[2] += cl.viewheight;
- oldz += steptime * 80;
- if (oldz > ent->render.origin[2])
- oldz = ent->render.origin[2];
- if (ent->render.origin[2] - oldz > 12)
- oldz = ent->render.origin[2] - 12;
- r_refdef.vieworg[2] += oldz - ent->render.origin[2];
- view->render.origin[2] += oldz - ent->render.origin[2];
-}
-else
- oldz = ent->render.origin[2];
- */
+ for (i=0 ; i<3 ; i++)
+ {
+ view->render.origin[i] += forward[i]*bob*0.4;
+ // view->render.origin[i] += right[i]*bob*0.4;
+ // view->render.origin[i] += up[i]*bob*0.8;
+ }
+ view->render.origin[2] += bob;
+
+ view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]];
+ view->render.frame = cl.stats[STAT_WEAPONFRAME];
+ view->render.colormap = -1; // no special coloring
-// LordHavoc: origin view kick added
- if (!intimerefresh && v_punch.value)
+ // set up the refresh position
+
+ // LordHavoc: this never looked all that good to begin with...
+ /*
+ // smooth out stair step ups
+ if (cl.onground && ent->render.origin[2] - oldz > 0)
{
- VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
- VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg);
+ float steptime;
+
+ steptime = cl.time - cl.oldtime;
+ if (steptime < 0)
+ //FIXME I_Error ("steptime < 0");
+ steptime = 0;
+
+ oldz += steptime * 80;
+ if (oldz > ent->render.origin[2])
+ oldz = ent->render.origin[2];
+ if (ent->render.origin[2] - oldz > 12)
+ oldz = ent->render.origin[2] - 12;
+ r_refdef.vieworg[2] += oldz - ent->render.origin[2];
+ view->render.origin[2] += oldz - ent->render.origin[2];
}
+ else
+ oldz = ent->render.origin[2];
+ */
- if (chase_active.value)
- Chase_Update ();
+ // LordHavoc: origin view kick added
+ if (!intimerefresh && v_punch.value)
+ {
+ VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
+ VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg);
+ }
+ }
}
/*
QFile *file;
int numlumps;
- COM_FOpenFile (filename, &file, false, true);
+ COM_FOpenFile (filename, &file, false, false);
if (!file)
{
if (complain)
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*/
+/*
+typedef struct link_s
+{
+ struct link_s *prev, *next;
+} link_t;
+*/
+
+
+void ClearLink (link_t *l);
+void RemoveLink (link_t *l);
+void InsertLinkBefore (link_t *l, link_t *before);
+void InsertLinkAfter (link_t *l, link_t *after);
+
+// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
+// ent = STRUCT_FROM_LINK(link,entity_t,order)
+// FIXME: remove this mess!
+//#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
+
+#define EDICT_FROM_AREA(l) ((edict_t *)((byte *)l - (int)&(((edict_t *)0)->area)))
+
+//============================================================================
+
+// ClearLink is used for new headnodes
+void ClearLink (link_t *l)
+{
+ l->prev = l->next = l;
+}
+
+void RemoveLink (link_t *l)
+{
+ l->next->prev = l->prev;
+ l->prev->next = l->next;
+}
+
+void InsertLinkBefore (link_t *l, link_t *before)
+{
+ l->next = before;
+ l->prev = before->prev;
+ l->prev->next = l;
+ l->next->prev = l;
+}
+void InsertLinkAfter (link_t *l, link_t *after)
+{
+ l->next = after->next;
+ l->prev = after;
+ l->prev->next = l;
+ l->next->prev = l;
+}
+
typedef struct
{
VectorSubtract (ent->v.mins, maxs, hullmins);
VectorSubtract (ent->v.maxs, mins, hullmaxs);
hull = SV_HullForBox (hullmins, hullmaxs);
-
+
VectorCopy (ent->v.origin, offset);
}
ClearLink (&anode->trigger_edicts);
ClearLink (&anode->solid_edicts);
-
+
if (depth == AREA_DEPTH)
{
anode->axis = -1;
anode->children[0] = anode->children[1] = NULL;
return anode;
}
-
+
VectorSubtract (maxs, mins, size);
if (size[0] > size[1])
anode->axis = 0;
else
anode->axis = 1;
-
+
anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
- VectorCopy (mins, mins1);
- VectorCopy (mins, mins2);
- VectorCopy (maxs, maxs1);
- VectorCopy (maxs, maxs2);
-
+ VectorCopy (mins, mins1);
+ VectorCopy (mins, mins2);
+ VectorCopy (maxs, maxs1);
+ VectorCopy (maxs, maxs2);
+
maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
-
+
anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
void SV_ClearWorld (void)
{
SV_InitBoxHull ();
-
+
memset (sv_areanodes, 0, sizeof(sv_areanodes));
sv_numareanodes = 0;
SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
continue;
if (ent->v.absmin[0] > touch->v.absmax[0]
- || ent->v.absmin[1] > touch->v.absmax[1]
- || ent->v.absmin[2] > touch->v.absmax[2]
- || ent->v.absmax[0] < touch->v.absmin[0]
- || ent->v.absmax[1] < touch->v.absmin[1]
- || ent->v.absmax[2] < touch->v.absmin[2] )
+ || ent->v.absmin[1] > touch->v.absmax[1]
+ || ent->v.absmin[2] > touch->v.absmax[2]
+ || ent->v.absmax[0] < touch->v.absmin[0]
+ || ent->v.absmax[1] < touch->v.absmin[1]
+ || ent->v.absmax[2] < touch->v.absmin[2])
continue;
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
pr_global_struct->self = old_self;
pr_global_struct->other = old_other;
}
-
+
// recurse down both sides
if (node->axis == -1)
return;
-
+
// LordHavoc: optimized recursion
// if (ent->v.absmax[node->axis] > node->dist) SV_TouchLinks (ent, node->children[0]);
// if (ent->v.absmin[node->axis] < node->dist) SV_TouchLinks (ent, node->children[1]);
*/
void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
{
- mplane_t *splitplane;
- mleaf_t *leaf;
- int sides;
- int leafnum;
-
loc0:
if (node->contents == CONTENTS_SOLID)
return;
-
+
// add an efrag if the node is a leaf
if ( node->contents < 0)
return;
}
- leaf = (mleaf_t *)node;
- leafnum = leaf - sv.worldmodel->leafs - 1;
-
- ent->leafnums[ent->num_leafs] = leafnum;
- ent->num_leafs++;
+ ent->leafnums[ent->num_leafs++] = (mleaf_t *)node - sv.worldmodel->leafs - 1;
return;
}
-
-// NODE_MIXED
- splitplane = node->plane;
- sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
-
// recurse down the contacted sides
- // LordHavoc: optimized recursion
+
+// sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane);
// if (sides & 1) SV_FindTouchedLeafs (ent, node->children[0]);
// if (sides & 2) SV_FindTouchedLeafs (ent, node->children[1]);
- switch (sides)
+
+ // LordHavoc: optimized recursion
+ switch (BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane))
{
case 1:
node = node->children[0];
// LordHavoc: enabling rotating bmodels
if (ent->v.solid == SOLID_BSP && (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]))
- { // expand for rotation
+ {
+ // expand for rotation
float max, v;
int i;
}
else
{
- VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
+ VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
}
ent->v.absmax[1] += 15;
}
else
- { // because movement is clipped an epsilon away from an actual edge,
+ {
+ // because movement is clipped an epsilon away from an actual edge,
// we must fully check even when bounding boxes don't quite touch
ent->v.absmin[0] -= 1;
ent->v.absmin[1] -= 1;
break; // crosses the node
}
-// link it in
+// link it in
if (ent->v.solid == SOLID_TRIGGER)
InsertLinkBefore (&ent->area, &node->trigger_edicts);
else
InsertLinkBefore (&ent->area, &node->solid_edicts);
-
+
// if touch_triggers, touch all entities at this node and descend for more
if (touch_triggers)
SV_TouchLinks ( ent, sv_areanodes );
{
while (num >= 0)
num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist];
-
+
return num;
}
trace_t trace;
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
-
+
if (trace.startsolid)
return sv.edicts;
continue;
if (clip->boxmins[0] > touch->v.absmax[0]
- || clip->boxmins[1] > touch->v.absmax[1]
- || clip->boxmins[2] > touch->v.absmax[2]
- || clip->boxmaxs[0] < touch->v.absmin[0]
- || clip->boxmaxs[1] < touch->v.absmin[1]
- || clip->boxmaxs[2] < touch->v.absmin[2] )
+ || clip->boxmins[1] > touch->v.absmax[1]
+ || clip->boxmins[2] > touch->v.absmax[2]
+ || clip->boxmaxs[0] < touch->v.absmin[0]
+ || clip->boxmaxs[1] < touch->v.absmin[1]
+ || clip->boxmaxs[2] < touch->v.absmin[2])
continue;
- if (clip->passedict!=0 && clip->passedict->v.size[0] && !touch->v.size[0])
+ if (clip->passedict != NULL && clip->passedict->v.size[0] && !touch->v.size[0])
continue; // points never interact
// might intersect, so do an exact clip
else if (trace.startsolid)
clip->trace.startsolid = true;
}
-
+
// recurse down both sides
if (node->axis == -1)
return;