From e348dc30a265dc0d46b20b92d1d6ec778d3c672f Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 13 May 2005 10:42:48 +0000 Subject: [PATCH] Changed vec4_t down to vec3_t, got the server browser integrated with the menu.dat. csqc is having fun, and nexuiz should work better. Enjoy. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1011 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 14 +- engine/client/cl_input.c | 191 +++++--- engine/client/cl_main.c | 1 + engine/client/cl_master.h | 49 +- engine/client/cl_parse.c | 4 + engine/client/cl_tent.c | 19 + engine/client/keys.c | 21 +- engine/client/net_master.c | 409 +++++++++++++++- engine/client/pr_menu.c | 113 ++++- engine/client/r_part.c | 242 +++++++++- engine/client/render.h | 3 + engine/client/renderer.c | 2 + engine/client/snd_win.c | 24 +- engine/client/spritegn.h | 1 + engine/client/zqtp.c | 17 +- engine/common/bothdefs.h | 2 +- engine/common/common.c | 1 + engine/common/gl_q2bsp.c | 83 ++-- engine/common/particles.h | 28 +- engine/common/protocol.h | 4 +- engine/common/q1bsp.c | 489 ++++++++++++++++++- engine/common/qvm.c | 4 +- engine/ftequake/ftequake.dsp | 8 + engine/gl/gl_alias.c | 65 +-- engine/gl/gl_backend.c | 18 +- engine/gl/gl_draw.c | 60 ++- engine/gl/gl_model.c | 71 ++- engine/gl/gl_model.h | 4 +- engine/gl/gl_ppl.c | 223 ++++++++- engine/gl/gl_rmain.c | 9 +- engine/gl/gl_rsurf.c | 14 +- engine/gl/gl_screen.c | 5 + engine/gl/gl_vidcommon.c | 3 + engine/gl/gl_warp.c | 9 +- engine/gl/glmod_doom.c | 897 +---------------------------------- engine/gl/glquake.h | 2 + engine/gl/model_hl.h | 3 +- engine/qclib/pr_edict.c | 6 +- engine/qclib/qccmain.c | 8 +- engine/server/pr_cmds.c | 25 +- engine/server/savegame.c | 3 +- engine/server/sv_ccmds.c | 7 + engine/server/sv_ents.c | 4 +- engine/server/sv_user.c | 25 +- 44 files changed, 2031 insertions(+), 1159 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 9a1a42a68..3d18a939d 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -482,9 +482,9 @@ void CL_ParsePacketEntities (qboolean delta) if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) { Con_DPrintf ("WARNING: from mismatch\n"); - FlushEntityPacket (); - cl.validsequence = 0; - return; +// FlushEntityPacket (); +// cl.validsequence = 0; +// return; } if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) { @@ -1502,7 +1502,7 @@ void CL_LinkPacketEntities (void) a1 -= 360; if (a1 - a2 < -180) a1 += 360; - angles[i] = a2 + f * (a1 - a2); + angles[i] = a1 + f * (a2 - a1); } } @@ -1516,7 +1516,11 @@ void CL_LinkPacketEntities (void) CL_RotateAroundTag(ent, s1->number, cl.lerpents[s1->number].tagent, cl.lerpents[s1->number].tagindex); } - if (ent->keynum <= MAX_CLIENTS && cls.demoplayback != DPB_NETQUAKE && (!cls.netcon || cls.netcon->qwprotocol)) + if (ent->keynum <= MAX_CLIENTS +#ifdef NQPROT + && cls.demoplayback != DPB_NETQUAKE && (!cls.netcon || cls.netcon->qwprotocol) +#endif + ) ent->keynum += MAX_EDICTS; // add automatic particle trails diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 54b990edf..89d74899e 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1456,6 +1456,131 @@ static char *VARGS vahunk(char *format, ...) return ret; } +void CL_RegisterSplitCommands(void) +{ + static int oldsplit; + char spn[8]; + int sp; + for (sp = 0; sp < MAX_SPLITS; sp++) + { + if (sp) + sprintf(spn, "%i", sp+1); + else + *spn = '\0'; + if (sp < cl.splitclients) + { + if (oldsplit & (1<=0; sp--) - { - if (sp) - { - if (nosplits) - continue; - sprintf(spn, "%i", sp+1); - } - else - *spn = '\0'; - - Cmd_AddCommand (vahunk("+moveup%s", spn), IN_UpDown); - Cmd_AddCommand (vahunk("-moveup%s", spn), IN_UpUp); - Cmd_AddCommand (vahunk("+movedown%s", spn), IN_DownDown); - Cmd_AddCommand (vahunk("-movedown%s", spn), IN_DownUp); - Cmd_AddCommand (vahunk("+left%s", spn), IN_LeftDown); - Cmd_AddCommand (vahunk("-left%s", spn), IN_LeftUp); - Cmd_AddCommand (vahunk("+right%s", spn), IN_RightDown); - Cmd_AddCommand (vahunk("-right%s", spn), IN_RightUp); - Cmd_AddCommand (vahunk("+forward%s", spn), IN_ForwardDown); - Cmd_AddCommand (vahunk("-forward%s", spn), IN_ForwardUp); - Cmd_AddCommand (vahunk("+back%s", spn), IN_BackDown); - Cmd_AddCommand (vahunk("-back%s", spn), IN_BackUp); - Cmd_AddCommand (vahunk("+lookup%s", spn), IN_LookupDown); - Cmd_AddCommand (vahunk("-lookup%s", spn), IN_LookupUp); - Cmd_AddCommand (vahunk("+lookdown%s", spn), IN_LookdownDown); - Cmd_AddCommand (vahunk("-lookdown%s", spn), IN_LookdownUp); - Cmd_AddCommand (vahunk("+strafe%s", spn), IN_StrafeDown); - Cmd_AddCommand (vahunk("-strafe%s", spn), IN_StrafeUp); - Cmd_AddCommand (vahunk("+moveleft%s", spn), IN_MoveleftDown); - Cmd_AddCommand (vahunk("-moveleft%s", spn), IN_MoveleftUp); - Cmd_AddCommand (vahunk("+moveright%s", spn), IN_MoverightDown); - Cmd_AddCommand (vahunk("-moveright%s", spn), IN_MoverightUp); - Cmd_AddCommand (vahunk("+speed%s", spn), IN_SpeedDown); - Cmd_AddCommand (vahunk("-speed%s", spn), IN_SpeedUp); - Cmd_AddCommand (vahunk("+attack%s", spn), IN_AttackDown); - Cmd_AddCommand (vahunk("-attack%s", spn), IN_AttackUp); - Cmd_AddCommand (vahunk("+use%s", spn), IN_UseDown); - Cmd_AddCommand (vahunk("-use%s", spn), IN_UseUp); - Cmd_AddCommand (vahunk("+jump%s", spn), IN_JumpDown); - Cmd_AddCommand (vahunk("-jump%s", spn), IN_JumpUp); - Cmd_AddCommand (vahunk("impulse%s", spn), IN_Impulse); - Cmd_AddCommand (vahunk("+klook%s", spn), IN_KLookDown); - Cmd_AddCommand (vahunk("-klook%s", spn), IN_KLookUp); - Cmd_AddCommand (vahunk("+mlook%s", spn), IN_MLookDown); - Cmd_AddCommand (vahunk("-mlook%s", spn), IN_MLookUp); - - - Cmd_AddCommand (vahunk("+button3%s", spn), IN_Button3Down); - Cmd_AddCommand (vahunk("-button3%s", spn), IN_Button3Up); - Cmd_AddCommand (vahunk("+button4%s", spn), IN_Button4Down); - Cmd_AddCommand (vahunk("-button4%s", spn), IN_Button4Up); - Cmd_AddCommand (vahunk("+button5%s", spn), IN_Button5Down); - Cmd_AddCommand (vahunk("-button5%s", spn), IN_Button5Up); - Cmd_AddCommand (vahunk("+button6%s", spn), IN_Button6Down); - Cmd_AddCommand (vahunk("-button6%s", spn), IN_Button6Up); - Cmd_AddCommand (vahunk("+button7%s", spn), IN_Button7Down); - Cmd_AddCommand (vahunk("-button7%s", spn), IN_Button7Up); - Cmd_AddCommand (vahunk("+button8%s", spn), IN_Button8Down); - Cmd_AddCommand (vahunk("-button8%s", spn), IN_Button8Up); - } + CL_RegisterSplitCommands(); Cmd_AddCommand("rotate", IN_Rotate_f); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 0bc307cf7..fe88988ff 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -483,6 +483,7 @@ void CL_SendConnectPacket ( NET_SendPacket (NS_CLIENT, strlen(data), data, adr); cl.splitclients = 0; + CL_RegisterSplitCommands(); } /* diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 0a891b06b..ee9331454 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -18,6 +18,31 @@ #define MT_MASTERQ2 8 //query +typedef enum{ + SLKEY_PING, + SLKEY_MAP, + SLKEY_NAME, + SLKEY_ADDRESS, + SLKEY_NUMPLAYERS, + SLKEY_MAXPLAYERS, + SLKEY_GAMEDIR, + + SLKEY_TOOMANY, + SLKEY_CUSTOM +} hostcachekey_t; + +typedef enum { + SLIST_TEST_CONTAINS, + SLIST_TEST_NOTCONTAIN, + SLIST_TEST_LESSEQUAL, + SLIST_TEST_LESS, + SLIST_TEST_EQUAL, + SLIST_TEST_GREATER, + SLIST_TEST_GREATEREQUAL, + SLIST_TEST_NOTEQUAL +} slist_test_t; + + //contains info about a server in greater detail. Could be too mem intensive. typedef struct serverdetailedinfo_s { char info[MAX_SERVERINFO_STRING]; @@ -41,8 +66,13 @@ typedef struct serverinfo_s { char name[64]; //hostname. netadr_t adr; - short players; - short maxplayers; + unsigned char players; + unsigned char maxplayers; + qbyte special; //flags + qbyte sends; + qbyte insortedlist; + + unsigned short ping; short tl; short fl; @@ -50,9 +80,6 @@ typedef struct serverinfo_s { char map[8+1]; float refreshtime; - qbyte special; //flags - unsigned short ping; - int sends; serverdetailedinfo_t *moreinfo; @@ -99,3 +126,15 @@ serverinfo_t *Master_InfoForNum (int num); int Master_TotalCount(void); void Master_QueryServer(serverinfo_t *server); void MasterInfo_WriteServers(void); + +int Master_KeyForName(char *keyname); +float Master_ReadKeyFloat(serverinfo_t *server, int keynum); +char *Master_ReadKeyString(serverinfo_t *server, int keynum); + +void Master_SetSortField(hostcachekey_t field, qboolean descending); +hostcachekey_t Master_GetSortField(void); +qboolean Master_GetSortDescending(void); + +int Master_NumSorted(void); +void Master_ClearMasks(void); +serverinfo_t *Master_SortedServer(int idx); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 928ce47d1..f12a636d2 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1258,6 +1258,7 @@ void CL_ParseServerData (void) cl.frames[i].playerstate[cl.playernum[0]].pm_type = PM_SPECTATOR; cl.splitclients = 1; + CL_RegisterSplitCommands(); } else { @@ -1284,6 +1285,7 @@ void CL_ParseServerData (void) Host_EndGame("Server sent us too many alternate clients\n"); } cl.splitclients = clnum+1; + CL_RegisterSplitCommands(); } // get the full level name @@ -1389,6 +1391,7 @@ void CLQ2_ParseServerData (void) // parse player entity number cl.playernum[0] = MSG_ReadShort (); cl.splitclients = 1; + CL_RegisterSplitCommands(); cl.spectator = false; // get the full level name @@ -1475,6 +1478,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } cl.splitclients = 1; + CL_RegisterSplitCommands(); /*cl.gametype =*/ MSG_ReadByte (); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 3aa0bcb36..db0b45236 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -935,6 +935,25 @@ void CL_ParseTEnt (void) CLQ2_RailTrail (pos, pos2); break; + case DPTE_SMOKE: + //org + pos[0] = MSG_ReadCoord (); + pos[0] = MSG_ReadCoord (); + pos[0] = MSG_ReadCoord (); + + //dir + pos2[0] = MSG_ReadCoord (); + pos2[0] = MSG_ReadCoord (); + pos2[0] = MSG_ReadCoord (); + + //count + cnt = MSG_ReadByte (); + { + extern int pt_smoke; + P_RunParticleEffectType(pos, pos2, cnt, pt_smoke); + } + break; + case 79: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); diff --git a/engine/client/keys.c b/engine/client/keys.c index 20c0d1c88..0302a4b2c 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1213,6 +1213,13 @@ void Key_Event (int key, qboolean down) if (key == K_SHIFT) shift_down = down; +#ifdef CSQC_DAT + //yes, csqc is allowed to steal the escape key. + if (key_dest == key_game) + if (CSQC_KeyPress(key, down)) //give csqc a chance to handle it. + return; +#endif + // // handle escape specialy, so the user can never unbind it // @@ -1221,14 +1228,10 @@ void Key_Event (int key, qboolean down) #ifdef TEXTEDITOR if (key_dest != key_editor) #endif - if (UI_KeyPress(key, down)) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu. - return; - -#ifdef CSQC_DAT - if (key_dest == key_game) - if (CSQC_KeyPress(key, down)) //give csqc a chance to handle it. + { + if (UI_KeyPress(key, down)) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu. return; -#endif + } if (!down) { @@ -1322,10 +1325,6 @@ void Key_Event (int key, qboolean down) { if (UI_KeyPress(key, down) && down) //UI is allowed to take these keydowns. Keyups are always maintained. return; -#ifdef CSQC_DAT - if (CSQC_KeyPress(key, down)) //give csqc a chance to handle it. - return; -#endif } diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 854b29fea..a2209e142 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -57,6 +57,41 @@ master_t *master; player_t *mplayers; serverinfo_t *firstserver; +static serverinfo_t **visibleservers; +static int numvisibleservers; +static int maxvisibleservers; + +static qboolean needsort; + +static hostcachekey_t sortfield; +static qboolean decreasingorder; + + + + +typedef struct { + hostcachekey_t fieldindex; + + float operandi; + char *operands; + + qboolean or; + int compareop; +} visrules_t; +#define MAX_VISRULES 8 +visrules_t visrules[MAX_VISRULES]; +int numvisrules; + + + + +#define SLIST_MAXKEYS 64 +char slist_keyname[SLIST_MAXKEYS][MAX_INFO_KEY]; +int slist_customkeys; + + + + #define POLLUDPSOCKETS 64 //it's big so we can have lots of messages when behind a firewall. Basically if a firewall only allows replys, and only remembers 3 servers per socket, we need this big cos it can take a while for a packet to find a fast optimised route and we might be waiting for a few secs for a reply the first time around. SOCKET pollsocketsUDP[POLLUDPSOCKETS]; @@ -73,6 +108,374 @@ int lastpollsockIPX; void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); +void Master_HideServer(serverinfo_t *server) +{ + int i, j; + for (i = 0; i < numvisibleservers;) + { + if (visibleservers[i] == server) + { + for (j = i; j < numvisibleservers-1; j++) + visibleservers[j] = visibleservers[j+1]; + visibleservers--; + } + else + i++; + } + server->insortedlist = false; +} + +void Master_InsertAt(serverinfo_t *server, int pos) +{ + int i; + for (i = numvisibleservers; i > pos; i--) + { + visibleservers[i] = visibleservers[i-1]; + } + visibleservers[pos] = server; + numvisibleservers++; + + server->insortedlist = true; +} + +qboolean Master_CompareInteger(int a, int b, slist_test_t rule) +{ + switch(rule) + { + case SLIST_TEST_CONTAINS: + return a&b; + case SLIST_TEST_NOTCONTAIN: + return !(a&b); + case SLIST_TEST_LESSEQUAL: + return a<=b; + case SLIST_TEST_LESS: + return ab; + case SLIST_TEST_GREATEREQUAL: + return a>=b; + case SLIST_TEST_NOTEQUAL: + return a!=b; + } + return false; +} +qboolean Master_CompareString(char *a, char *b, slist_test_t rule) +{ + switch(rule) + { + case SLIST_TEST_CONTAINS: + return !!strstr(a, b); + case SLIST_TEST_NOTCONTAIN: + return !strstr(a, b); + case SLIST_TEST_LESSEQUAL: + return strcmp(a, b)<=0; + case SLIST_TEST_LESS: + return strcmp(a, b)<0; + case SLIST_TEST_EQUAL: + return strcmp(a, b)==0; + case SLIST_TEST_GREATER: + return strcmp(a, b)>0; + case SLIST_TEST_GREATEREQUAL: + return strcmp(a, b)>=0; + case SLIST_TEST_NOTEQUAL: + return strcmp(a, b)!=0; + } + return false; +} + +qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b) +{ + switch(sortfield) + { + case SLKEY_PING: + return Master_CompareInteger(a->ping, b->ping, SLIST_TEST_LESS); + case SLKEY_NUMPLAYERS: + return Master_CompareInteger(a->players, b->players, SLIST_TEST_LESS); + case SLKEY_MAXPLAYERS: + return Master_CompareInteger(a->maxplayers, b->maxplayers, SLIST_TEST_LESS); + case SLKEY_MAP: + return Master_CompareString(a->map, b->map, SLIST_TEST_LESS); + case SLKEY_GAMEDIR: + return Master_CompareString(a->gamedir, b->gamedir, SLIST_TEST_LESS); + case SLKEY_NAME: + return Master_CompareString(a->name, b->name, SLIST_TEST_LESS); + } + return false; +} + +qboolean Master_PassesMasks(serverinfo_t *a) +{ + int i; + //always filter out dead unresponsive servers. + if (!a->ping) + return false; + + for (i = 0; i < numvisrules; i++) + { + switch(visrules[i].fieldindex) + { + case SLKEY_PING: + if (!Master_CompareInteger(a->ping, visrules[i].operandi, visrules[i].compareop)) + return false; + break; + case SLKEY_NUMPLAYERS: + if (!Master_CompareInteger(a->players, visrules[i].operandi, visrules[i].compareop)) + return false; + break; + case SLKEY_MAXPLAYERS: + if (!Master_CompareInteger(a->maxplayers, visrules[i].operandi, visrules[i].compareop)) + return false; + break; + + case SLKEY_MAP: + if (!Master_CompareString(a->map, visrules[i].operands, visrules[i].compareop)) + return false; + break; + case SLKEY_NAME: + if (!Master_CompareString(a->name, visrules[i].operands, visrules[i].compareop)) + return false; + break; + case SLKEY_GAMEDIR: + if (!Master_CompareString(a->gamedir, visrules[i].operands, visrules[i].compareop)) + return false; + break; + } + } + + return true; +} + +void Master_ClearMasks(void) +{ + numvisrules = 0; +} + +void Master_SetMaskString(qboolean or, hostcachekey_t field, char *param, slist_test_t testop) +{ + if (numvisrules == MAX_VISRULES) + return; //just don't add it. + + visrules[numvisrules].fieldindex = field; + visrules[numvisrules].compareop = testop; + visrules[numvisrules].operands = param; + visrules[numvisrules].or = or; + numvisrules++; +} +void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_test_t testop) +{ + if (numvisrules == MAX_VISRULES) + return; //just don't add it. + + visrules[numvisrules].fieldindex = field; + visrules[numvisrules].compareop = testop; + visrules[numvisrules].operandi = param; + visrules[numvisrules].or = or; + numvisrules++; +} +void Master_SetSortField(hostcachekey_t field, qboolean descending) +{ + sortfield = field; + decreasingorder = descending; +} +hostcachekey_t Master_GetSortField(void) +{ + return sortfield; +} +qboolean Master_GetSortDescending(void) +{ + return decreasingorder; +} + +void Master_ShowServer(serverinfo_t *server) +{ + int i; + if (!numvisibleservers) + { + Master_InsertAt(server, 0); + return; + } + + if (!decreasingorder) + { + for (i = 0; i < numvisibleservers; i++) + { + if (!Master_ServerIsGreater(server, visibleservers[i])) + { + Master_InsertAt(server, i); + return; + } + } + + } + else + { + for (i = 0; i < numvisibleservers; i++) + { + if (Master_ServerIsGreater(server, visibleservers[i])) + { + Master_InsertAt(server, i); + return; + } + } + } + + Master_InsertAt(server, numvisibleservers); +} + +void Master_ResortServer(serverinfo_t *server) +{ + if (server->insortedlist) + { + if (!Master_PassesMasks(server)) + Master_HideServer(server); + } + else + { + if (Master_PassesMasks(server)) + Master_ShowServer(server); + } +} + +void Master_SortServers(void) +{ + serverinfo_t *server; + + int total = Master_TotalCount(); + if (maxvisibleservers < total) + { + maxvisibleservers = total; + visibleservers = BZ_Realloc(visibleservers, maxvisibleservers*sizeof(serverinfo_t*)); + } + + { + numvisibleservers = 0; + for (server = firstserver; server; server = server->next) + server->insortedlist = false; + } + + for (server = firstserver; server; server = server->next) + { + Master_ResortServer(server); + } + + needsort = false; +} + +serverinfo_t *Master_SortedServer(int idx) +{ + if (needsort) + Master_SortServers(); + + if (idx < 0 || idx >= numvisibleservers) + return NULL; + + return visibleservers[idx]; +} + +int Master_NumSorted(void) +{ +// if (needsort) + Master_SortServers(); + + return numvisibleservers; +} + + + +float Master_ReadKeyFloat(serverinfo_t *server, int keynum) +{ + if (!server) + return -1; + else if (keynum < SLKEY_CUSTOM) + { + switch(keynum) + { + case SLKEY_PING: + return server->ping; + case SLKEY_NUMPLAYERS: + return server->players; + case SLKEY_MAXPLAYERS: + return server->maxplayers; + + default: + return atof(Master_ReadKeyString(server, keynum)); + } + } + else if (server->moreinfo) + return atof(Info_ValueForKey(server->moreinfo->info, slist_keyname[keynum-SLKEY_CUSTOM])); + + return 0; +} + +char *Master_ReadKeyString(serverinfo_t *server, int keynum) +{ + if (keynum < SLKEY_CUSTOM) + { + switch(keynum) + { + case SLKEY_MAP: + return server->map; + case SLKEY_NAME: + return server->name; + case SLKEY_ADDRESS: + return NET_AdrToString(server->adr); + case SLKEY_GAMEDIR: + return server->gamedir; + + default: + { + static char s[64]; + sprintf(s, "%f", Master_ReadKeyFloat(server, keynum)); + return s; + } + } + } + else if (server->moreinfo) + return Info_ValueForKey(server->moreinfo->info, slist_keyname[keynum-SLKEY_CUSTOM]); + + return ""; +} + +int Master_KeyForName(char *keyname) +{ + int i; + if (!strcmp(keyname, "map")) + return SLKEY_MAP; + else if (!strcmp(keyname, "ping")) + return SLKEY_PING; + else if (!strcmp(keyname, "name")) + return SLKEY_NAME; + else if (!strcmp(keyname, "address") || !strcmp(keyname, "cname")) + return SLKEY_ADDRESS; + else if (!strcmp(keyname, "maxplayers")) + return SLKEY_MAXPLAYERS; + else if (!strcmp(keyname, "numplayers")) + return SLKEY_NUMPLAYERS; + else if (!strcmp(keyname, "gamedir") || !strcmp(keyname, "game") || !strcmp(keyname, "*gamedir") || !strcmp(keyname, "mod")) + return SLKEY_GAMEDIR; + + else if (slist_customkeys == SLIST_MAXKEYS) + return SLKEY_TOOMANY; + else + { + for (i = 0; i < slist_customkeys; i++) + { + if (!strcmp(slist_keyname[i], keyname)) + { + return i + SLKEY_CUSTOM; + } + } + Q_strncpyz(slist_keyname[slist_customkeys], keyname, MAX_INFO_KEY); + + slist_customkeys++; + + return slist_customkeys-1 + SLKEY_CUSTOM; + } +} + + void Master_AddMaster (char *address, int type, char *description) @@ -641,7 +1044,7 @@ void MasterInfo_Begin(void) void Master_QueryServer(serverinfo_t *server) { char data[2048]; - server->sends++; + server->sends--; server->refreshtime = Sys_DoubleTime(); sprintf(data, "%c%c%c%cstatus", 255, 255, 255, 255); NET_SendPollPacket (strlen(data), data, server->adr); @@ -665,7 +1068,7 @@ void CL_QueryServers(void) if (op == 0) { - if (server->sends < 1) + if (server->sends > 0) { Master_QueryServer(server); } @@ -967,7 +1370,7 @@ void CL_MasterListParse(qboolean isq2) info->adr.port = (int)((short)(p1 + (p2<<8))); if ((old = Master_InfoForServer(info->adr))) //remove if the server already exists. { - old->sends = 0; //reset. + old->sends = 1; //reset. Z_Free(info); } else diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 3d22ffdaf..435dfd6af 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -601,29 +601,77 @@ static void PF_CopyEntity (progfuncs_t *prinst, struct globalvars_s *pr_globals) memcpy(out->fields, in->fields, menuentsize); } +#ifdef CL_MASTER +#include "cl_master.h" + +typedef enum{ + SLIST_HOSTCACHEVIEWCOUNT, + SLIST_HOSTCACHETOTALCOUNT, + SLIST_MASTERQUERYCOUNT, + SLIST_MASTERREPLYCOUNT, + SLIST_SERVERQUERYCOUNT, + SLIST_SERVERREPLYCOUNT, + SLIST_SORTFIELD, + SLIST_SORTDESCENDING +} hostcacheglobal_t; + void PF_gethostcachevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - #pragma message ("PF_gethostcachevalue: stub") + hostcacheglobal_t hcg = G_FLOAT(OFS_PARM0); G_FLOAT(OFS_RETURN) = 0; -} + switch(hcg) + { + case SLIST_HOSTCACHEVIEWCOUNT: + G_FLOAT(OFS_RETURN) = Master_NumSorted(); + return; + case SLIST_HOSTCACHETOTALCOUNT: + CL_QueryServers(); + NET_CheckPollSockets(); + G_FLOAT(OFS_RETURN) = Master_TotalCount(); + return; -void PF_gethostcachestring (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - #pragma message ("PF_gethostcachestring: stub") - G_INT(OFS_RETURN) = 0; + case SLIST_MASTERQUERYCOUNT: + case SLIST_MASTERREPLYCOUNT: + case SLIST_SERVERQUERYCOUNT: + case SLIST_SERVERREPLYCOUNT: + G_FLOAT(OFS_RETURN) = 0; + return; + + case SLIST_SORTFIELD: + G_FLOAT(OFS_RETURN) = Master_GetSortField(); + return; + case SLIST_SORTDESCENDING: + G_FLOAT(OFS_RETURN) = Master_GetSortDescending(); + return; + default: + return; + } } //void resethostcachemasks(void) = #615; void PF_M_resethostcachemasks(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + Master_ClearMasks(); } //void sethostcachemaskstring(float mask, float fld, string str, float op) = #616; void PF_M_sethostcachemaskstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + int mask = G_FLOAT(OFS_PARM0); + int field = G_FLOAT(OFS_PARM1); + char *str = PR_GetStringOfs(prinst, OFS_PARM2); + int op = G_FLOAT(OFS_PARM3); + + Master_SetMaskString(mask, field, str, op); } //void sethostcachemasknumber(float mask, float fld, float num, float op) = #617; void PF_M_sethostcachemasknumber(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + int mask = G_FLOAT(OFS_PARM0); + int field = G_FLOAT(OFS_PARM1); + int str = G_FLOAT(OFS_PARM2); + int op = G_FLOAT(OFS_PARM3); + + Master_SetMaskInteger(mask, field, str, op); } //void resorthostcache(void) = #618; void PF_M_resorthostcache(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -632,24 +680,77 @@ void PF_M_resorthostcache(progfuncs_t *prinst, struct globalvars_s *pr_globals) //void sethostcachesort(float fld, float descending) = #619; void PF_M_sethostcachesort(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + Master_SetSortField(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); } //void refreshhostcache(void) = #620; void PF_M_refreshhostcache(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + MasterInfo_Begin(); } //float gethostcachenumber(float fld, float hostnr) = #621; void PF_M_gethostcachenumber(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + float ret = 0; + int keynum = G_FLOAT(OFS_PARM0); + int svnum = G_FLOAT(OFS_PARM1); + serverinfo_t *sv; + sv = Master_SortedServer(svnum); + + ret = Master_ReadKeyFloat(sv, keynum); + + G_FLOAT(OFS_RETURN) = ret; } +void PF_gethostcachestring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *keyname = PF_TempStr(); + char *ret = ""; + int keynum = G_FLOAT(OFS_PARM0); + int svnum = G_FLOAT(OFS_PARM1); + serverinfo_t *sv; + sv = Master_SortedServer(svnum); + + ret = Master_ReadKeyString(sv, keynum); + + Q_strncpyz(keyname, ret, MAXTEMPBUFFERLEN); + RETURN_SSTRING(keyname); +} + //float gethostcacheindexforkey(string key) = #622; void PF_M_gethostcacheindexforkey(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + int i; + char *keyname = PR_GetStringOfs(prinst, OFS_PARM0); + + G_FLOAT(OFS_RETURN) = Master_KeyForName(keyname); } //void addwantedhostcachekey(string key) = #623; void PF_M_addwantedhostcachekey(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + PF_M_gethostcacheindexforkey(prinst, pr_globals); } +#else +void PF_gethostcachevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;} +void PF_gethostcachestring (progfuncs_t *prinst, struct globalvars_s *pr_globals) {G_INT(OFS_RETURN) = 0;} +//void resethostcachemasks(void) = #615; +void PF_M_resethostcachemasks(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +//void sethostcachemaskstring(float mask, float fld, string str, float op) = #616; +void PF_M_sethostcachemaskstring(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +//void sethostcachemasknumber(float mask, float fld, float num, float op) = #617; +void PF_M_sethostcachemasknumber(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +//void resorthostcache(void) = #618; +void PF_M_resorthostcache(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +//void sethostcachesort(float fld, float descending) = #619; +void PF_M_sethostcachesort(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +//void refreshhostcache(void) = #620; +void PF_M_refreshhostcache(progfuncs_t *prinst, struct globalvars_s *pr_globals) {} +//float gethostcachenumber(float fld, float hostnr) = #621; +void PF_M_gethostcachenumber(progfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;} +//float gethostcacheindexforkey(string key) = #622; +void PF_M_gethostcacheindexforkey(progfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;} +//void addwantedhostcachekey(string key) = #623; +void PF_M_addwantedhostcachekey(progfuncs_t *prinst, struct globalvars_s *pr_globals){} +#endif void PF_localsound (progfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/client/r_part.c b/engine/client/r_part.c index cfe08aa18..cdba2b106 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -55,7 +55,8 @@ int pt_explosion, pt_superbullet, pt_bullet, pt_spark, - pt_plasma; + pt_plasma, + pt_smoke; int pe_default, pe_size2, @@ -86,21 +87,24 @@ void P_ReadPointFile_f (void); #define MAX_BEAMS 2048 // default max # of beam segments #define MAX_PARTICLES 32768 // default max # of particles at one // time +#define MAX_DECALS 32768 // this is going to be expensive //int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; //int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; //int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3, 2, 1}; particle_t *free_particles; - particle_t *particles; //contains the initial list of alloced particles. int r_numparticles; beamseg_t *free_beams; - beamseg_t *beams; int r_numbeams; +clippeddecal_t *free_decals; +clippeddecal_t *decals; +int r_numdecals; + vec3_t r_pright, r_pup, r_ppn; extern cvar_t r_bouncysparks; @@ -190,7 +194,7 @@ typedef struct part_type_s { float offsetup; // make this into a vec3_t later with dir, possibly for mdls - enum {SM_BOX, SM_CIRCLE, SM_BALL, SM_SPIRAL, SM_TRACER, SM_TELEBOX, SM_LAVASPLASH, SM_UNICIRCLE, SM_FIELD} spawnmode; + enum {SM_BOX, SM_CIRCLE, SM_BALL, SM_SPIRAL, SM_TRACER, SM_TELEBOX, SM_LAVASPLASH, SM_UNICIRCLE, SM_FIELD, SM_DECAL} spawnmode; //box = even spread within the area //circle = around edge of a circle //ball = filled sphere @@ -212,6 +216,7 @@ typedef struct part_type_s { int loaded; particle_t *particles; + clippeddecal_t *clippeddecals; beamseg_t *beams; skytris_t *skytris; @@ -617,6 +622,8 @@ void P_ParticleEffect_f(void) ptype->spawnmode = SM_UNICIRCLE; else if (!strcmp(value, "syncfield")) ptype->spawnmode = SM_FIELD; + else if (!strcmp(value, "decal")) + ptype->spawnmode = SM_DECAL; else ptype->spawnmode = SM_BOX; @@ -1062,11 +1069,16 @@ void P_InitParticles (void) r_numbeams = MAX_BEAMS; + r_numdecals = MAX_DECALS; + particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); beams = (beamseg_t *) Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beams"); + + decals = (clippeddecal_t *) + Hunk_AllocName (r_numdecals * sizeof(clippeddecal_t), "decals"); Cmd_AddCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :) @@ -1123,6 +1135,7 @@ void P_InitParticles (void) pt_spark = P_AllocateParticleType("te_spark"); pt_plasma = P_AllocateParticleType("te_plasma"); + pt_smoke = P_AllocateParticleType("te_smoke"); pe_default = P_AllocateParticleType("pe_default"); pe_size2 = P_AllocateParticleType("pe_size2"); @@ -1140,13 +1153,16 @@ void P_ClearParticles (void) int i; free_particles = &particles[0]; - for (i=0 ;iloaded) return 1; + if (ptype->spawnmode == SM_DECAL) + { + clippeddecal_t *d; + int decalcount; + float dist; + vec3_t tangent, t2; + vec3_t vec={0.5, 0.5, 0.5}; + static vec3_t up = {0,0.73,-0.73}; + float *decverts; + int i; + + if (!free_decals) + return 0; + + if (!dir) + dir = up; + + VectorNormalize(vec); + CrossProduct(dir, vec, tangent); + CrossProduct(dir, tangent, t2); + + decalcount = Q1BSP_ClipDecal(org, dir, tangent, ptype->scale, &decverts); + while(decalcount) + { + if (!free_decals) + break; + + d = free_decals; + free_decals = d->next; + d->next = ptype->clippeddecals; + ptype->clippeddecals = d; + + VectorCopy((decverts+0), d->vertex[0]); + VectorCopy((decverts+3), d->vertex[1]); + VectorCopy((decverts+6), d->vertex[2]); + + for (i = 0; i < 3; i++) + { + VectorSubtract(d->vertex[i], org, vec); + dist = DotProduct(vec, dir)/ptype->scale; + d->texcoords[i][0] = ((DotProduct(vec, t2)*(1-dist))/ptype->scale)+0.5; + d->texcoords[i][1] = ((DotProduct(vec, tangent)*(1-dist))/ptype->scale)+0.5; + } + + d->die = ptype->randdie*frandom(); + + if (ptype->die) + d->alpha = ptype->alpha-d->die*(ptype->alpha/ptype->die)*ptype->alphachange; + else + d->alpha = ptype->alpha; + + if (ptype->colorindex >= 0) + { + int cidx; + cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; + cidx = ptype->colorindex + cidx; + if (cidx > 255) + d->alpha = d->alpha / 2; // Hexen 2 style transparency + cidx = d_8to24rgbtable[cidx & 0xff]; + d->rgb[0] = (cidx & 0xff) * (1/255.0); + d->rgb[1] = (cidx >> 8 & 0xff) * (1/255.0); + d->rgb[2] = (cidx >> 16 & 0xff) * (1/255.0); + } + else + VectorCopy(ptype->rgb, d->rgb); + vec[2] = frandom(); + vec[0] = vec[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); + vec[1] = vec[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); + vec[2] = vec[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); + d->rgb[0] += vec[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*d->die; + d->rgb[1] += vec[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*d->die; + d->rgb[2] += vec[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*d->die; + + d->die = particletime + ptype->die - d->die; + + decverts += 3*3; + decalcount--; + } + + return 0; + } + // get msvc to shut up j = k = l = 0; m = 0; @@ -3002,6 +3101,37 @@ void GL_DrawParticleBeam_Untextured(beamseg_t *b, part_type_t *type) // qglEnd(); } +void GL_DrawClippedDecal(clippeddecal_t *d, part_type_t *type) +{ + if (lasttype != type) + { + lasttype = type; + qglEnd(); + qglEnable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + if (type->blendmode == BM_ADD) //addative + qglBlendFunc(GL_SRC_ALPHA, GL_ONE); +// else if (type->blendmode == BM_SUBTRACT) //subtractive +// qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_TRIANGLES); + } + + qglColor4f(d->rgb[0], + d->rgb[1], + d->rgb[2], + d->alpha); + + qglTexCoord2fv(d->texcoords[0]); + qglVertex3fv(d->vertex[0]); + qglTexCoord2fv(d->texcoords[1]); + qglVertex3fv(d->vertex[1]); + qglTexCoord2fv(d->texcoords[2]); + qglVertex3fv(d->vertex[2]); +} + #endif #ifdef SWQUAKE void SWD_DrawParticleSpark(particle_t *p, part_type_t *type) @@ -3102,7 +3232,7 @@ void SWD_DrawParticleBeam(beamseg_t *beam, part_type_t *type) } #endif -void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void sparklineparticles(particle_t*,part_type_t*), void sparkfanparticles(particle_t*,part_type_t*), void beamparticlest(beamseg_t*,part_type_t*), void beamparticlesut(beamseg_t*,part_type_t*)) +void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void sparklineparticles(particle_t*,part_type_t*), void sparkfanparticles(particle_t*,part_type_t*), void beamparticlest(beamseg_t*,part_type_t*), void beamparticlesut(beamseg_t*,part_type_t*), void drawdecalparticles(clippeddecal_t*,part_type_t*)) { RSpeedMark(); @@ -3114,11 +3244,14 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void vec3_t stop, normal; part_type_t *type; particle_t *p, *kill; + clippeddecal_t *d, *dkill; ramp_t *ramp; float grav; vec3_t friction; float dist; - particle_t *kill_list, *kill_first; + particle_t *kill_list, *kill_first; //the kill list is to stop particles from being freed and reused whilst still in this loop + //which is bad because beams need to find out when particles died. Reuse can do wierd things. + //remember that they're not drawn instantly either. beamseg_t *b, *bkill; int traces=r_particle_tracelimit.value; @@ -3148,6 +3281,70 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void for (i = 0, type = &part_type[i]; i < numparticletypes; i++, type++) { + if (type->clippeddecals) + { + /* for ( ;; ) + { + dkill = type->clippeddecals; + if (dkill && dkill->die < particletime) + { + type->clippeddecals = dkill->next; + free_decals = + + + dkill->next = (clippeddecal_t *)kill_list; + kill_list = (particle_t*)dkill; + if (!kill_first) + kill_first = kill_list; + continue; + } + break; + }*/ + for (d=type->clippeddecals ; d ; d=d->next) + { + /* for ( ;; ) + { + dkill = d->next; + if (dkill && dkill->die < particletime) + { + d->next = dkill->next; + dkill->next = (clippeddecal_t *)kill_list; + kill_list = (particle_t*)dkill; + if (!kill_first) + kill_first = kill_list; + continue; + } + break; + } +*/ + + + switch (type->rampmode) + { + case RAMP_ABSOLUTE: + ramp = type->ramp + (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); + VectorCopy(ramp->rgb, d->rgb); + d->alpha = ramp->alpha; + break; + case RAMP_DELTA: //particle ramps + ramp = type->ramp + (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); + VectorMA(d->rgb, pframetime, ramp->rgb, d->rgb); + d->alpha -= pframetime*ramp->alpha; + break; + case RAMP_NONE: //particle changes acording to it's preset properties. + if (particletime < (d->die-type->die+type->rgbchangetime)) + { + d->rgb[0] += pframetime*type->rgbchange[0]; + d->rgb[1] += pframetime*type->rgbchange[1]; + d->rgb[2] += pframetime*type->rgbchange[2]; + } + d->alpha -= pframetime*(type->alpha/type->die)*type->alphachange; + } + + drawdecalparticles(d, type); + } + } + if (!type->particles) continue; @@ -3457,10 +3654,6 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void RSpeedEnd(RSPEED_PARTICLES); - RSpeedRemark(); - RQ_RenderDistAndClear(); - RSpeedEnd(RSPEED_PARTICLESDRAW); - // lazy delete for particles is done here if (kill_list) { @@ -3478,6 +3671,8 @@ R_DrawParticles */ void P_DrawParticles (void) { + RSpeedMark(); + P_AddRainParticles(); #if defined(RGLQUAKE) if (qrenderer == QR_OPENGL) @@ -3490,14 +3685,23 @@ void P_DrawParticles (void) GL_TexEnv(GL_MODULATE); qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (qglPolygonOffset) + qglPolygonOffset(-1, 0); + qglEnable(GL_POLYGON_OFFSET_FILL); qglBegin(GL_QUADS); - if (r_drawflat.value == 2) - DrawParticleTypes(GL_DrawSketchParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured);//GL_DrawParticleBeam_Sketched, GL_DrawParticleBeam_Sketched); + DrawParticleTypes(GL_DrawSketchParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); else - DrawParticleTypes(GL_DrawTexturedParticle, GL_DrawSparkedParticle, GL_DrawTrifanParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured); - + DrawParticleTypes(GL_DrawTexturedParticle, GL_DrawSparkedParticle, GL_DrawTrifanParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); qglEnd(); + qglDisable(GL_POLYGON_OFFSET_FILL); + + RSpeedRemark(); + qglBegin(GL_QUADS); + RQ_RenderDistAndClear(); + qglEnd(); + RSpeedEnd(RSPEED_PARTICLESDRAW); + qglEnable(GL_TEXTURE_2D); GL_TexEnv(GL_MODULATE); @@ -3510,9 +3714,13 @@ void P_DrawParticles (void) #ifdef SWQUAKE if (qrenderer == QR_SOFTWARE) { + DrawParticleTypes(SWD_DrawParticleBlob, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleBeam, SWD_DrawParticleBeam, NULL); + + RSpeedRemark(); D_StartParticles(); - DrawParticleTypes(SWD_DrawParticleBlob, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleBeam, SWD_DrawParticleBeam); + RQ_RenderDistAndClear(); D_EndParticles(); + RSpeedEnd(RSPEED_PARTICLESDRAW); return; } #endif diff --git a/engine/client/render.h b/engine/client/render.h index 6a7e28ff4..bc81bf375 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -377,4 +377,7 @@ int rquant[RQUANT_MAX]; #define RSpeedLocals() int rsp #define RSpeedMark() int rsp = r_speeds.value?Sys_DoubleTime()*1000000:0 #define RSpeedRemark() rsp = r_speeds.value?Sys_DoubleTime()*1000000:0 + +//extern void (_stdcall *qglFinish) (void); +//#define RSpeedEnd(spt) do {qglFinish(); rspeeds[spt] += r_speeds.value?Sys_DoubleTime()*1000000 - rsp:0;}while (0) #define RSpeedEnd(spt) rspeeds[spt] += r_speeds.value?Sys_DoubleTime()*1000000 - rsp:0 diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 26125d77e..28ce6bc86 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -143,6 +143,7 @@ extern cvar_t gl_maxdist; cvar_t gl_specular = {"gl_specular", "0"}; #endif cvar_t gl_detail = {"gl_detail", "0", NULL, CVAR_ARCHIVE}; +cvar_t gl_overbright = {"gl_overbright", "0", NULL, CVAR_ARCHIVE}; cvar_t r_shadows = {"r_shadows", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH}; cvar_t r_shadow_realtime_world = {"r_shadow_realtime_world", "0", NULL, CVAR_CHEAT}; cvar_t r_noaliasshadows = {"r_noaliasshadows", "0", NULL, CVAR_ARCHIVE}; @@ -315,6 +316,7 @@ void GLRenderer_Init(void) Cvar_Register (&gl_compress, GLRENDEREROPTIONS); Cvar_Register (&gl_driver, GLRENDEREROPTIONS); Cvar_Register (&gl_detail, GRAPHICALNICETIES); + Cvar_Register (&gl_overbright, GRAPHICALNICETIES); Cvar_Register (&gl_dither, GRAPHICALNICETIES); Cvar_Register (&r_fb_models, GRAPHICALNICETIES); Cvar_Register (&r_fb_bmodels, GRAPHICALNICETIES); diff --git a/engine/client/snd_win.c b/engine/client/snd_win.c index 9c0403a5e..5f3e96d01 100644 --- a/engine/client/snd_win.c +++ b/engine/client/snd_win.c @@ -513,9 +513,11 @@ sndinitstat SNDDMA_InitDirect (soundcardinfo_t *sc) dsnd_guids=0; dsndguid=NULL; dsndcard="DirectSound"; - if (snd_multipledevices) if (pDirectSoundEnumerate) pDirectSoundEnumerate(&DSEnumCallback, NULL); + if (!snd_multipledevices) + dsndguid=NULL; + aimedforguid++; if (!dsndguid) //no more... @@ -523,11 +525,15 @@ sndinitstat SNDDMA_InitDirect (soundcardinfo_t *sc) return SIS_NOMORE; //EAX attempt #ifndef MINIMAL - CoInitialize(NULL); - if (FAILED(CoCreateInstance( &CLSID_EAXDirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&sc->pDS ))) - sc->pDS=NULL; - else - IDirectSound_Initialize(sc->pDS, dsndguid); + sc->pDS = NULL; + if (snd_eax.value) + { + CoInitialize(NULL); + if (FAILED(CoCreateInstance( &CLSID_EAXDirectSound, dsndguid, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&sc->pDS ))) + sc->pDS=NULL; + else + IDirectSound_Initialize(sc->pDS, dsndguid); + } if (!sc->pDS) #endif @@ -548,7 +554,7 @@ sndinitstat SNDDMA_InitDirect (soundcardinfo_t *sc) // { Con_SafePrintf (": failure\n" " hardware already in use\n" - " Close the app then use snd_restart\n"); + " Close the other app then use snd_restart\n"); return SIS_NOTAVAIL; // } } @@ -1016,7 +1022,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) sc->snd_isdirect = true; if (snd_firsttime) - Con_SafePrintf ("%s initialized\n", sc->name); + Con_DPrintf ("%s initialized\n", sc->name); return 1; } @@ -1025,7 +1031,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) else { sc->snd_isdirect = false; - Con_SafePrintf ("DirectSound failed to init\n"); + Con_DPrintf ("DirectSound failed to init\n"); } } } diff --git a/engine/client/spritegn.h b/engine/client/spritegn.h index 99e1a64ad..8b66928f2 100644 --- a/engine/client/spritegn.h +++ b/engine/client/spritegn.h @@ -59,6 +59,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #define SPRITE_VERSION 1 +#define SPRITEHL_VERSION 2 #define SPRITE32_VERSION 32 // must match definition in modelgen.h diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 32164b8ac..14e3c5332 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -182,7 +182,22 @@ static void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) \ TP_CVAR(tp_name_enemy, "enemy"); \ TP_CVAR(tp_name_teammate, ""); \ - TP_CVAR(tp_name_eyes, "eyes") + TP_CVAR(tp_name_eyes, "eyes"); \ + \ + TP_CVAR(loc_name_seperator, "-"); \ + TP_CVAR(loc_name_ssg, "ssg"); \ + TP_CVAR(loc_name_ng, "ng"); \ + TP_CVAR(loc_name_sng, "sng"); \ + TP_CVAR(loc_name_gl, "gl"); \ + TP_CVAR(loc_name_rl, "rl"); \ + TP_CVAR(loc_name_lg, "lg"); \ + TP_CVAR(loc_name_ga, "ga"); \ + TP_CVAR(loc_name_ya, "ya"); \ + TP_CVAR(loc_name_ra, "ra"); \ + TP_CVAR(loc_name_quad, "quad"); \ + TP_CVAR(loc_name_pent, "pent"); \ + TP_CVAR(loc_name_ring, "ring"); \ + TP_CVAR(loc_name_suit, "suit") //create the globals for all the TP cvars. #define TP_CVAR(name,def) cvar_t name = {#name, def} diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 46e9c6e8a..86e0a9f64 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -105,7 +105,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ZYMOTICMODELS //zymotic skeletal models. #define HUFFNETWORK //huffman network compression #define HALFLIFEMODELS //halflife model support (experimental) - #define DOOMWADS //doom wad/map/sprite support +// #define DOOMWADS //doom wad/map/sprite support //#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet) #define Q2BSPS //quake 2 bsp support #define Q3BSPS //quake 3 bsp support diff --git a/engine/common/common.c b/engine/common/common.c index 048447fa7..bc70c1c24 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -4201,6 +4201,7 @@ potentialgamepath_t pgp[] = { {"%s/id1/pak0.pak", "%s/id1"}, //quake1 {"%s/baseq2/pak0.pak", "%s/baseq2"}, //quake2 {"%s/data1/pak0.pak", "%s/data1"}, //hexen2 + {"%s/data/data.pk3", "%s/data"}, //nexuiz {"%s/baseq3/pak0.pk3", "%s/baseq3"}, //quake3 {"%s/base/assets0.pk3", "%s/base"} //jk2 }; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index d351aadac..9883e6d1e 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -332,7 +332,7 @@ int c_pointcontents; int c_traces, c_brush_traces; -vec4_t *map_verts; //3points + pad (I'm not entirly sure of the need for the pad, maybe it's just faster) +vec3_t *map_verts; //3points int numvertexes; vec2_t *map_vertstmexcoords; @@ -435,7 +435,7 @@ qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2 Patch_FlatnessTest =============== */ -static int Patch_FlatnessTest ( float maxflat, vec4_t point0, vec4_t point1, vec4_t point2 ) +static int Patch_FlatnessTest ( float maxflat, const vec3_t point0, const vec3_t point1, const vec3_t point2 ) { vec3_t v1, v2, v3; vec3_t t, n; @@ -473,7 +473,7 @@ static int Patch_FlatnessTest ( float maxflat, vec4_t point0, vec4_t point1, vec Patch_GetFlatness =============== */ -void Patch_GetFlatness ( float maxflat, vec4_t *points, int *patch_cp, int *flat ) +void Patch_GetFlatness ( float maxflat, const vec3_t *points, int *patch_cp, int *flat ) { int i, p, u, v; @@ -528,7 +528,7 @@ static void Patch_Evaluate_QuadricBezier ( float t, vec4_t point0, vec4_t point1 Patch_Evaluate =============== */ -void Patch_Evaluate ( vec4_t *p, int *numcp, int *tess, vec4_t *dest ) +void Patch_Evaluate ( const vec4_t *p, const int *numcp, const int *tess, vec4_t *dest ) { int num_patches[2], num_tess[2]; int index[3], dstpitch, i, u, v, x, y; @@ -725,10 +725,10 @@ void CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surface } } -void CM_CreatePatch ( q3cpatch_t *patch, int numverts, vec4_t *verts, int *patch_cp ) +void CM_CreatePatch ( q3cpatch_t *patch, int numverts, const vec3_t *verts, int *patch_cp ) { int step[2], size[2], flat[2], i, u, v; - vec4_t points[MAX_CM_PATCH_VERTS]; + vec4_t points[MAX_CM_PATCH_VERTS], pointss[MAX_CM_PATCH_VERTS]; vec3_t tverts[4], tverts2[4]; q2cbrush_t *brush; mplane_t mainplane; @@ -746,8 +746,10 @@ void CM_CreatePatch ( q3cpatch_t *patch, int numverts, vec4_t *verts, int *patch return; } + for (i = 0; i < numverts; i++) + VectorCopy(verts[i], pointss[i]); // fill in - Patch_Evaluate ( verts, patch_cp, step, points ); + Patch_Evaluate ( pointss, patch_cp, step, points ); patch->brushes = brush = map_brushes + numbrushes; patch->numbrushes = 0; @@ -1857,7 +1859,7 @@ void CModQ3_LoadSubmodels (lump_t *l) } } -void CModQ3_LoadShaders (lump_t *l) +void CModQ3_LoadShaders (lump_t *l, qboolean useshaders) { dq3shader_t *in; q2mapsurface_t *out; @@ -1889,8 +1891,7 @@ void CModQ3_LoadShaders (lump_t *l) loadmodel->texinfo[i].texture = Hunk_Alloc(sizeof(texture_t)); Q_strncpyz(loadmodel->texinfo[i].texture->name, in->shadername, sizeof(loadmodel->texinfo[i].texture->name)); #ifdef RGLQUAKE -#ifndef Q3SHADERS - if (qrenderer == QR_OPENGL) + if (qrenderer == QR_OPENGL && !useshaders) { loadmodel->texinfo[i].texture->gl_texturenum = Mod_LoadHiResTexture(in->shadername, loadname, true, false, true); if (!loadmodel->texinfo[i].texture->gl_texturenum) @@ -1898,7 +1899,6 @@ void CModQ3_LoadShaders (lump_t *l) loadmodel->texinfo[i].texture->gl_texturenumfb = 0; loadmodel->texinfo[i].texture->gl_texturenumbumpmap = 0; } -#endif #endif loadmodel->textures[i] = loadmodel->texinfo[i].texture; @@ -1918,7 +1918,7 @@ void CModQ3_LoadShaders (lump_t *l) void CModQ3_LoadVertexes (lump_t *l) { q3dvertex_t *in; - vec4_t *out; + vec3_t *out; vec3_t *nout; int i, count, j; vec2_t *lmout, *stout; @@ -1966,7 +1966,7 @@ void CModQ3_LoadVertexes (lump_t *l) void CModRBSP_LoadVertexes (lump_t *l) { rbspvertex_t *in; - vec4_t *out; + vec3_t *out; vec3_t *nout; int i, count, j; vec2_t *lmout, *stout; @@ -2222,7 +2222,7 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in int numindexes, patch_cp[2], step[2], size[2], flat[2], i, u, v, p; vec4_t colors[MAX_ARRAY_VERTS], points[MAX_ARRAY_VERTS], normals[MAX_ARRAY_VERTS], lm_st[MAX_ARRAY_VERTS], tex_st[MAX_ARRAY_VERTS]; - vec4_t c, colors2[MAX_ARRAY_VERTS], normals2[MAX_ARRAY_VERTS], lm_st2[MAX_ARRAY_VERTS], tex_st2[MAX_ARRAY_VERTS]; + vec4_t c, colors2[MAX_ARRAY_VERTS], points2[MAX_ARRAY_VERTS], normals2[MAX_ARRAY_VERTS], lm_st2[MAX_ARRAY_VERTS], tex_st2[MAX_ARRAY_VERTS]; mesh_t *mesh; index_t *indexes; float subdivlevel; @@ -2247,7 +2247,7 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in } // find the degree of subdivision in the u and v directions - Patch_GetFlatness ( subdivlevel, points, patch_cp, flat ); + Patch_GetFlatness ( subdivlevel, map_verts+firstvert, patch_cp, flat ); // allocate space for mesh step[0] = (1 << flat[0]); @@ -2263,7 +2263,7 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in mesh = (mesh_t *)Hunk_TempAllocMore ( sizeof(mesh_t)); mesh->numvertexes = numverts; - mesh->xyz_array = Hunk_TempAllocMore ( numverts * sizeof(vec4_t)); + mesh->xyz_array = Hunk_TempAllocMore ( numverts * sizeof(vec3_t)); mesh->normals_array = Hunk_TempAllocMore ( numverts * sizeof(vec3_t)); mesh->st_array = Hunk_TempAllocMore ( numverts * sizeof(vec2_t)); mesh->lmst_array = Hunk_TempAllocMore ( numverts * sizeof(vec2_t)); @@ -2273,7 +2273,7 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in mesh->patchHeight = size[1]; // fill in - Patch_Evaluate ( points, patch_cp, step, mesh->xyz_array ); + Patch_Evaluate ( points, patch_cp, step, points2 ); Patch_Evaluate ( colors, patch_cp, step, colors2 ); Patch_Evaluate ( normals, patch_cp, step, normals2 ); Patch_Evaluate ( lm_st, patch_cp, step, lm_st2 ); @@ -2281,6 +2281,7 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in for (i = 0; i < numverts; i++) { + VectorCopy ( points2[i], mesh->xyz_array[i] ); VectorNormalize2 ( normals2[i], mesh->normals_array[i] ); ColorNormalize ( colors2[i], c ); Vector4Scale ( c, 255.0, mesh->colors_array[i] ); @@ -2333,8 +2334,8 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in #endif - -void CModQ3_LoadRFaces (lump_t *l) +mesh_t nullmesh; +void CModQ3_LoadRFaces (lump_t *l, qboolean useshaders) { #ifndef Q3SHADERS int polysize = sizeof(glpoly_t) - VERTEXSIZE*sizeof(float); @@ -2352,12 +2353,7 @@ void CModQ3_LoadRFaces (lump_t *l) int numverts, numindexes; int fv; - mesh_t *mesh; - - extern cvar_t gl_shadeq3; - - int shaders = gl_shadeq3.value; - + mesh_t *mesh; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -2405,7 +2401,7 @@ continue; out->flags |= SURF_DRAWSKY; #ifdef Q3SHADERS - if (!out->texinfo->texture->shader && shaders) + if (!out->texinfo->texture->shader && useshaders) { extern cvar_t r_vertexlight; if (in->facetype == MST_FLARE) @@ -2423,9 +2419,7 @@ continue; #endif if (map_surfaces[in->shadernum].c.flags & (Q3SURF_NODRAW | Q3SURF_SKIP)) { - if (map_surfaces[in->shadernum].c.flags & Q3SURF_SKIP) - Con_Printf("Surface skip\n"); - out->mesh = NULL; + out->mesh = &nullmesh; } else if (in->facetype == MST_PATCH) { @@ -2455,7 +2449,7 @@ continue; extern index_t r_quad_indexes[6]; mesh = out->mesh = (mesh_t *)Hunk_Alloc ( sizeof(mesh_t)); - mesh->xyz_array = (vec4_t *)Hunk_Alloc ( sizeof(vec4_t)); + mesh->xyz_array = (vec3_t *)Hunk_Alloc ( sizeof(vec3_t)); mesh->numvertexes = 1; mesh->indexes = r_quad_indexes; mesh->numindexes = 6; @@ -2475,7 +2469,7 @@ continue; } } -void CModRBSP_LoadRFaces (lump_t *l) +void CModRBSP_LoadRFaces (lump_t *l, qboolean useshaders) { #ifndef Q3SHADERS int polysize = sizeof(glpoly_t) - VERTEXSIZE*sizeof(float); @@ -2494,10 +2488,6 @@ void CModRBSP_LoadRFaces (lump_t *l) int fv; mesh_t *mesh; - - extern cvar_t gl_shadeq3; - - int shaders = gl_shadeq3.value; in = (void *)(mod_base + l->fileofs); @@ -2546,7 +2536,7 @@ continue; out->flags |= SURF_DRAWSKY; #ifdef Q3SHADERS - if (!out->texinfo->texture->shader && shaders) + if (!out->texinfo->texture->shader && useshaders) { extern cvar_t r_vertexlight; if (in->facetype == MST_FLARE) @@ -2596,7 +2586,7 @@ continue; extern index_t r_quad_indexes[6]; mesh = out->mesh = (mesh_t *)Hunk_Alloc ( sizeof(mesh_t)); - mesh->xyz_array = (vec4_t *)Hunk_Alloc ( sizeof(vec4_t)); + mesh->xyz_array = (vec3_t *)Hunk_Alloc ( sizeof(vec3_t)); mesh->numvertexes = 1; mesh->indexes = r_quad_indexes; mesh->numindexes = 6; @@ -3121,6 +3111,8 @@ void CMQ3_CalcPHS (void) map_q3phs->rowsize = map_q3pvs->rowsize; map_q3phs->numclusters = numclusters = map_q3pvs->numclusters; + if (!numclusters) + return; vcount = 0; for (i=0 ; ifromgame = fg_quake3; for (i=0 ; ichildren[1]); } +#define MAXFRAGMENTTRIS 256 +vec3_t decalfragmentverts[MAXFRAGMENTTRIS*3]; + +typedef struct { + vec3_t center; + + vec3_t normal; + vec3_t tangent1; + vec3_t tangent2; + + vec3_t planenorm[6]; + float planedist[6]; + + vec_t radius; + int numtris; + +} fragmentdecal_t; + +#define FloatInterpolate(a, bness, b, c) (c) = (a)*(1-bness) + (b)*bness +#define VectorInterpolate(a, bness, b, c) FloatInterpolate((a)[0], bness, (b)[0], (c)[0]),FloatInterpolate((a)[1], bness, (b)[1], (c)[1]),FloatInterpolate((a)[2], bness, (b)[2], (c)[2]) + +//#define SHOWCLIPS +//#define FRAGMENTASTRIANGLES //works, but produces more fragments. + +#ifdef FRAGMENTASTRIANGLES + +//if the triangle is clipped away, go recursive if there are tris left. +void Fragment_ClipTriToPlane(int trinum, float *plane, float planedist, fragmentdecal_t *dec) +{ + float *point[3]; + float dotv[3]; + + vec3_t impact1, impact2; + float t; + + int i, i2, i3; + int clippedverts = 0; + + for (i = 0; i < 3; i++) + { + point[i] = decalfragmentverts[trinum*3+i]; + dotv[i] = DotProduct(point[i], plane)-planedist; + clippedverts += dotv[i] < 0; + } + + //if they're all clipped away, scrap the tri + switch (clippedverts) + { + case 0: + return; //plane does not clip the triangle. + + case 1: //split into 3, disregard the clipped vert + for (i = 0; i < 3; i++) + { + if (dotv[i] < 0) + { //This is the vertex that's getting clipped. + + if (dotv[i] > -DIST_EPSILON) + return; //it's only over the line by a tiny ammount. + + i2 = (i+1)%3; + i3 = (i+2)%3; + + if (dotv[i2] < DIST_EPSILON) + return; + if (dotv[i3] < DIST_EPSILON) + return; + + //work out where the two lines impact the plane + t = (dotv[i]) / (dotv[i]-dotv[i2]); + VectorInterpolate(point[i], t, point[i2], impact1); + + t = (dotv[i]) / (dotv[i]-dotv[i3]); + VectorInterpolate(point[i], t, point[i3], impact2); + +#ifdef SHOWCLIPS + if (dec->numtris != MAXFRAGMENTTRIS) + { + VectorCopy(impact2, decalfragmentverts[dec->numtris*3+0]); + VectorCopy(decalfragmentverts[trinum*3+i], decalfragmentverts[dec->numtris*3+1]); + VectorCopy(impact1, decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + } +#endif + + + //shrink the tri, putting the impact into the killed vertex. + VectorCopy(impact2, point[i]); + + + if (dec->numtris == MAXFRAGMENTTRIS) + return; //:( + + //build the second tri + VectorCopy(impact1, decalfragmentverts[dec->numtris*3+0]); + VectorCopy(decalfragmentverts[trinum*3+i2], decalfragmentverts[dec->numtris*3+1]); + VectorCopy(impact2, decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + + return; + } + } + Sys_Error("Fragment_ClipTriToPlane: Clipped vertex not founc\n"); + return; //can't handle it + case 2: //split into 3, disregarding both the clipped. + for (i = 0; i < 3; i++) + { + if (!(dotv[i] < 0)) + { //This is the vertex that's staying. + + if (dotv[i] < DIST_EPSILON) + break; //only just inside + + i2 = (i+1)%3; + i3 = (i+2)%3; + + //work out where the two lines impact the plane + t = (dotv[i]) / (dotv[i]-dotv[i2]); + VectorInterpolate(point[i], t, point[i2], impact1); + + t = (dotv[i]) / (dotv[i]-dotv[i3]); + VectorInterpolate(point[i], t, point[i3], impact2); + + //shrink the tri, putting the impact into the killed vertex. + +#ifdef SHOWCLIPS + if (dec->numtris != MAXFRAGMENTTRIS) + { + VectorCopy(impact1, decalfragmentverts[dec->numtris*3+0]); + VectorCopy(point[i2], decalfragmentverts[dec->numtris*3+1]); + VectorCopy(point[i3], decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + } + if (dec->numtris != MAXFRAGMENTTRIS) + { + VectorCopy(impact1, decalfragmentverts[dec->numtris*3+0]); + VectorCopy(point[i3], decalfragmentverts[dec->numtris*3+1]); + VectorCopy(impact2, decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + } +#endif + + VectorCopy(impact1, point[i2]); + VectorCopy(impact2, point[i3]); + return; + } + } + case 3://scrap it + //fill the verts with the verts of the last and go recursive (due to the nature of Fragment_ClipTriangle, which doesn't actually know if we clip them away) +#ifndef SHOWCLIPS + dec->numtris--; + VectorCopy(decalfragmentverts[dec->numtris*3+0], decalfragmentverts[trinum*3+0]); + VectorCopy(decalfragmentverts[dec->numtris*3+1], decalfragmentverts[trinum*3+1]); + VectorCopy(decalfragmentverts[dec->numtris*3+2], decalfragmentverts[trinum*3+2]); + if (trinum < dec->numtris) + Fragment_ClipTriToPlane(trinum, plane, planedist, dec); +#endif + return; + } +} + +void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c) +{ + //emit the triangle, and clip it's fragments. + int start, i; + + int p; + + if (dec->numtris == MAXFRAGMENTTRIS) + return; //:( + + start = dec->numtris; + + VectorCopy(a, decalfragmentverts[dec->numtris*3+0]); + VectorCopy(b, decalfragmentverts[dec->numtris*3+1]); + VectorCopy(c, decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + + //clip all the fragments to all of the planes. + //This will produce a quad if the source triangle was big enough. + + for (p = 0; p < 6; p++) + { + for (i = start; i < dec->numtris; i++) + Fragment_ClipTriToPlane(i, dec->planenorm[p], dec->plantdist[p], dec); + } +} + +#else + +#define MAXFRAGMENTVERTS 128 +int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float *plane, float planedist) +{ + float dotv[MAXFRAGMENTVERTS]; + int i, i2, i3; + int outcount = 0; + int clippedcount = 0; + vec3_t impact; + + float *lastvalid; //the reason these arn't just an index is because it'd need to be a special case for the first vert. + float lastvaliddot; + + for (i = 0; i < incount; i++) + { + dotv[i] = DotProduct((inverts+i*3), plane) - planedist; + if (dotv[i]<-DIST_EPSILON) + clippedcount++; + else + { + lastvalid = inverts+i*3; + lastvaliddot = dotv[i]; + } + } + + if (clippedcount == incount) + return 0; //all were clipped + if (clippedcount == 0) + { + memcpy(outverts, inverts, sizeof(float)*3*incount); + return incount; + } + + for (i = 0; i < incount; ) + { + if (dotv[i] < -DIST_EPSILON) //clipped + { + //work out where the line impacts the plane + lastvaliddot = (dotv[i]) / (dotv[i]-lastvaliddot); + VectorInterpolate((inverts+i*3), lastvaliddot, lastvalid, impact); + + if (outcount+1 >= MAXFRAGMENTVERTS) //bum + break; + + outverts[outcount*3 + 0] = impact[0]; + outverts[outcount*3 + 1] = impact[1]; + outverts[outcount*3 + 2] = impact[2]; + outcount++; + + i3 = (i+1); + while (dotv[i3%incount] < -DIST_EPSILON) //clipped + i3++; + i = (i3-1)%incount; + i2=i3%incount; + + lastvaliddot = (dotv[i]) / (dotv[i]-dotv[i2]); + VectorInterpolate((inverts+i*3), lastvaliddot, (inverts+i2*3), impact); + + outverts[outcount*3 + 0] = impact[0]; + outverts[outcount*3 + 1] = impact[1]; + outverts[outcount*3 + 2] = impact[2]; + outcount++; + lastvalid = outverts+outcount*3; + lastvaliddot = 0; // :) + + i = i3; + } + else + { //this vertex wasn't clipped. Just copy to the output. + + if (outcount == MAXFRAGMENTVERTS) //bum + break; + + outverts[outcount*3 + 0] = inverts[i*3 + 0]; + outverts[outcount*3 + 1] = inverts[i*3 + 1]; + outverts[outcount*3 + 2] = inverts[i*3 + 2]; + lastvalid = inverts+i*3; + lastvaliddot = dotv[i]; + + outcount++; + i++; + } + } + + return outcount; +} + +void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c) +{ + //emit the triangle, and clip it's fragments. + int start, i; + int p; + float verts[MAXFRAGMENTVERTS*3]; + float verts2[MAXFRAGMENTVERTS*3]; + int numverts; + + + if (dec->numtris == MAXFRAGMENTTRIS) + return; //don't bother + + VectorCopy(a, (verts+0*3)); + VectorCopy(b, (verts+1*3)); + VectorCopy(c, (verts+2*3)); + numverts = 3; + + //clip the triangle to the 6 planes. + for (p = 0; p < 6; p+=2) + { + numverts = Fragment_ClipPolyToPlane(verts, verts2, numverts, dec->planenorm[p], dec->planedist[p]); + if (numverts < 3) //totally clipped. + return; + + numverts = Fragment_ClipPolyToPlane(verts2, verts, numverts, dec->planenorm[p+1], dec->planedist[p+1]); + if (numverts < 3) //totally clipped. + return; + } + + //decompose the resultant polygon into triangles. + + while(numverts>2) + { + if (dec->numtris == MAXFRAGMENTTRIS) + return; + + numverts--; + + VectorCopy((verts+3*0), decalfragmentverts[dec->numtris*3+0]); + VectorCopy((verts+3*(numverts-1)), decalfragmentverts[dec->numtris*3+1]); + VectorCopy((verts+3*numverts), decalfragmentverts[dec->numtris*3+2]); + dec->numtris++; + } +} + +#endif + +//this could be inlined, but I'm lazy. +void Q1BSP_FragmentToMesh (fragmentdecal_t *dec, mesh_t *mesh) +{ + int i; + + float *a, *b, *c; + + for (i = 0; i < mesh->numindexes; i+=3) + { + if (dec->numtris == MAXFRAGMENTTRIS) + break; + a = mesh->xyz_array[mesh->indexes[i+0]]; + b = mesh->xyz_array[mesh->indexes[i+1]]; + c = mesh->xyz_array[mesh->indexes[i+2]]; + + Fragment_ClipTriangle(dec, a, b, c); + } +} + +#include "glquake.h" +void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) +{ + mplane_t *splitplane; + float dist; + msurface_t *surf; + int i; + + if (node->contents < 0) + return; + + splitplane = node->plane; + dist = DotProduct (dec->center, splitplane->normal) - splitplane->dist; + + if (dist > dec->radius) + { + Q1BSP_ClipDecalToNodes (dec, node->children[0]); + return; + } + if (dist < -dec->radius) + { + Q1BSP_ClipDecalToNodes (dec, node->children[1]); + return; + } + +// mark the polygons + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + Q1BSP_FragmentToMesh(dec, surf->mesh); + } + + Q1BSP_ClipDecalToNodes (dec, node->children[0]); + Q1BSP_ClipDecalToNodes (dec, node->children[1]); +} + +int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent, float size, float **out) +{ //quad marks a full, independant quad + int p; + fragmentdecal_t dec; + + VectorCopy(center, dec.center); + VectorCopy(normal, dec.normal); + VectorCopy(tangent, dec.tangent1); + CrossProduct(tangent, normal, dec.tangent2); + dec.radius = size/2; + dec.numtris = 0; + + VectorCopy(dec.tangent1, dec.planenorm[0]); + VectorNegate(dec.tangent1, dec.planenorm[1]); + VectorCopy(dec.tangent2, dec.planenorm[2]); + VectorNegate(dec.tangent2, dec.planenorm[3]); + VectorCopy(dec.normal, dec.planenorm[4]); + VectorNegate(dec.normal, dec.planenorm[5]); + for (p = 0; p < 6; p++) + dec.planedist[p] = -(dec.radius - DotProduct(dec.center, dec.planenorm[p])); + + Q1BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes); + + *out = (float *)decalfragmentverts; + return dec.numtris; +} + +//This is spike's testing function, and is only usable by gl. :) +void Q1BSP_TestClipDecal(void) +{ + /* + int i; + int numtris; + vec3_t fwd; + vec3_t start; + vec3_t center, normal, tangent; + float *verts; + + if (cls.state != ca_active) + return; + + VectorCopy(cl.simorg[0], start); + start[2]+=22; + VectorMA(start, 10000, vpn, fwd); + + TraceLineN(start, fwd, center, normal); + + CrossProduct(fwd, normal, tangent); + VectorNormalize(tangent); + + numtris = Q1BSP_ClipDecal(center, normal, tangent, 128, &verts); + qglDisable(GL_TEXTURE_2D); + qglDisable(GL_BLEND); + qglDisable(GL_DEPTH_TEST); + + qglColor3f(1, 0, 0); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_TRIANGLES); + for (i = 0; i < numtris; i++) + { + qglVertex3fv(verts+i*9+0); + qglVertex3fv(verts+i*9+3); + qglVertex3fv(verts+i*9+6); + } + qglEnd(); + + qglColor3f(1, 1, 1); + qglBegin(GL_LINES); + for (i = 0; i < numtris; i++) + { + qglVertex3fv(verts+i*9+0); + qglVertex3fv(verts+i*9+3); + qglVertex3fv(verts+i*9+3); + qglVertex3fv(verts+i*9+6); + qglVertex3fv(verts+i*9+6); + qglVertex3fv(verts+i*9+0); + } + + qglVertex3fv(center); + VectorMA(center, 10, normal, fwd); + qglVertex3fv(fwd); + + qglColor3f(0, 1, 0); + qglVertex3fv(center); + VectorMA(center, 10, tangent, fwd); + qglVertex3fv(fwd); + + qglColor3f(0, 0, 1); + qglVertex3fv(center); + CrossProduct(tangent, normal, fwd); + VectorMA(center, 10, fwd, fwd); + qglVertex3fv(fwd); + + qglColor3f(1, 1, 1); + + qglEnd(); + qglEnable(GL_TEXTURE_2D); + qglEnable(GL_DEPTH_TEST); + */ +} + #endif /* Rendering functions (Client only) @@ -328,6 +808,10 @@ void Q1BSP_FatPVS (vec3_t org, qboolean add) qboolean Q1BSP_EdictInFatPVS(edict_t *ent) { int i; + + if (ent->num_leafs == MAX_ENT_LEAFS+1) + return true; //it's in too many leafs for us to cope with. Just trivially accept it. + for (i=0 ; i < ent->num_leafs ; i++) if (fatpvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) )) return true; //we might be able to see this one. @@ -356,8 +840,11 @@ void Q1BSP_RFindTouchedLeafs (edict_t *ent, mnode_t *node) if ( node->contents < 0) { - if (ent->num_leafs == MAX_ENT_LEAFS) + if (ent->num_leafs >= MAX_ENT_LEAFS) + { + ent->num_leafs = MAX_ENT_LEAFS+1; //too many. mark it as such so we can trivially accept huge mega-big brush models. return; + } leaf = (mleaf_t *)node; leafnum = leaf - sv.worldmodel->leafs - 1; diff --git a/engine/common/qvm.c b/engine/common/qvm.c index c961a188d..7c5e8a193 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -963,7 +963,7 @@ vm_t *VM_Create(vm_t *vm, const char *name, sys_call_t syscall, sys_callex_t sys { if((vm->hInst=Sys_LoadDLL(name, (void**)&vm->vmMain, syscall))) { - Con_Printf("Creating native machine \"%s\"\n", name); + Con_DPrintf("Creating native machine \"%s\"\n", name); vm->type=VM_NATIVE; return vm; } @@ -972,7 +972,7 @@ vm_t *VM_Create(vm_t *vm, const char *name, sys_call_t syscall, sys_callex_t sys if((vm->hInst=QVM_Load(name, syscallex))) { - Con_Printf("Creating virtual machine \"%s\"\n", name); + Con_DPrintf("Creating virtual machine \"%s\"\n", name); vm->type=VM_BYTECODE; return vm; } diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 92b79adef..17603e714 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -2571,6 +2571,14 @@ SOURCE=..\client\zqtp.c # PROP Default_Filter "" # Begin Source File +SOURCE=..\gl\doomclip.c +# End Source File +# Begin Source File + +SOURCE=..\gl\doommap.h +# End Source File +# Begin Source File + SOURCE=..\gl\gl_alias.c !IF "$(CFG)" == "ftequake - Win32 Release" diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 2d6ee519c..0f5ef23eb 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -58,7 +58,7 @@ int numTempColours; byte_vec4_t *tempColours; int numTempVertexCoords; -vec4_t *tempVertexCoords; +vec3_t *tempVertexCoords; int numTempNormals; vec3_t *tempNormals; @@ -179,14 +179,11 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float if (p1v == p2v || r_nolerp.value) { mesh->normals_array = (vec3_t*)((char *)p1 + p1->ofsnormals); + mesh->xyz_array = p1v; if (r_nolightdir.value) { for (i = 0; i < mesh->numvertexes; i++) { - mesh->xyz_array[i][0] = p1v[i][0]; - mesh->xyz_array[i][1] = p1v[i][1]; - mesh->xyz_array[i][2] = p1v[i][2]; - mesh->colors_array[i][0] = /*ambientlight[0]/2*/+shadelight[0]; mesh->colors_array[i][1] = /*ambientlight[1]/2*/+shadelight[1]; mesh->colors_array[i][2] = /*ambientlight[2]/2*/+shadelight[2]; @@ -197,10 +194,6 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float { for (i = 0; i < mesh->numvertexes; i++) { - mesh->xyz_array[i][0] = p1v[i][0]; - mesh->xyz_array[i][1] = p1v[i][1]; - mesh->xyz_array[i][2] = p1v[i][2]; - l = DotProduct(mesh->normals_array[i], shadevector); temp = l*ambientlight[0]+shadelight[0]; @@ -276,11 +269,25 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float } if (expand) { - for (i = 0; i < mesh->numvertexes; i++) + if (mesh->xyz_array == p1v) { - mesh->xyz_array[i][0] += mesh->normals_array[i][0]*expand; - mesh->xyz_array[i][1] += mesh->normals_array[i][1]*expand; - mesh->xyz_array[i][2] += mesh->normals_array[i][2]*expand; + mesh->xyz_array = tempVertexCoords; + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->xyz_array[i][0] = p1v[i][0] + mesh->normals_array[i][0]*expand; + mesh->xyz_array[i][1] = p1v[i][1] + mesh->normals_array[i][1]*expand; + mesh->xyz_array[i][2] = p1v[i][2] + mesh->normals_array[i][2]*expand; + } + + } + else + { + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->xyz_array[i][0] += mesh->normals_array[i][0]*expand; + mesh->xyz_array[i][1] += mesh->normals_array[i][1]*expand; + mesh->xyz_array[i][2] += mesh->normals_array[i][2]*expand; + } } } } @@ -341,7 +348,7 @@ static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int po v = weights; for (i = 0;i < numweights;i++, v++) { - out = outhead + v->vertexindex * 4; + out = outhead + v->vertexindex * 3; matrix = bonepose[v->boneindex]; // FIXME: this can very easily be optimized with SSE or 3DNow out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; @@ -893,7 +900,7 @@ static void R_ProjectShadowVolume(mesh_t *mesh, vec3_t lightpos) { int numverts = mesh->numvertexes; int i; - vec4_t *input = mesh->xyz_array; + vec3_t *input = mesh->xyz_array; vec3_t *projected; if (numProjectedShadowVerts < numverts) { @@ -915,7 +922,7 @@ static void R_DrawShadowVolume(mesh_t *mesh) { int t; vec3_t *proj = ProjectedShadowVerts; - vec4_t *verts = mesh->xyz_array; + vec3_t *verts = mesh->xyz_array; index_t *indexes = mesh->indexes; int *neighbours = mesh->trneighbors; int numtris = mesh->numindexes/3; @@ -990,7 +997,7 @@ void GL_DrawAliasMesh_Sketch (mesh_t *mesh) qglDisable(GL_TEXTURE_2D); - qglVertexPointer(3, GL_FLOAT, 16, mesh->xyz_array); + qglVertexPointer(3, GL_FLOAT, 0, mesh->xyz_array); qglEnableClientState( GL_VERTEX_ARRAY ); if (mesh->normals_array && qglNormalPointer) //d3d wrapper doesn't support normals, and this is only really needed for truform @@ -1075,7 +1082,7 @@ void GL_DrawAliasMesh (mesh_t *mesh, int texnum) GL_TexEnv(GL_MODULATE); - qglVertexPointer(3, GL_FLOAT, 16, mesh->xyz_array); + qglVertexPointer(3, GL_FLOAT, 0, mesh->xyz_array); qglEnableClientState( GL_VERTEX_ARRAY ); if (mesh->normals_array && qglNormalPointer) //d3d wrapper doesn't support normals, and this is only really needed for truform @@ -1595,7 +1602,7 @@ void GL_LightMesh (mesh_t *mesh, vec3_t lightpos, vec3_t colours, float radius) vec3_t dir; int i; float dot; - vec4_t *xyz = mesh->xyz_array; + vec3_t *xyz = mesh->xyz_array; vec3_t *normals = mesh->normals_array; byte_vec4_t *out = mesh->colors_array; @@ -1924,6 +1931,7 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; break; + case ALIAS_GROUP: case ALIAS_GROUP_SWAPPED: // prerelease ingroup = (daliasgroup_t *)(pframetype+1); @@ -2003,6 +2011,7 @@ static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) outskin->skinheight = pq1inmodel->skinheight; //LH's naming scheme ("models" is likly to be ignored) + fbtexture = 0; _snprintf(skinname, sizeof(skinname), "%s_%i", loadmodel->name, i); texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); if (texture) @@ -2019,8 +2028,6 @@ static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) sprintf(skinname, "%s_%i_luma", loadname, i); fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); } - else - fbtexture = 0; } if (!texture) @@ -2933,12 +2940,12 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) texnum->shader = R_RegisterSkin(inshader->name); #else - texnum->base = Mod_LoadHiResTexture(inshader->name, true, true, true); + texnum->base = Mod_LoadHiResTexture(inshader->name, "models", true, true, true); if (!texnum->base) { strcpy(name, loadmodel->name); strcpy(COM_SkipPath(name), COM_SkipPath(inshader->name)); //eviile eh? - texnum->base = Mod_LoadHiResTexture(name, true, true, true); + texnum->base = Mod_LoadHiResTexture(name, "models", true, true, true); } texnum->bump = 0; @@ -2946,25 +2953,25 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) { COM_StripExtension(inshader->name, name); //go for the normalmap strcat(name, "_norm"); - texnum->bump = Mod_LoadHiResTexture(name, true, true, false); + texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); if (!texnum->bump) { strcpy(name, loadmodel->name); COM_StripExtension(COM_SkipPath(inshader->name), COM_SkipPath(name)); strcat(name, "_norm"); - texnum->bump = Mod_LoadHiResTexture(name, true, true, false); + texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); if (!texnum->bump) { COM_StripExtension(inshader->name, name); //bother, go for heightmap and convert strcat(name, "_bump"); - texnum->bump = Mod_LoadBumpmapTexture(name); + texnum->bump = Mod_LoadBumpmapTexture(name, "models"); if (!texnum->bump) { strcpy(name, loadmodel->name); strcpy(COM_SkipPath(name), COM_SkipPath(inshader->name)); //eviile eh? COM_StripExtension(name, name); strcat(name, "_bump"); - texnum->bump = Mod_LoadBumpmapTexture(name); + texnum->bump = Mod_LoadBumpmapTexture(name, "models"); } } } @@ -2973,14 +2980,14 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) { COM_StripExtension(inshader->name, name); //go for the normalmap strcat(name, "_luma"); - texnum->fullbright = Mod_LoadHiResTexture(name, true, true, true); + texnum->fullbright = Mod_LoadHiResTexture(name, "models", true, true, true); if (!texnum->base) { strcpy(name, loadmodel->name); strcpy(COM_SkipPath(name), COM_SkipPath(inshader->name)); //eviile eh? COM_StripExtension(name, name); strcat(name, "_luma"); - texnum->fullbright = Mod_LoadBumpmapTexture(name); + texnum->fullbright = Mod_LoadBumpmapTexture(name, "models"); } } #endif diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 69b8827ea..e93ac76e0 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -223,10 +223,10 @@ vec3_t *trNormalsArray; vec2_t *coordsArray; vec2_t *lightmapCoordsArray; -vec4_t vertexArray[MAX_ARRAY_VERTS*2]; +vec3_t vertexArray[MAX_ARRAY_VERTS*2]; vec3_t normalsArray[MAX_ARRAY_VERTS]; -vec4_t tempVertexArray[MAX_ARRAY_VERTS]; +vec3_t tempVertexArray[MAX_ARRAY_VERTS]; vec3_t tempNormalsArray[MAX_ARRAY_VERTS]; index_t tempIndexesArray[MAX_ARRAY_INDEXES]; @@ -362,8 +362,8 @@ void R_PushMesh ( mesh_t *mesh, int features ) numverts = MAX_ARRAY_VERTS - numVerts; } - memcpy ( currentVertex, mesh->xyz_array, numverts * sizeof(vec4_t) ); - currentVertex += numverts * 4; + memcpy ( currentVertex, mesh->xyz_array, numverts * sizeof(vec3_t) ); + currentVertex += numverts * 3; if ( mesh->normals_array && (features & MF_NORMALS) ) { memcpy ( currentNormal, mesh->normals_array, numverts * sizeof(vec3_t) ); @@ -402,6 +402,14 @@ void R_PushMesh ( mesh_t *mesh, int features ) } +qboolean R_MeshWillExceed(mesh_t *mesh) +{ + if (numVerts + mesh->numvertexes > MAX_ARRAY_VERTS) + return true; + if (numIndexes + mesh->numindexes > MAX_ARRAY_INDEXES) + return true; + return false; +} extern index_t r_quad_indexes[6];// = { 0, 1, 2, 0, 2, 3 }; @@ -487,7 +495,7 @@ qboolean varrayactive; void R_IBrokeTheArrays(void) { varrayactive = true; - qglVertexPointer( 3, GL_FLOAT, 16, vertexArray ); // padded for SIMD + qglVertexPointer( 3, GL_FLOAT, 0, vertexArray ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); qglEnableClientState( GL_VERTEX_ARRAY ); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 4521d81b6..9fe392236 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. int glx, gly, glwidth, glheight; mesh_t draw_mesh; -vec4_t draw_mesh_xyz[4]; +vec3_t draw_mesh_xyz[4]; vec2_t draw_mesh_st[4]; byte_vec4_t draw_mesh_colors[4]; @@ -3247,6 +3247,30 @@ void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, qboolean } GL_Upload32 (NULL, (unsigned*)trans, width, height, mipmap, alpha); } +void GL_Upload8Pal32 (qbyte *data, qbyte *pal, int width, int height, qboolean mipmap, qboolean alpha) +{ + qbyte *trans = uploadmemorybufferintermediate; + int i, s; + qboolean noalpha; + int p; + extern qbyte gammatable[256]; + + s = width*height; + if (s > sizeofuploadmemorybufferintermediate/4) + Sys_Error("GL_Upload8Pal32: image too big (%i*%i)", width, height); + + if (s&3) + Sys_Error ("GL_Upload8: s&3"); + for (i=0 ; itexnum; + } + + glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); + glt->next = gltextures; + gltextures = glt; + + + strcpy (glt->identifier, identifier); + glt->texnum = texture_extension_number; + glt->width = width; + glt->height = height; + glt->bpp = 32; + glt->mipmap = mipmap; + + Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); + + GL_Bind(texture_extension_number ); + + GL_Upload8Pal32 (data, palette32, width, height, mipmap, alpha); + + texture_extension_number++; + + return texture_extension_number-1; +} int GL_LoadTexture32 (char *identifier, int width, int height, unsigned *data, qboolean mipmap, qboolean alpha) { diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 1b842c7a7..9a5c114b6 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -669,7 +669,7 @@ couldntload: case 30: //hl case 29: //q1 - case 28: + case 28: //prerel GLMod_LoadBrushModel (mod, buf); break; #ifdef ZYMOTICMODELS @@ -2807,7 +2807,7 @@ void GLMod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight ) Mod_LoadSpriteFrame ================= */ -void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int version) +void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int version, unsigned char *palette) { dspriteframe_t *pinframe; mspriteframe_t *pspriteframe; @@ -2839,15 +2839,25 @@ void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum COM_StripExtension(loadmodel->name, name); strcat(name, va("_%i", framenum)); pspriteframe->gl_texturenum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); + if (version == SPRITE32_VERSION) { size *= 4; - if (!pspriteframe->gl_texturenum) pspriteframe->gl_texturenum = GL_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), true, true); + if (!pspriteframe->gl_texturenum) + pspriteframe->gl_texturenum = GL_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), true, true); + } + else if (version == SPRITEHL_VERSION) + { + if (!pspriteframe->gl_texturenum) + pspriteframe->gl_texturenum = GL_LoadTexture8Pal32 (name, width, height, (unsigned *)(pinframe + 1), palette, true, true); + } + else + { + if (!pspriteframe->gl_texturenum) + pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (qbyte *)(pinframe + 1), true, true); } - else - if (!pspriteframe->gl_texturenum) pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (qbyte *)(pinframe + 1), true, true); - return (void *)((qbyte *)pinframe + sizeof (dspriteframe_t) + size); + return (void *)((qbyte *)(pinframe+1) + size); } @@ -2856,7 +2866,7 @@ void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum Mod_LoadSpriteGroup ================= */ -void * GLMod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int version) +void * GLMod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int version, unsigned char *palette) { dspritegroup_t *pingroup; mspritegroup_t *pspritegroup; @@ -2896,7 +2906,7 @@ void * GLMod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum for (i=0 ; iframes[i], framenum * 100 + i, version); + ptemp = GLMod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i, version, palette); } return ptemp; @@ -2916,15 +2926,27 @@ void GLMod_LoadSpriteModel (model_t *mod, void *buffer) int numframes; int size; dspriteframetype_t *pframetype; + int rendertype=0; + unsigned char pal[256*4]; + int sptype; pin = (dsprite_t *)buffer; version = LittleLong (pin->version); - if (version != SPRITE32_VERSION) if (version != SPRITE_VERSION) + if (version != SPRITE32_VERSION) + if (version != SPRITEHL_VERSION) Sys_Error ("%s has wrong version number " "(%i should be %i)", mod->name, version, SPRITE_VERSION); + sptype = LittleLong (pin->type); + + if (pin->version == SPRITEHL_VERSION) + { + pin = (dsprite_t*)((char*)pin + 4); + rendertype = LittleLong (pin->type); + } + numframes = LittleLong (pin->numframes); size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); @@ -2932,8 +2954,8 @@ void GLMod_LoadSpriteModel (model_t *mod, void *buffer) psprite = Hunk_AllocName (size, loadname); mod->cache.data = psprite; + psprite->type = sptype; - psprite->type = LittleLong (pin->type); psprite->maxwidth = LittleLong (pin->width); psprite->maxheight = LittleLong (pin->height); psprite->beamlength = LittleFloat (pin->beamlength); @@ -2944,7 +2966,28 @@ void GLMod_LoadSpriteModel (model_t *mod, void *buffer) mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; mod->mins[2] = -psprite->maxheight/2; mod->maxs[2] = psprite->maxheight/2; - + + if (pin->version == SPRITEHL_VERSION) + { + int i; + short *numi = (short*)(pin+1); + unsigned char *src = (unsigned char *)(numi+1); + if (*numi != 256) + Sys_Error("%s has wrong number of palette indexes (we only support 256)\n", mod->name); + + for (i = 0; i < 256; i++) + { + pal[i*4+0] = *src++; + pal[i*4+1] = *src++; + pal[i*4+2] = *src++; + pal[i*4+3] = 255; + } + + pframetype = (dspriteframetype_t *)(src); + } + else + pframetype = (dspriteframetype_t *)(pin + 1); + // // load the frames // @@ -2953,8 +2996,6 @@ void GLMod_LoadSpriteModel (model_t *mod, void *buffer) mod->numframes = numframes; - pframetype = (dspriteframetype_t *)(pin + 1); - for (i=0 ; iframes[i].frameptr, i, version); + &psprite->frames[i].frameptr, i, version, pal); } else { pframetype = (dspriteframetype_t *) GLMod_LoadSpriteGroup (pframetype + 1, - &psprite->frames[i].frameptr, i, version); + &psprite->frames[i].frameptr, i, version, pal); } } diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index bd1892e59..1647e48d3 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -50,7 +50,7 @@ typedef int index_t; typedef struct mesh_s { int numvertexes; - vec4_t *xyz_array; + vec3_t *xyz_array; vec3_t *normals_array; vec2_t *st_array; vec2_t *lmst_array; @@ -73,7 +73,7 @@ struct meshbuffer_s; void R_PushMesh ( mesh_t *mesh, int features ); void R_RenderMeshBuffer ( struct meshbuffer_s *mb, qboolean shadowpass ); - +qboolean R_MeshWillExceed(mesh_t *mesh); extern int gl_canbumpmap; diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 7aa8250f8..aa85be69c 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -15,6 +15,7 @@ extern int *lightmap_textures; extern int lightmap_bytes; // 1, 2, or 4 extern cvar_t gl_detail; +extern cvar_t gl_overbright; extern cvar_t r_fb_bmodels; extern cvar_t gl_part_flame; @@ -31,6 +32,8 @@ extern cvar_t r_drawflat; extern cvar_t r_wallcolour; extern cvar_t r_floorcolour; +int overbright; + extern lightmapinfo_t **lightmap; extern model_t *currentmodel; @@ -277,9 +280,10 @@ static void PPL_BaseChain_NoBump_2TMU(msurface_t *s, texture_t *tex) qglClientActiveTextureARB(GL_TEXTURE1_ARB); qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->lmst_array); - qglVertexPointer(3, GL_FLOAT, sizeof(vec4_t), s->mesh->xyz_array); + qglVertexPointer(3, GL_FLOAT, 0, s->mesh->xyz_array); - qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); + qglDrawRangeElements(GL_TRIANGLES, 0, s->mesh->numvertexes, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); + //qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); } qglDisable(GL_TEXTURE_2D); @@ -289,6 +293,195 @@ static void PPL_BaseChain_NoBump_2TMU(msurface_t *s, texture_t *tex) qglDisableClientState(GL_TEXTURE_COORD_ARRAY); } +static void PPL_BaseChain_NoBump_2TMU_Overbright(msurface_t *s, texture_t *tex) +{ //doesn't merge surfaces, but tells gl to do each vertex arrayed surface individually, which means no vertex copying. + int vi; + glRect_t *theRect; + + PPL_EnableVertexArrays(); + + if (tex->alphaed) + { + qglEnable(GL_BLEND); + GL_TexEnv(GL_MODULATE); + } + else + { + qglDisable(GL_BLEND); + GL_TexEnv(GL_REPLACE); + } + + + GL_MBind(GL_TEXTURE0_ARB, tex->gl_texturenum); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + + GL_SelectTexture(GL_TEXTURE1_ARB); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + + + if (overbright != 1) + { + GL_TexEnv(GL_COMBINE_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, overbright); //this is the key + } + + vi = -1; + for (; s ; s=s->texturechain) + { + if (vi != s->lightmaptexturenum) + { + if (vi<0) + qglEnable(GL_TEXTURE_2D); + vi = s->lightmaptexturenum; + + if (vi>=0) + { + GL_Bind(lightmap_textures[vi] ); + if (lightmap[vi]->modified) + { + lightmap[vi]->modified = false; + theRect = &lightmap[vi]->rectchange; + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, + lightmap[vi]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + } + else + qglDisable(GL_TEXTURE_2D); + } + + qglClientActiveTextureARB(GL_TEXTURE0_ARB); + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->st_array); + qglClientActiveTextureARB(GL_TEXTURE1_ARB); + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->lmst_array); + + qglVertexPointer(3, GL_FLOAT, 0, s->mesh->xyz_array); + + qglDrawRangeElements(GL_TRIANGLES, 0, s->mesh->numvertexes, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); + } + + if (overbright != 1) + { + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1); //just in case + GL_TexEnv(GL_MODULATE); + } + + qglDisable(GL_TEXTURE_2D); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + GL_SelectTexture(GL_TEXTURE0_ARB); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +/* +static void PPL_BaseChain_NoBump_2TMU_TEST(msurface_t *s, texture_t *tex) +{ //this was just me testing efficiency between arrays/glbegin. + int vi, i; + glRect_t *theRect; + + PPL_EnableVertexArrays(); + + if (tex->alphaed) + { + qglEnable(GL_BLEND); + GL_TexEnv(GL_MODULATE); + } + else + { + qglDisable(GL_BLEND); + GL_TexEnv(GL_REPLACE); + } + + qglCullFace(GL_BACK); + + + GL_MBind(GL_TEXTURE0_ARB, tex->gl_texturenum); + + GL_SelectTexture(GL_TEXTURE1_ARB); + GL_TexEnv(GL_MODULATE); + + vi = -1; + for (; s ; s=s->texturechain) + { + if (vi != s->lightmaptexturenum) + { + if (vi<0) + qglEnable(GL_TEXTURE_2D); + vi = s->lightmaptexturenum; + + if (vi>=0) + { + GL_Bind(lightmap_textures[vi] ); + if (lightmap[vi]->modified) + { + lightmap[vi]->modified = false; + theRect = &lightmap[vi]->rectchange; + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, + lightmap[vi]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + } + else + qglDisable(GL_TEXTURE_2D); + } + + qglBegin(GL_POLYGON); + switch(s->mesh->numvertexes) + { + default: + for (i = s->mesh->numvertexes-1; i >= 6; i--) + { + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[i][0], s->mesh->st_array[i][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[i][0], s->mesh->lmst_array[i][1]); + qglVertex3fv(s->mesh->xyz_array[i]); + } + case 6: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[5][0], s->mesh->st_array[5][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[5][0], s->mesh->lmst_array[5][1]); + qglVertex3fv(s->mesh->xyz_array[5]); + case 5: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[4][0], s->mesh->st_array[4][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[4][0], s->mesh->lmst_array[4][1]); + qglVertex3fv(s->mesh->xyz_array[4]); + case 4: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[3][0], s->mesh->st_array[3][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[3][0], s->mesh->lmst_array[3][1]); + qglVertex3fv(s->mesh->xyz_array[3]); + case 3: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[2][0], s->mesh->st_array[2][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[2][0], s->mesh->lmst_array[2][1]); + qglVertex3fv(s->mesh->xyz_array[2]); + case 2: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[1][0], s->mesh->st_array[1][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[1][0], s->mesh->lmst_array[1][1]); + qglVertex3fv(s->mesh->xyz_array[1]); + case 1: + qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, s->mesh->st_array[0][0], s->mesh->st_array[0][1]); + qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, s->mesh->lmst_array[0][0], s->mesh->lmst_array[0][1]); + qglVertex3fv(s->mesh->xyz_array[0]); + case 0: + break; + } + qglEnd(); + } + + qglDisable(GL_TEXTURE_2D); + + GL_SelectTexture(GL_TEXTURE0_ARB); +} +*/ + static void PPL_BaseChain_Bump_2TMU(msurface_t *first, texture_t *tex) { int vi; @@ -1194,9 +1387,9 @@ static void PPL_BaseTextureChain(msurface_t *first) if (s->mesh) { - redraw = mb.fog != s->fog || mb.infokey != vi|| mb.shader->flags&SHADER_DEFORMV_BULGE; + redraw = mb.fog != s->fog || mb.infokey != vi|| mb.shader->flags&SHADER_DEFORMV_BULGE || R_MeshWillExceed(s->mesh); - if (redraw)// || numIndexes + s->mesh->numindexes > MAX_ARRAY_INDEXES) + if (redraw) { if (mb.mesh) R_RenderMeshBuffer ( &mb, false ); @@ -1265,7 +1458,9 @@ static void PPL_BaseTextureChain(msurface_t *first) } else { - PPL_BaseChain_NoBump_2TMU(first, t); +// PPL_BaseChain_NoBump_2TMU_TEST(first, t); +// PPL_BaseChain_NoBump_2TMU(first, t); + PPL_BaseChain_NoBump_2TMU_Overbright(first, t); } } } @@ -1326,6 +1521,13 @@ void PPL_BaseTextures(model_t *model) qglShadeModel(GL_FLAT); + if (gl_overbright.value>=2) + overbright = 4; + else if (gl_overbright.value) + overbright = 2; + else + overbright = 1; + currentmodel = model; currententity->alpha = 1; @@ -2477,6 +2679,9 @@ void PPL_SchematicsTextureChain(msurface_t *first) float frow, fcol; int e, en; + if (!cl.worldmodel->surfedges) + return; + qglEnable(GL_ALPHA_TEST); if (qglPolygonOffset) @@ -4010,13 +4215,14 @@ void PPL_DrawWorld (void) vec3_t mins, maxs; int maxshadowlights = gl_maxshadowlights.value; - +/* if (!lightmap) { R_PreNewMap(); R_NewMap(); return; // :/ } + */ if (maxshadowlights < 1) maxshadowlights = 1; @@ -4165,7 +4371,6 @@ void PPL_DrawWorld (void) R_IBrokeTheArrays(); } -#endif void PPL_CreateShaderObjects(void) { @@ -4173,4 +4378,6 @@ void PPL_CreateShaderObjects(void) PPL_CreateLightTexturesProgram(); #endif PPL_LoadSpecularFragmentProgram(); -} \ No newline at end of file +} + +#endif diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 3ed6704b8..1dcf72d6b 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1908,9 +1908,6 @@ void GLR_RenderView (void) qglPNTrianglesfATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_ati_truform_tesselation.value); } - - - if (gl_finish.value) { RSpeedMark(); @@ -2011,12 +2008,10 @@ void GLR_RenderView (void) if (qglGetError()) Con_Printf("GL Error drawing scene\n"); - if (!scenepp_ww_program) - return; - // SCENE POST PROCESSING // we check if we need to use any shaders - currently it's just waterwarp - if ( (r_waterwarp.value && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER)) + if (scenepp_ww_program) + if ((r_waterwarp.value && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER)) { float vwidth = 1, vheight = 1; float vs, vt; diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 0bed7764a..79f410931 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -3077,10 +3077,10 @@ static void GLR_LeafWorldNode (void) // check for door connected areas // if ( areabits ) { - if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) - { - continue; // not visible - } +// if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) +// { +// continue; // not visible +// } } clipflags = 15; // 1 | 2 | 4 | 8 @@ -3509,11 +3509,11 @@ void BuildSurfaceDisplayList (msurface_t *fa) //#ifdef Q3SHADERS // if (fa->texinfo->texture->shader) { //build a nice mesh instead of a poly. - int size = sizeof(mesh_t) + sizeof(index_t)*(lnumverts-2)*3 + (sizeof(vec4_t) + sizeof(vec3_t) + 2*sizeof(vec2_t) + sizeof(byte_vec4_t))*lnumverts; + int size = sizeof(mesh_t) + sizeof(index_t)*(lnumverts-2)*3 + (sizeof(vec3_t) + sizeof(vec3_t) + 2*sizeof(vec2_t) + sizeof(byte_vec4_t))*lnumverts; mesh_t *mesh; fa->mesh = mesh = Hunk_Alloc(size); - mesh->xyz_array = (vec4_t*)(mesh + 1); + mesh->xyz_array = (vec3_t*)(mesh + 1); mesh->normals_array = (vec3_t*)(mesh->xyz_array + lnumverts); mesh->st_array = (vec2_t*)(mesh->normals_array + lnumverts); mesh->lmst_array = (vec2_t*)(mesh->st_array + lnumverts); @@ -3704,7 +3704,7 @@ void GL_CreateSurfaceLightmap (msurface_t *surf) smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; - if (smax > LMBLOCK_WIDTH || tmax > LMBLOCK_HEIGHT || smax <= 0 || tmax <= 0) + if (smax > LMBLOCK_WIDTH || tmax > LMBLOCK_HEIGHT || smax < 0 || tmax < 0) { //whoa, buggy. surf->lightmaptexturenum = -1; return; diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 4afdf80f0..d54ef79c0 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -97,6 +97,8 @@ void RSpeedShow(void) s = va("%i %-30s", samplerquant[i], RQntNames[i]); Draw_String(vid.width-strlen(s)*8, (i+RSPEED_MAX)*8, s); } + s = va("%f %-30s", 100000000.0f/samplerspeeds[RSPEED_TOTALREFRESH], "Framerate"); + Draw_String(vid.width-strlen(s)*8, (i+RSPEED_MAX)*8, s); if (framecount++>=100) { @@ -269,7 +271,10 @@ void GLSCR_UpdateScreen (void) else #endif if (cl.worldmodel && uimenu != 1) + { V_RenderView (); + Q1BSP_TestClipDecal(); + } else GL_DoSwap(); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 0764847d4..5f3d80145 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -69,6 +69,7 @@ void (APIENTRY *qglVertex3fv) (const GLfloat *v); void (APIENTRY *qglViewport) (GLint x, GLint y, GLsizei width, GLsizei height); void (APIENTRY *qglGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint *params); +void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); void (APIENTRY *qglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); void (APIENTRY *qglArrayElement) (GLint i); void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); @@ -524,6 +525,8 @@ void GL_Init(void *(*getglfunction) (char *name)) qglEnableClientState = (void *)getglcore("glEnableClientState"); qglDisableClientState = (void *)getglcore("glDisableClientState"); + qglDrawRangeElements = (void *)getglext("glDrawRangeElements"); + //fixme: definatly make non-core qglStencilOp = (void *)getglcore("glStencilOp"); qglStencilFunc = (void *)getglcore("glStencilFunc"); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 1a4fd8f24..af22537ce 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -207,7 +207,7 @@ void R_DrawSkyChain (msurface_t *s) qglDisableClientState( GL_COLOR_ARRAY ); for (fa=s ; fa ; fa=fa->texturechain) { - qglVertexPointer(3, GL_FLOAT, 16, fa->mesh->xyz_array); + qglVertexPointer(3, GL_FLOAT, 0, fa->mesh->xyz_array); qglDrawElements(GL_TRIANGLES, fa->mesh->numindexes, GL_UNSIGNED_INT, fa->mesh->indexes); } R_IBrokeTheArrays(); @@ -591,7 +591,7 @@ void R_DrawSkyBoxChain (msurface_t *s) #define skygridyrecip (1.0f / (skygridy)) #define skysphere_numverts (skygridx1 * skygridy1) #define skysphere_numtriangles (skygridx * skygridy * 2) -static float skysphere_vertex4f[skysphere_numverts * 4]; +static float skysphere_vertex3f[skysphere_numverts * 3]; static float skysphere_texcoord2f[skysphere_numverts * 2]; static int skysphere_element3i[skysphere_numtriangles * 3]; mesh_t skymesh; @@ -621,7 +621,7 @@ static void skyspherecalc(int skytype) skymesh.indexes = skysphere_element3i; skymesh.st_array = (void*)skysphere_texcoord2f; skymesh.lmst_array = (void*)skysphere_texcoord2f; - skymesh.xyz_array = (void*)skysphere_vertex4f; + skymesh.xyz_array = (void*)skysphere_vertex3f; skymesh.numindexes = skysphere_numtriangles * 3; skymesh.numvertexes = skysphere_numverts; @@ -629,7 +629,7 @@ static void skyspherecalc(int skytype) dx = 16; dy = 16; dz = 16 / 3; - vertex3f = skysphere_vertex4f; + vertex3f = skysphere_vertex3f; texcoord2f = skysphere_texcoord2f; for (j = 0;j <= skygridy;j++) { @@ -649,7 +649,6 @@ static void skyspherecalc(int skytype) *vertex3f++ = v[0]; *vertex3f++ = v[1]; *vertex3f++ = v[2]; - vertex3f++; } } e = skysphere_element3i; diff --git a/engine/gl/glmod_doom.c b/engine/gl/glmod_doom.c index 62dfa29a7..e5bc1452f 100644 --- a/engine/gl/glmod_doom.c +++ b/engine/gl/glmod_doom.c @@ -1,6 +1,8 @@ #include "quakedef.h" #include "glquake.h" +#include "doommap.h" + #ifdef DOOMWADS vec_t VectorNormalize2 (vec3_t v, vec3_t out); @@ -18,14 +20,6 @@ int PlaneTypeForNormal ( vec3_t normal ); void Doom_SetHullFuncs(hull_t *hull); void Doom_SetModelFunc(model_t *mod); -//expand to Quake style ent lump -typedef struct { - short xpos; - short ypos; - short angle; - unsigned short type; - unsigned short flags; -} dthing_t; //skill/dm is appears in rather than quake's excuded in. #define THING_EASY 1 #define THING_MEDIUM 2 @@ -62,168 +56,31 @@ enum { } THING_TYPES; -typedef struct { - short xpos; - short ypos; -} ddoomvertex_t; - -typedef struct { - float xpos; - float ypos; -} mdoomvertex_t; - -typedef struct { - unsigned short vert[2]; - unsigned short flags; - short types; - short tag; - unsigned short sidedef[2]; //(0xffff is none for sidedef[1]) -} dlinedef_t; -#define LINEDEF_IMPASSABLE 1 -#define LINEDEF_BLOCKMONSTERS 2 -#define LINEDEF_TWOSIDED 4 -#define LINEDEF_UPPERUNPEGGED 8 -#define LINEDEF_LOWERUNPEGGED 16 -#define LINEDEF_SECRET 32 //seen as singlesided on automap, does nothing else. -#define LINEDEF_BLOCKSOUND 64 -#define LINEDEF_NOTONMAP 128 //doesn't appear on automap. -#define LINEDEF_STARTONMAP 256 -//others are ignored. - -typedef struct { - char name[8]; - short width; - short height; - int gltexture; -// shader_t *glshader; // :o) -} gldoomtexture_t; - -static gldoomtexture_t *gldoomtextures; -static int numgldoomtextures; - -typedef struct { - short texx; - short texy; - char uppertex[8]; - char lowertex[8]; - char middletex[8]; - unsigned short sector; -} dsidedef_t; -typedef struct { - unsigned short texx; - unsigned short texy; - - unsigned short uppertex; - unsigned short lowertex; - unsigned short middletex; - - unsigned short sector; -} msidedef_t; - -typedef struct { //figure out which linedef to use and throw the rest away. - unsigned short vert[2]; - short angle; - unsigned short linedef; - short direction; - short offset; -} dseg_t; - -typedef struct { - unsigned short vert[2]; - unsigned short linedef; - short direction; - unsigned short Partner; //the one on the other side of the owner's linedef -} dgl_seg1_t; - -typedef struct { - unsigned int vert[2]; - unsigned short linedef; - short direction; - unsigned int Partner; //the one on the other side of the owner's linedef -} dgl_seg3_t; - -typedef struct { - unsigned short segcount; - unsigned short first; -} dssector_t; - -typedef struct { - short x; - short y; - short dx; - short dy; - short y1upper; - short y1lower; - short x1lower; - short x1upper; - short y2upper; - short y2lower; - short x2lower; - short x2upper; - unsigned short node1; - unsigned short node2; -} ddoomnode_t; -#define NODE_IS_SSECTOR 0x8000 - -typedef struct { - short floorheight; - short ceilingheight; - char floortexture[8]; - char ceilingtexture[8]; - short lightlevel; - short specialtype; - short tag; -} dsector_t; - -typedef struct { - int visframe; - int floortex; - int ceilingtex; - - short floorheight; - short ceilingheight; - - qbyte lightlev; - qbyte pad; - int numflattris; - short tag; - short specialtype; - - unsigned short *flats; -} msector_t; - - -typedef struct { - short xorg; - short yorg; - short columns; - short rows; -} blockmapheader_t; +extern ddoomnode_t *nodel; +extern dssector_t *ssectorsl; +extern dthing_t *thingsl; +extern mdoomvertex_t *vertexesl; +extern dgl_seg3_t *segsl; +extern dlinedef_t *linedefsl; +extern msidedef_t *sidedefsm; +extern msector_t *sectorm; +extern plane_t *nodeplanes; +extern plane_t *lineplanes; +extern blockmapheader_t *blockmapl; +extern unsigned short *blockmapofs; +extern unsigned int nodec; +extern unsigned int sectorc; +extern unsigned int segsc; +extern unsigned int ssectorsc; +extern unsigned int thingsc; +extern unsigned int linedefsc; +extern unsigned int sidedefsc; +extern unsigned int vertexesc; +extern unsigned int vertexsglbase; -static ddoomnode_t *nodel; -static dssector_t *ssectorsl; -static dthing_t *thingsl; -static mdoomvertex_t *vertexesl; -static dgl_seg3_t *segsl; -static dlinedef_t *linedefsl; -static msidedef_t *sidedefsm; -static msector_t *sectorm; -static plane_t *nodeplanes; -static plane_t *lineplanes; -static blockmapheader_t *blockmapl; -static unsigned short *blockmapofs; -static unsigned int nodec; -static unsigned int sectorc; -static unsigned int segsc; -static unsigned int ssectorsc; -static unsigned int thingsc; -static unsigned int linedefsc; -static unsigned int sidedefsc; -static unsigned int vertexesc; -static unsigned int vertexsglbase; extern model_t *loadmodel; extern char loadname[]; @@ -1684,715 +1541,7 @@ qboolean Mod_LoadDoomLevel(model_t *mod) return true; } -int Doom_SectorNearPoint(vec3_t p) -{ - ddoomnode_t *node; - plane_t *plane; - int num; - int seg; - float d; - num = nodec-1; - while (1) - { - if (num & NODE_IS_SSECTOR) - { - num -= NODE_IS_SSECTOR; - for (seg = ssectorsl[num].first; seg < ssectorsl[num].first + ssectorsl[num].segcount; seg++) - if (segsl[seg].linedef != 0xffff) - break; - return sidedefsm[linedefsl[segsl[seg].linedef].sidedef[segsl[seg].direction]].sector; - } - - node = nodel + num; - plane = nodeplanes + num; - -// if (plane->type < 3) -// d = p[plane->type] - plane->dist; -// else - d = DotProduct (plane->normal, p) - plane->dist; - if (d < 0) - num = node->node2; - else - num = node->node1; - } - - return num; -} - -int Doom_PointContents(hull_t *hull, vec3_t p) -{ - int sec = Doom_SectorNearPoint(p); - if (p[2] < sectorm[sec].floorheight-hull->clip_mins[2]) - return FTECONTENTS_SOLID; - if (p[2] > sectorm[sec].ceilingheight-hull->clip_maxs[2]) - return FTECONTENTS_SOLID; - return FTECONTENTS_EMPTY; -} - -//#define NEWTRACES -#ifdef NEWTRACES -static qboolean ispoint; -static void ClipToBlockMap(hull_t *hull, int block, vec3_t start, vec3_t end, trace_t *trace) -{ - unsigned short *linedefs; - dlinedef_t *ld; - plane_t *lp; - float planedist; - - float d1, d2; //distance start, end - - if (block < 0 || block >= blockmapl->columns*blockmapl->rows) - { - trace->fraction = 0; - return; - } - - - trace->endpos[0] = end[0]; - trace->endpos[1] = end[1]; - trace->endpos[2] = end[2]; - - trace->fraction = 1; - - for(linedefs = (short*)blockmapl + blockmapofs[block]+1; *linedefs != 0xffff; linedefs++) - { - ld = linedefsl + *linedefs; - - lp = lineplanes + *linedefs; - - if (ispoint) - planedist = lp->dist; - else - { //figure out how far to move the plane out by (tracebox instead of tracecylinder - vec3_t ofs; - int j; - for (j=0 ; j<2 ; j++) - { - if (lp->normal[j] < 0) - ofs[j] = hull->clip_maxs[j]; - else - ofs[j] = hull->clip_mins[j]; - } - ofs[2] = 0; - planedist = lp->dist - DotProduct (ofs, lp->normal); - } - - d1 = DotProduct(lp->normal, start) - (planedist); - d2 = DotProduct(lp->normal, end) - (planedist); - if (d1 > 0 && d2 > 0) - continue; //both points on the front side. - - if (d1 < 0 && d2 < 0) - continue; //both points on the back side. - - //line crossed plane - - if (d1<0) //moved onto backside - { - - LeaveSector(sidedefsm[ld->sidedef[0]].sector); - EnterSector(sidedefsm[ld->sidedef[1]].sector); - } - } -} - -static int numinsectors; -static int insector[8]; -static trace_t *trace_trace; -static hull_t *trace_hull; -static vec3_t trace_end; -static vec3_t trace_start; -static qboolean EnterSector(int secnum, float z) -{ - int i; - for (i = 0; i < numinsectors; i++) - if (insector[i] == secnum) - return true; //erm. already in this one - - if (i == sizeof(insector)/sizeof(insector[0])) - { - Con_DPrintf("Trace was in too many sectors\n"); - return false; //you're not allowed to enter - } - if (z + trace_hull->clip_mins[2] < sectorm[secnum].floorheight) //was outside - return false; - if (z + trace_hull->clip_mins[2] > sectorm[secnum].ceilingheight) //was outside - return false; - - insector[i] = secnum; - return true; //yay, the trace entered a big enough hole! -} -void LeaveSector(int secnum, float x, float y) -{ - float z; - - int i; - for (i = 0; i < numinsectors; i++) - if (insector[i] == secnum) - { - //switch with last. - insector[i] = insector[numinsectors-1]; - numinsectors--; - - //z at x,y - if (trace_end[0]-trace_start[0]) - z = (trace_end[2]-trace_start[2])/(trace_end[0]-trace_start[0]); - else if (trace_end[1]-trace_start[1]) - z = (trace_end[2]-trace_start[2])/(trace_end[1]-trace_start[1]); - else - { //was a vertical trace. - z = trace_end[2]; - } - if (z > sectorm[secnum].ceilingheight) - { - z = sectorm[secnum].ceilingheight; - if (z < trace_trace->endpos[2]) - { - trace_trace->endpos[0] -= (trace_end[0]-trace_start[0])/(z-trace_start[0]); - trace_trace->endpos[1] -= (trace_end[1]-trace_start[1])/(z-trace_start[1]); - trace_trace->endpos[2] = z; - } - } - if (z < sectorm[secnum].floorheight) - { - z = sectorm[secnum].floorheight; - if (z < trace_trace->endpos[2]) - { - trace_trace->endpos[0] -= (trace_end[0]-trace_start[0])/(z-trace_start[0]); - trace_trace->endpos[1] -= (trace_end[1]-trace_start[1])/(z-trace_start[1]); - trace_trace->endpos[2] = z; - } - } - return; - } - - Con_DPrintf("Trace wasn't in sector\n"); -} - -void Doom_ClipToInitialNode(int nodenum) -{ - int s; - int seg; - ddoomnode_t *node; - if (nodenum & NODE_IS_SSECTOR) - { - nodenum -= NODE_IS_SSECTOR; - for (seg = ssectorsl[nodenum].first; seg < ssectorsl[nodenum].first + ssectorsl[nodenum].segcount; seg++) - if (segsl[seg].linedef != 0xffff) - break; - - s = sidedefsm[linedefsl[segsl[seg].linedef].sidedef[segsl[seg].direction]].sector; - - if (!EnterSector(s, trace_start[2])) - { //clipped by floor - trace_trace->fraction = 0; - trace_trace->allsolid = trace_trace->startsolid = true; - trace_trace->endpos[0] = trace_start[0]; - trace_trace->endpos[1] = trace_start[1]; - trace_trace->endpos[2] = trace_start[2]; //yeah, we do mean this - startsolid - // if (IS_NAN(trace->endpos[2])) - // Con_Printf("Nanny\n"); - } - return; - } - - node = nodel + nodenum; - - if (node->x1lower+trace_hull->clip_mins[0] <= trace_start[0] && node->x1upper+trace_hull->clip_maxs[0] >= trace_start[0]) - if (node->y1lower+trace_hull->clip_mins[1] <= trace_start[1] && node->y1upper+trace_hull->clip_maxs[1] >= trace_start[1]) - Doom_ClipToInitialNode(node->node1); - - if (node->x2lower+trace_hull->clip_mins[0] <= trace_start[0] && node->x2upper+trace_hull->clip_maxs[0] >= trace_start[0]) - if (node->y2lower+trace_hull->clip_mins[1] <= trace_start[1] && node->y2upper+trace_hull->clip_maxs[1] >= trace_start[1]) - Doom_ClipToInitialNode(node->node2); - -} - -void Doom_ClipToInitialSectors(void) -{ - Doom_ClipToInitialNode(nodec-1); -/* - ddoomnode_t *node; - plane_t *plane; - int num; - int seg; - float d; - num = nodec-1; - while (1) - { - if (num & NODE_IS_SSECTOR) - { - num -= NODE_IS_SSECTOR; - for (seg = ssectorsl[num].first; seg < ssectorsl[num].first + ssectorsl[num].segcount; seg++) - if (segsl[seg].linedef != 0xffff) - break; - - return sidedefsm[linedefsl[segsl[seg].linedef].sidedef[segsl[seg].direction]].sector; - } - - node = nodel + num; - plane = nodeplanes + num; - -// if (plane->type < 3) -// d = p[plane->type] - plane->dist; -// else - d = DotProduct (plane->normal, p) - plane->dist; - if (d < 0) - num = node->node2; - else - num = node->node1; - } - - return num; -*/ -} -qboolean Doom_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t start, vec3_t end, trace_t *trace) -{ - int bmi; - ispoint = !hull->clip_mins[0] && !hull->clip_mins[1] && !hull->clip_maxs[0] && !hull->clip_maxs[1]; - - trace->allsolid = trace->startsolid = false; - trace->contents = FTECONTENTS_EMPTY; - - - trace_trace = trace; - trace_hull = hull; - trace_end[0] = end[0]; - trace_end[1] = end[1]; - trace_end[2] = end[2]; - trace_start[0] = start[0]; - trace_start[1] = start[1]; - trace_start[2] = start[2]; - - - - Doom_ClipToInitialNode(nodec-1); - - if (trace->allsolid) //started outside gamespace - return trace->fraction==1; - - //clip to the blockmap. - //blockmap is 128*128 - bmi = ((int)start[0] - blockmapl->xorg)/128 + (((int)start[1] - blockmapl->yorg)/128)*blockmapl->columns; - if (end[0] - start[0] > 0) - { - if (end[1] - start[1] > 0) - { - ClipToBlockMap(hull, bmi, start, end, trace); - } - else - { - trace->endpos[0] = start[0]; - trace->endpos[1] = start[1]; - trace->endpos[2] = start[2]; - - trace->fraction = 0; - } - } - else - { - trace->endpos[0] = start[0]; - trace->endpos[1] = start[1]; - trace->endpos[2] = start[2]; - - trace->fraction = 0; - } - - return trace->fraction==1; -} - -#else -qboolean Doom_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t start, vec3_t p2, trace_t *trace) -{ -#define TRACESTEP 16 - unsigned short *linedefs; - dlinedef_t *ld; - int bmi, obmi; - vec3_t delta; - int sec1 = Doom_SectorNearPoint(start); - vec3_t p1, pointonplane, ofs; - float d1, d2, c1, c2, planedist; - plane_t *lp; - mdoomvertex_t *v1, *v2; - int j; - - float clipfrac; - qboolean ispoint; -#define DIST_EPSILON (0.03125) - - ispoint = !hull->clip_mins[0] && !hull->clip_mins[1] && !hull->clip_maxs[0] && !hull->clip_maxs[1]; - -// Con_Printf("%i\n", sec1); - - if (start[2] < sectorm[sec1].floorheight-hull->clip_mins[2]) //whoops, started outside... ? - { - trace->fraction = 0; - trace->allsolid = trace->startsolid = true; - trace->endpos[0] = start[0]; - trace->endpos[1] = start[1]; - trace->endpos[2] = start[2]; //yeah, we do mean this - startsolid -// if (IS_NAN(trace->endpos[2])) -// Con_Printf("Nanny\n"); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = 1; - trace->plane.dist = sectorm[sec1].floorheight-hull->clip_mins[2]; - - return false; - } - if (start[2] > sectorm[sec1].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ? - { - trace->fraction = 0; - trace->allsolid = trace->startsolid = true; - trace->endpos[0] = start[0]; - trace->endpos[1] = start[1]; - trace->endpos[2] = start[2]; - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = -1; - trace->plane.dist = -(sectorm[sec1].ceilingheight-hull->clip_maxs[2]); - return false; - } - - VectorCopy(start, p1); - obmi = -1; - VectorSubtract(p2, p1, delta); - p2f = Length(delta)+DIST_EPSILON; - if (IS_NAN(p2f) || p2f > 100000) - p2f = 100000; - VectorNormalize(delta); - - trace->endpos[0] = p2[0]; - trace->endpos[1] = p2[1]; - trace->endpos[2] = p2[2]; - - trace->fraction = 1; - while(1) - { - bmi = ((int)p1[0] - blockmapl->xorg)/128 + (((int)p1[1] - blockmapl->yorg)/128)*blockmapl->columns; -// Con_Printf("%i of %i ", bmi, blockmapl->rows*blockmapl->columns); - if (bmi >= 0 && bmi < blockmapl->rows*blockmapl->columns) - if (bmi != obmi) - { -#if 1 - short dummy; - linedefs = &dummy; - for (dummy = 0; dummy < linedefsc; dummy++) -#else - for(linedefs = (short*)blockmapl + blockmapofs[bmi]+1; *linedefs != 0xffff; linedefs++) -#endif - { - ld = linedefsl + *linedefs; - if (ld->sidedef[1] != 0xffff) - { - if (sectorm[sidedefsm[ld->sidedef[0]].sector].floorheight == sectorm[sidedefsm[ld->sidedef[1]].sector].floorheight && - sectorm[sidedefsm[ld->sidedef[0]].sector].ceilingheight == sectorm[sidedefsm[ld->sidedef[1]].sector].ceilingheight) - continue; - } - - lp = lineplanes + *linedefs; - - if (!ispoint) - { //figure out how far to move the plane out by - for (j=0 ; j<2 ; j++) - { - if (lp->normal[j] < 0) - ofs[j] = hull->clip_maxs[j]; - else - ofs[j] = hull->clip_mins[j]; - } - ofs[2] = 0; - planedist = lp->dist - DotProduct (ofs, lp->normal); - } - else - planedist = lp->dist; - - d1 = DotProduct(lp->normal, start) - (planedist); - d2 = DotProduct(lp->normal, p2) - (planedist); - if (d1 > 0 && d2 > 0) - continue; //both points on the front side. - if (d1 < 0) //start on back side - { - if (ld->sidedef[1] != 0xffff) //two sided (optimisation) - { - planedist = -planedist+lp->dist; - if (/*d1 < planedist*-1 &&*/ d1 > planedist*2) - { //right, we managed to end up just on the other side of a wall's plane. - v1 = &vertexesl[ld->vert[0]]; - v2 = &vertexesl[ld->vert[1]]; - if (!(d1 - d2)) - continue; - if (d1<0) //back to front. - c1 = (d1+DIST_EPSILON) / (d1 - d2); - else - c1 = (d1-DIST_EPSILON) / (d1 - d2); - c2 = 1-c1; - pointonplane[0] = start[0]*c2 + p2[0]*c1; -/* if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0]) - continue; - if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0]) - continue; -*/ pointonplane[1] = start[1]*c2 + p2[1]*c1; -/* if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1]) - continue; - if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1]) - continue; -*/ - pointonplane[2] = start[2]*c2 + p2[2]*c1; - - Con_Printf("Started in wall\n"); - j = sidedefsm[ld->sidedef[d1 < planedist]].sector; - //yup, we are in the thing - //prevent ourselves from entering the back-sector's floor/ceiling - if (pointonplane[2] < sectorm[j].floorheight-hull->clip_mins[2]) //whoops, started outside... ? - { - Con_Printf("Started in floor\n"); - trace->allsolid = trace->startsolid = false; - trace->endpos[2] = sectorm[j].floorheight-hull->clip_mins[2]; - trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]); - trace->endpos[0] = start[0]+delta[0]*trace->fraction*p2f; - trace->endpos[1] = start[1]+delta[1]*trace->fraction*p2f; - // if (IS_NAN(trace->endpos[2])) - // Con_Printf("Nanny\n"); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = 1; - trace->plane.dist = sectorm[j].floorheight-hull->clip_mins[2]; - - continue; - } - if (pointonplane[2] > sectorm[j].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ? - { - Con_Printf("Started in ceiling\n"); - trace->allsolid = trace->startsolid = false; - trace->endpos[0] = pointonplane[0]; - trace->endpos[1] = pointonplane[1]; - trace->endpos[2] = sectorm[j].ceilingheight-hull->clip_maxs[2]; - trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = -1; - trace->plane.dist = -(sectorm[j].ceilingheight-hull->clip_maxs[2]); - continue; - } - } - } - if (d2 < 0) - continue; //both points on the reverse side. - } - - //line crosses plane. - - v1 = &vertexesl[ld->vert[0]]; - v2 = &vertexesl[ld->vert[1]]; - - if (d1<0) //back to front. - { - if (ld->sidedef[1] == 0xffff) - continue; //hack to allow them to pass - c1 = (d1+DIST_EPSILON) / (d1 - d2); - } - else - c1 = (d1-DIST_EPSILON) / (d1 - d2); - c2 = 1-c1; - pointonplane[0] = start[0]*c2 + p2[0]*c1; - if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0]) - continue; - if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0]) - continue; - pointonplane[1] = start[1]*c2 + p2[1]*c1; - if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1]) - continue; - if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1]) - continue; - pointonplane[2] = start[2]*c2 + p2[2]*c1; - - if (ld->flags & LINEDEF_IMPASSABLE || ld->sidedef[1] == 0xffff) //unconditionally unpassable. - { //unconditionally clipped. - } - else - { //ensure that the side we are passing on to passes the clip (no ceiling/floor clips happened first) - msector_t *sec2; - - if (d1<0) - sec2 = §orm[sidedefsm[ld->sidedef[1]].sector]; - else - sec2 = §orm[sidedefsm[ld->sidedef[0]].sector]; - - if (pointonplane[2] < sec2->floorheight-hull->clip_mins[2]) - { //hit the floor first. - c1 = fabs(sectorm[sec1].floorheight-hull->clip_mins[2] - start[2]); - c2 = fabs(p2[2] - start[2]); - if (!c2) - c1 = 1; - else - c1 = (c1-DIST_EPSILON) / c2; - if (trace->fraction > c1) - { -// Con_Printf("Hit floor\n"); - trace->fraction = c1; - trace->allsolid = trace->startsolid = true; - trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); - trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); - trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = 1; - trace->plane.dist = sectorm[sec1].floorheight-hull->clip_mins[2]; - } - continue; - } - - if (pointonplane[2] > sec2->ceilingheight-hull->clip_maxs[2]) - { //hit the floor first. - c1 = fabs((sectorm[sec1].ceilingheight-hull->clip_maxs[2]) - start[2]); - c2 = fabs(p2[2] - start[2]); - if (!c2) - c1 = 1; - else - c1 = (c1-DIST_EPSILON) / c2; - - - if (trace->fraction > c1) - { -// Con_Printf("Hit ceiling\n"); - trace->fraction = c1; - trace->allsolid = trace->startsolid = true; - trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); - trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); - trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = -1; - trace->plane.dist = -(sectorm[sec1].ceilingheight-hull->clip_maxs[2]); - } - continue; - } - - if (d1<0) - sec2 = §orm[sidedefsm[ld->sidedef[0]].sector]; - else - sec2 = §orm[sidedefsm[ld->sidedef[1]].sector]; - - if(sec2->ceilingheight == sec2->floorheight) - sec2->ceilingheight += 64; - - if (pointonplane[2] > sec2->floorheight-hull->clip_mins[2] && - pointonplane[2] < sec2->ceilingheight-hull->clip_maxs[2]) - { - Con_Printf("Two sided passed\n"); - continue; - } - -// Con_Printf("blocked by two sided line\n"); -// sec2->floorheight--; - } - - if (d1<0) //back to front. - c1 = (d1+DIST_EPSILON) / (d1 - d2); - else - c1 = (d1-DIST_EPSILON) / (d1 - d2); - - - clipfrac = c1; - - if (clipfrac < 0) - clipfrac = 0; - if (clipfrac > 1) - clipfrac = 1; - - if (trace->fraction > clipfrac) - { - trace->fraction = clipfrac; - VectorMA(pointonplane, 0, lp->normal, trace->endpos); - VectorMA(trace->endpos, -0.1, delta, trace->endpos); -// if (IS_NAN(trace->endpos[2])) -// Con_Printf("Buggy clipping\n"); - VectorCopy(lp->normal, trace->plane.normal); - trace->plane.dist = planedist; -// if (IS_NAN(trace->plane.normal[2])) -// Con_Printf("Buggy clipping\n"); - - if (clipfrac) - Con_Printf("Clip Wall %f\n", clipfrac); - } - } - - obmi = bmi; - } - - p1f += TRACESTEP; - if (p1f >= p2f) - break; - - VectorMA(p1, TRACESTEP, delta, p1); - } - -// VectorMA(start, p2f*trace->fraction, delta, p2); - - if (p2[2] != start[2]) - { - if (sec1 == Doom_SectorNearPoint(p2)) //special test. - { - if (p2[2] <= sectorm[sec1].floorheight-hull->clip_mins[2]) //whoops, started outside... ? - { - p1f = fabs(sectorm[sec1].floorheight-hull->clip_mins[2] - start[2]); - p2f = fabs(p2[2] - start[2]); - if (!p2f) - c1 = 1; - else - c1 = (p1f-DIST_EPSILON) / p2f; - if (trace->fraction > c1) - { - trace->fraction = c1; - trace->allsolid = trace->startsolid = false; - trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); - trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); - trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = 1; - trace->plane.dist = sectorm[sec1].floorheight-hull->clip_mins[2]; - } - -// if (IS_NAN(trace->endpos[2])) -// Con_Printf("Nanny\n"); - } - if (p2[2] >= sectorm[sec1].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ? - { - p1f = fabs(sectorm[sec1].ceilingheight-hull->clip_maxs[2] - start[2]); - p2f = fabs(p2[2] - start[2]); - if (!p2f) - c1 = 1; - else - c1 = (p1f-DIST_EPSILON) / p2f; - if (trace->fraction > c1) - { - trace->fraction = c1; - trace->allsolid = trace->startsolid = false; - trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); - trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); - trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); - trace->plane.normal[0] = 0; - trace->plane.normal[1] = 0; - trace->plane.normal[2] = -1; - trace->plane.dist = -(sectorm[sec1].ceilingheight-hull->clip_maxs[2]); - } - -// if (IS_NAN(trace->endpos[2])) -// Con_Printf("Nanny\n"); - } - } - } - - //we made it all the way through. yay. - - trace->allsolid = trace->startsolid = false; -//Con_Printf("total = %f\n", trace->fraction); - return trace->fraction==1; -} -#endif void Doom_SetHullFuncs(hull_t *hull) { diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index cf6486d8f..7edc2bc13 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -712,6 +712,8 @@ extern BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); extern BOOL (WINAPI *qSwapBuffers)(HDC); #endif +extern void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); + /* extern qboolean gl_arb_fragment_program; extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; diff --git a/engine/gl/model_hl.h b/engine/gl/model_hl.h index 5d19389b7..f810d2459 100644 --- a/engine/gl/model_hl.h +++ b/engine/gl/model_hl.h @@ -14,6 +14,7 @@ #define HLPOLYHEADER (('T' << 24) + ('S' << 16) + ('D' << 8) + 'I') /* little-endian "IDST" */ #define HLMDLHEADER "IDST" +typedef vec_t vec4_t[4]; /* ----------------------------------------------------------------------------------------------------------------------- main model header @@ -207,7 +208,7 @@ typedef struct int frame; /* Current animation sequence and frame */ float frametime; /* Time of last frame drawn */ float controller[4]; /* Position of bone controllers */ - vec4_t adjust; + float adjust[4]; /* Static pointers */ hlmdl_header_t *header; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 64d4c1e3e..47da40431 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -594,7 +594,7 @@ char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) _snprintf (line, sizeof(line), "%s", val->string+progfuncs->stringtable); break; case ev_entity: - sprintf (line, "%i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict))); + sprintf (line, "%i", val->_int); break; case ev_function: i = (val->function & 0xff000000)>>24; @@ -1049,7 +1049,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, break; case ev_entity: - *(int *)d = EDICT_TO_PROG(progfuncs, EDICT_NUM(progfuncs, atoi (s))); + *(int *)d = atoi (s); break; case ev_field: @@ -2093,7 +2093,7 @@ char *SaveEnt (progfuncs_t *progfuncs, char *buf, int *size, struct edict_s *ed) if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars - v = (int *)(((char *)ed + externs->edictsize) + d->ofs*4); + v = (int*)((edictrun_t*)ed)->fields + d->ofs; // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 61e833c75..1e9f58d94 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -166,12 +166,12 @@ optimisations_t optimisations[] = {&opt_overlaptemps, "r", 1, FLAG_ASDEFAULT, "overlaptemps", "Optimises the pr_globals count by overlapping temporaries. In QC, every multiplication, division or operation in general produces a temporary variable. This optimisation prevents excess, and in the case of Hexen2's gamecode, reduces the count by 50k. This is the most important optimisation, ever."}, {&opt_constantarithmatic, "a", 1, FLAG_ASDEFAULT, "constantarithmatic", "5*6 actually emits an operation into the progs. This prevents that happening, effectivly making the compiler see 30"}, {&opt_precache_file, "pf", 2, 0, "precache_file", "Strip out stuff wasted used in function calls and strings to the precache_file builtin (which is actually a stub in quake)."}, - {&opt_return_only, "ro", 3, 0, "return_only", "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."}, - {&opt_compound_jumps, "cj", 3, 0, "compound_jumps", "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."}, + {&opt_return_only, "ro", 3, FLAG_KILLSDEBUGGERS, "return_only", "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."}, + {&opt_compound_jumps, "cj", 3, FLAG_KILLSDEBUGGERS, "compound_jumps", "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."}, // {&opt_comexprremoval, "cer", 4, 0, "expression_removal", "Eliminate common sub-expressions"}, //this would be too hard... {&opt_stripfunctions, "sf", 3, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games."}, - {&opt_locals_marshalling, "lm", 4, FLAG_HIDDENINGUI|FLAG_KILLSDEBUGGERS, "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."}, - {&opt_vectorcalls, "vc", 4, 0, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."}, + {&opt_locals_marshalling, "lm", 4, FLAG_KILLSDEBUGGERS, "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."}, + {&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."}, {NULL} }; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 521f57ee8..76cc71142 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -2695,10 +2695,7 @@ static void PF_traceboxh2 (progfuncs_t *prinst, struct globalvars_s *pr_globals) pr_global_struct->trace_fraction = trace.fraction; pr_global_struct->trace_inwater = trace.inwater; pr_global_struct->trace_inopen = trace.inopen; -// if (trace.fraction != 1) -// VectorMA (trace.endpos, 4, trace.plane.normal, P_VEC(trace_endpos)); -// else - VectorCopy (trace.endpos, P_VEC(trace_endpos)); + VectorCopy (trace.endpos, P_VEC(trace_endpos)); VectorCopy (trace.plane.normal, P_VEC(trace_plane_normal)); pr_global_struct->trace_plane_dist = trace.plane.dist; if (trace.ent) @@ -3053,9 +3050,7 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *str; - str = PR_GetStringOfs(prinst, OFS_PARM0); - RETURN_CSTRING(Cvar_VariableString (str)); } @@ -3373,13 +3368,14 @@ void PF_precache_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *s; int i; + s = PR_GetStringOfs(prinst, OFS_PARM0); +/* if (sv.state != ss_loading) { - PR_BIError (prinst, "PF_Precache_*: Precache can only be done in spawn functions"); + PR_BIError (prinst, "PF_Precache_*: Precache can only be done in spawn functions (%s)", s); return; } - - s = PR_GetStringOfs(prinst, OFS_PARM0); +*/ G_INT(OFS_RETURN) = G_INT(OFS_PARM0); if (s[0] <= ' ') @@ -3405,15 +3401,16 @@ void PF_precache_model (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *s; int i; - + + s = PR_GetStringOfs(prinst, OFS_PARM0); +/* if (sv.state != ss_loading) { - PR_BIError (prinst, "PF_Precache_*: Precache can only be done in spawn functions"); + PR_BIError (prinst, "PF_Precache_*: Precache can only be done in spawn functions (%s)", s); G_FLOAT(OFS_RETURN) = 1; return; } - - s = PR_GetStringOfs(prinst, OFS_PARM0); +*/ G_INT(OFS_RETURN) = G_INT(OFS_PARM0); if (s[0] <= ' ') @@ -8260,7 +8257,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //FIXME: distinguish between qw and nq parameters here? {"sprint", PF_sprint, 24, 24, 24}, // void(entity client, string s) sprint = #24; {"dprint", PF_dprint, 25, 0, 25}, // void(string s) dprint = #25; - {"print", PF_print, 0, 25, 25}, // void(string s) print = #25; + {"print", PF_print, 0, 25, 0}, // void(string s) print = #25; {"ftos", PF_ftos, 26, 26, 26}, // void(string s) ftos = #26; {"vtos", PF_vtos, 27, 27, 27}, // void(string s) vtos = #27; {"coredump", PF_coredump, 28, 28, 28}, //28 diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 80e594d88..a54bb3d68 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -698,6 +698,8 @@ void SV_SaveLevelCache(qboolean dontharmgame) sprintf (name, "%s/saves/%s", com_gamedir, cache->mapname); COM_DefaultExtension (name, ".lvc"); + COM_CreatePath(name); + if (!dontharmgame) //save game in progress Con_TPrintf (STL_SAVEGAMETO, name); @@ -713,7 +715,6 @@ void SV_SaveLevelCache(qboolean dontharmgame) } #endif - f = fopen (name, "wb"); if (!f) { diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index a4c6e3f1e..ab4470509 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -432,6 +432,7 @@ void SV_Map_f (void) qboolean issamelevel = false; qboolean newunit = false; qboolean cinematic = false; + qboolean waschangelevel = false; int i; char *startspot; @@ -444,6 +445,8 @@ void SV_Map_f (void) strcpy (level, Cmd_Argv(1)); startspot = ((Cmd_Argc() == 2)?NULL:Cmd_Argv(2)); + waschangelevel = !strcmp(Cmd_Argv(0), "changelevel"); + nextserver = strchr(level, '+'); if (nextserver) { @@ -545,7 +548,11 @@ void SV_Map_f (void) #endif if (newunit || !startspot || !SV_LoadLevelCache(level, startspot, false)) + { + if (waschangelevel && !startspot) + startspot = ""; SV_SpawnServer (level, startspot, false, cinematic); + } SV_BroadcastCommand ("reconnect\n"); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index f2d31aec3..0e2024e69 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2145,7 +2145,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } } - if (!ignorepvs) +/* if (!ignorepvs) { //branch out to the pvs testing. if (ent->tagent) @@ -2165,7 +2165,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore continue; } } - +*/ diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index de32c1573..05e4f498d 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1010,14 +1010,25 @@ void SV_PreSpawn_f (void) else { if (sv.democausesreconnect) - SZ_Write (&host_client->netchan.message, - sv.demosignon_buffers[buf], - sv.demosignon_buffer_size[buf]); + { + if (host_client->netchan.message.cursize+sv.signon_buffer_size[buf] < host_client->netchan.message.maxsize) + { + SZ_Write (&host_client->netchan.message, + sv.demosignon_buffers[buf], + sv.demosignon_buffer_size[buf]); + buf++; + } + } else - SZ_Write (&host_client->netchan.message, - sv.signon_buffers[buf], - sv.signon_buffer_size[buf]); - buf++; + { + if (host_client->netchan.message.cursize+sv.signon_buffer_size[buf] < host_client->netchan.message.maxsize) + { + SZ_Write (&host_client->netchan.message, + sv.signon_buffers[buf], + sv.signon_buffer_size[buf]); + buf++; + } + } } if (buf == bufs+sv.numextrastatics+sv.num_edicts+255) { // all done prespawning