diff --git a/engine/client/cd_win.c b/engine/client/cd_win.c index cf5a3fb1b..55d11c32a 100644 --- a/engine/client/cd_win.c +++ b/engine/client/cd_win.c @@ -227,6 +227,9 @@ void CDAudio_Resume(void) if (!wasPlaying) return; + + if (!cdvolume) + return; mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0); mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0); diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 77f92bd1b..7fb0bd046 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BUTTON_ATTACK 1 #define MAX_ANGLE_TURN 10 -static vec3_t desired_position[MAX_SPLITS]; // where the camera wants to be +vec3_t desired_position[MAX_SPLITS]; // where the camera wants to be static qboolean locked[MAX_SPLITS]; static int oldbuttons[MAX_SPLITS]; @@ -106,8 +106,8 @@ qboolean Cam_DrawPlayer(int pnum, int playernum) { // if (playernum == cl.playernum[pnum]) // return false; - if (cl.spectator && autocam[pnum] && locked[pnum] && cl_chasecam.value && - spec_track[pnum] == playernum) + if (cl.spectator && autocam[pnum] && locked[pnum] && (cl_chasecam.value||scr_chatmode==2) && + spec_track[pnum] == playernum && r_secondaryview != 2) return false; return true; } @@ -351,7 +351,7 @@ static void Cam_CheckHighTarget(int pnum) else Cam_Unlock(pnum); } - + // ZOID // // Take over the user controls and track a player. @@ -396,52 +396,56 @@ void Cam_Track(int pnum, usercmd_t *cmd) } } else + { cam_lastviewtime[pnum] = realtime; - - // couldn't track for some reason + } + + //tracking failed. if (!locked[pnum] || !autocam[pnum]) return; - if (cl_chasecam.value) + + if (cl_chasecam.value || scr_chatmode == 2) { + if (scr_chatmode != 2) + cam_lastviewtime[pnum] = realtime; + cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; VectorCopy(player->viewangles, cl.viewangles[pnum]); - VectorCopy(player->origin, desired_position[pnum]); - if (memcmp(&desired_position[pnum], &self->origin, sizeof(desired_position[pnum])) != 0) + if (memcmp(player->origin, &self->origin, sizeof(player->origin)) != 0) { MSG_WriteByte (&cls.netchan.message, clc_tmove); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][0]); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][1]); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][2]); + MSG_WriteCoord (&cls.netchan.message, player->origin[0]); + MSG_WriteCoord (&cls.netchan.message, player->origin[1]); + MSG_WriteCoord (&cls.netchan.message, player->origin[2]); // move there locally immediately - VectorCopy(desired_position[pnum], self->origin); + VectorCopy(player->origin, self->origin); } self->weaponframe = player->weaponframe; + return; } - else - { - // Ok, move to our desired position and set our angles to view - // the player - VectorSubtract(desired_position[pnum], self->origin, vec); - len = vlen(vec); - cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; - if (len > 16) - { // close enough? - MSG_WriteByte (&cls.netchan.message, clc_tmove); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][0]); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][1]); - MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][2]); - } - - // move there locally immediately - VectorCopy(desired_position[pnum], self->origin); - - VectorSubtract(player->origin, desired_position[pnum], vec); - vectoangles(vec, cl.viewangles[pnum]); - cl.viewangles[pnum][0] = -cl.viewangles[pnum][0]; + + // Ok, move to our desired position and set our angles to view + // the player + VectorSubtract(desired_position[pnum], self->origin, vec); + len = vlen(vec); + cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; + if (len > 16) + { // close enough? + MSG_WriteByte (&cls.netchan.message, clc_tmove); + MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][0]); + MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][1]); + MSG_WriteCoord (&cls.netchan.message, desired_position[pnum][2]); } + + // move there locally immediately + VectorCopy(desired_position[pnum], self->origin); + + VectorSubtract(player->origin, desired_position[pnum], vec); + vectoangles(vec, cl.viewangles[pnum]); + cl.viewangles[pnum][0] = -cl.viewangles[pnum][0]; } void Cam_TrackCrosshairedPlayer(int pnum) @@ -449,7 +453,7 @@ void Cam_TrackCrosshairedPlayer(int pnum) frame_t *frame; player_state_t *player; int i; - float dot = 0.1, bestdot; + float dot = 0.1, bestdot=0; int best = -1; vec3_t selforg; vec3_t dir; diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 79f647e48..a7cdad386 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1241,6 +1241,8 @@ void CL_TimeDemo_f (void) if (cls.state != ca_demostart) return; + CL_ReadPackets(); + // cls.td_starttime will be grabbed at the second frame of the demo, so // all the loading time doesn't get counted diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index b29d67656..625eb8481 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -32,6 +32,7 @@ extern cvar_t r_rocketlight; extern cvar_t r_lightflicker; extern cvar_t cl_r2g; extern cvar_t r_powerupglow; +extern cvar_t v_powerupshell; extern cvar_t cl_gibfilter, cl_deadbodyfilter; extern int cl_playerindex; @@ -1356,6 +1357,27 @@ void CL_LinkPacketEntities (void) { s1 = &pack->entities[pnum]; + ent = &cl_visedicts[cl_numvisedicts]; +#ifdef Q3SHADERS + ent->forcedshader = NULL; +#endif + + //figure out the lerp factor + if (!cl.lerpents[s1->number].lerprate) + ent->lerptime = 0; + else + ent->lerptime = 1-(cl.time-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate; + if (ent->lerptime<0) + ent->lerptime=0; + if (ent->lerptime>1) + ent->lerptime=1; + f = ent->lerptime; + + // calculate origin + for (i=0 ; i<3 ; i++) + ent->origin[i] = s1->origin[i] + + f * (cl.lerpents[s1->number].origin[i] - s1->origin[i]); + //bots or powerup glows. Bots always glow, powerups can be disabled if (s1->modelindex != cl_playerindex && r_powerupglow.value); { @@ -1391,8 +1413,6 @@ void CL_LinkPacketEntities (void) continue; } - - ent = &cl_visedicts[cl_numvisedicts]; cl_numvisedicts++; ent->visframe = 0; @@ -1404,6 +1424,8 @@ void CL_LinkPacketEntities (void) ent->model = model; ent->flags = 0; + if (s1->effects & NQEF_ADDATIVE) + ent->flags |= Q2RF_ADDATIVE; // set colormap if (s1->colormap && (s1->colormap <= MAX_CLIENTS) @@ -1428,19 +1450,6 @@ void CL_LinkPacketEntities (void) ent->frame = s1->frame; ent->oldframe = cl.lerpents[s1->number].frame; - if (!cl.lerpents[s1->number].lerprate) - { - ent->lerptime = 0; - } - else - { - ent->lerptime = 1-(cl.time-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate; - } - - if (ent->lerptime<0)ent->lerptime=0; - if (ent->lerptime>1)ent->lerptime=1; - - f = ent->lerptime; // f = (sin(realtime)+1)/2; @@ -1461,11 +1470,6 @@ void CL_LinkPacketEntities (void) ent->fatness = s1->fatness; #endif - // calculate origin - for (i=0 ; i<3 ; i++) - ent->origin[i] = s1->origin[i] + - f * (cl.lerpents[s1->number].origin[i] - s1->origin[i]); - // rotate binary objects locally if (model && model->flags & EF_ROTATE) { @@ -1543,7 +1547,22 @@ void CL_LinkPacketEntities (void) } if (model->particletrail>=0) + { +// Con_Printf("(%f %f %f) (%f %f %f)\n", ent->origin[0], ent->origin[1], ent->origin[2], old_origin[0], old_origin[1], old_origin[2]); +/* + if (ent->origin[0] == old_origin[0] || ent->origin[1] == old_origin[1] || ent->origin[2] == old_origin[2]) + { + if (ent->origin[0] == old_origin[0] && ent->origin[1] == old_origin[1] && ent->origin[2] == old_origin[2]) + { + Con_Printf("Total match!!\n"); + } + else + Con_Printf("impartial match!!\n"); + }*/ + + P_ParticleTrail (old_origin, ent->origin, model->particletrail, &cl.lerpents[s1->number].trailstate); + } //dlights are not so customisable. if (r_rocketlight.value) @@ -1902,7 +1921,10 @@ void CL_ParsePlayerinfo (void) else state->weaponframe = 0; - state->hullnum = 1; + if (cl.worldmodel && cl.worldmodel->fromgame == fg_quake && cl.worldmodel->fromgame == fg_halflife) + state->hullnum = 1; + else + state->hullnum = 56; state->scale = 1; state->trans = 1; state->fatness = 0; @@ -1929,8 +1951,6 @@ void CL_ParsePlayerinfo (void) if (flags & PF_HULLSIZE_Z) state->hullnum = MSG_ReadByte(); } - else - state->hullnum = 1; //should be passed to player move func. #endif @@ -2259,9 +2279,9 @@ void CL_LinkPlayers (void) if (cl.worldmodel->fromgame == fg_halflife) ent->origin[2]-=12; - if (state->effects & EF_FLAG1) + if (state->effects & QWEF_FLAG1) CL_AddFlagModels (ent, 0); - else if (state->effects & EF_FLAG2) + else if (state->effects & QWEF_FLAG2) CL_AddFlagModels (ent, 1); else if (info->vweapindex) CL_AddVWeapModel (ent, info->vweapindex); @@ -2269,7 +2289,9 @@ void CL_LinkPlayers (void) } } - +#ifdef Q3SHADERS //fixme: do better. +#include "shader.h" +#endif void CL_LinkViewModel(void) { @@ -2350,6 +2372,32 @@ void CL_LinkViewModel(void) ent.flags = Q2RF_WEAPONMODEL|Q2RF_DEPTHHACK; V_AddEntity(&ent); + + if (!v_powerupshell.value) + return; + + if (cl.stats[r_refdef.currentplayernum][STAT_ITEMS] & IT_QUAD) + ent.flags |= Q2RF_SHELL_BLUE; + + if (!(ent.flags & (Q2RF_SHELL_RED|Q2RF_SHELL_GREEN|Q2RF_SHELL_BLUE))) + return; + + ent.fatness = 0.5; + ent.alpha *= 0.1; +#ifdef Q3SHADERS //fixme: do better. + //fixme: this is woefully gl specific. :( + if (qrenderer == QR_OPENGL) + { + extern void Shader_DefaultSkinShell(char *shortname, shader_t *s); + ent.shaderRGBA[0] = (!!(ent.flags & Q2RF_SHELL_RED)) * 255; + ent.shaderRGBA[1] = (!!(ent.flags & Q2RF_SHELL_GREEN)) * 255; + ent.shaderRGBA[2] = (!!(ent.flags & Q2RF_SHELL_BLUE)) * 255; + ent.shaderRGBA[3] = ent.alpha*255; + ent.forcedshader = R_RegisterCustom("q2/shell", Shader_DefaultSkinShell); + } +#endif + + V_AddEntity(&ent); } //====================================================================== @@ -2588,11 +2636,11 @@ void CL_EmitEntities (void) CL_SwapEntityLists(); - CL_LinkViewModel (); CL_LinkPlayers (); CL_LinkPacketEntities (); CL_LinkProjectiles (); CL_UpdateTEnts (); + CL_LinkViewModel (); } diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index ba9d4adf1..d3fe90350 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -34,6 +34,7 @@ cvar_t cl_c2sImpulseBackup = {"cl_c2sImpulseBackup","3"}; cvar_t cl_netfps = {"cl_netfps", "0"}; +cvar_t cl_smartjump = {"cl_smartjump", "1"}; /* @@ -189,8 +190,40 @@ void IN_AttackUp(void) {KeyUp(&in_attack);} void IN_UseDown (void) {KeyDown(&in_use);} void IN_UseUp (void) {KeyUp(&in_use);} -void IN_JumpDown (void) {KeyDown(&in_jump);} -void IN_JumpUp (void) {KeyUp(&in_jump);} +void IN_JumpDown (void) +{ + qboolean condition; + + + int pnum; + char *c; + c = Cmd_Argv(0); + pnum = atoi(c+strlen(c)-1); + if (pnum)pnum--; + + + + condition = (cls.state == ca_active && cl_smartjump.value); +#ifdef Q2CLIENT + if (condition && cls.q2server) + KeyDown(&in_up); + else +#endif + if (condition && cl.stats[pnum][STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator && + cl.waterlevel[pnum] >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1)) + ) + KeyDown(&in_up); + else if (condition && cl.spectator && Cam_TrackNum(pnum) == -1) + KeyDown(&in_up); + else + KeyDown(&in_jump); +} +void IN_JumpUp (void) +{ + if (cl_smartjump.value) + KeyUp(&in_up); + KeyUp(&in_jump); +} void IN_Button3Down(void) {KeyDown(&in_button3);} @@ -800,18 +833,18 @@ void AddComponant(vec3_t angles, vec3_t dest, float fm, float rm, float um) } #define bound(n,v,x) vx?x:v) -qboolean CL_FilterTime (double time, float wantfps) +float CL_FilterTime (double time, float wantfps) //now returns the extra time not taken in this slot. Note that negative 1 means uncapped. { extern cvar_t rate; float fps, fpscap; if (cls.timedemo) - return true; + return -1; if (cls.demoplayback != DPB_NONE) { if (!wantfps) - return true; + return -1; fps = max (30.0, wantfps); } else @@ -832,7 +865,7 @@ qboolean CL_FilterTime (double time, float wantfps) if (time < 1000 / fps) return false; - return true; + return time - (1000 / fps); } qboolean allowindepphys; @@ -1270,8 +1303,10 @@ void CL_SendCmd (float frametime) Cam_FinishMove(plnum, cmd); +#ifdef Q2CLIENT if (cls.q2server && cmd->buttons) cmd->buttons |= 128; +#endif for (i=0 ; i<3 ; i++) cmd->angles[i] = ((int)(cl.viewangles[plnum][i]*65536.0/360)&65535); @@ -1504,6 +1539,8 @@ void CL_InitInput (void) Cvar_Register (&cl_c2sImpulseBackup, inputnetworkcvargroup); Cvar_Register (&cl_c2spps, inputnetworkcvargroup); Cvar_Register (&cl_netfps, inputnetworkcvargroup); + + Cvar_Register (&cl_smartjump, inputnetworkcvargroup); } /* diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 40c11696f..de7ecbb17 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -33,17 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -//imap exports -extern void IMAP_CreateConnection(char *servername, char *username, char *password); -extern cvar_t imap_checkfrequency; -extern void IMAP_Think (void); - -//pop3 -extern void POP3_CreateConnection(char *servername, char *username, char *password); -extern cvar_t pop3_checkfrequency; -extern void POP3_Think (void); - - // we need to declare some mouse variables here, because the menu system // references them even when on a unix system. @@ -114,6 +103,7 @@ cvar_t r_rocketlight = {"r_rocketlight", "1"}; cvar_t r_lightflicker = {"r_lightflicker", "1"}; cvar_t cl_r2g = {"cl_r2g", "0"}; cvar_t r_powerupglow = {"r_powerupglow", "1"}; +cvar_t v_powerupshell = {"v_powerupshell", "0"}; cvar_t cl_gibfilter = {"cl_gibfilter", "0"}; cvar_t cl_deadbodyfilter = {"cl_deadbodyfilter", "0"}; @@ -366,8 +356,10 @@ void CL_SendConnectPacket ( fteprotextsupported &= ftepext; +#ifdef Q2CLIENT if (cls.q2server) fteprotextsupported = 0; +#endif cls.fteprotocolextensions = fteprotextsupported; #endif @@ -964,6 +956,8 @@ void CL_Disconnect (void) COM_FlushTempoaryPacks(); + cl.spectator = 0; + #ifdef NQPROT cls.signon=0; NET_Close(cls.netcon); @@ -1084,7 +1078,7 @@ void CL_Color_f (void) return; } - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) server_owns_colour = true; else server_owns_colour = false; @@ -1200,6 +1194,8 @@ void CL_CheckServerInfo(void) cls.maxfps = atof(Info_ValueForKey(cl.serverinfo, "maxfps")); + if (cls.maxfps < 20) + cls.maxfps = 72; if (!atoi(Info_ValueForKey(cl.serverinfo, "deathmatch"))) cls.gamemode = GAME_COOP; @@ -1265,7 +1261,7 @@ void CL_FullServerinfo_f (void) char *p; float v; - if (!Cmd_FromServer()) + if (!Cmd_FromGamecode()) { Con_Printf("Hey! fullserverinfo is meant to come from the server!\n"); return; @@ -1428,7 +1424,7 @@ void CL_Packet_f (void) return; } - if (Cmd_FromServer()) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from. + if (Cmd_FromGamecode()) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from. { //unfortunatly, 50% of servers are badly configured. if (adr.type == NA_IP) if (adr.ip[0] == 127) @@ -1441,7 +1437,7 @@ void CL_Packet_f (void) adr.ip[2] = cls.netchan.remote_address.ip[2]; adr.ip[3] = cls.netchan.remote_address.ip[3]; adr.port = cls.netchan.remote_address.port; - Con_Printf ("^b^1Server is broken. Ignoring 'realip' packet request\n"); + Con_Printf ("^b^1Server is broken. Trying to send to server instead.\n"); } @@ -1839,7 +1835,9 @@ client_connect: //fixme: make function #ifdef NQPROT cls.netchan.qsocket = cls.netcon; #endif +#ifdef Q3CLIENT if (cls.q2server < 2) +#endif CL_SendClientCommand(true, "new"); cls.state = ca_connected; Con_TPrintf (TLC_CONNECTED); @@ -2093,7 +2091,7 @@ void CL_Download_f (void) #ifdef WEBCLIENT if (!strnicmp(url, "http://", 7) || !strnicmp(url, "ftp://", 6)) { - if (Cmd_FromServer()) + if (Cmd_IsInsecure()) return; HTTP_CL_Get(url, Cmd_Argv(2));//"test.txt"); return; @@ -2123,7 +2121,7 @@ void CL_Download_f (void) return; } - if (Cmd_FromServer()) //mark server specified downloads. + if (Cmd_IsInsecure()) //mark server specified downloads. { if (!strncmp(url, "game", 4) || !strcmp(url, "progs.dat") || !strcmp(url, "menu.dat") || !strcmp(url, "csqc.dat") || !strcmp(url, "qwprogs.dat") || strstr(url, "..") || strstr(url, ".dll") || strstr(url, ".so")) { //yes, I know the user can use a different progs from the one that is specified. If you leave it blank there will be no problem. (server isn't allowed to stuff progs cvar) @@ -2217,17 +2215,6 @@ void CL_IRC_f(void) IRC_Command(Cmd_Args()); } #endif -#ifdef EMAILCLIENT -void CL_IMAPPoll_f(void) -{ - IMAP_CreateConnection(Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3)); -} - -void CL_POP3Poll_f(void) -{ - POP3_CreateConnection(Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3)); -} -#endif void SCR_ShowPic_Script_f(void); /* @@ -2322,6 +2309,7 @@ void CL_Init (void) Cvar_Register (&r_lightflicker, "Item effects"); Cvar_Register (&cl_r2g, "Item effects"); Cvar_Register (&r_powerupglow, "Item effects"); + Cvar_Register (&r_powerupglow, "v_powerupshell"); Cvar_Register (&cl_gibfilter, "Item effects"); Cvar_Register (&cl_deadbodyfilter, "Item effects"); @@ -2359,14 +2347,6 @@ void CL_Init (void) Cmd_AddCommand ("ftp", CL_FTP_f); #endif -#ifdef EMAILCLIENT - Cvar_Register (&imap_checkfrequency, "Email notifications"); - Cmd_AddCommand ("imapaccount", CL_IMAPPoll_f); - - Cvar_Register (&pop3_checkfrequency, "Email notifications"); - Cmd_AddCommand ("pop3account", CL_POP3Poll_f); -#endif - Cmd_AddCommand ("version", CL_Version_f); Cmd_AddCommand ("changing", CL_Changing_f); @@ -2584,7 +2564,7 @@ extern qboolean recordingdemo; extern cvar_t cl_netfps; int nopacketcount; void SNDDMA_SetUnderWater(qboolean underwater); -qboolean CL_FilterTime (double time, float wantfps); +float CL_FilterTime (double time, float wantfps); void Host_Frame (float time) { static double time1 = 0; @@ -2593,6 +2573,7 @@ void Host_Frame (float time) int pass1, pass2, pass3; // float fps; float realframetime; + static float spare; RSpeedLocals(); @@ -2625,10 +2606,6 @@ void Host_Frame (float time) #ifdef IRCCLIENT IRC_Frame(); #endif -#ifdef EMAILCLIENT - IMAP_Think(); - POP3_Think(); -#endif #ifdef PLUGINS Plug_Tick(); @@ -2643,18 +2620,6 @@ void Host_Frame (float time) cl.gametimemark += time; -#if defined(NQPROT) || defined(Q2CLIENT) -#if defined(NQPROT) && defined(Q2CLIENT) - if (cls.q2server || cls.demoplayback == DPB_NETQUAKE) -#elif defined(NQPROT) - if (cls.demoplayback == DPB_NETQUAKE) -#elif defined(Q2CLIENT) - if (cls.q2server) -#endif - cl.time += time; -#endif - - #ifdef VOICECHAT CLVC_Poll(); @@ -2678,12 +2643,34 @@ void Host_Frame (float time) } else { - if (!CL_FilterTime((realtime - oldrealtime)*1000, cl_maxfps.value>0?cl_maxfps.value:cl_netfps.value)) + realtime += spare/1000; //don't use it all! + spare = CL_FilterTime((realtime - oldrealtime)*1000, cl_maxfps.value>0?cl_maxfps.value:cl_netfps.value); + if (!spare) return; + if (spare < 0 || cls.state < ca_onserver) + spare = 0; //uncapped. + if (spare > 10) + spare = 10; + + realtime -= spare/1000; //don't use it all! } host_frametime = (realtime - oldrealtime)*cl.gamespeed; oldrealtime = realtime; + + +#if defined(NQPROT) || defined(Q2CLIENT) +#if defined(NQPROT) && defined(Q2CLIENT) + if (cls.q2server || cls.demoplayback == DPB_NETQUAKE) +#elif defined(NQPROT) + if (cls.demoplayback == DPB_NETQUAKE) +#elif defined(Q2CLIENT) + if (cls.q2server) +#endif + cl.time += host_frametime; +#endif + + // if (host_frametime > 0.2) // host_frametime = 0.2; @@ -2745,7 +2732,7 @@ void Host_Frame (float time) } } - RSpeedEnd(RSPEED_CLIENT); + RSpeedEnd(RSPEED_PROTOCOL); // update video if (host_speeds.value) @@ -2755,6 +2742,13 @@ void Host_Frame (float time) if (SCR_UpdateScreen) { extern mleaf_t *r_viewleaf; + extern cvar_t scr_chatmodecvar; + + if (scr_chatmodecvar.value && !cl.intermission) + scr_chatmode = (cl.spectator&&cl.splitclients<2&&cls.state == ca_active)?2:1; + else + scr_chatmode = 0; + SCR_UpdateScreen (); if (cls.state >= ca_active && r_viewleaf) SNDDMA_SetUnderWater(r_viewleaf->contents <= Q1CONTENTS_WATER); diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index f005dfee2..e0e479b46 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -717,6 +717,7 @@ fixedorg: } out: CL_CalcCrouch (pnum); + cl.waterlevel[pnum] = pmove.waterlevel; } void CL_PredictMove (void) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index d702a4e89..7e0e5d0eb 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -673,9 +673,6 @@ void SCR_CalcRefdef (void) int h; qboolean full = false; - scr_chatmode = scr_chatmodecvar.value; - - scr_fullupdate = 0; // force a background redraw vid.recalc_refdef = 0; scr_viewsize.modified = false; @@ -716,7 +713,7 @@ void SCR_CalcRefdef (void) else sb_lines = 24+16+8; - if (scr_viewsize.value >= 100.0) { + if (scr_viewsize.value >= 100.0 || scr_chatmode) { full = true; size = 100.0; } else @@ -755,9 +752,11 @@ void SCR_CalcRefdef (void) if (scr_chatmode) { - r_refdef.vrect.height= r_refdef.vrect.y=vid.height/2; + if (scr_chatmode != 2) + r_refdef.vrect.height= r_refdef.vrect.y=vid.height/2; r_refdef.vrect.width = r_refdef.vrect.x=vid.width/2; - sb_lines=0; + if (r_refdef.vrect.width<320 || r_refdef.vrect.height<200) //disable hud if too small + sb_lines=0; } r_refdef.fov_x = scr_fov.value; @@ -1001,6 +1000,15 @@ void SCR_DrawFPS (void) lastframetime = t; } } + else if (show_fps.value == 3) //alternate mode that displays the highest noticed + { + if (lastfps < 1/host_frametime) + { + lastfps = 1/host_frametime; + fps_count = 0; + lastframetime = t; + } + } sprintf(str, "%3.1f FPS", lastfps); SCR_StringXY(str, show_fps_x.value, show_fps_y.value); @@ -1790,25 +1798,26 @@ void SCR_TileClear (void) } else { - if (r_refdef.vrect.x > 0) { + if (scr_vrect.x > 0) { // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); + Draw_TileClear (0, 0, scr_vrect.x, vid.height - sb_lines); // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + Draw_TileClear (scr_vrect.x + scr_vrect.width, 0, + vid.width - scr_vrect.x + scr_vrect.width, vid.height - sb_lines); } - if (r_refdef.vrect.y > 0) { + if (scr_vrect.y > 0) + { // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); + Draw_TileClear (scr_vrect.x, 0, + scr_vrect.x + scr_vrect.width, + scr_vrect.y); // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - sb_lines - - (r_refdef.vrect.height + r_refdef.vrect.y)); + Draw_TileClear (scr_vrect.x, + scr_vrect.y + scr_vrect.height, + scr_vrect.width, + vid.height - cl_sbar.value?sb_lines:0 - + (scr_vrect.height + scr_vrect.y)); } } } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 3251d13eb..50cf122bd 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -808,7 +808,7 @@ void CL_ParseTEnt (void) CL_ParseStream (type); break; - case 50: //TE_BLOOD + case DPTE_BLOOD: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); @@ -824,7 +824,7 @@ void CL_ParseTEnt (void) } break; - case 51://TE_SPARK + case DPTE_SPARK: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); @@ -840,7 +840,7 @@ void CL_ParseTEnt (void) } break; - case 72://TE_SMALLFLASH + case DPTE_SMALLFLASH: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); @@ -856,7 +856,7 @@ void CL_ParseTEnt (void) dl->color[2] = 0.4; break; - case 73://TE_CUSTOMFLASH + case DPTE_CUSTOMFLASH: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); @@ -876,7 +876,7 @@ void CL_ParseTEnt (void) break; - case 74://TE_FLAMEJET + case DPTE_FLAMEJET: // origin pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); @@ -894,7 +894,7 @@ void CL_ParseTEnt (void) P_RunParticleEffect (pos, pos2, 232, cnt); break; - case 75://TE_PLASMABURN + case DPTE_PLASMABURN: // origin pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); @@ -919,38 +919,37 @@ void CL_ParseTEnt (void) case 76: #pragma message("CL_ParseTEnt: effect 76 not implemented") -pos[0] = MSG_ReadCoord (); -pos[1] = MSG_ReadCoord (); -pos[2] = MSG_ReadCoord (); + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); -pos2[0] = MSG_ReadCoord (); -pos2[1] = MSG_ReadCoord (); -pos2[2] = MSG_ReadCoord (); + pos2[0] = MSG_ReadCoord (); + pos2[1] = MSG_ReadCoord (); + pos2[2] = MSG_ReadCoord (); -//sigh... -MSG_ReadCoord (); -MSG_ReadCoord (); -MSG_ReadCoord (); + //sigh... + MSG_ReadCoord (); + MSG_ReadCoord (); + MSG_ReadCoord (); -CLQ2_RailTrail (pos, pos2); + CLQ2_RailTrail (pos, pos2); break; case 79: -#pragma message("CL_ParseTEnt: effect 79 not implemented") -pos[0] = MSG_ReadCoord (); -pos[1] = MSG_ReadCoord (); -pos[2] = MSG_ReadCoord (); + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); -//dir -pos2[0] = MSG_ReadCoord (); -pos2[1] = MSG_ReadCoord (); -pos2[2] = MSG_ReadCoord (); -cnt = MSG_ReadByte (); + //dir + pos2[0] = MSG_ReadCoord (); + pos2[1] = MSG_ReadCoord (); + pos2[2] = MSG_ReadCoord (); + cnt = MSG_ReadByte (); -{ - extern int pt_plasma; - P_RunParticleEffectType(pos, pos2, cnt, pt_plasma); -} + { + extern int pt_plasma; + P_RunParticleEffectType(pos, pos2, cnt, pt_plasma); + } break; default: diff --git a/engine/client/client.h b/engine/client/client.h index 9faff07d5..0c2b1360c 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -211,7 +211,21 @@ typedef struct // // client_state_t should hold all pieces of the client state // -#define MAX_DLIGHTS 256 +#define MAX_SWLIGHTS 32 //sw lighting, aka: r_dynamic, uses unsigned ints as a mask for cached lit flags. We could increase this on 64bit platforms or by just using more fields. + +#ifdef RGLQUAKE +#define MAX_RTLIGHTS 256 //r_shadow_realtime_world needs a LOT of lights. +#else +#define MAX_RTLIGHTS 0 //but sw rendering doesn't have that. +#endif + +#if MAX_SWLIGHTS > MAX_RTLIGHTS +#define MAX_DLIGHTS MAX_SWLIGHTS +#else +#define MAX_DLIGHTS MAX_RTLIGHTS +#endif + + typedef struct dlight_s { int key; // so entities can reuse same entry @@ -501,6 +515,7 @@ typedef struct #endif qboolean gamedirchanged; + int waterlevel[MAX_SPLITS]; //for smartjump char q2statusbar[1024]; char q2layout[1024]; diff --git a/engine/client/console.c b/engine/client/console.c index eac23109d..07c6dcda5 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -290,7 +290,7 @@ void QT_Create(char *command) void Con_QTerm_f(void) { - if(Cmd_FromServer()) + if(Cmd_IsInsecure()) Con_Printf("Server tried stuffcmding a restricted commandqterm %s\n", Cmd_Args()); else QT_Create(Cmd_Args()); @@ -411,7 +411,10 @@ void Con_ResizeCon (console_t *con) int i, j, width, oldwidth, oldtotallines, numlines, numchars; unsigned short tbuf[CON_TEXTSIZE]; - width = (vid.width >> 3) - 2; + if (scr_chatmode == 2) + width = (vid.width >> 4) - 2; + else + width = (vid.width >> 3) - 2; if (width == con->linewidth) return; diff --git a/engine/client/keys.c b/engine/client/keys.c index d5d553fdb..5f86daf9f 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -931,7 +931,7 @@ void Key_BindLevel_f (void) return; } - if (Cmd_FromServer()) + if (Cmd_IsInsecure()) { Con_Printf("Server attempted usage of bindat\n"); return; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 99ffe9140..382cf7f38 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -139,13 +139,13 @@ void Media_Seek (float time) #endif for (sc = sndcardinfo; sc; sc=sc->next) { - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].pos += sc->sn.speed*time; - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].end += sc->sn.speed*time; + sc->channel[NUM_AMBIENTS].pos += sc->sn.speed*time; + sc->channel[NUM_AMBIENTS].end += sc->sn.speed*time; - if (sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].pos < 0) + if (sc->channel[NUM_AMBIENTS].pos < 0) { - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].end -= sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].pos; - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].pos=0; + sc->channel[NUM_AMBIENTS].end -= sc->channel[NUM_AMBIENTS].pos; + sc->channel[NUM_AMBIENTS].pos=0; } //if we seek over the end, ignore it. The sound playing code will spot that. } @@ -232,15 +232,17 @@ void Media_Clear (void) soundcardinfo_t *sc; for (sc = sndcardinfo; sc; sc=sc->next) { - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].end = 0; - s = sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].sfx; - sc->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS].sfx = NULL; + sc->channel[NUM_AMBIENTS].end = 0; + s = sc->channel[NUM_AMBIENTS].sfx; + sc->channel[NUM_AMBIENTS].sfx = NULL; if (s) if (s->decoder) if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly. { s->decoder->abort(s); + if (s->cache.data) + Cache_Free(&s->cache); } } } @@ -1437,7 +1439,7 @@ void Media_RecordFilm_f (void) return; } - if (Cmd_FromServer()) //err... don't think so sony. + if (Cmd_IsInsecure()) //err... don't think so sony. return; if (!aviinited) diff --git a/engine/client/m_single.c b/engine/client/m_single.c index d5d4dd436..042a8d5ea 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -451,7 +451,6 @@ void M_Menu_ParticleSets_f (void) info->command[0] = "r_particlesdesc"; info->ext[0] = ".cfg"; - info->command[1] = "playdemo"; info->numext = 1; MC_AddWhiteText(menu, 24, 8, "Choose a Particle Set", false); diff --git a/engine/client/menu.c b/engine/client/menu.c index a6a075d68..01718aa27 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -798,6 +798,7 @@ void M_Menu_FPS_f (void); void M_Menu_Particles_f (void); void M_Menu_ParticleSets_f (void); void M_Menu_Audio_Speakers_f (void); +void Menu_DownloadStuff_f (void); static qboolean internalmenusregistered; void M_Init_Internal (void) { @@ -840,6 +841,10 @@ void M_Init_Internal (void) Cmd_AddRemCommand ("menu_fps", M_Menu_FPS_f); Cmd_AddRemCommand ("menu_particles", M_Menu_Particles_f); Cmd_AddRemCommand ("menu_particlesets", M_Menu_ParticleSets_f); + +#ifndef MINIMAL + Cmd_AddRemCommand ("menu_download", Menu_DownloadStuff_f); +#endif } void M_DeInit_Internal (void) @@ -879,6 +884,8 @@ void M_DeInit_Internal (void) Cmd_RemoveCommand ("menu_fps"); Cmd_RemoveCommand ("menu_particles"); Cmd_RemoveCommand ("menu_particlesets"); + + Cmd_RemoveCommand ("menu_download"); } //menu.dat is loaded later... after the video and everything is up. diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index fabd4f784..57416928d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -42,6 +42,9 @@ cvar_t cl_csqcdebug = {"cl_csqcdebug", "0"}; //prints entity numbers which arriv globalvector(trace_plane_normal, "trace_plane_normal"); /*vector written by traceline*/ \ globalfloat(trace_plane_dist, "trace_plane_dist"); /*float written by traceline*/ \ globalentity(trace_ent, "trace_ent"); /*entity written by traceline*/ \ + \ + globalfloat(player_localentnum, "player_localentnum"); /*float the entity number of the local player*/ \ + typedef struct { #define globalfloat(name,qcname) float *name @@ -78,8 +81,12 @@ void CSQC_FindGlobals(void) #undef globalentity #undef globalstring #undef globalfunction + if (csqcg.time) *csqcg.time = Sys_DoubleTime(); + + if (csqcg.player_localentnum) + *csqcg.player_localentnum = cl.playernum[0]+1; } diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index fddd1d75a..f3b1ce9fa 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -77,8 +77,13 @@ void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_traceon (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_traceoff (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void search_close_progs(progfuncs_t *prinst, qboolean complain); +void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals); -void PF_fclose_progs (progfuncs_t *prinst); +void PR_fclose_progs (progfuncs_t *prinst); char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals); //new generic functions. @@ -177,191 +182,6 @@ void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = (float)(((int)G_FLOAT(OFS_PARM0))%((int)G_FLOAT(OFS_PARM1))); } -typedef struct prvmsearch_s { - int handle; - progfuncs_t *fromprogs; //share across menu/server - int entries; - char **names; - int *sizes; - - struct prvmsearch_s *next; -} prvmsearch_t; -prvmsearch_t *prvmsearches; -int prvm_nextsearchhandle; - -void search_close (progfuncs_t *prinst, int handle) -{ - int i; - prvmsearch_t *prev, *s; - - prev = NULL; - for (s = prvmsearches; s; ) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Handle wasn't valid with that progs\n"); - return; - } - if (prev) - prev->next = s->next; - else - prvmsearches = s->next; - - for (i = 0; i < s->entries; i++) - { - BZ_Free(s->names[i]); - } - BZ_Free(s->names); - BZ_Free(s->sizes); - BZ_Free(s); - - return; - } - - prev = s; - s = s->next; - } -} -//a progs was closed... hunt down it's searches, and warn about any searches left open. -void search_close_progs(progfuncs_t *prinst, qboolean complain) -{ - int i; - prvmsearch_t *prev, *s; - - prev = NULL; - for (s = prvmsearches; s; ) - { - if (s->fromprogs == prinst) - { //close it down. - - if (complain) - Con_Printf("Warning: Progs search was still active\n"); - if (prev) - prev->next = s->next; - else - prvmsearches = s->next; - - for (i = 0; i < s->entries; i++) - { - BZ_Free(s->names[i]); - } - BZ_Free(s->names); - BZ_Free(s->sizes); - BZ_Free(s); - - if (prev) - s = prev->next; - else - s = prvmsearches; - continue; - } - - prev = s; - s = s->next; - } - - if (!prvmsearches) - prvm_nextsearchhandle = 0; //might as well. -} - -int search_enumerate(char *name, int fsize, void *parm) -{ - prvmsearch_t *s = parm; - - s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); - s->sizes = BZ_Realloc(s->sizes, ((s->entries+64)&~63) * sizeof(int)); - s->names[s->entries] = BZ_Malloc(strlen(name)+1); - strcpy(s->names[s->entries], name); - s->sizes[s->entries] = fsize; - - s->entries++; - return true; -} - -//float search_begin(string pattern, float caseinsensitive, float quiet) = #74; -void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ //< 0 for error, > 0 for handle. - char *pattern = PR_GetStringOfs(prinst, OFS_PARM0); -// qboolean caseinsensative = G_FLOAT(OFS_PARM1); -// qboolean quiet = G_FLOAT(OFS_PARM2); - prvmsearch_t *s; - - s = BZ_Malloc(sizeof(*s)); - s->fromprogs = prinst; - s->handle = prvm_nextsearchhandle++; - - COM_EnumerateFiles(pattern, search_enumerate, s); - - if (s->entries==0) - { - BZ_Free(s); - G_FLOAT(OFS_RETURN) = -1; - return; - } - s->next = prvmsearches; - prvmsearches = s; - G_FLOAT(OFS_RETURN) = s->handle; -} -//void search_end(float handle) = #75; -void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - search_close(prinst, handle); -} -//float search_getsize(float handle) = #76; -void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - prvmsearch_t *s; - G_FLOAT(OFS_RETURN) = -1; - for (s = prvmsearches; s; s = s->next) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Handle wasn't valid with that progs\n"); - return; - } - - G_FLOAT(OFS_RETURN) = s->entries; - return; - } - } -} -//string search_getfilename(float handle, float num) = #77; -void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - int num = G_FLOAT(OFS_PARM1); - prvmsearch_t *s; - G_INT(OFS_RETURN) = 0; - - for (s = prvmsearches; s; s = s->next) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Search handle wasn't valid with that progs\n"); - return; - } - - if (num < 0 || num >= s->entries) - return; - G_INT(OFS_RETURN) = (int)(s->names[num] - prinst->stringtable); - return; - } - } - - Con_Printf("Search handle wasn't valid\n"); -} - - - - static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1297,7 +1117,7 @@ void MP_Shutdown (void) if (temp && !inmenuprogs) PR_ExecuteProgram(menuprogs, temp); - PF_fclose_progs(menuprogs); + PR_fclose_progs(menuprogs); search_close_progs(menuprogs, true); CloseProgs(menuprogs); diff --git a/engine/client/r_part.c b/engine/client/r_part.c index c3428bde6..a341f7784 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -287,7 +287,7 @@ qboolean P_DescriptionIsLoaded(char *name) static void P_SetModified(void) //called when the particle system changes (from console). { - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) return; //server stuffed particle descriptions don't count. f_modified_particles = true; @@ -608,13 +608,25 @@ void P_ParticleEffect_f(void) // old names else if (!strcmp(var, "areaspread")) + { + Con_DPrintf("areaspread is deprechiated, use spawnorg\n"); ptype->areaspread = atof(value); + } else if (!strcmp(var, "areaspreadvert")) + { + Con_DPrintf("areaspreadvert is deprechiated, use spawnorg\n"); ptype->areaspreadvert = atof(value); + } else if (!strcmp(var, "offsetspread")) + { + Con_DPrintf("offsetspread is deprechiated, use spawnvel\n"); ptype->offsetspread = atof(value); + } else if (!strcmp(var, "offsetspreadvert")) + { + Con_DPrintf("offsetspreadvert is deprechiated, use spawnvel\n"); ptype->offsetspreadvert = atof(value); + } // new names else if (!strcmp(var, "spawnorg")) @@ -1170,7 +1182,20 @@ void P_NewServer(void) Cbuf_AddText(particle_set_highfps, RESTRICT_SERVER); else { - Cbuf_AddText(va("exec %s.cfg\n", r_particlesdesc.string), RESTRICT_LOCAL); + char *file = COM_LoadMallocFile(va("particles/%s.cfg", r_particlesdesc.string)); + if (!file) + file = COM_LoadMallocFile(va("%s.cfg", r_particlesdesc.string)); + if (file) + { + Cbuf_AddText(file, RESTRICT_LOCAL); + Cbuf_AddText("\n", RESTRICT_LOCAL); //I'm paranoid. + BZ_Free(file); + } + else + { + Con_Printf("Couldn't find particle description, using spikeset\n"); + Cbuf_AddText(particle_set_spikeset, RESTRICT_SERVER); + } /*#if defined(_DEBUG) && defined(WIN32) //expand the particles cfg into a C style quoted string, and copy to clipboard so I can paste it in. { char *TL_ExpandToCString(char *in); diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c index 17adf034e..04519c279 100644 --- a/engine/client/r_partset.c +++ b/engine/client/r_partset.c @@ -520,6 +520,7 @@ char *particle_set_spikeset = " stains 0\n" " blend add\n" " areaspread 6\n" +" up -8\n" " areaspreadvert 0\n" " spawnmode box\n" " offsetspread -15\n" diff --git a/engine/client/render.h b/engine/client/render.h index 7817264ae..bf16e8028 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -72,6 +72,8 @@ typedef struct entity_s // that splits bmodel, or NULL if // not split + float bonecontrols[4]; + int flags; #ifdef Q3SHADERS @@ -340,10 +342,11 @@ extern cvar_t r_palconvwrite; enum { RSPEED_TOTALREFRESH, - RSPEED_CLIENT, + RSPEED_LINKENTITIES, + RSPEED_PROTOCOL, RSPEED_WORLDNODE, RSPEED_WORLD, - RSPEED_ENTITIES, + RSPEED_DRAWENTITIES, RSPEED_STENCILSHADOWS, RSPEED_FULLBRIGHTS, RSPEED_DYNAMIC, diff --git a/engine/client/renderer.c b/engine/client/renderer.c index d74b400c9..26125d77e 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -142,7 +142,6 @@ extern cvar_t gl_maxdist; #ifdef SPECULAR cvar_t gl_specular = {"gl_specular", "0"}; #endif -cvar_t gl_waterripples = {"gl_waterripples", "0"}; cvar_t gl_detail = {"gl_detail", "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}; @@ -239,8 +238,6 @@ cvar_t gl_ztrick = {"gl_ztrick","1"}; cvar_t gl_lerpimages = {"gl_lerpimages", "1"}; extern cvar_t r_waterlayers; cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", NULL, CVAR_ARCHIVE}; -cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", NULL, CVAR_ARCHIVE}; -cvar_t gl_subdivide_water = {"gl_subdivide_water", "0", NULL, CVAR_ARCHIVE}; cvar_t vid_hardwaregamma = {"vid_hardwaregamma", "1", NULL, CVAR_ARCHIVE}; void GLRenderer_Init(void) { @@ -250,10 +247,6 @@ void GLRenderer_Init(void) Cvar_Register (&vid_hardwaregamma, GLRENDEREROPTIONS); - //model - Cvar_Register (&gl_subdivide_size, GLRENDEREROPTIONS); - Cvar_Register (&gl_subdivide_water, GLRENDEREROPTIONS); - //renderer Cvar_Register (&r_novis, GLRENDEREROPTIONS); Cvar_Register (&r_wateralpha, GLRENDEREROPTIONS); @@ -311,7 +304,6 @@ void GLRenderer_Init(void) #ifdef WATERLAYERS Cvar_Register (&r_waterlayers, GRAPHICALNICETIES); #endif - Cvar_Register (&gl_waterripples, GRAPHICALNICETIES); Cvar_Register (&gl_nobind, GLRENDEREROPTIONS); Cvar_Register (&gl_max_size, GLRENDEREROPTIONS); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 3685f0efb..ec05ff2d1 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -184,6 +184,9 @@ void Draw_FunStringLen(int x, int y, unsigned char *str, int len) while(*str) { + if (--len< 0) + break; + if (*str == '^') { str++; @@ -239,8 +242,6 @@ void Draw_FunStringLen(int x, int y, unsigned char *str, int len) } Draw_ColouredCharacter (x, y, (*str++) + ext); x += 8; - if (--len< 0) - break; } } @@ -1610,7 +1611,7 @@ void Sbar_Draw (void) for (pnum = 0; pnum < cl.splitclients; pnum++) { - if (cl.splitclients>1) + if (cl.splitclients>1 || scr_chatmode) { SCR_VRectForPlayer(&sbar_rect, pnum); } @@ -2069,7 +2070,9 @@ void Sbar_ChatModeOverlay(void) // scores Sbar_SortFrags (true); - if (cl.playernum[0]>=0 && cl.playernum[0]=0) + Q_strncpyz (team, Info_ValueForKey(cl.players[Cam_TrackNum(0)].userinfo, "team"), sizeof(team)); + else if (cl.playernum[0]>=0 && cl.playernum[0]type == mod_dummy) model = NULL; @@ -262,9 +264,11 @@ qbyte *Skin_Cache8 (skin_t *skin) return out; } +#ifdef Q2CLIENT if (cls.q2server) sprintf (name, "players/%s.pcx", skin->name); else +#endif sprintf (name, "skins/%s.pcx", skin->name); raw = COM_LoadTempFile (name); if (!raw) diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 2795e8948..1455de23b 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -603,20 +603,24 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime) if (ch->sfx->decoder) { + int len_diff; soundcardinfo_t *sndc; #define qmax(x, y) (x>y)?(x):(y) + len_diff = scache->length; ch->sfx->decoder->decodemore(ch->sfx, - ch->pos + end-ltime+1000); + ch->pos + endtime-ltime+1000); //ch->pos + qmax(end-ltime+1000, 1000)); //try to exceed by a little. + scache = S_LoadSound (ch->sfx); if (!scache) continue; + len_diff = scache->length - len_diff; for (sndc = sndcardinfo; sndc; sndc=sndc->next) { for (j = 0; j < sndc->total_chans; j++) if (sndc->channel[j].sfx == ch->sfx) //extend all of these. - ch->end = ltime + (scache->length - ch->pos); + ch->end += len_diff; } } diff --git a/engine/client/snd_mp3.c b/engine/client/snd_mp3.c index 462ab68d4..2cf291619 100644 --- a/engine/client/snd_mp3.c +++ b/engine/client/snd_mp3.c @@ -158,8 +158,9 @@ sfxcache_t *S_LoadMP3Sound (sfx_t *s) } } - if (!s->decoder) - s->decoder = Z_Malloc(sizeof(decoderbuffer_t) + sizeof(sfxdecode_t)); + if (s->decoder) + Sys_Error("Decoding already decoding file\n"); + s->decoder = Z_Malloc(sizeof(decoderbuffer_t) + sizeof(sfxdecode_t)); buffer = (decoderbuffer_t*)(s->decoder+1); buffer->mp3aswavpos=0; @@ -182,6 +183,8 @@ sfxcache_t *S_LoadMP3Sound (sfx_t *s) } s->decoder->decodemore(s, 100); + if (!s->decoder) //wow, short file. :/ + return s->cache.data; s->cache.fake=true; return buffer->s->cache.data; @@ -387,7 +390,7 @@ enum mad_flow error(void *data, stream->error, mad_stream_errorstr(stream), stream->this_frame - buffer->start); -// buffer->failed = true; + buffer->failed = true; return MAD_FLOW_IGNORE; } @@ -438,7 +441,7 @@ int DecodeSomeMP3(sfx_t *s, int minlength) if (!dec->start) return 1; - while(dec->mp3sc.length < minlength) + while(dec->mp3sc.length <= minlength) { if (!mymad_run(&dec->decoder) || dec->failed) { @@ -455,9 +458,9 @@ int DecodeSomeMP3(sfx_t *s, int minlength) s->cache.fake = false; //give it a true cache now, and hope that we don't need to free it while it's still playing. s->cache.data=NULL; - newmem = Cache_Alloc(&s->cache, dec->mp3aswavbuflen+sizeof(sfxcache_t), s->name); if (dec->mp3aswavdata) { + newmem = Cache_Alloc(&s->cache, dec->mp3aswavbuflen+sizeof(sfxcache_t), s->name); memcpy(newmem, dec->mp3aswavdata, dec->mp3aswavbuflen+sizeof(sfxcache_t)); BZ_Free(dec->mp3aswavdata); } diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index f552d2934..e99f67e5b 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -273,8 +273,10 @@ static ov_callbacks callbacks = { qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer) { #ifdef WINDOWSDYNAMICLINK - if (!oggvorbislibrary) + static qboolean tried; + if (!oggvorbislibrary && !tried) { + tried = true; oggvorbislibrary = LoadLibrary("vorbisfile.dll"); if (!oggvorbislibrary) { @@ -304,7 +306,7 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf /* Print the comments plus a few lines about the bitstream we're decoding */ { - char **ptr=p_ov_comment(&buffer->vf,-1)->user_comments; +// char **ptr=p_ov_comment(&buffer->vf,-1)->user_comments; vorbis_info *vi=p_ov_info(&buffer->vf,-1); if (vi->channels < 1 || vi->channels > 2) @@ -316,16 +318,16 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf buffer->mediasc.stereo = vi->channels-1; buffer->mediasc.loopstart = -1; buffer->srcspeed = vi->rate; - +/* while(*ptr){ Con_Printf("%s\n",*ptr); - ++ptr; + ptr++; } Con_Printf("\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); Con_Printf("\nDecoded length: %ld samples\n", (long)p_ov_pcm_total(&buffer->vf,-1)); Con_Printf("Encoded by: %s\n\n",p_ov_comment(&buffer->vf,-1)->vendor); - } +*/ } return true; } #endif diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 3c26a8644..f1fb432e4 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1156,7 +1156,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin SetHookState(sys_disableWinKeys.value); - Sleep(0); +// Sleep(0); } } diff --git a/engine/client/textedit.c b/engine/client/textedit.c index da42f07a0..40b2ea022 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -924,6 +924,9 @@ void Editor_Draw(void) int QCLibEditor(char *filename, int line, int nump, char **parms) { + editprogfuncs = svprogfuncs; + + if (editormodal || !developer.value) return line; //whoops diff --git a/engine/client/view.c b/engine/client/view.c index 31a4e8e91..d708619f7 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -455,7 +455,7 @@ void V_cshift_f (void) Con_Printf("v_cshift: v_cshift \n"); return; } - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { cl.cshifts[CSHIFT_SERVER].destcolor[0] = atoi(Cmd_Argv(1)); cl.cshifts[CSHIFT_SERVER].destcolor[1] = atoi(Cmd_Argv(2)); @@ -479,7 +479,7 @@ When you run over an item, the server sends this command */ void V_BonusFlash_f (void) { - if (v_bonusflash.value || !Cmd_FromServer()) + if (v_bonusflash.value || !Cmd_FromGamecode()) { cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; @@ -1250,6 +1250,12 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) vrect->height = scr_vrect.height; vrect->x = scr_vrect.x; vrect->y = scr_vrect.y; + + if (scr_chatmode == 2) + { + vrect->height/=2; + vrect->y += vrect->height; + } break; case 2: //horizontal bands @@ -1309,6 +1315,30 @@ void V_RenderPlayerViews(int plnum) else #endif R_RenderView (); + + if (scr_chatmode == 2) + { + extern vec3_t desired_position[MAX_SPLITS]; + vec3_t dir; + extern void vectoangles(vec3_t vec, vec3_t ang); + + gl_ztrickdisabled|=16; + r_refdef.vrect.y -= r_refdef.vrect.height; + vid.recalc_refdef=true; + r_secondaryview = 2; + + VectorSubtract(r_refdef.vieworg, desired_position[plnum], dir); + vectoangles(dir, r_refdef.viewangles); + r_refdef.viewangles[0] = -r_refdef.viewangles[0]; //flip the pitch. :( + + + VectorCopy(desired_position[plnum], r_refdef.vieworg); + R_RenderView (); + vid.recalc_refdef=true; + r_secondaryview = false; + } + else + gl_ztrickdisabled&=~16; r_secondaryview = 2; @@ -1438,6 +1468,7 @@ void V_RenderView (void) if (cl.worldmodel) { + RSpeedMark(); CL_AllowIndependantSendCmd(false); //work out which packet entities are solid @@ -1456,6 +1487,8 @@ void V_RenderView (void) CL_EmitEntities (); CL_AllowIndependantSendCmd(true); + + RSpeedEnd(RSPEED_LINKENTITIES); } view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index cbaa0728d..b16c83db8 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -473,7 +473,7 @@ static char *Macro_Powerups (void) } effects = cl.frames[cl.parsecount&UPDATE_MASK].playerstate[cl.playernum[SP]].effects; - if ( (effects & (EF_FLAG1|EF_FLAG2)) || // CTF + if ( (effects & (QWEF_FLAG1|QWEF_FLAG2)) || // CTF (cl.teamfortress && cl.stats[SP][STAT_ITEMS] & (IT_KEY1|IT_KEY2)) ) // TF { if (macro_buf[0]) diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 37750a165..4b88834ee 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -39,7 +39,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AVAIL_JPEGLIB #define AVAIL_ZLIB -// #define AVAIL_OGGVORBIS + #define AVAIL_MP3 + + #define AVAIL_OGGVORBIS #endif #define AVAIL_MASM @@ -96,8 +98,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ZLIB //zip/pk3 support #define WEBSERVER //http/ftp servers #define WEBCLIENT //http/ftp clients. - #define EMAILSERVER //smtp/pop3 server should you feel a need - #define EMAILCLIENT //smtp/pop3 clients (email notifications) #define RUNTIMELIGHTING //calculate lit/lux files the first time the map is loaded and doesn't have a loadable lit. // #define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm. #define CL_MASTER //query master servers and stuff for a dynamic server listing. @@ -161,7 +161,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef Q3CLIENT #undef WEBCLIENT #undef IRCCLIENT - #undef EMAILCLIENT #undef TEXTEDITOR #undef RUNTIMELIGHTING #undef PLUGINS //we don't have any server side stuff. @@ -170,7 +169,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef CLIENTONLY //remove optional server componants that make no sence on a client only build. #undef Q2SERVER #undef WEBSERVER - #undef EMAILSERVER #endif //remove any options that depend upon GL. diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 77bdc631d..1df23c2e4 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -216,7 +216,7 @@ typedef struct #define AMBIENT_LAVA 3 #define NUM_AMBIENTS 4 // automatic ambient sounds -#define NUM_MUSICS 2 // so the streaming media can just switch between the two, allowing it to seamlessly continue. +#define NUM_MUSICS 1 // leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas // all other leafs need visibility info diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 243c9d7be..d46fe3e36 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -470,7 +470,6 @@ Cmd_Exec_f void Cmd_Exec_f (void) { char *f; - int mark; char name[256]; if (Cmd_Argc () != 2) @@ -491,9 +490,7 @@ void Cmd_Exec_f (void) else Q_strncpyz(name, Cmd_Argv(1), sizeof(name)); - // FIXME: is this safe freeing the hunk here??? - mark = Hunk_LowMark (); - f = (char *)COM_LoadHunkFile (name); + f = (char *)COM_LoadMallocFile(name); if (!f) { Con_TPrintf (TL_EXECFAILED,name); @@ -501,10 +498,10 @@ void Cmd_Exec_f (void) } if (cl_warncmd.value || developer.value) Con_TPrintf (TL_EXECING,name); - + Cbuf_InsertText ("\n", Cmd_ExecLevel); //well this is inefficient... Cbuf_InsertText (f, Cmd_ExecLevel); - Hunk_FreeToLowMark (mark); + BZ_Free(f); } @@ -571,7 +568,7 @@ void Cmd_Alias_f (void) if (Cmd_Argc() == 1) //list em all. { - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { if (Cmd_ExecLevel==RESTRICT_SERVER) { @@ -609,7 +606,7 @@ void Cmd_Alias_f (void) { if (Cvar_FindVar (s)) { - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { _snprintf(cmd, sizeof(cmd), "%s_a", s); Con_Printf ("Can't register alias, %s is a cvar\nAlias has been named %s instead\n", s, cmd); @@ -625,7 +622,7 @@ void Cmd_Alias_f (void) // check for overlap with a command if (Cmd_Exists (s)) { - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { _snprintf(cmd, sizeof(cmd), "%s_a", s); Con_Printf ("Can't register alias, %s is a command\nAlias has been named %s instead\n", s, cmd); @@ -660,7 +657,7 @@ void Cmd_Alias_f (void) a->next = cmd_alias; cmd_alias = a; } - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) a->flags |= ALIAS_FROMSERVER; else a->flags &= ~ALIAS_FROMSERVER; @@ -756,7 +753,7 @@ void Cmd_Alias_f (void) } } } - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { a->execlevel = RESTRICT_SERVER; //server-set aliases MUST run at the server's level. a->restriction = 1; //and be runnable at the user's level @@ -1609,7 +1606,7 @@ void Cmd_ExecuteString (char *text, int level) Cmd_ExecLevel = level; - text = Cmd_ExpandString(text, dest, sizeof(dest), level, !Cmd_FromServer()?true:false); + text = Cmd_ExpandString(text, dest, sizeof(dest), level, !Cmd_IsInsecure()?true:false); Cmd_TokenizeString (text, level == RESTRICT_LOCAL?true:false, false); // execute the command line @@ -1663,7 +1660,7 @@ void Cmd_ExecuteString (char *text, int level) Cbuf_InsertText (a->value, level); - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) return; //don't do the cmd_argc/cmd_argv stuff. When it's from the server, we had a tendancy to lock aliases, so don't set them anymore. Cbuf_InsertText (va("set cmd_argc \"%i\"\n", cmd_argc), level); @@ -2221,7 +2218,7 @@ void Cmd_set_f(void) var = Cvar_Get (Cmd_Argv(1), "0", 0, "Custom variables"); - if (Cmd_FromServer()) //AAHHHH!!! + if (Cmd_FromGamecode()) //AAHHHH!!! Q2 set command is different { text = Cmd_Argv(3); if (!strcmp(text, "u")) @@ -2250,13 +2247,13 @@ void Cmd_set_f(void) if (var) { - if (var->flags & CVAR_NOTFROMSERVER && Cmd_FromServer()) + if (var->flags & CVAR_NOTFROMSERVER && Cmd_FromGamecode()) { Con_Printf ("Server tried setting %s cvar\n", var->name); return; } - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { if (forceflags) { @@ -2274,7 +2271,7 @@ void Cmd_set_f(void) else { text = If_Token(text, &end); - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { var = Cvar_Get(Cmd_Argv(1), "", 0, "Game variables"); Cvar_LockFromServer(var, text); @@ -2283,7 +2280,7 @@ void Cmd_set_f(void) var = Cvar_Get(Cmd_Argv(1), text, 0, "User variables"); } - if (!Cmd_FromServer()) + if (!Cmd_FromGamecode()) if (!stricmp(Cmd_Argv(0), "seta")) var->flags |= CVAR_ARCHIVE|CVAR_USERCREATED; } @@ -2308,7 +2305,7 @@ void Cvar_Inc_f (void) Con_Printf ("Unknown variable \"%s\"\n", Cmd_Argv(1)); return; } - if (var->flags & CVAR_NOTFROMSERVER && Cmd_FromServer()) + if (var->flags & CVAR_NOTFROMSERVER && Cmd_FromGamecode()) { Con_Printf ("Server tried setting %s cvar\n", var->name); return; diff --git a/engine/common/cmd.h b/engine/common/cmd.h index 4afaedee5..996b63bca 100644 --- a/engine/common/cmd.h +++ b/engine/common/cmd.h @@ -118,11 +118,13 @@ void Cmd_ExecuteString (char *text, int restrictionlevel); #define RESTRICT_MIN 1 //rcon get's 63, local always gets 64 #define RESTRICT_LOCAL RESTRICT_MAX -#define RESTRICT_SERVER RESTRICT_MAX+1 +#define RESTRICT_INSECURE RESTRICT_MAX+1 +#define RESTRICT_SERVER RESTRICT_MAX+2 #define RESTRICT_RCON rcon_level.value #define RESTRICT_PROGS RESTRICT_MAX-2 -#define Cmd_FromServer() (Cmd_ExecLevel>=RESTRICT_SERVER) +#define Cmd_FromGamecode() (Cmd_ExecLevel>=RESTRICT_SERVER) //cheat provention +#define Cmd_IsInsecure() (Cmd_ExecLevel>=RESTRICT_INSECURE) //prevention from the server from breaking/crashing/wiping us. // Parses a single line of text into arguments and tries to execute it // as if it was typed at the console diff --git a/engine/common/common.c b/engine/common/common.c index 1e49e140e..6b4205d75 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -163,6 +163,23 @@ void InsertLinkAfter (link_t *l, link_t *after) ============================================================================ */ +void Q_strncpyz(char *d, const char *s, int n) +{ + int i; + n--; + if (n < 0) + return; //this could be an error + + for (i=0; *s; i++) + { + if (i == n) + break; + *d++ = *s++; + } + *d='\0'; +} + + #if 0 void Q_memset (void *dest, int fill, int count) { diff --git a/engine/common/common.h b/engine/common/common.h index 7915fda07..bc37ff9f0 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -180,10 +180,15 @@ int wildcmp(char *wild, char *string); //1 if match #define Q_strcmp(s1, s2) strcmp((s1), (s2)) #define Q_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) + #define Q_strncpyS(d, s, n) do{const char *____in=(s);char *____out=(d);int ____i; for (____i=0;*(____in); ____i++){if (____i == (n))break;*____out++ = *____in++;}if (____i < (n))*____out='\0';}while(0) //only use this when it should be used. If undiciided, use N #define Q_strncpyN(d, s, n) do{if (n < 0)Sys_Error("Bad length in strncpyz");Q_strncpyS((d), (s), (n));((char *)(d))[n] = '\0';}while(0) //this'll stop me doing buffer overflows. (guarenteed to overflow if you tried the wrong size.) -#define Q_strncpyNCHECKSIZE(d, s, n) do{if (n < 1)Sys_Error("Bad length in strncpyz");Q_strncpyS((d), (s), (n));((char *)(d))[n-1] = '\0';((char *)(d))[n] = '255';}while(0) //This forces nothing else to be within the buffer. Should be used for testing and nothing else. +//#define Q_strncpyNCHECKSIZE(d, s, n) do{if (n < 1)Sys_Error("Bad length in strncpyz");Q_strncpyS((d), (s), (n));((char *)(d))[n-1] = '\0';((char *)(d))[n] = '255';}while(0) //This forces nothing else to be within the buffer. Should be used for testing and nothing else. +#if 0 #define Q_strncpyz(d, s, n) Q_strncpyN(d, s, (n)-1) +#else +void Q_strncpyz(char*d, const char*s, int n); +#endif //#define Q_strncpy Please remove all strncpys /*#ifndef strncpy #define strncpy Q_strncpy diff --git a/engine/common/console.h b/engine/common/console.h index 16c431996..f564a6340 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -79,6 +79,8 @@ extern console_t *con_current; // point to either con_main or con_chat extern int con_ormask; +extern int scr_chatmode; + //extern int con_totallines; extern qboolean con_initialized; extern qbyte *con_chars; diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 8a8b2c9a6..3bff21f63 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -162,10 +162,6 @@ char *Cvar_CompleteVariable (char *partial) */ -#ifdef SERVERONLY -void SV_SendServerInfoChange(char *key, char *value); -#endif - /* ============ Cvar_Set @@ -255,18 +251,20 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force) } #endif - if (var->string) - { - if (strcmp(var->string, value)) - var->modified++; //only modified if it changed. - - Z_Free (var->string); // free the old value string - } + latch = var->string; var->string = (char*)Z_Malloc (Q_strlen(value)+1); Q_strcpy (var->string, value); var->value = Q_atof (var->string); + if (latch) + { + if (strcmp(latch, value)) + var->modified++; //only modified if it changed. + + Z_Free (latch); // free the old value string + } + if (var->latched_string) //we may as well have this here. { Z_Free(var->latched_string); @@ -554,7 +552,7 @@ qboolean Cvar_Command (int level) return true; } - if (v->flags & CVAR_NOTFROMSERVER && Cmd_FromServer()) + if (v->flags & CVAR_NOTFROMSERVER && Cmd_FromGamecode()) { Con_Printf ("Server tried setting %s cvar\n", v->name); return true; @@ -587,7 +585,7 @@ qboolean Cvar_Command (int level) if (v->flags & CVAR_SERVEROVERRIDE) { - if (Cmd_FromServer()) + if (Cmd_FromGamecode()) { if (!strcmp(v->defaultstr, str)) //returning to default { @@ -603,7 +601,7 @@ qboolean Cvar_Command (int level) } //let cvar_set latch if needed. } - else if (Cmd_FromServer()) + else if (Cmd_FromGamecode()) { Cvar_LockFromServer(v, str); return true; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 8b5e11091..56e35ceae 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1320,9 +1320,6 @@ void CMod_LoadFaces (lump_t *l) out->firstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); out->flags = 0; -#if defined(RGLQUAKE) - out->polys = NULL; -#endif planenum = LittleShort(in->planenum); side = LittleShort(in->side); @@ -1377,10 +1374,6 @@ void CMod_LoadFaces (lump_t *l) out->extents[i] = 16384; out->texturemins[i] = -8192; } -#ifdef RGLQUAKE - if (qrenderer == QR_OPENGL) - GL_SubdivideSurface (out, 64); // cut up polygon for warps -#endif } } @@ -2346,19 +2339,10 @@ continue; if (map_surfaces[in->shadernum].c.flags & Q3SURF_SKIP) Con_Printf("Surface skip\n"); out->mesh = NULL; - out->polys = NULL; } else if (in->facetype == MST_PATCH) { out->mesh = GL_CreateMeshForPatch(loadmodel, in); - -#ifdef Q3SHADERS - if (!out->texinfo->texture->shader) - { - out->polys = GL_MeshToGLPoly(out->mesh); - out->mesh = NULL; - } -#endif } else if (in->facetype == MST_PLANAR || in->facetype == MST_TRIANGLE_SOUP) { @@ -2367,7 +2351,6 @@ continue; if (numindexes%3) Host_Error("mesh indexes should be multiples of 3"); -#ifdef Q3SHADERS out->mesh = Hunk_Alloc(sizeof(mesh_t) + (sizeof(vec3_t)) * numverts); out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); out->mesh->colors_array = map_colors_array + LittleLong(in->firstvertex); @@ -2378,40 +2361,6 @@ continue; out->mesh->numindexes = numindexes; out->mesh->numvertexes = numverts; -#else - - p = Hunk_AllocName (polysize*numindexes/3, "SDList"); - fv = LittleLong(in->firstvertex); - fi = LittleLong(in->firstindex); - for (gv = 0; gv < numindexes; ) - { - for (v = gv; v < gv+3; v++) - { - rv = fv+map_surfindexes[fi+v]; - p->verts[v%3][0] = map_verts[rv][0]; - p->verts[v%3][1] = map_verts[rv][1]; - p->verts[v%3][2] = map_verts[rv][2]; - p->verts[v%3][3] = map_vertstmexcoords[rv][0]; - p->verts[v%3][4] = map_vertstmexcoords[rv][1]; - p->verts[v%3][5] = map_vertlstmexcoords[rv][0]; - p->verts[v%3][6] = map_vertlstmexcoords[rv][1]; - } - gv+=3; - - p->next = out->polys; - p->numverts = 3; - out->polys = p; - p = (glpoly_t *)((char *)p + polysize); - } -#endif - -#ifdef Q3SHADERS - if (!out->texinfo->texture->shader) - { - out->polys = GL_MeshToGLPoly(out->mesh); - out->mesh = NULL; - } -#endif } else { diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 793a49643..3752f6ca0 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -40,6 +40,8 @@ struct mplane_s; extern vec3_t vec3_origin; extern int nanmask; +#define bound(min,num,max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min)) + #define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) #define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) diff --git a/engine/common/pmove.h b/engine/common/pmove.h index c21f03cef..ea0601ec0 100644 --- a/engine/common/pmove.h +++ b/engine/common/pmove.h @@ -38,45 +38,13 @@ typedef struct vec3_t angles; model_t *model; // only for bsp models vec3_t mins, maxs; // only for non-bsp models - int info; // for client or server to identify - int nonsolid:1; - int notouch:1; + unsigned short info; // for client or server to identify + qbyte nonsolid; + qbyte notouch; } physent_t; typedef struct { -/* int sequence; // just for debugging prints - - // player state - vec3_t origin; - vec3_t angles; - vec3_t velocity; - int oldbuttons; - float waterjumptime; - qboolean dead; - int spectator; - - int hullnum; - - // world state - int numphysent; - physent_t physents[MAX_PHYSENTS]; // 0 should be the world - - // input - usercmd_t cmd; - - // results - int numtouch; - int touchindex[MAX_PHYSENTS]; - qboolean onground; - int groundent; - - int waterlevel; - int watertype; - - pmtype_t pm_type;*/ - - int sequence; // just for debugging prints // player state diff --git a/engine/common/protocol.h b/engine/common/protocol.h index a4dbfdbcc..09e431b49 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -595,9 +595,15 @@ enum { TE_CHAINLIGHTNING = 81 }; -#define NQTE_EXPLOSION2 12 -#define NQTE_BEAM 13 +#define NQTE_EXPLOSION2 12 +#define NQTE_BEAM 13 +#define DPTE_BLOOD 50 +#define DPTE_SPARK 51 +#define DPTE_SMALLFLASH 72 +#define DPTE_CUSTOMFLASH 73 +#define DPTE_FLAMEJET 74 +#define DPTE_PLASMABURN 75 #define TE_SEEF_BRIGHTFIELD 200 #define TE_SEEF_DARKLIGHT 201 @@ -838,6 +844,7 @@ typedef struct q1usercmd_s #define Q2RF_TRANSLUCENT 32 #define Q2RF_FRAMELERP 64 #define Q2RF_BEAM 128 + #define Q2RF_CUSTOMSKIN 256 // skin is an index in image_precache #define Q2RF_GLOW 512 // pulse lighting for bonus items #define Q2RF_SHELL_RED 1024 @@ -851,6 +858,8 @@ typedef struct q1usercmd_s #define Q2RF_USE_DISGUISE 0x00040000 //ROGUE +#define Q2RF_ADDATIVE 0x00080000 + // player_state_t->refdef flags #define Q2RDF_UNDERWATER 1 // warp the screen as apropriate #define Q2RDF_NOWORLDMODEL 2 // used for player configuration screen diff --git a/engine/common/zone.c b/engine/common/zone.c index d1795c72d..679e54f43 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -42,7 +42,7 @@ void Cache_FreeHigh (int new_high_hunk); //must be multiple of 4. #define TEMPDEBUG 4 -#define ZONEDEBUG 64 +#define ZONEDEBUG 4 #define HUNKDEBUG 4 #define CACHEDEBUG 4 diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index d6ef0f53f..aae5f0d1c 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -106,7 +106,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /D "AVAIL_OGGVORBIS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c +# ADD CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 @@ -1314,6 +1314,10 @@ SOURCE=..\client\keys.c # End Source File # Begin Source File +SOURCE=..\client\m_download.c +# End Source File +# Begin Source File + SOURCE=..\client\m_items.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -5083,11 +5087,6 @@ SOURCE=..\common\md4.c # End Source File # Begin Source File -SOURCE=..\common\md5.c -# ADD CPP /Yu -# End Source File -# Begin Source File - SOURCE=..\common\net_chan.c # End Source File # Begin Source File @@ -7702,39 +7701,6 @@ SOURCE=..\http\httpserver.c # End Source File # Begin Source File -SOURCE=..\email\imapnoti.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -# SUBTRACT CPP /YX /Yc /Yu - -!ENDIF - -# End Source File -# Begin Source File - SOURCE=..\irc\ircclient.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -7777,105 +7743,6 @@ SOURCE=..\http\iwebiface.c # End Source File # Begin Source File -SOURCE=..\email\pop3noti.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -# SUBTRACT CPP /YX /Yc /Yu - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\email\sv_pop3.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -# SUBTRACT CPP /YX /Yc /Yu - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\email\sv_smtp.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -# SUBTRACT CPP /YX /Yc /Yu - -!ENDIF - -# End Source File -# Begin Source File - SOURCE=..\http\webgen.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -8123,6 +7990,10 @@ SOURCE=..\client\client.h # End Source File # Begin Source File +SOURCE=..\common\cvar.h +# End Source File +# Begin Source File + SOURCE=..\sw\d_ifacea.h # End Source File # Begin Source File diff --git a/engine/ftequake/ftequake.dsw b/engine/ftequake/ftequake.dsw index 92f3187f8..12c0cc844 100644 --- a/engine/ftequake/ftequake.dsw +++ b/engine/ftequake/ftequake.dsw @@ -3,6 +3,30 @@ Microsoft Developer Studio Workspace File, Format Version 6.00 ############################################################################### +Project: "emailnot"=..\..\PLUGINS\emailnot\emailnot.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "emailsv"=..\..\plugins\emailsv\emailsv.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "ftequake"=.\ftequake.dsp - Package Owner=<4> Package=<5> @@ -11,6 +35,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name gas2masm + End Project Dependency }}} ############################################################################### diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 51fb27c9f..db55af170 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1128,6 +1128,9 @@ void R_DrawGAliasModel (entity_t *e) // if (e->flags & Q2RF_VIEWERMODEL && e->keynum == cl.playernum[r_refdef.currentplayernum]+1) // return; + if (r_secondaryview && e->flags & Q2RF_WEAPONMODEL) + return; + { extern int cl_playerindex; if (e->scoreboard && e->model == cl.model_precache[cl_playerindex]) diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 9d80eb049..bc22ef608 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -840,7 +840,6 @@ int Matrix3_Compare(mat3_t in, mat3_t out) extern model_t *currentmodel; #define clamp(v,min,max) (v) = (((v)<(min))?(min):(((v)>(max))?(max):(v))) -#define bound(min,v,max) (((v)<(min))?(min):(((v)>(max))?(max):(v))) extern qbyte FloatToByte( float x ); @@ -2802,7 +2801,7 @@ void R_FinishMeshBuffer ( meshbuffer_t *mb ) qglEnable ( GL_BLEND ); qglDisable ( GL_ALPHA_TEST ); - qglDepthMask ( GL_FALSE ); +// qglDepthMask ( GL_FALSE ); //FIZME // if ( dlight ) { diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 94d69b64a..9d222786a 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -1061,7 +1061,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); qglClearColor (1,0,0,0); TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); - PPL_LoadSpecularFragmentProgram(); + PPL_CreateShaderObjects(); #ifdef PLUGINS Plug_DrawReloadImages(); @@ -1643,14 +1643,20 @@ void GLDraw_ConsoleBackground (int lines) y = (vid.height * 3) >> 2; conback->width = vid.conwidth; conback->height = vid.conheight; + if (scr_chatmode == 2) + { + y=0; + conback->height>>=1; + conback->width>>=1; + } if (lines > y) { qglColor3f (1,1,1); - GLDraw_Pic(0, lines-vid.height, conback); + GLDraw_Pic(0, lines-conback->height, conback); } else { - GLDraw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y); + GLDraw_AlphaPic (0, lines - conback->height, conback, (float)(1.2 * lines)/y); } } @@ -2343,24 +2349,24 @@ void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, for (i=0 ; i> 1; + frac = outwidth*fracstep; j=outwidth-4; while (j&3) { out[j] = inrow[frac>>16]; - frac += fracstep; + frac -= fracstep; j--; } for ( ; j>=0 ; j-=4) { - out[j] = inrow[frac>>16]; - frac += fracstep; - out[j+1] = inrow[frac>>16]; - frac += fracstep; - out[j+2] = inrow[frac>>16]; - frac += fracstep; out[j+3] = inrow[frac>>16]; - frac += fracstep; + frac -= fracstep; + out[j+2] = inrow[frac>>16]; + frac -= fracstep; + out[j+1] = inrow[frac>>16]; + frac -= fracstep; + out[j+0] = inrow[frac>>16]; + frac -= fracstep; } } } diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 3c0942091..683e27689 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -373,11 +373,11 @@ void HL_CalcBoneAdj(hlmodel_t *model) if(control[i].type & 0x8000) { - value = model->controller[j] * (360.0 / 256.0) + control[i].start; + value = model->controller[j] + control[i].start; } else { - value = model->controller[j] / 255.0; + value = model->controller[j]; if(value < 0) value = 0; else if(value > 1.0) @@ -482,10 +482,10 @@ void R_DrawHLModel(entity_t *curent) sequence = (hlmdl_sequencelist_t *) ((qbyte *) model.header + model.header->seqindex) + model.sequence; - model.controller[0] = 127; - model.controller[1] = 127; - model.controller[2] = 127; - model.controller[3] = 127; + model.controller[0] = curent->bonecontrols[0]; + model.controller[1] = curent->bonecontrols[1]; + model.controller[2] = curent->bonecontrols[2]; + model.controller[3] = curent->bonecontrols[3]; model.controller[4] = 0;//sin(cl.time)*127+127; model.frametime += (cl.time - cl.lerpents[curent->keynum].framechange)*sequence->timing; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 6c832762f..5e687600d 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -95,8 +95,6 @@ extern cvar_t r_loadlits; extern cvar_t gl_specular; #endif extern cvar_t r_fb_bmodels; -extern cvar_t gl_subdivide_size; -extern cvar_t gl_subdivide_water; #ifdef RUNTIMELIGHTING @@ -1850,9 +1848,6 @@ void GLMod_LoadFaces (lump_t *l) if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky { out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); -#ifndef QUAKE2 - GL_SubdivideSurface (out, gl_subdivide_size.value); // cut up polygon for warps -#endif continue; } @@ -1864,7 +1859,6 @@ void GLMod_LoadFaces (lump_t *l) out->extents[i] = 16384; out->texturemins[i] = -8192; } - GL_SubdivideSurface (out, (gl_subdivide_water.value?gl_subdivide_water.value:gl_subdivide_size.value)); // cut up polygon for warps continue; } @@ -2306,12 +2300,12 @@ void GLMod_MakeHull0 (void) dclipnode_t *out; int i, j, count; hull_t *hull; - + hull = &loadmodel->hulls[0]; - + in = loadmodel->nodes; count = loadmodel->numnodes; - out = Hunk_AllocName ( count*sizeof(*out), loadname); + out = Hunk_AllocName ( count*sizeof(*out), loadname); hull->clipnodes = out; hull->firstclipnode = 0; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index c182e0fc1..d6a107aad 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -93,12 +93,14 @@ m*_t structures are in-memory #define EF_MUZZLEFLASH 2 #define EF_BRIGHTLIGHT 4 #define EF_DIMLIGHT 8 -#define EF_FLAG1 16 -#define EF_FLAG2 32 +#define QWEF_FLAG1 16 //only applies to player entities +#define NQEF_NODRAW 16 //so packet entities are free to get this instead +#define QWEF_FLAG2 32 //only applies to player entities +#define NQEF_ADDATIVE 32 //so packet entities are free to get this instead #define EF_BLUE 64 #define EF_RED 128 -#define EF_NODRAW 0x80 //this is going to get complicated... +#define H2EF_NODRAW 0x80 //this is going to get complicated... /* ============================================================================== @@ -253,9 +255,6 @@ typedef struct msurface_s #endif mesh_t *mesh; entity_t *ownerent; - glpoly_t *polys; // multiple if warped -// vec3_t center; //adverage -// float radius; //max dist from center struct msurface_s *texturechain; vec3_t normal; diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index a6bee8141..665629982 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -22,6 +22,8 @@ extern cvar_t gl_part_flame; extern cvar_t gl_maxshadowlights; extern cvar_t r_shadow_realtime_world; extern int detailtexture; +extern cvar_t gl_bump; +extern cvar_t gl_specular; //end header confict extern cvar_t gl_schematics; @@ -43,7 +45,11 @@ int shadowedgecount; int shadowlightfaces; int shadowemittedeges; -int ppl_specular_fragmentprogram; +int ppl_specular_shader; +int ppl_specular_shader_vieworg; +int ppl_specular_shader_texr; +int ppl_specular_shader_texu; +int ppl_specular_shader_texf; //#define glBegin glEnd @@ -107,174 +113,35 @@ inline void PPL_FlushArrays(void) } static void PPL_GenerateArrays(msurface_t *surf) { - glpoly_t *p; int vi; - int vc_s; - float *v; - - if (!surf->polys) - { //hmm. mesh mode. - if (!surf->mesh) - return; - if (surf->mesh->numindexes > MAXARRAYVERTS) - return; - if (surf->mesh->numvertexes > MAXARRAYVERTS) - return; - if (!surf->mesh->st_array) - return; - if (!surf->mesh->lmst_array) - return; - if (varray_ic) //FIXME: go muuuch faster please - PPL_FlushArrays(); - for (vi = 0; vi < surf->mesh->numindexes; vi++) - varray_i[vi] = surf->mesh->indexes[vi]; - for (vi = 0; vi < surf->mesh->numvertexes; vi++) - { - VectorCopy(surf->mesh->xyz_array[vi], varray_v[vi].xyz); - varray_v[vi].stw[0] = surf->mesh->st_array[vi][0]; - varray_v[vi].stw[1] = surf->mesh->st_array[vi][1]; - varray_v[vi].stl[0] = surf->mesh->lmst_array[vi][0]; - varray_v[vi].stl[1] = surf->mesh->lmst_array[vi][1]; - } - - varray_vc = surf->mesh->numvertexes; - varray_ic = surf->mesh->numindexes; + if (!surf->mesh) return; - } - - for (p = surf->polys; p; p=p->next) + if (surf->mesh->numindexes > MAXARRAYVERTS) + return; + if (surf->mesh->numvertexes > MAXARRAYVERTS) + return; + if (!surf->mesh->st_array) + return; + if (!surf->mesh->lmst_array) + return; + if (varray_ic) //FIXME: go muuuch faster please + PPL_FlushArrays(); + for (vi = 0; vi < surf->mesh->numindexes; vi++) + varray_i[vi] = surf->mesh->indexes[vi]; + for (vi = 0; vi < surf->mesh->numvertexes; vi++) { - if (varray_ic + p->numverts*3>MAXARRAYVERTS) - { - PPL_FlushArrays(); - } - - vc_s = varray_vc; - v = p->verts[0]; - - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - varray_vc++; - v += VERTEXSIZE; - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - varray_vc++; - v += VERTEXSIZE; - for (vi=2 ; vinumverts ; vi++, v+= VERTEXSIZE) - { - varray_i[varray_ic] = vc_s; - varray_i[varray_ic+1] = varray_vc-1; - varray_i[varray_ic+2] = varray_vc; - varray_ic+=3; - - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - varray_vc++; - } + VectorCopy(surf->mesh->xyz_array[vi], varray_v[vi].xyz); + varray_v[vi].stw[0] = surf->mesh->st_array[vi][0]; + varray_v[vi].stw[1] = surf->mesh->st_array[vi][1]; + varray_v[vi].stl[0] = surf->mesh->lmst_array[vi][0]; + varray_v[vi].stl[1] = surf->mesh->lmst_array[vi][1]; } + + varray_vc = surf->mesh->numvertexes; + varray_ic = surf->mesh->numindexes; } -#ifdef SPECULAR -//same as above, but also generates cubemap texture coords for light reflection (based on blinn's formula) -static void PPL_GenerateArraysBlinnCubeMap(msurface_t *surf) -{ - glpoly_t *p; - int vi; - int vc_s; - float *v; - vec3_t eye, halfdir; - - for (p = surf->polys; p; p=p->next) - { - if (varray_ic + p->numverts*3>MAXARRAYVERTS) - { - PPL_FlushArrays(); - } - - vc_s = varray_vc; - v = p->verts[0]; - - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - VectorSubtract(r_refdef.vieworg, v, eye); - VectorNormalize(eye); - VectorAdd(eye, (v+7), halfdir); -// VectorCopy(eye, halfdir); - varray_v[varray_vc].ncm[0] = DotProduct(surf->texinfo->vecs[0], halfdir); - varray_v[varray_vc].ncm[1] = DotProduct(surf->texinfo->vecs[1], halfdir); - if (surf->flags & SURF_PLANEBACK) - varray_v[varray_vc].ncm[2] = -DotProduct(surf->plane->normal, halfdir); - else - varray_v[varray_vc].ncm[2] = DotProduct(surf->plane->normal, halfdir); - varray_vc++; - v += VERTEXSIZE; - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - VectorSubtract(r_refdef.vieworg, v, eye); - VectorNormalize(eye); - VectorAdd(eye, (v+7), halfdir); - varray_v[varray_vc].ncm[0] = DotProduct(surf->texinfo->vecs[0], halfdir); - varray_v[varray_vc].ncm[1] = DotProduct(surf->texinfo->vecs[1], halfdir); - if (surf->flags & SURF_PLANEBACK) - varray_v[varray_vc].ncm[2] = -DotProduct(surf->plane->normal, halfdir); - else - varray_v[varray_vc].ncm[2] = DotProduct(surf->plane->normal, halfdir); - varray_vc++; - v += VERTEXSIZE; - for (vi=2 ; vinumverts ; vi++, v+= VERTEXSIZE) - { - varray_i[varray_ic] = vc_s; - varray_i[varray_ic+1] = varray_vc-1; - varray_i[varray_ic+2] = varray_vc; - varray_ic+=3; - - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - varray_v[varray_vc].stl[0] = v[5]; - varray_v[varray_vc].stl[1] = v[6]; - VectorSubtract(r_refdef.vieworg, v, eye); - VectorNormalize(eye); - VectorAdd(eye, (v+7), halfdir); - varray_v[varray_vc].ncm[0] = DotProduct(surf->texinfo->vecs[0], halfdir); - varray_v[varray_vc].ncm[1] = DotProduct(surf->texinfo->vecs[1], halfdir); - if (surf->flags & SURF_PLANEBACK) - varray_v[varray_vc].ncm[2] = -DotProduct(surf->plane->normal, halfdir); - else - varray_v[varray_vc].ncm[2] = DotProduct(surf->plane->normal, halfdir); - varray_vc++; - } - } -} -#endif /* static void PPL_BaseChain_NoLightmap(msurface_t *first, texture_t *tex) { @@ -351,75 +218,6 @@ static void PPL_BaseChain_NoBump_1TMU(msurface_t *first, texture_t *tex) } static void PPL_BaseChain_NoBump_2TMU(msurface_t *s, texture_t *tex) -{ - 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); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); - - GL_SelectTexture(GL_TEXTURE1_ARB); - GL_TexEnv(GL_MODULATE); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stl); - - vi = -1; - for (; s ; s=s->texturechain) - { - if (vi != s->lightmaptexturenum) - { - PPL_FlushArrays(); - 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); - } - - PPL_GenerateArrays(s); - } - PPL_FlushArrays(); - - 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_NoMerge(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; @@ -475,13 +273,13 @@ static void PPL_BaseChain_NoBump_2TMU_NoMerge(msurface_t *s, texture_t *tex) } qglClientActiveTextureARB(GL_TEXTURE0_ARB); - qglTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(GL_FLOAT), s->polys[0].verts[0]+3); + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->st_array); qglClientActiveTextureARB(GL_TEXTURE1_ARB); - qglTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(GL_FLOAT), s->polys[0].verts[0]+5); + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->lmst_array); - qglVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(GL_FLOAT), s->polys[0].verts[0]); + qglVertexPointer(3, GL_FLOAT, sizeof(vec4_t), s->mesh->xyz_array); - qglDrawElements(GL_TRIANGLES, (s->polys[0].numverts-2)*3, GL_UNSIGNED_INT, varray_i_polytotri); + qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); } qglDisable(GL_TEXTURE_2D); @@ -882,91 +680,109 @@ glBlendFunc(GL_DST_COLOR, GL_ZERO); void PPL_LoadSpecularFragmentProgram(void) { - GLint errorPos, isNative; - int i; - const char *error; +//#define SMOOOOOTH //define this to calculate everything per-pixel as opposed to interpolating the halfdir + char *vert = + "varying vec2 tcbase;\n" + "varying vec2 tclm;\n" + "uniform vec3 vieworg;\n" +#ifdef SMOOOOOTH + "varying vec3 fragpos;\n" + "varying vec3 norm;\n" +#else + "uniform vec3 texr, texu, texf;\n" + "varying vec3 halfnorm;\n" +#endif + "void main (void)\n" + "{\n" + " gl_Position = ftransform();\n" - //What should the minimum resource limits be? + " tcbase = gl_MultiTexCoord0.xy;\n" //pass the texture coords straight through + " tclm = gl_MultiTexCoord1.xy;\n" - //RESOLVED: 10 attributes, 24 parameters, 4 texture indirections, - //48 ALU instructions, 24 texture instructions, and 16 temporaries. +#ifdef SMOOOOOTH + " fragpos = vec3(gl_Vertex.xyz);\n" + "norm = gl_Normal;\n" +#else + " vec3 eye = normalize(vieworg - vec3(gl_Vertex.xyz));\n" + " vec3 halfdir = (eye + texf) / 2.0;\n" + " halfnorm.x = dot(texr, halfdir);\n" //put halfnorm into object space + " halfnorm.y = dot(texu, halfdir);\n" + " halfnorm.z = dot(texf, halfdir);\n" +#endif + "}\n" + ; - //16 temps? hmm. that means we should be keeping the indirections instead of temp usage. - //temps should be same speed, indirections could prevent texture loading for a bit. +/* + VectorSubtract(r_refdef.vieworg, v, eye); + VectorNormalize(eye); + VectorAdd(eye, (v+7), halfdir); //v+7 is the light dir (or plane normal) + varray_v[varray_vc].ncm[0] = DotProduct(surf->texinfo->vecs[0], halfdir); + varray_v[varray_vc].ncm[1] = DotProduct(surf->texinfo->vecs[1], halfdir); + if (surf->flags & SURF_PLANEBACK) + varray_v[varray_vc].ncm[2] = -DotProduct(surf->plane->normal, halfdir); + else + varray_v[varray_vc].ncm[2] = DotProduct(surf->plane->normal, halfdir); +*/ + char *frag = + "uniform sampler2D baset;\n" + "uniform sampler2D bumpt;\n" + "uniform sampler2D lightmapt;\n" + "uniform sampler2D deluxt;\n" + "uniform sampler2D speculart;\n" + "varying vec2 tcbase;\n" + "varying vec2 tclm;\n" - char *fp = - //FP to do: - //(diffuse*n.l + gloss*(n.h)^8)*lm - //note excessive temp reuse... - "!!ARBfp1.0\n" +#ifdef SMOOOOOTH + "uniform vec3 vieworg;\n" + "varying vec3 fragpos;\n" + "uniform vec3 texr, texu, texf;\n" +#else + "varying vec3 halfnorm;\n" +#endif + "void main (void)\n" + "{\n" + " vec3 bases = vec3(texture2D(baset, tcbase));\n" + " vec3 bumps = vec3(texture2D(bumpt, tcbase)) * 2.0 - 1.0;\n" + " vec3 deluxs = vec3(texture2D(deluxt, tclm)) * 2.0 - 1.0;\n" + " vec3 lms = vec3(texture2D(lightmapt, tclm));\n" + " vec3 specs = vec3(texture2D(speculart, tcbase));\n" + " vec3 diff, spec;\n" - "PARAM c0 = {2, 1, 8, 0};\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEX R0.xyz, fragment.texcoord[0], texture[1], 2D;\n" - "TEX R1.xyz, fragment.texcoord[1], texture[3], 2D;\n" - "MAD R0.xyz, R0, c0.x, -c0.y;\n" - "MAD R1.xyz, R1, c0.x, -c0.y;\n" - "DP3 R0.w, R0, R1;\n" - "DP3 R1.x, fragment.texcoord[2], fragment.texcoord[2];\n" - "RSQ R1.x, R1.x;\n" - "MUL R1.xyz, R1.x, fragment.texcoord[2];\n" - "DP3 R0.x, R1, R0;\n" - "POW R0.x, R0.x, c0.z;\n" - "TEX R1.xyz, fragment.texcoord[0], texture[4], 2D;\n" - "TEX R2.xyz, fragment.texcoord[0], texture[0], 2D;\n" - "MUL R0.xyz, R0.x, R1;\n" - "MAD R0.xyz, R2, R0.w, R0;\n" - "TEX R1.xyz, fragment.texcoord[1], texture[2], 2D;\n" - "MUL result.color.xyz, R0, R1;\n" +#ifdef SMOOOOOTH + " vec3 eye = normalize(vieworg - fragpos);\n" + " vec3 halfdir = (eye + texf) / 2.0;\n" + " vec3 halfnorm;\n" + " halfnorm.x = dot(texr, halfdir);\n" //put halfnorm into object space + " halfnorm.y = dot(texu, halfdir);\n" + " halfnorm.z = dot(texf, halfdir);\n" +#endif - //that's all folks. - "END"; + " diff = bases * dot(bumps, deluxs);\n" + " float dv = dot(normalize(halfnorm), bumps);\n" + " spec = pow(dv, 8.0) * specs;\n" + " gl_FragColor = vec4((diff+spec)*lms, 1.0);\n" + "}\n" + ; - ppl_specular_fragmentprogram = 0; + ppl_specular_shader = GLSlang_CreateProgram(NULL, vert, frag); - for (i = 0; i < MAXARRAYVERTS; i++) + if (ppl_specular_shader) { - varray_i_forward[i] = i; + GLSlang_UseProgram(ppl_specular_shader); + + qglUniform1iARB(qglGetUniformLocationARB(ppl_specular_shader, "baset"), 0); + qglUniform1iARB(qglGetUniformLocationARB(ppl_specular_shader, "bumpt"), 1); + qglUniform1iARB(qglGetUniformLocationARB(ppl_specular_shader, "lightmapt"), 2); + qglUniform1iARB(qglGetUniformLocationARB(ppl_specular_shader, "deluxt"), 3); + qglUniform1iARB(qglGetUniformLocationARB(ppl_specular_shader, "speculart"), 4); + + ppl_specular_shader_vieworg = qglGetUniformLocationARB(ppl_specular_shader, "vieworg"); + ppl_specular_shader_texr = qglGetUniformLocationARB(ppl_specular_shader, "texr"); + ppl_specular_shader_texu = qglGetUniformLocationARB(ppl_specular_shader, "texu"); + ppl_specular_shader_texf = qglGetUniformLocationARB(ppl_specular_shader, "texf"); + + GLSlang_UseProgram(0); } - for (i = 0; i < MAXARRAYVERTS/3; i++) - { - varray_i_polytotri[i*3+0] = 0; - varray_i_polytotri[i*3+1] = i+1; - varray_i_polytotri[i*3+2] = i+2; - } - - if (!gl_config.arb_fragment_program) - return; - - qglEnable(GL_FRAGMENT_PROGRAM_ARB); - - qglGenProgramsARB( 1, &ppl_specular_fragmentprogram ); - qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ppl_specular_fragmentprogram); - - if (qglGetError()) - Con_Printf("GL Error binding fragment program\n"); - - qglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); - if (qglGetError()) - { - qglGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); - error = qglGetString(GL_PROGRAM_ERROR_STRING_ARB); - Con_Printf("Fragment program error \'%s\'\n", error); - ppl_specular_fragmentprogram = 0; - } - else - { - qglGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative); - if (!isNative) - Con_Printf("Warning: Fragment program is emulated. You will likly experience poor performace.\n"); - } - - if (qglGetError()) - Con_Printf("GL Error loading fragment program\n"); - - qglDisable(GL_FRAGMENT_PROGRAM_ARB); } static void PPL_BaseChain_Specular_FP(msurface_t *s, texture_t *tex) @@ -976,49 +792,33 @@ static void PPL_BaseChain_Specular_FP(msurface_t *s, texture_t *tex) PPL_EnableVertexArrays(); - qglEnable(GL_FRAGMENT_PROGRAM_ARB); - qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ppl_specular_fragmentprogram); + GLSlang_UseProgram(ppl_specular_shader); if (qglGetError()) Con_Printf("GL Error on shadow lighting\n"); GL_MBind(GL_TEXTURE0_ARB, tex->gl_texturenum); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); GL_MBind(GL_TEXTURE1_ARB, tex->gl_texturenumbumpmap); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stl); - GL_SelectTexture(GL_TEXTURE2_ARB); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(3, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->ncm); +// GL_MBind(GL_TEXTURE2_ARB, lightmap_textures[vi] ); - //qglActiveTextureARB(GL_TEXTURE2_ARB); - //GL_BindType(GL_TEXTURE_2D, ); //lightmap - - //qglActiveTextureARB(GL_TEXTURE3_ARB); - //GL_BindType(GL_TEXTURE_2D, ); //deluxmap - - if (qglGetError()) - Con_Printf("GL Error on shadow lighting\n"); +// GL_MBind(GL_TEXTURE3_ARB, deluxmap_textures[vi] ); GL_MBind(GL_TEXTURE4_ARB, tex->gl_texturenumspec); - GL_SelectTexture(GL_TEXTURE5_ARB); - GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, normalisationCubeMap); - - + qglUniform3fvARB(ppl_specular_shader_vieworg, 1, r_refdef.vieworg); if (qglGetError()) - Con_Printf("GL Error on shadow lighting\n"); + Con_Printf("GL Error early during PPL_BaseChain_Specular_FP\n"); vi = -1; for (; s ; s=s->texturechain) { if (vi != s->lightmaptexturenum) { - PPL_FlushArrays(); vi = s->lightmaptexturenum; GL_MBind(GL_TEXTURE3_ARB, deluxmap_textures[vi] ); @@ -1048,14 +848,24 @@ static void PPL_BaseChain_Specular_FP(msurface_t *s, texture_t *tex) theRect->w = 0; } } - PPL_GenerateArraysBlinnCubeMap(s); + + qglUniform3fvARB(ppl_specular_shader_texr, 1, s->texinfo->vecs[0]); + qglUniform3fvARB(ppl_specular_shader_texu, 1, s->texinfo->vecs[1]); + if (s->flags & SURF_PLANEBACK) + qglUniform3fARB(ppl_specular_shader_texf, -s->plane->normal[0], -s->plane->normal[1], -s->plane->normal[2]); + else + qglUniform3fvARB(ppl_specular_shader_texf, 1, s->plane->normal); + + 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, sizeof(GL_FLOAT)*4, s->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); } - PPL_FlushArrays(); - if (qglGetError()) - Con_Printf("GL Error on shadow lighting\n"); - - qglDisable(GL_FRAGMENT_PROGRAM_ARB); + GLSlang_UseProgram(0); GL_SelectTexture(GL_TEXTURE2_ARB); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1068,223 +878,9 @@ static void PPL_BaseChain_Specular_FP(msurface_t *s, texture_t *tex) if (qglGetError()) - Con_Printf("GL Error on shadow lighting\n"); + Con_Printf("GL Error on specular lighting\n"); } -#define GL_MODULATE_ADD_ATI 0x8744 -//we actually only use 7, so nur. -static void PPL_BaseChain_Specular_8TMU(msurface_t *first, texture_t *tex) -{ //uses blinn shading instead of phong. This way we don't have to generate lots of complex stuff. - int vi; - glRect_t *theRect; - msurface_t *s; - -// float fourhalffloats[4] = {0.5,0.5,0.5,0.5}; - - PPL_EnableVertexArrays(); - -/* lets do things in parallel. -normalmap -> rgb -rgb . halfvector -> alpha -alpha*alpha -> alpha normalmap -> rgb -(alpha*alpha -> alpha) rgb . luxmap -> rgb -alpha*gloss -> alpha rgb * diffuse -> rgb -rgb + alpha -> rgb -rgb * lightmap -> rgb - - //note: crossbar could use third input texture removing the first tmu. - //note: could combine3 combine the last two? - //note: 5 tmus: not enough to work on a gf4. -*/ - qglDisable(GL_BLEND); - -//0 takes a normalmap - GL_MBind(GL_TEXTURE0_ARB, tex->gl_texturenumbumpmap); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); - GL_TexEnv(GL_REPLACE); - -//1 takes a cubemap for specular half-vectors. - GL_SelectTexture(GL_TEXTURE1_ARB); - GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, normalisationCubeMap); - qglDisable(GL_TEXTURE_2D); - qglEnable(GL_TEXTURE_CUBE_MAP_ARB); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(3, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->ncm); - 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_DOT3_RGBA_ARB); //writes alpha - -//2 takes a normalmap - GL_MBind(GL_TEXTURE2_ARB, tex->gl_texturenumbumpmap); - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); - GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); - - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); //square the alpha - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - -//3 takes the deluxmap - GL_SelectTexture(GL_TEXTURE3_ARB); - qglEnable(GL_TEXTURE_2D); //bind with the surface texturenum - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stl); - 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_DOT3_RGB_ARB); - - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); //square the alpha again. - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - -//4 multiplies with diffuse - GL_MBind(GL_TEXTURE4_ARB, tex->gl_texturenum); - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); - - GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); - - //nothing to the alpha (square yet again?) -// glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); -// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); - - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); //square the alpha again. - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - -//5 halves rgb and alpha (so that adding will not clamp) - GL_MBind(GL_TEXTURE5_ARB, tex->gl_texturenum); //need to bind something. - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); -/* glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fourhalffloats); - - GL_TexEnv(GL_COMBINE_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); -*/ - GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); - -//6 adds rgb and alpha, using the glossmap... - GL_MBind(GL_TEXTURE6_ARB, tex->gl_texturenumspec); - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); - - //broken diffuse + specular - GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE_ADD_ATI); - //perfect diffuse -/* GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); -*/ - //perfect specular -/* GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); -*/ -//7 multiplies by lightmap - GL_SelectTexture(GL_TEXTURE7_ARB); - qglEnable(GL_TEXTURE_2D); //bind with the surface texturenum - - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stl); - - GL_TexEnv(GL_COMBINE_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); - - vi = -1; - for (s = first; s ; s=s->texturechain) - { - if (vi != s->lightmaptexturenum) - { - PPL_FlushArrays(); - vi = s->lightmaptexturenum; - - GL_MBind(GL_TEXTURE3_ARB, deluxmap_textures[vi] ); - if (lightmap[vi]->deluxmodified) - { - lightmap[vi]->deluxmodified = false; - theRect = &lightmap[vi]->deluxrectchange; - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, - lightmap[vi]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - } - GL_MBind(GL_TEXTURE7_ARB, 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; - } - } - PPL_GenerateArraysBlinnCubeMap(s); - } - PPL_FlushArrays(); - - qglColorMask(1,1,1,0); - - for (vi = 7; vi > 0; vi--) - { - GL_SelectTexture(GL_TEXTURE0_ARB+vi); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - qglDisable(GL_TEXTURE_CUBE_MAP_ARB);//1 - - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - - GL_SelectTexture(GL_TEXTURE0_ARB); -} #endif //single textured. @@ -1373,6 +969,7 @@ static void PPL_BaseChain_Flat(msurface_t *first) } PPL_GenerateArrays(s); } + PPL_FlushArrays(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglColor3f(1,1,1); @@ -1477,46 +1074,26 @@ static void PPL_BaseChain_NPR_Sketch(msurface_t *first) //draw some extra lines around the edge for added coolness. qglColor3f(0,0,0); - if (first->texinfo->texture->shader) - { - for (vi = 0; vi < 2; vi++) - { - for (s = first; s ; s=s->texturechain) - { - if (!s->mesh) - continue; - for (i=0; imesh->numindexes; i+=3) - { - qglBegin(GL_LINE_LOOP); - qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+0]][0]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+0]][1]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+0]][2]+5*(rand()/(float)RAND_MAX-0.5)); - qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+1]][0]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+1]][1]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+1]][2]+5*(rand()/(float)RAND_MAX-0.5)); - qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+2]][0]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+2]][1]+5*(rand()/(float)RAND_MAX-0.5), - s->mesh->xyz_array[s->mesh->indexes[i+2]][2]+5*(rand()/(float)RAND_MAX-0.5)); - qglEnd(); - } - } - } - - } - else + for (vi = 0; vi < 2; vi++) { - for (vi = 0; vi < 5; vi++) + for (s = first; s ; s=s->texturechain) { - for (s = first; s ; s=s->texturechain) + if (!s->mesh) + continue; + + for (i=0; imesh->numindexes; i+=3) { - if (!s->polys) - continue; qglBegin(GL_LINE_LOOP); - for (i=s->polys->numverts-1; i>=0; i--) - qglVertex3f( s->polys->verts[i][0]+5*(rand()/(float)RAND_MAX-0.5), - s->polys->verts[i][1]+5*(rand()/(float)RAND_MAX-0.5), - s->polys->verts[i][2]+5*(rand()/(float)RAND_MAX-0.5)); + qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+0]][0]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+0]][1]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+0]][2]+5*(rand()/(float)RAND_MAX-0.5)); + qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+1]][0]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+1]][1]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+1]][2]+5*(rand()/(float)RAND_MAX-0.5)); + qglVertex3f(s->mesh->xyz_array[s->mesh->indexes[i+2]][0]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+2]][1]+5*(rand()/(float)RAND_MAX-0.5), + s->mesh->xyz_array[s->mesh->indexes[i+2]][2]+5*(rand()/(float)RAND_MAX-0.5)); qglEnd(); } } @@ -1527,7 +1104,6 @@ static void PPL_BaseChain_NPR_Sketch(msurface_t *first) static void PPL_BaseTextureChain(msurface_t *first) { - extern cvar_t gl_bump, gl_specular; texture_t *t; if (r_drawflat.value) { @@ -1674,10 +1250,10 @@ static void PPL_BaseTextureChain(msurface_t *first) { if (t->gl_texturenumspec && gl_specular.value) { - if (ppl_specular_fragmentprogram) + if (ppl_specular_shader) PPL_BaseChain_Specular_FP(first, t); - else if (gl_mtexarbable>=8) - PPL_BaseChain_Specular_8TMU(first, t); +// else if (gl_mtexarbable>=8) +// PPL_BaseChain_Specular_8TMU(first, t); else PPL_BaseChain_Bump_4TMU(first, t); //can't do specular. } @@ -1689,8 +1265,7 @@ static void PPL_BaseTextureChain(msurface_t *first) } else { - PPL_BaseChain_NoBump_2TMU_NoMerge(first, t); -// PPL_BaseChain_NoBump_2TMU(first, t); + PPL_BaseChain_NoBump_2TMU(first, t); } } } @@ -1831,7 +1406,7 @@ void PPL_BaseBModelTextures(entity_t *e) // instanced model if (currentmodel->firstmodelsurface != 0 && r_dynamic.value) { - for (k=0 ; kpolys; p; p=p->next) + shadowlightfaces++; + +// if (varray_vc + surf->mesh->numvertexes*3>MAXARRAYVERTS) { - shadowlightfaces++; + PPL_FlushArrays(); + } - if (varray_ic + p->numverts*3>MAXARRAYVERTS) - { - PPL_FlushArrays(); - } + v = surf->mesh->xyz_array[0]; + stw = surf->mesh->st_array[0]; - vc_s = varray_vc; - v = p->verts[0]; + out = &varray_v[varray_vc]; - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; + for (vi=0 ; vimesh->numvertexes ; vi++, v+=4, stw+=2, out++) + { + out->xyz[0] = v[0]; + out->xyz[1] = v[1]; + out->xyz[2] = v[2]; + out->stw[0] = stw[0]; + out->stw[1] = stw[1]; lightdir[0] = relativelightorigin[0] - v[0]; lightdir[1] = relativelightorigin[1] - v[1]; lightdir[2] = relativelightorigin[2] - v[2]; @@ -2065,64 +1641,247 @@ static void PPL_GenerateLightArrays(msurface_t *surf, vec3_t relativelightorigin (lightdir[1])*(lightdir[1]) + (lightdir[2])*(lightdir[2])) / light->radius); VectorNormalize(lightdir); - varray_v[varray_vc].stl[0] = colour[0]*dist; - varray_v[varray_vc].stl[1] = colour[1]*dist; - varray_v[varray_vc].stl[2] = colour[2]*dist; - varray_v[varray_vc].ncm[0] = DotProduct(lightdir, surf->texinfo->vecs[0]); - varray_v[varray_vc].ncm[1] = -DotProduct(lightdir, surf->texinfo->vecs[1]); - varray_v[varray_vc].ncm[2] = DotProduct(lightdir, surf->normal); + out->stl[0] = colour[0]*dist; + out->stl[1] = colour[1]*dist; + out->stl[2] = colour[2]*dist; + out->ncm[0] = DotProduct(lightdir, surf->texinfo->vecs[0]); + out->ncm[1] = -DotProduct(lightdir, surf->texinfo->vecs[1]); + out->ncm[2] = DotProduct(lightdir, surf->normal); + } + for (vi=0 ; vimesh->numindexes ; vi++) + { + varray_i[varray_ic++] = varray_vc+vi; + } + + varray_vc += surf->mesh->numvertexes; +} + +//flags +enum{ +PERMUTATION_GENERIC = 0, +PERMUTATION_BUMPMAP = 1, +PERMUTATION_SPECULAR = 2, +PERMUTATION_BUMP_SPEC = 3, + +PERMUTATIONS +}; +int ppl_light_shader[PERMUTATIONS]; +int ppl_light_shader_eyeposition[PERMUTATIONS]; +int ppl_light_shader_lightposition[PERMUTATIONS]; +int ppl_light_shader_lightcolour[PERMUTATIONS]; +int ppl_light_shader_lightradius[PERMUTATIONS]; + +void PPL_CreateLightTexturesProgram(void) +{ + int i; + + char *permutation[PERMUTATIONS] = { + "", + "#define BUMP\n", + "#define SPECULAR\n", + "#define SPECULAR\n#define BUMP\n" + }; + char *vert = + "varying vec2 tcbase;\n" + "uniform vec3 texr, texu, texf;\n" + "varying vec3 LightVector;\n" + "uniform vec3 LightPosition;\n" + + "#ifdef SPECULAR\n" + "uniform vec3 EyePosition;\n" + "varying vec3 EyeVector;\n" + "#endif\n" + + "void main (void)\n" + "{\n" + " gl_Position = ftransform();\n" + + " tcbase = gl_MultiTexCoord0.xy;\n" //pass the texture coords straight through + + " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n" + " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n" + " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n" + " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n" + + "#ifdef SPECULAR\n" + " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n" + " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n" + " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n" + " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n" + "#endif\n" + "}\n" + ; + + char *frag = + "uniform sampler2D baset;\n" + "#ifdef BUMP\n" + "uniform sampler2D bumpt;\n" + "#endif\n" + "#ifdef SPECULAR\n" + "uniform sampler2D speculart;\n" + "#endif\n" + + "varying vec2 tcbase;\n" + "varying vec3 LightVector;\n" + + "uniform float lightradius;\n" + "uniform vec3 LightColour;\n" + + "#ifdef SPECULAR\n" + "varying vec3 EyeVector;\n" + "#endif\n" - varray_vc++; - v += VERTEXSIZE; - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - lightdir[0] = relativelightorigin[0] - v[0]; - lightdir[1] = relativelightorigin[1] - v[1]; - lightdir[2] = relativelightorigin[2] - v[2]; - dist = 1-(sqrt( (lightdir[0])*(lightdir[0]) + - (lightdir[1])*(lightdir[1]) + - (lightdir[2])*(lightdir[2])) / light->radius); - VectorNormalize(lightdir); - varray_v[varray_vc].stl[0] = colour[0]*dist; - varray_v[varray_vc].stl[1] = colour[1]*dist; - varray_v[varray_vc].stl[2] = colour[2]*dist; - varray_v[varray_vc].ncm[0] = DotProduct(lightdir, surf->texinfo->vecs[0]); - varray_v[varray_vc].ncm[1] = -DotProduct(lightdir, surf->texinfo->vecs[1]); - varray_v[varray_vc].ncm[2] = DotProduct(lightdir, surf->normal); - varray_vc++; - v += VERTEXSIZE; - for (vi=2 ; vinumverts ; vi++, v+= VERTEXSIZE) + "void main (void)\n" + "{\n" + "#ifdef BUMP\n" + " vec3 bases = vec3(texture2D(baset, tcbase));\n" + " vec3 bumps = vec3(texture2D(bumpt, tcbase)) * 2.0 - 1.0;\n" + "#else\n" + " vec3 diff = vec3(texture2D(baset, tcbase));\n" + "#endif\n" + "#ifdef SPECULAR\n" + " vec3 specs = vec3(texture2D(speculart, tcbase));\n" + "#endif\n" + + " vec3 nl = normalize(LightVector);\n" + " float colorscale = max(1.0 - dot(LightVector, LightVector)/(lightradius*lightradius), 0.0);\n" + + "#ifdef BUMP\n" + " vec3 diff;\n" + " diff = bases * max(dot(bumps, nl), 0.0);\n" + "#endif\n" + "#ifdef SPECULAR\n" + " vec3 halfdir = (normalize(EyeVector) + normalize(LightVector))/2.0;\n" + " float dv = dot(halfdir, bumps);\n" + " diff += pow(dv, 8.0) * specs;\n" + "#endif\n" + " gl_FragColor.rgb = diff*colorscale*LightColour;\n" + "}\n" + ; + + for (i = 0; i < PERMUTATIONS; i++) + { + ppl_light_shader[i] = GLSlang_CreateProgram(permutation[i], vert, frag); + + if (ppl_light_shader[i]) { - varray_i[varray_ic] = vc_s; - varray_i[varray_ic+1] = varray_vc-1; - varray_i[varray_ic+2] = varray_vc; - varray_ic+=3; + GLSlang_UseProgram(ppl_light_shader[i]); - varray_v[varray_vc].xyz[0] = v[0]; - varray_v[varray_vc].xyz[1] = v[1]; - varray_v[varray_vc].xyz[2] = v[2]; - varray_v[varray_vc].stw[0] = v[3]; - varray_v[varray_vc].stw[1] = v[4]; - lightdir[0] = relativelightorigin[0] - v[0]; - lightdir[1] = relativelightorigin[1] - v[1]; - lightdir[2] = relativelightorigin[2] - v[2]; - dist = 1-(sqrt( (lightdir[0])*(lightdir[0]) + - (lightdir[1])*(lightdir[1]) + - (lightdir[2])*(lightdir[2])) / light->radius); - VectorNormalize(lightdir); - varray_v[varray_vc].stl[0] = colour[0]*dist; - varray_v[varray_vc].stl[1] = colour[1]*dist; - varray_v[varray_vc].stl[2] = colour[2]*dist; - varray_v[varray_vc].ncm[0] = DotProduct(lightdir, surf->texinfo->vecs[0]); - varray_v[varray_vc].ncm[1] = -DotProduct(lightdir, surf->texinfo->vecs[1]); - varray_v[varray_vc].ncm[2] = DotProduct(lightdir, surf->normal); - varray_vc++; + qglUniform1iARB(qglGetUniformLocationARB(ppl_light_shader[i], "baset"), 0); + qglUniform1iARB(qglGetUniformLocationARB(ppl_light_shader[i], "bumpt"), 1); + qglUniform1iARB(qglGetUniformLocationARB(ppl_light_shader[i], "speculart"), 2); + + ppl_light_shader_eyeposition[i] = qglGetUniformLocationARB(ppl_light_shader[i], "EyePosition"); + ppl_light_shader_lightposition [i]= qglGetUniformLocationARB(ppl_light_shader[i], "LightPosition"); + ppl_light_shader_lightcolour[i] = qglGetUniformLocationARB(ppl_light_shader[i], "LightColour"); + ppl_light_shader_lightradius[i] = qglGetUniformLocationARB(ppl_light_shader[i], "lightradius"); + + GLSlang_UseProgram(0); } } +}; + +void PPL_LightTexturesFP(model_t *model, vec3_t modelorigin, dlight_t *light, vec3_t colour) +{ + int i; + texture_t *t; + msurface_t *s; + int p, lp=-1; + extern cvar_t gl_specular; + + vec3_t relativelightorigin; + vec3_t relativeeyeorigin; + + if (qglGetError()) + Con_Printf("GL Error before lighttextures\n"); + + VectorSubtract(light->origin, modelorigin, relativelightorigin); + VectorSubtract(r_refdef.vieworg, modelorigin, relativeeyeorigin); + + qglEnable(GL_BLEND); + GL_TexEnv(GL_MODULATE); + qglBlendFunc(GL_ONE, GL_ONE); + + if (qglGetError()) + Con_Printf("GL Error early in lighttextures\n"); + + for (i=0 ; inumtextures ; i++) + { + t = model->textures[i]; + if (!t) + continue; + s = t->texturechain; + if (!s) + continue; + +// if ((s->flags & SURF_DRAWTURB) && r_wateralphaval != 1.0) +// continue; // draw translucent water later + + t = GLR_TextureAnimation (t); + + + p = 0; + if (t->gl_texturenumbumpmap) + p |= PERMUTATION_BUMPMAP; + if (gl_specular.value && t->gl_texturenumspec) + p |= PERMUTATION_SPECULAR; + + if (p != lp) + { + lp = p; + GLSlang_UseProgram(ppl_light_shader[p]); + qglUniform3fvARB(ppl_light_shader_eyeposition[p], 1, relativeeyeorigin); + qglUniform3fvARB(ppl_light_shader_lightposition[p], 1, relativelightorigin); + qglUniform3fvARB(ppl_light_shader_lightcolour[p], 1, colour); + qglUniform1fARB(ppl_light_shader_lightradius[p], light->radius); + } + + + GL_MBind(GL_TEXTURE0_ARB, t->gl_texturenum); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + GL_MBind(GL_TEXTURE1_ARB, t->gl_texturenumbumpmap); + GL_MBind(GL_TEXTURE2_ARB, t->gl_texturenumspec); + GL_SelectTexture(GL_TEXTURE0_ARB); + + for (; s; s=s->texturechain) + { +// if (s->shadowframe != r_shadowframe) +// continue; + +/* + if (s->flags & SURF_PLANEBACK) + {//inverted normal. + if (-DotProduct(s->plane->normal, relativelightorigin)+s->plane->dist > lightradius) + continue; + } + else + { + if (DotProduct(s->plane->normal, relativelightorigin)-s->plane->dist > lightradius) + continue; + } +*/ + + qglMultiTexCoord3fARB(GL_TEXTURE1_ARB, s->texinfo->vecs[0][0], s->texinfo->vecs[0][1], s->texinfo->vecs[0][2]); + qglMultiTexCoord3fARB(GL_TEXTURE2_ARB, -s->texinfo->vecs[1][0], -s->texinfo->vecs[1][1], -s->texinfo->vecs[1][2]); + + if (s->flags & SURF_PLANEBACK) + qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, -s->plane->normal[0], -s->plane->normal[1], -s->plane->normal[2]); + else + qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, s->plane->normal[0], s->plane->normal[1], s->plane->normal[2]); + + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->st_array); + qglVertexPointer(3, GL_FLOAT, sizeof(float)*4, s->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); + + } + + } + GLSlang_UseProgram(0); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (qglGetError()) + Con_Printf("GL Error during lighttextures\n"); } void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light, vec3_t colour) @@ -2133,6 +1892,12 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light, vec3 vec3_t relativelightorigin; + if (ppl_light_shader) + { + PPL_LightTexturesFP(model, modelorigin, light, colour); + return; + } + PPL_EnableVertexArrays(); VectorSubtract(light->origin, modelorigin, relativelightorigin); @@ -2237,6 +2002,7 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light, vec3 if (DotProduct(s->plane->normal, relativelightorigin)-s->plane->dist > lightradius) continue; } + PPL_GenerateLightArrays(s, relativelightorigin, light, colour); } PPL_FlushArrays(); @@ -2267,6 +2033,84 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light, vec3 } +void PPL_LightBModelTexturesFP(entity_t *e, dlight_t *light, vec3_t colour) +{ + int i; + texture_t *t; + msurface_t *s; + model_t *model = e->model; + texture_t *tnum = NULL; + int p, lp = -1; + + vec3_t relativelightorigin; + vec3_t relativeeyeorigin; + + + + if (qglGetError()) + Con_Printf("GL Error before lighttextures\n"); +//Fixme: rotate + VectorSubtract(light->origin, e->origin, relativelightorigin); + VectorSubtract(r_refdef.vieworg, e->origin, relativeeyeorigin); + + qglEnable(GL_BLEND); + GL_TexEnv(GL_MODULATE); + qglBlendFunc(GL_ONE, GL_ONE); + + if (qglGetError()) + Con_Printf("GL Error early in lighttextures\n"); + + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + { + if (tnum != s->texinfo->texture) + { + tnum = s->texinfo->texture; + + t = GLR_TextureAnimation (tnum); + + p = 0; + if (t->gl_texturenumbumpmap) + p |= PERMUTATION_BUMPMAP; + if (gl_specular.value && t->gl_texturenumspec) + p |= PERMUTATION_SPECULAR; + if (p != lp) + { + lp = p; + GLSlang_UseProgram(ppl_light_shader[p]); + qglUniform3fvARB(ppl_light_shader_eyeposition[p], 1, relativeeyeorigin); + qglUniform3fvARB(ppl_light_shader_lightposition[p], 1, relativelightorigin); + qglUniform3fvARB(ppl_light_shader_lightcolour[p], 1, colour); + qglUniform1fARB(ppl_light_shader_lightradius[p], light->radius); + } + + GL_MBind(GL_TEXTURE0_ARB, t->gl_texturenum); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + GL_MBind(GL_TEXTURE1_ARB, t->gl_texturenumbumpmap); + GL_MBind(GL_TEXTURE2_ARB, t->gl_texturenumspec); + GL_SelectTexture(GL_TEXTURE0_ARB); + } + + qglMultiTexCoord3fARB(GL_TEXTURE1_ARB, -s->texinfo->vecs[0][0], -s->texinfo->vecs[0][1], -s->texinfo->vecs[0][2]); + qglMultiTexCoord3fARB(GL_TEXTURE2_ARB, s->texinfo->vecs[1][0], s->texinfo->vecs[1][1], s->texinfo->vecs[1][2]); + + if (s->flags & SURF_PLANEBACK) + qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, -s->plane->normal[0], -s->plane->normal[1], -s->plane->normal[2]); + else + qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, s->plane->normal[0], s->plane->normal[1], s->plane->normal[2]); + + qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->st_array); + qglVertexPointer(3, GL_FLOAT, sizeof(float)*4, s->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes); + + + } + GLSlang_UseProgram(0); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (qglGetError()) + Con_Printf("GL Error during lighttextures\n"); +} + void PPL_LightBModelTextures(entity_t *e, dlight_t *light, vec3_t colour) { int i; @@ -2275,10 +2119,18 @@ void PPL_LightBModelTextures(entity_t *e, dlight_t *light, vec3_t colour) msurface_t *s; texture_t *t; - vec3_t relativelightorigin; + vec3_t relativelightorigin; qglPushMatrix(); R_RotateForEntity(e); + + if (ppl_light_shader) + { + PPL_LightBModelTexturesFP(e, light, colour); + qglPopMatrix(); + return; + } + qglColor4f(1, 1, 1, 1); PPL_EnableVertexArrays(); @@ -2556,7 +2408,8 @@ void PPL_DrawEntFullBrights(void) { int i; - PPL_FullBrights(cl.worldmodel); +// if (gl_detail.value || (r_fb_bmodels.value && cls.allow_luma)) + PPL_FullBrights(cl.worldmodel); if (!r_drawentities.value) return; @@ -2612,7 +2465,7 @@ void PPL_SchematicsTextureChain(msurface_t *first) { extern int char_texture; msurface_t *s; - int v1, v2; + float *v1, *v2; float len; unsigned char str[64]; int sl, c; @@ -2620,36 +2473,51 @@ void PPL_SchematicsTextureChain(msurface_t *first) vec3_t pos, v; const float size = 0.0625; float frow, fcol; + int e, en; - - qglEnable(GL_TEXTURE_2D); - GL_Bind(char_texture); qglEnable(GL_ALPHA_TEST); if (qglPolygonOffset) qglPolygonOffset(-1, 0); - qglEnable(GL_POLYGON_OFFSET_FILL); frow = rand()/(float)RAND_MAX; frow=frow/2+0.5; qglColor3f(frow, frow, 0); + //draw the distances if (gl_schematics.value != 2) { + qglEnable(GL_POLYGON_OFFSET_FILL); + + qglEnable(GL_TEXTURE_2D); + GL_Bind(char_texture); + qglBegin(GL_QUADS); for (s = first; s ; s=s->texturechain) { - for (v1 = 0; v1 < s->polys->numverts; v1++) + for (e = s->numedges; e >= 0; e--) { - v2 = v1+1; - if (v2 == s->polys->numverts) - v2 = 0; //wrapped. - VectorSubtract(s->polys->verts[v1], s->polys->verts[v2], dir); + en = cl.worldmodel->surfedges[e+s->firstedge]; + if (en<0) //backwards + { + en = -en; + v2 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[0]].position; + v1 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[1]].position; + } + else + { + v1 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[0]].position; + v2 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[1]].position; + } + + + + VectorSubtract(v1, v2, dir); len = Length(dir); VectorNormalize(dir); sprintf(str, "%i", (len<1)?1:(int)len); sl = strlen(str); - VectorMA(s->polys->verts[v2], len/2 + sl*4, dir, pos); + VectorMA(v2, len/2 + sl*4, dir, pos); for (c = 0; c < sl; c++) { @@ -2671,9 +2539,10 @@ void PPL_SchematicsTextureChain(msurface_t *first) } } qglEnd(); + + qglDisable(GL_POLYGON_OFFSET_FILL); } - qglDisable(GL_POLYGON_OFFSET_FILL); qglEnable(GL_POLYGON_OFFSET_LINE); qglDisable(GL_TEXTURE_2D); @@ -2681,12 +2550,16 @@ void PPL_SchematicsTextureChain(msurface_t *first) qglBegin(GL_LINES); for (s = first; s ; s=s->texturechain) { - for (v1 = 0; v1 < s->polys->numverts; v1++) + for (e = s->numedges; e >= 0; e--) { - v2 = v1+1; - if (v2 == s->polys->numverts) - v2 = 0; //wrapped. - VectorSubtract(s->polys->verts[v2], s->polys->verts[v1], dir); + en = cl.worldmodel->surfedges[e+s->firstedge]; + if (en<0) //backwards + en = -en; + v1 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[0]].position; + v2 = cl.worldmodel->vertexes[cl.worldmodel->edges[en].v[1]].position; + + + VectorSubtract(v2, v1, dir); len = Length(dir); VectorNormalize(dir); @@ -2699,7 +2572,7 @@ void PPL_SchematicsTextureChain(msurface_t *first) sl = 0; //left side. (find arrowhead part) - VectorMA(s->polys->verts[v1], 4, s->normal, pos); + VectorMA(v1, 4, s->normal, pos); VectorMA(pos, 4, dir, v); VectorMA(v, -4, s->normal, v); @@ -2716,7 +2589,7 @@ void PPL_SchematicsTextureChain(msurface_t *first) qglVertex3fv(pos); //right hand side. - VectorMA(s->polys->verts[v2], 4, s->normal, pos); + VectorMA(v2, 4, s->normal, pos); VectorMA(pos, -4, dir, v); VectorMA(v, -4, s->normal, v); @@ -2736,6 +2609,8 @@ void PPL_SchematicsTextureChain(msurface_t *first) } qglEnd(); qglDisable(GL_POLYGON_OFFSET_LINE); + + qglEnable(GL_TEXTURE_2D); } // :) @@ -2809,7 +2684,6 @@ void PPL_RecursiveWorldNode_r (mnode_t *node) msurface_t *surf, **mark; mleaf_t *pleaf; double dot; - glpoly_t *p; int v; float *v1; @@ -2965,19 +2839,17 @@ void PPL_RecursiveWorldNode_r (mnode_t *node) } } - for (p = surf->polys; p; p=p->next) - { - shadowsurfcount++; + shadowsurfcount++; - //front face - qglVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*VERTEXSIZE, p->verts[0]); - qglDrawElements(GL_TRIANGLES, (p->numverts-2)*3, GL_UNSIGNED_INT, varray_i_polytotri); + qglVertexPointer(3, GL_FLOAT, sizeof(float)*4, surf->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, surf->mesh->numindexes, GL_UNSIGNED_INT, surf->mesh->indexes); + //fixme:this only works becuse q1bsps don't have combined meshes yet... //back (depth precision doesn't matter) qglBegin(GL_POLYGON); - for (v = p->numverts-1; v >=0; v--) + for (v = surf->mesh->numvertexes-1; v >=0; v--) { - v1 = p->verts[v]; + v1 = surf->mesh->xyz_array[v]; v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; @@ -2985,8 +2857,6 @@ void PPL_RecursiveWorldNode_r (mnode_t *node) qglVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); } qglEnd(); - - } } } } @@ -3003,7 +2873,6 @@ void PPL_RecursiveWorldNodeQ2_r (mnode_t *node) msurface_t *surf, **mark; mleaf_t *pleaf; double dot; - glpoly_t *p; int v; float *v1; @@ -3146,27 +3015,24 @@ void PPL_RecursiveWorldNodeQ2_r (mnode_t *node) } } + //front face + qglVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*4, surf->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, surf->mesh->numindexes, GL_UNSIGNED_INT, surf->mesh->indexes); - for (p = surf->polys; p; p=p->next) + //fixme:this only works becuse q1bsps don't have combined meshes yet... + //back (depth precision doesn't matter) + qglBegin(GL_POLYGON); + for (v = surf->mesh->numvertexes-1; v >=0; v--) { - //front face - qglVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*VERTEXSIZE, p->verts); - qglDrawElements(GL_TRIANGLES, (p->numverts-2)*3, GL_UNSIGNED_INT, varray_i_polytotri); + v1 = surf->mesh->xyz_array[v]; + v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; + v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; + v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; -//back - qglBegin(GL_POLYGON); - for (v = p->numverts-1; v >=0; v--) - { - v1 = p->verts[v]; - v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; - - qglVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); - } - qglEnd(); - + qglVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); } + qglEnd(); + } } } @@ -3182,14 +3048,13 @@ void PPL_RecursiveWorldNodeQ3_r (mnode_t *node) msurface_t *surf, **mark; mleaf_t *pleaf; double dot; - glpoly_t *p; - int v; +// glpoly_t *p; +// int v; - float *v2; - vec3_t v4; +// float *v2; +// vec3_t v4; - float *v1; - vec3_t v3; +// vec3_t v3; if (node->contents == Q2CONTENTS_SOLID) return; // solid @@ -3240,6 +3105,8 @@ void PPL_RecursiveWorldNodeQ3_r (mnode_t *node) }*/ + Sys_Error("PPL_RecursiveWorldNodeQ3_r needs work"); + /* for (p = surf->polys; p; p=p->next) { @@ -3286,6 +3153,7 @@ void PPL_RecursiveWorldNodeQ3_r (mnode_t *node) qglEnd(); } + */ } while (--c); } return; @@ -3395,7 +3263,7 @@ void PPL_RecursiveWorldNode (dlight_t *dl) if (varray_vc + 4>MAXARRAYVERTS) { - qglDrawElements(GL_QUADS, varray_vc, GL_UNSIGNED_INT, varray_i_forward); + qglDrawArrays(GL_QUADS, 0, varray_vc); if (qglGetError()) Con_Printf("GL Error on entities\n"); varray_vc=0; @@ -3445,7 +3313,7 @@ void PPL_RecursiveWorldNode (dlight_t *dl) shadowedgecount++; } - qglDrawElements(GL_QUADS, varray_vc, GL_UNSIGNED_INT, varray_i_forward); + qglDrawArrays(GL_QUADS, 0, varray_vc); if (qglGetError()) Con_Printf("GL Error on entities\n"); @@ -3455,9 +3323,8 @@ void PPL_RecursiveWorldNode (dlight_t *dl) firstedge=0; } -void PPL_DrawBrushModel(dlight_t *dl, entity_t *e) +void PPL_DrawBrushModelShadow(dlight_t *dl, entity_t *e) { - glpoly_t *p; int v; float *v1, *v2; vec3_t v3, v4; @@ -3490,63 +3357,55 @@ void PPL_DrawBrushModel(dlight_t *dl, entity_t *e) continue; } - for (p = surf->polys; p; p=p->next) - { //front face - qglVertexPointer(3, GL_FLOAT, sizeof(p->verts[0]), p->verts[0]); - qglDrawElements(GL_POLYGON, p->numverts, GL_UNSIGNED_INT, varray_i_forward); - /* glBegin(GL_POLYGON); - for (v = 0; v < p->numverts; v++) - glVertex3fv(p->verts[v]); - glEnd();*/ + qglVertexPointer(3, GL_FLOAT, 4*sizeof(float), surf->mesh->xyz_array); + qglDrawArrays(GL_POLYGON, 0, surf->mesh->numvertexes); - for (v = 0; v < p->numverts; v++) - { - //border - v1 = p->verts[v]; - v2 = p->verts[( v+1 )%p->numverts]; + for (v = 0; v < surf->mesh->numvertexes; v++) + { + //border + v1 = surf->mesh->xyz_array[v]; + v2 = surf->mesh->xyz_array[( v+1 )%surf->mesh->numvertexes]; - //get positions of v3 and v4 based on the light position - v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; + //get positions of v3 and v4 based on the light position + v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; + v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; + v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; - v4[0] = ( v2[0]-lightorg[0] )*PROJECTION_DISTANCE; - v4[1] = ( v2[1]-lightorg[1] )*PROJECTION_DISTANCE; - v4[2] = ( v2[2]-lightorg[2] )*PROJECTION_DISTANCE; + v4[0] = ( v2[0]-lightorg[0] )*PROJECTION_DISTANCE; + v4[1] = ( v2[1]-lightorg[1] )*PROJECTION_DISTANCE; + v4[2] = ( v2[2]-lightorg[2] )*PROJECTION_DISTANCE; - //Now draw the quad from the two verts to the projected light - //verts - qglBegin( GL_QUAD_STRIP ); - qglVertex3f( v1[0], v1[1], v1[2] ); - qglVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); - qglVertex3f( v2[0], v2[1], v2[2] ); - qglVertex3f( v2[0]+v4[0], v2[1]+v4[1], v2[2]+v4[2] ); - qglEnd(); - } + //Now draw the quad from the two verts to the projected light + //verts + qglBegin( GL_QUAD_STRIP ); + qglVertex3fv(v1); + qglVertex3f (v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2]); + qglVertex3fv(v2); + qglVertex3f (v2[0]+v4[0], v2[1]+v4[1], v2[2]+v4[2]); + qglEnd(); + } //back - - qglBegin(GL_POLYGON); - for (v = p->numverts-1; v >=0; v--) - { - v1 = p->verts[v]; - v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; + //the same applies as earlier + qglBegin(GL_POLYGON); + for (v = surf->mesh->numvertexes-1; v >=0; v--) + { + v1 = surf->mesh->xyz_array[v]; + v3[0] = (v1[0]-lightorg[0])*PROJECTION_DISTANCE; + v3[1] = (v1[1]-lightorg[1])*PROJECTION_DISTANCE; + v3[2] = (v1[2]-lightorg[2])*PROJECTION_DISTANCE; - qglVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); - } - qglEnd(); - + qglVertex3f(v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2]); } + qglEnd(); } qglPopMatrix(); } void PPL_DrawShadowMeshes(dlight_t *dl) { - int i, j; + int i; if (!r_drawentities.value) return; @@ -3556,9 +3415,6 @@ void PPL_DrawShadowMeshes(dlight_t *dl) { currententity = &cl_visedicts[i]; - if (currententity->flags & Q2RF_WEAPONMODEL) - continue; //weapon models don't cast shadows. - if (r_inmirror) { if (currententity->flags & Q2RF_WEAPONMODEL) @@ -3566,26 +3422,13 @@ void PPL_DrawShadowMeshes(dlight_t *dl) } else { - j = currententity->keynum; - while(j) - { - - if (j == (cl.viewentity[r_refdef.currentplayernum]?cl.viewentity[r_refdef.currentplayernum]:(cl.playernum[r_refdef.currentplayernum]+1))) - break; - - j = cl.lerpents[j].tagent; - } - if (j) - continue; - - if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum]) - continue; - if (!Cam_DrawPlayer(0, currententity->keynum-1)) + if (currententity->keynum == dl->key) continue; } if (currententity->flags & Q2RF_BEAM) { + R_DrawBeam(currententity); continue; } if (!currententity->model) @@ -3612,7 +3455,7 @@ void PPL_DrawShadowMeshes(dlight_t *dl) break; case mod_brush: - PPL_DrawBrushModel (dl, currententity); + PPL_DrawBrushModelShadow (dl, currententity); break; default: @@ -4191,7 +4034,7 @@ void PPL_DrawWorld (void) RSpeedRemark(); TRACE(("dbg: calling PPL_BaseEntTextures\n")); PPL_BaseEntTextures(); - RSpeedEnd(RSPEED_ENTITIES); + RSpeedEnd(RSPEED_DRAWENTITIES); // CL_NewDlightRGB(1, r_refdef.vieworg[0], r_refdef.vieworg[1]-16, r_refdef.vieworg[2]-24, 128, 1, 1, 1, 1); @@ -4321,3 +4164,9 @@ void PPL_DrawWorld (void) R_IBrokeTheArrays(); } #endif + +void PPL_CreateShaderObjects(void) +{ + PPL_CreateLightTexturesProgram(); + PPL_LoadSpecularFragmentProgram(); +} \ No newline at end of file diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index b06a40706..a870e1a8d 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -349,7 +349,7 @@ void GLR_PushDlights (void) l = cl_dlights; - for (i=0 ; iradius || l->nodynamic) continue; @@ -359,7 +359,7 @@ void GLR_PushDlights (void) /* if (cl.worldmodel->fromgame == fg_quake3) { - for (i=0 ; idie < cl.time || !l->radius) continue; @@ -369,7 +369,7 @@ void GLR_PushDlights (void) } if (cl.worldmodel->fromgame == fg_quake2) { - for (i=0 ; idie < cl.time || !l->radius) continue; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 3f26dbf6e..f858ee56b 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -152,8 +152,6 @@ int scenepp_ww_parm_ampscalef; // processing shaders void GL_InitSceneProcessingShaders (void) { - int vert, frag; - char *genericvert = "\ varying vec2 v_texCoord0;\ varying vec2 v_texCoord1;\ @@ -196,10 +194,7 @@ void GL_InitSceneProcessingShaders (void) if (qglGetError()) Con_Printf("GL Error before initing shader object\n"); - vert = GLSlang_CreateShader(genericvert, 1);//GL_VERTEX_SHADER_ARB); - frag = GLSlang_CreateShader(wwfrag, 0);//GL_FRAGMENT_SHADER_ARB); - - scenepp_ww_program = GLSlang_CreateProgram(vert, frag); + scenepp_ww_program = GLSlang_CreateProgram(NULL, genericvert, wwfrag); if (!scenepp_ww_program) return; @@ -508,10 +503,16 @@ void R_DrawSpriteModel (entity_t *e) GL_Bind(frame->gl_texturenum); - if (e->alpha<1) + if (e->flags & Q2RF_ADDATIVE) { qglEnable(GL_BLEND); - qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + qglBlendFunc(GL_SRC_ALPHA, GL_ONE); + } + else if (e->alpha<1) + { + qglEnable(GL_BLEND); + qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else qglEnable (GL_ALPHA_TEST); @@ -543,6 +544,9 @@ void R_DrawSpriteModel (entity_t *e) qglDisable(GL_BLEND); qglDisable (GL_ALPHA_TEST); + + if (e->flags & Q2RF_ADDATIVE) //back to regular blending for us! + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } #if 0 extern int gldepthfunc; @@ -715,7 +719,7 @@ R_DrawEntitiesOnList */ void GLR_DrawEntitiesOnList (void) { - int i; + int i, j; if (!r_drawentities.value) return; @@ -725,18 +729,40 @@ void GLR_DrawEntitiesOnList (void) { currententity = &cl_visedicts[i]; - if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum]) - continue; + if (r_inmirror) + { + if (currententity->flags & Q2RF_WEAPONMODEL) + continue; + } + else + { + j = currententity->keynum; + while(j) + { + + if (j == (cl.viewentity[r_refdef.currentplayernum]?cl.viewentity[r_refdef.currentplayernum]:(cl.playernum[r_refdef.currentplayernum]+1))) + break; - if (!Cam_DrawPlayer(0, currententity->keynum-1)) - continue; + j = cl.lerpents[j].tagent; + } + if (j) + continue; + + if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum]) + continue; + if (!Cam_DrawPlayer(0, currententity->keynum-1)) + continue; + } if (currententity->flags & Q2RF_BEAM) + { + R_DrawBeam(currententity); continue; - + } if (!currententity->model) continue; + if (cls.allow_anyparticles || currententity->visframe) //allowed or static { if (currententity->model->particleeffect>=0) @@ -787,12 +813,36 @@ void GLR_DrawEntitiesOnList (void) { currententity = &cl_visedicts[i]; - if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum]) - continue; + if (r_inmirror) + { + if (currententity->flags & Q2RF_WEAPONMODEL) + continue; + } + else + { + j = currententity->keynum; + while(j) + { + + if (j == (cl.viewentity[r_refdef.currentplayernum]?cl.viewentity[r_refdef.currentplayernum]:(cl.playernum[r_refdef.currentplayernum]+1))) + break; + + j = cl.lerpents[j].tagent; + } + if (j) + continue; + + if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum]) + continue; + if (!Cam_DrawPlayer(0, currententity->keynum-1)) + continue; + } if (currententity->flags & Q2RF_BEAM) + { + R_DrawBeam(currententity); continue; - + } if (!currententity->model) continue; @@ -1335,7 +1385,7 @@ void R_SetupGL (void) qglLoadIdentity (); screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; - if (!r_shadows.value || !gl_canstencil)//gl_nv_range_clamp) + if ((!r_shadows.value || !gl_canstencil) && gl_maxdist.value>0)//gl_nv_range_clamp) { // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; @@ -1636,9 +1686,9 @@ void R_MirrorAddPlayerModels (void) VectorCopy(cl.simorg[0], ent->origin); - if (state->effects & EF_FLAG1) + if (state->effects & QWEF_FLAG1) CL_AddFlagModels (ent, 0); - else if (state->effects & EF_FLAG2) + else if (state->effects & QWEF_FLAG2) CL_AddFlagModels (ent, 1); if (info->vweapindex) @@ -1954,7 +2004,7 @@ void GLR_RenderView (void) // Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); } - if (!gl_config.arb_shader_objects) + if (!scenepp_ww_program) return; // SCENE POST PROCESSING diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 11c477ae4..fc0a88c10 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -875,6 +875,7 @@ void R_LoadRTLights(void) float radius; vec3_t rgb; + //delete all old lights for (i=0 ; iextents[1]>>4)+1; tex = surf->texinfo; - for (lnum=0 ; lnumdlightbits & (1<extents[1]>>4)+1; tex = surf->texinfo; - for (lnum=0 ; lnumdlightbits & (1<extents[1]>>4)+1; tex = surf->texinfo; - for (lnum=0 ; lnumdlightbits & (1<verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[5], v[6]); - - nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[2] = v[2]; - - glVertex3fv (nv); - } - glEnd (); -} -#endif /* ================ DrawGLPoly ================ */ -static void DrawGLPoly (glpoly_t *p) +static void DrawGLPoly (mesh_t *p) { + Sys_Error("DrawGLWaterPoly needs work"); + /* int i; float *v; @@ -1821,6 +1803,7 @@ static void DrawGLPoly (glpoly_t *p) qglEnd (); p=p->next; } + */ } @@ -1953,9 +1936,9 @@ void R_RenderBrushPoly (msurface_t *fa) if (((r_viewleaf->contents==Q1CONTENTS_EMPTY && (fa->flags & SURF_UNDERWATER)) || (r_viewleaf->contents!=Q1CONTENTS_EMPTY && !(fa->flags & SURF_UNDERWATER))) && !(fa->flags & SURF_DONTWARP)) - DrawGLWaterPoly (fa->polys); + DrawGLWaterPoly (fa->mesh); else - DrawGLPoly (fa->polys); + DrawGLPoly (fa->mesh); } /* @@ -1971,7 +1954,7 @@ void R_RenderDynamicLightmaps (msurface_t *fa) glRect_t *theRect; int smax, tmax; - if (!fa->polys) + if (!fa->mesh) return; c_brush_polys++; @@ -2110,14 +2093,6 @@ void GLR_DrawWaterSurfaces (void) GL_TexEnv(GL_MODULATE); } - if (gl_waterripples.value) - { - qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - qglEnable(GL_TEXTURE_GEN_S); - qglEnable(GL_TEXTURE_GEN_T); - } - for (i=0 ; inumtextures ; i++) { t = cl.worldmodel->textures[i]; @@ -2143,10 +2118,6 @@ void GLR_DrawWaterSurfaces (void) qglColor4f (1,1,1,1); qglDisable (GL_BLEND); } - - qglDisable(GL_TEXTURE_GEN_S); - qglDisable(GL_TEXTURE_GEN_T); - } @@ -2192,6 +2163,8 @@ static void GLR_DrawAlphaSurface(msurface_t *s) } else { + Sys_Error("GLR_DrawAlphaSurface needs work"); + /* if (gl_mtexable) { int i; @@ -2220,12 +2193,13 @@ static void GLR_DrawAlphaSurface(msurface_t *s) GL_DisableMultitexture(); } else + */ { if (s->samples) //could do true vertex lighting... ? qglColor4ub (*s->samples,*s->samples,*s->samples,255); else qglColor4f (1,1,1,1); - DrawGLPoly (s->polys); + DrawGLPoly (s->mesh); } } @@ -2238,7 +2212,7 @@ static void GLR_DrawAlphaSurface(msurface_t *s) // else if(s->texinfo->flags & SURF_FLOWING) // PGM 9/16/98 // DrawGLFlowingPoly (s); // PGM else - DrawGLPoly (s->polys); + DrawGLPoly (s->mesh); qglPopMatrix(); } @@ -2283,7 +2257,8 @@ void GLR_DrawAlphaSurfaces (void) qglPushMatrix(); R_RotateForEntity(currententity); } - + Sys_Error("GLR_DrawAlphaSurfaces needs work"); +/* if (gl_mtexable) { int i; @@ -2313,12 +2288,13 @@ void GLR_DrawAlphaSurfaces (void) GL_DisableMultitexture(); } else +*/ { if (s->samples) //could do true vertex lighting... ? qglColor4ub (*s->samples,*s->samples,*s->samples,255); else qglColor4f (1,1,1,1); - DrawGLPoly (s->polys); + DrawGLPoly (s->mesh); qglColor4f (1,1,1,1); } continue; @@ -2784,7 +2760,7 @@ static void R_DrawBrushModel (entity_t *e) // instanced model if (currentmodel->firstmodelsurface != 0 && !r_flashblend.value) { - for (k=0 ; kcontents == Q1CONTENTS_SOLID) return; // solid @@ -2874,7 +2852,7 @@ static void GLR_RecursiveWorldNode (mnode_t *node) return; if (R_CullBox (node->minmaxs, node->minmaxs+3)) return; - + // if a leaf node, draw stuff if (node->contents < 0) { @@ -2944,15 +2922,8 @@ static void GLR_RecursiveWorldNode (mnode_t *node) if (surf->visframe != r_framecount) continue; -// surf->visframe = -1; - - // don't backface underwater surfaces, because they warp - if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) - continue; // wrong side - if ( !(((r_viewleaf->contents==Q1CONTENTS_EMPTY && (surf->flags & SURF_UNDERWATER)) || - (r_viewleaf->contents!=Q1CONTENTS_EMPTY && !(surf->flags & SURF_UNDERWATER))) - && !(surf->flags & SURF_DONTWARP)) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) - continue; // wrong side +// if (((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK))) +// continue; // wrong side R_RenderDynamicLightmaps (surf); // if sorting by texture, just store it out @@ -2972,7 +2943,9 @@ static void GLR_RecursiveWorldNode (mnode_t *node) } // recurse down the back side - GLR_RecursiveWorldNode (node->children[!side]); + //GLR_RecursiveWorldNode (node->children[!side]); + node = node->children[!side]; + goto start; } #ifdef Q2BSPS @@ -3106,7 +3079,7 @@ static void GLR_LeafWorldNode (void) { if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) { - // continue; // not visible + continue; // not visible } } @@ -3138,34 +3111,9 @@ static void GLR_LeafWorldNode (void) if ( surf->visframe != r_framecount ) //sufraces exist in multiple leafs. { surf->visframe = r_framecount; -// if (surf->mesh) -// { -// GL_DrawMesh(surf->mesh, NULL, surf->texinfo->texture->gl_texturenum, lightmap_textures+ surf->lightmaptexturenum); -// } -// else -// R_DrawSequentialPoly ( surf ); - - - /* if (surf->flags & SURF_DRAWALPHA) - { // add to the translucent chain - surf->nextalphasurface = r_alpha_surfaces; - r_alpha_surfaces = surf; - surf->ownerent = &r_worldentity; - continue; - } - else*/ - { - /* if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) - { // add to the translucent chain - surf->nextalphasurface = r_alpha_surfaces; - r_alpha_surfaces = surf; - surf->ownerent = &r_worldentity; - continue; - }*/ - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; } } while (--i); @@ -3549,7 +3497,6 @@ void BuildSurfaceDisplayList (msurface_t *fa) int vertpage; float *vec; float s, t; - glpoly_t *poly; int lm; // reconstruct the polygon @@ -3559,8 +3506,8 @@ void BuildSurfaceDisplayList (msurface_t *fa) if (lnumverts<3) return; //q3 map. -#ifdef Q3SHADERS - if (fa->texinfo->texture->shader) +//#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; mesh_t *mesh; @@ -3635,10 +3582,11 @@ void BuildSurfaceDisplayList (msurface_t *fa) return; } -#endif +//#endif // // draw texture // + /* poly = Hunk_AllocName (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float), "SDList"); poly->next = fa->polys; fa->polys = poly; @@ -3685,19 +3633,8 @@ void BuildSurfaceDisplayList (msurface_t *fa) poly->verts[i][6] = t; #ifdef SPECULAR -/* if (currentmodel->deluxdata&&fa->samples) - { - qbyte *dlm = fa->samples - currentmodel->lightdata + currentmodel->deluxdata; - dlm += lm; - poly->verts[i][7] = (dlm[0]-127)/128.0f; - poly->verts[i][8] = (dlm[1]-127)/128.0f; - poly->verts[i][9] = (dlm[2]-127)/128.0f; - } - else*/ - if (fa->flags & SURF_PLANEBACK) - { - VectorNegate(fa->plane->normal, (poly->verts[i]+7)); - } + if (fa->flags & SURF_PLANEBACK) + VectorNegate(fa->plane->normal, (poly->verts[i]+7)); else VectorCopy(fa->plane->normal, (poly->verts[i]+7)); #endif @@ -3743,31 +3680,8 @@ void BuildSurfaceDisplayList (msurface_t *fa) } } -#ifdef SHADERS //adjust the s + t coords so we can rotate around the center of the texture rather than the center of the world. - s=0;t=0; - for (i=0 ; iverts[i][3]; - t+=poly->verts[i][4]; - } - poly->texcenter[0] = s/lnumverts; - poly->texcenter[1] = t/lnumverts; - - s = (int)poly->texcenter[0]; - t = (int)poly->texcenter[1]; - if (s <=0)s--; - if (t <=0)t--; - poly->texcenter[0] -= s; - poly->texcenter[1] -= t; - for (i=0 ; iverts[i][3] -= s; - poly->verts[i][4] -= t; - } -#endif - poly->numverts = lnumverts; - + */ } /* @@ -3781,22 +3695,21 @@ void GL_CreateSurfaceLightmap (msurface_t *surf) qbyte *base, *luxbase; stmap *stainbase; if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) - { surf->lightmaptexturenum = -1; - return; - } - if (currentmodel->fromgame == fg_halflife) - if (surf->texinfo->flags & TEX_SPECIAL) - { - surf->lightmaptexturenum = -1; - return; //it comes in stupid sizes. - } + if (surf->texinfo->flags & TEX_SPECIAL) + surf->lightmaptexturenum = -1; if (surf->lightmaptexturenum<0) return; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; + if (smax > LMBLOCK_WIDTH || tmax > LMBLOCK_HEIGHT || smax <= 0 || tmax <= 0) + { //whoa, buggy. + surf->lightmaptexturenum = -1; + return; + } + if (currentmodel->fromgame == fg_quake3) GLFillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); else @@ -3947,7 +3860,7 @@ void GL_BuildLightmaps (void) GL_CreateSurfaceLightmap (m->surfaces + i); P_EmitSkyEffectTris(m, &m->surfaces[i]); - if (m->surfaces[i].polys) //there are some surfaces that have a display list already (the subdivided ones) + if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (the subdivided ones) continue; BuildSurfaceDisplayList (m->surfaces + i); } diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 23be218ca..4afdf80f0 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -61,7 +61,8 @@ void RSpeedShow(void) memset(RSpNames, 0, sizeof(RSpNames)); RSpNames[RSPEED_TOTALREFRESH] = "Total refresh"; - RSpNames[RSPEED_CLIENT] = "Protocol and entity setup"; + RSpNames[RSPEED_PROTOCOL] = "Protocol"; + RSpNames[RSPEED_LINKENTITIES] = "Entity setup"; RSpNames[RSPEED_WORLDNODE] = "World walking"; RSpNames[RSPEED_WORLD] = "World rendering"; RSpNames[RSPEED_DYNAMIC] = "Lightmap updates"; @@ -70,6 +71,8 @@ void RSpeedShow(void) RSpNames[RSPEED_2D] = "2d elements"; RSpNames[RSPEED_SERVER] = "Server"; + RSpNames[RSPEED_DRAWENTITIES] = "Entity rendering"; + RSpNames[RSPEED_PALETTEFLASHES] = "Palette flashes"; RSpNames[RSPEED_STENCILSHADOWS] = "Stencil Shadows"; @@ -246,9 +249,6 @@ void GLSCR_UpdateScreen (void) vid.recalc_refdef = true; } - if (scr_chatmode != scr_chatmodecvar.value) - vid.recalc_refdef = true; - if (vid.recalc_refdef || scr_viewsize.modified) SCR_CalcRefdef (); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 6ccf2d15a..25bb56cd8 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -267,7 +267,7 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) } } -/*static void Shader_ParseSkySides ( char **ptr, image_t *images ) +static void Shader_ParseSkySides ( char **ptr, int *images ) { int i; char *token; @@ -285,7 +285,7 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) } } } -*/ + static void Shader_ParseFunc ( char **ptr, shaderfunc_t *func ) { char *token; @@ -428,8 +428,7 @@ static void Shader_DeformVertexes ( shader_t *shader, shaderpass_t *pass, char * static void Shader_SkyParms ( shader_t *shader, shaderpass_t *pass, char **ptr ) { - //FIZME: skydomes? -/* int i; + int i; skydome_t *skydome; float skyheight; @@ -455,8 +454,8 @@ static void Shader_SkyParms ( shader_t *shader, shaderpass_t *pass, char **ptr ) Shader_ParseSkySides ( ptr, skydome->nearbox_textures ); - R_CreateSkydome ( shader, skyheight ); -*/ +// R_CreateSkydome ( shader, skyheight ); + shader->flags |= SHADER_SKY; shader->sort = SHADER_SORT_SKY; } @@ -1053,14 +1052,17 @@ void Shader_Free (shader_t *shader) shaderpass_t *pass; if ( shader->flags & SHADER_SKY ) { -/* for ( i = 0; i < 5; i++ ) { - Z_Free ( shader->skydome->meshes[i].xyz_array ); - Z_Free ( shader->skydome->meshes[i].normals_array ); - Z_Free ( shader->skydome->meshes[i].st_array ); + for ( i = 0; i < 5; i++ ) { + if (shader->skydome->meshes[i].xyz_array) + { + Z_Free ( shader->skydome->meshes[i].xyz_array ); + Z_Free ( shader->skydome->meshes[i].normals_array ); + Z_Free ( shader->skydome->meshes[i].st_array ); + } } Z_Free ( shader->skydome ); -*/ } + } pass = shader->passes; for ( i = 0; i < shader->numpasses; i++, pass++ ) { diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 6e7f39d20..a9b9aa8df 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -106,6 +106,8 @@ PFNGLGETINFOLOGARBPROC qglGetInfoLogARB; PFNGLLINKPROGRAMARBPROC qglLinkProgramARB; PFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; PFNGLUNIFORM4FARBPROC qglUniform4fARB; +PFNGLUNIFORM3FARBPROC qglUniform3fARB; +PFNGLUNIFORM3FVARBPROC qglUniform3fvARB; PFNGLUNIFORM1IARBPROC qglUniform1iARB; PFNGLUNIFORM1FARBPROC qglUniform1fARB; @@ -339,6 +341,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglLinkProgramARB = (void *)getglext("glLinkProgramARB"); qglGetUniformLocationARB = (void *)getglext("glGetUniformLocationARB"); qglUniform4fARB = (void *)getglext("glUniform4fARB"); + qglUniform3fARB = (void *)getglext("glUniform3fARB"); + qglUniform3fvARB = (void *)getglext("glUniform3fvARB"); qglUniform1iARB = (void *)getglext("glUniform1iARB"); qglUniform1fARB = (void *)getglext("glUniform1fARB"); @@ -349,29 +353,21 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) // glslang helper api function definitions // type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB -GLhandleARB GLSlang_CreateShader (char *shadersource, int shadertype) +GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource, GLenum shadertype) { GLhandleARB shader; - GLenum type; GLint compiled; char str[1024]; - switch (shadertype) - { - case 0: - type = GL_FRAGMENT_SHADER_ARB; - break; - case 1: - type = GL_VERTEX_SHADER_ARB; - break; - default: - return -1; - break; - } + char *prstrings[2]; + if (!precompilerconstants) + precompilerconstants = ""; + prstrings[0] = precompilerconstants; + prstrings[1] = shadersource; - shader = qglCreateShaderObjectARB(type); + shader = qglCreateShaderObjectARB(shadertype); - qglShaderSourceARB(shader, 1, (const GLcharARB**)&shadersource, NULL); + qglShaderSourceARB(shader, 2, (const GLcharARB**)prstrings, NULL); qglCompileShaderARB(shader); qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); @@ -380,23 +376,23 @@ GLhandleARB GLSlang_CreateShader (char *shadersource, int shadertype) qglGetInfoLogARB(shader, sizeof(str), NULL, str); switch (shadertype) { - case 0: + case GL_FRAGMENT_SHADER_ARB: Con_Printf("Fragment shader compilation error:\n----------\n%s\n----------\n", str); break; - case 1: + case GL_VERTEX_SHADER_ARB: Con_Printf("Vertex shader compilation error:\n----------\n%s\n----------\n", str); break; default: Con_Printf("Shader_CreateShader: This shouldn't happen ever\n"); break; } - return -1; + return 0; } return shader; } -GLhandleARB GLSlang_CreateProgram (GLhandleARB vert, GLhandleARB frag) +GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag) { GLhandleARB program; GLint linked; @@ -420,6 +416,21 @@ GLhandleARB GLSlang_CreateProgram (GLhandleARB vert, GLhandleARB frag) return program; } +GLhandleARB GLSlang_CreateProgram(char *precompilerconstants, char *vert, char *frag) +{ + GLhandleARB vs; + GLhandleARB fs; + + if (!gl_config.arb_shader_objects) + return 0; + + vs = GLSlang_CreateShader(precompilerconstants, vert, GL_VERTEX_SHADER_ARB); + fs = GLSlang_CreateShader(precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB); + if (!vs || !fs) + return 0; + return GLSlang_CreateProgramObject(vs, fs); +} + GLint GLSlang_GetUniformLocation (int prog, char *name) { int i = qglGetUniformLocationARB(prog, name); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index cd1b9a022..7a3d7b8cb 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -22,8 +22,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #ifdef RGLQUAKE #include "glquake.h" +#ifdef Q3SHADERS +#include "shader.h" +#endif #include + +extern void GL_DrawAliasMesh (mesh_t *mesh, int texnum); + +void R_DrawSkySphere (msurface_t *fa); + extern model_t *loadmodel; int skytexturenum; @@ -37,11 +45,11 @@ qboolean usingskybox; msurface_t *warpface; extern cvar_t gl_skyboxname; -extern cvar_t gl_waterripples; extern cvar_t gl_skyboxdist; extern cvar_t r_fastsky; extern cvar_t r_fastskycolour; -char loadedskybox[256]; +char defaultskybox[MAX_QPATH]; +qboolean reloadskybox; void R_DrawSkyBox (msurface_t *s); void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) @@ -62,144 +70,17 @@ void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) } } -void SubdividePolygon (int numverts, float *verts, float dividesize) -{ - int i, j, k; - vec3_t mins, maxs; - float m; - float *v; - vec3_t front[64], back[64]; - int f, b; - float dist[64]; - float frac; - glpoly_t *poly; - float s, t; - - if (numverts > 60 || numverts <= 0) - Sys_Error ("numverts = %i", numverts); - - BoundPoly (numverts, verts, mins, maxs); - - for (i=0 ; i<3 ; i++) - { - m = (mins[i] + maxs[i]) * 0.5; - m = dividesize * floor (m/dividesize + 0.5); - if (maxs[i] - m < 8) - continue; - if (m - mins[i] < 8) - continue; - - // cut it - v = verts + i; - for (j=0 ; j= 0) - { - VectorCopy (v, front[f]); - f++; - } - if (dist[j] <= 0) - { - VectorCopy (v, back[b]); - b++; - } - if (dist[j] == 0 || dist[j+1] == 0) - continue; - if ( (dist[j] > 0) != (dist[j+1] > 0) ) - { - // clip point - frac = dist[j] / (dist[j] - dist[j+1]); - for (k=0 ; k<3 ; k++) - front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); - f++; - b++; - } - } - - SubdividePolygon (f, front[0], dividesize); - SubdividePolygon (b, back[0], dividesize); - return; - } - - poly = Hunk_AllocName (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float), "subpoly"); - poly->next = warpface->polys; - warpface->polys = poly; - poly->numverts = numverts; - for (i=0 ; iverts[i]); - s = DotProduct (verts, warpface->texinfo->vecs[0]); - t = DotProduct (verts, warpface->texinfo->vecs[1]); - poly->verts[i][3] = s; - poly->verts[i][4] = t; - } -} - -/* -================ -GL_SubdivideSurface - -Breaks a polygon up along axial 64 unit -boundaries so that turbulent and sky warps -can be done reasonably. -================ -*/ -void GL_SubdivideSurface (msurface_t *fa, float dividesize) -{ - vec3_t verts[64]; - int numverts; - int i; - int lindex; - float *vec; - - warpface = fa; - - // - // convert edges back to a normal polygon - // - numverts = 0; - for (i=0 ; inumedges ; i++) - { - lindex = loadmodel->surfedges[fa->firstedge + i]; - - if (lindex > 0) - vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; - else - vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; - VectorCopy (vec, verts[numverts]); - numverts++; - - if(numverts >= 64) - { - Con_Printf("Too many verts on surface\n"); - break; - } - } - - SubdividePolygon (numverts, verts[0], dividesize); -} - //========================================================= - +/* // speed up sin calculations - Ed float turbsin[] = { #include "gl_warp_sin.h" }; #define TURBSCALE (256.0 / (2 * M_PI)) - +*/ /* ============= EmitWaterPolys @@ -209,105 +90,57 @@ Does a water warp on the pre-fragmented glpoly_t chain */ void EmitWaterPolys (msurface_t *fa, float basealpha) { - glpoly_t *p; - float *v; - int i; - float s, t, os, ot; - -#ifdef WATERLAYERS + float a; + int l; extern cvar_t r_waterlayers; + //the code prior to april 2005 gave a nicer result, but was incompatable with meshes and required poly lists instead + //the new code uses vertex arrays but sacrifises the warping. We're left only with scaling. + //The default settings still look nicer than origional quake but not pre-april. + //in the plus side, you can never see the junction glitches of the old warping. :) - - if (gl_waterripples.value) +#ifdef Q3SHADERS + if (fa->texinfo->texture->shader) { - float f = 10; - - qglEnable(GL_AUTO_NORMAL); - for (p=fa->polys ; p ; p=p->next) - { - qglBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - os = v[3]; - ot = v[4]; - - s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; - s *= (1.0/64); - - t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; - t *= (1.0/64); - - qglNormal3f(fa->plane->normal[0] + (sin(realtime+v[0]/f+v[1]/f))/4, fa->plane->normal[1] +(sin(realtime-v[1]/f))/4, fa->plane->normal[2] + (sin(realtime+v[2]/f))/4); - qglTexCoord2f (s, t); - qglVertex3fv (v); - } - qglEnd (); - } - qglDisable(GL_AUTO_NORMAL); + meshbuffer_t mb; + mb.sortkey = 0; + mb.infokey = 0; + mb.dlightbits = 0; + mb.entity = &r_worldentity; + mb.shader = fa->texinfo->texture->shader; + mb.fog = NULL; + mb.mesh = fa->mesh; + R_RenderMeshBuffer(&mb, false); + return; } - else if (r_waterlayers.value>=1) +#endif + if (r_waterlayers.value>=1) { - float a, stm, ttm; - int l; - qglDisable(GL_ALPHA_TEST); qglEnable(GL_BLEND); //to ensure. + qglMatrixMode(GL_TEXTURE); + fa->mesh->colors_array=NULL; for (a=basealpha,l = 0; l < r_waterlayers.value; l++,a=a*4/6) { + qglPushMatrix(); qglColor4f(1, 1, 1, a); - stm =cos(l)/10; - ttm =sin(l)/10; - for (p=fa->polys ; p ; p=p->next) - { - qglBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - os = v[3]/(l*0.5+0.2); - ot = v[4]/(l*0.5+0.2); - - s = os + turbsin[(int)((ot*0.125+cl.time+l*8) * TURBSCALE) & 255];//*r_watersurfacewarp.value; - s *= (1.0/64); - - t = ot + turbsin[(int)((os*0.125+cl.time+l*8) * TURBSCALE) & 255];//*r_watersurfacewarp.value; - t *= (1.0/64); - - qglTexCoord2f (s+cl.time*stm, t+cl.time*ttm); - qglVertex3fv (v); - } - qglEnd (); - } + qglTranslatef (sin(cl.time+l*4) * 0.04f+cos(cl.time/2+l)*0.02f+cl.time/(64+l*8), cos(cl.time+l*4) * 0.06f+sin(cl.time/2+l)*0.02f+cl.time/(16+l*2), 0); + GL_DrawAliasMesh(fa->mesh, fa->texinfo->texture->gl_texturenum); + qglPopMatrix(); } - + qglMatrixMode(GL_MODELVIEW); + qglDisable(GL_BLEND); //to ensure. } - else + else //dull (fast) single player { -#endif - for (p=fa->polys ; p ; p=p->next) - { - qglBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - os = v[3]; - ot = v[4]; - - s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; - s *= (1.0/64); - - t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; - t *= (1.0/64); - - qglTexCoord2f (s, t); - qglVertex3fv (v); - } - qglEnd (); - } -#ifdef WATERLAYERS + qglColor4f(1, 1, 1, 1); + qglMatrixMode(GL_TEXTURE); + qglPushMatrix(); + qglTranslatef (sin(cl.time) * 0.4f, cos(cl.time) * 0.06f, 0); + GL_DrawAliasMesh(fa->mesh, fa->texinfo->texture->gl_texturenum); + qglPopMatrix(); + qglMatrixMode(GL_MODELVIEW); } -#endif } - - - /* ============= EmitSkyPolys @@ -315,49 +148,7 @@ EmitSkyPolys */ void EmitSkyPolys (msurface_t *fa) { - glpoly_t *p; - float *v; - int i; - float s, t; - vec3_t dir; - float length; - if (fa->mesh) - { - extern void GL_DrawAliasMesh (mesh_t *mesh, int texnum); - - fa->mesh->colors_array = NULL; - qglDisable(GL_TEXTURE_2D); - qglColor3f(0,0,0); - GL_DrawAliasMesh(fa->mesh, 1); - qglEnable(GL_TEXTURE_2D); - } - else - { - for (p=fa->polys ; p ; p=p->next) - { - qglBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - VectorSubtract (v, r_origin, dir); - dir[2] *= 3; // flatten the sphere - - length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; - length = sqrt (length); - length = 6*63/length; - - dir[0] *= length; - dir[1] *= length; - - s = (speedscale + dir[0]) * (1.0/128); - t = (speedscale + dir[1]) * (1.0/128); - - qglTexCoord2f (s, t); - qglVertex3fv (v); - } - qglEnd (); - } - } } /* @@ -413,8 +204,13 @@ void R_DrawSkyChain (msurface_t *s) pal = host_basepal+fc*3; qglDisable(GL_TEXTURE_2D); qglColor3f(pal[0]/255.0f, pal[1]/255.0f, pal[2]/255.0f); + qglDisableClientState( GL_COLOR_ARRAY ); for (fa=s ; fa ; fa=fa->texturechain) - EmitSkyPolys (fa); + { + qglVertexPointer(3, GL_FLOAT, 16, fa->mesh->xyz_array); + qglDrawElements(GL_TRIANGLES, fa->mesh->numindexes, GL_UNSIGNED_INT, fa->mesh->indexes); + } + R_IBrokeTheArrays(); qglColor3f(1, 1, 1); qglEnable(GL_TEXTURE_2D); @@ -426,6 +222,11 @@ void R_DrawSkyChain (msurface_t *s) R_DrawSkyBoxChain(s); return; } +// if (usingskydome) + { + R_DrawSkySphere(s); + return; + } // used when gl_texsort is on GL_Bind(solidskytexture); @@ -469,19 +270,43 @@ int skyboxtex[6]; void R_LoadSkys (void) { int i; - char name[64]; + char name[MAX_QPATH]; + char *boxname; - for (i=0 ; i<6 ; i++) - { - sprintf (name, "env/%s%s.tga", gl_skyboxname.string, suf[i]); + if (*gl_skyboxname.string) + boxname = gl_skyboxname.string; //user forced + else + boxname = defaultskybox; - skyboxtex[i] = Mod_LoadHiResTexture(name, false, false, true); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (!*boxname) + { //wipe the box + for (i=0 ; i<6 ; i++) + skyboxtex[i] = 0; } - Q_strncpyz(loadedskybox, gl_skyboxname.string, sizeof(loadedskybox)); - gl_skyboxname.modified = false; + else + { + for(;;) + { + for (i=0 ; i<6 ; i++) + { + _snprintf (name, sizeof(name), "env/%s%s.tga", boxname, suf[i]); + + skyboxtex[i] = Mod_LoadHiResTexture(name, false, false, true); + if (!skyboxtex[i]) + break; + + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + if (boxname != defaultskybox && i < 6) + { + boxname = defaultskybox; + continue; + } + break; + } + } + reloadskybox = false; } @@ -489,10 +314,13 @@ qboolean GLR_CheckSky() { return true; } -void GLR_SetSky(char *name, float rotate, vec3_t axis) +void GLR_SetSky(char *name, float rotate, vec3_t axis) //called from the client code, once per level { - if (*name) - Cvar_Set(&gl_skyboxname, name); + Q_strncpyz(defaultskybox, name, sizeof(defaultskybox)); + if (!*gl_skyboxname.string) //don't override a user's settings + { + reloadskybox = true; + } } vec3_t skyclip[6] = { @@ -548,16 +376,7 @@ void DrawSkyPolygon (int nump, vec3_t vecs) float *vp; c_sky++; -#if 0 -glBegin (GL_POLYGON); -for (i=0 ; itexturechain) { - if (fa->mesh) + //triangulate + for (i=2 ; imesh->numvertexes ; i++) { - //triangulate - for (i=2 ; imesh->numvertexes ; i++) - { - VectorSubtract (fa->mesh->xyz_array[0], r_origin, verts[0]); - VectorSubtract (fa->mesh->xyz_array[i-1], r_origin, verts[1]); - VectorSubtract (fa->mesh->xyz_array[i], r_origin, verts[2]); - ClipSkyPolygon (3, verts[0], 0); - } - } - else - { - for (p=fa->polys ; p ; p=p->next) - { - for (i=0 ; inumverts ; i++) - { - VectorSubtract (p->verts[i], r_origin, verts[i]); - } - ClipSkyPolygon (p->numverts, verts[0], 0); - } + VectorSubtract (fa->mesh->xyz_array[0], r_origin, verts[0]); + VectorSubtract (fa->mesh->xyz_array[i-1], r_origin, verts[1]); + VectorSubtract (fa->mesh->xyz_array[i], r_origin, verts[2]); + ClipSkyPolygon (3, verts[0], 0); } } R_DrawSkyBox (s); - - qglColorMask(0, 0, 0, 0); - for (fa=s ; fa ; fa=fa->texturechain) - { - if (fa->mesh) - GL_DrawAliasMesh(fa->mesh, 1); - else - { - for (p=fa->polys ; p ; p=p->next) - { - qglBegin(GL_POLYGON); - for (i = 0; i < p->numverts; i++) - qglVertex3fv(p->verts[i]); - qglEnd(); - } - } - } - qglColorMask(1, 1, 1, 1); } -void R_AddSkySurface (msurface_t *fa) +#define skygridx 32 +#define skygridx1 (skygridx + 1) +#define skygridxrecip (1.0f / (skygridx)) +#define skygridy 32 +#define skygridy1 (skygridy + 1) +#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_texcoord2f[skysphere_numverts * 2]; +static int skysphere_element3i[skysphere_numtriangles * 3]; +mesh_t skymesh; + +int skymade; + +static void skyspherecalc(int skytype) +{ //yes, this is basically stolen from DarkPlaces + int i, j, *e; + float a, b, x, ax, ay, v[3], length, *vertex3f, *texcoord2f; + float dx, dy, dz; + + float texscale; + + if (skymade == skytype) + return; + + skymade = skytype; + + if (skymade == 2) + texscale = 1/16.0f; + else + texscale = 1/1.5f; + + texscale*=3; + + skymesh.indexes = skysphere_element3i; + skymesh.st_array = (void*)skysphere_texcoord2f; + skymesh.lmst_array = (void*)skysphere_texcoord2f; + skymesh.xyz_array = (void*)skysphere_vertex4f; + + skymesh.numindexes = skysphere_numtriangles * 3; + skymesh.numvertexes = skysphere_numverts; + + dx = 16; + dy = 16; + dz = 16 / 3; + vertex3f = skysphere_vertex4f; + texcoord2f = skysphere_texcoord2f; + for (j = 0;j <= skygridy;j++) + { + a = j * skygridyrecip; + ax = cos(a * M_PI * 2); + ay = -sin(a * M_PI * 2); + for (i = 0;i <= skygridx;i++) + { + b = i * skygridxrecip; + x = cos((b + 0.5) * M_PI); + v[0] = ax*x * dx; + v[1] = ay*x * dy; + v[2] = -sin((b + 0.5) * M_PI) * dz; + length = texscale / sqrt(v[0]*v[0]+v[1]*v[1]+(v[2]*v[2]*9)); + *texcoord2f++ = v[0] * length; + *texcoord2f++ = v[1] * length; + *vertex3f++ = v[0]; + *vertex3f++ = v[1]; + *vertex3f++ = v[2]; + vertex3f++; + } + } + e = skysphere_element3i; + for (j = 0;j < skygridy;j++) + { + for (i = 0;i < skygridx;i++) + { + *e++ = j * skygridx1 + i; + *e++ = j * skygridx1 + i + 1; + *e++ = (j + 1) * skygridx1 + i; + + *e++ = j * skygridx1 + i + 1; + *e++ = (j + 1) * skygridx1 + i + 1; + *e++ = (j + 1) * skygridx1 + i; + } + } +} +void R_DrawSkySphere (msurface_t *fa) { - int i; - vec3_t verts[MAX_CLIP_VERTS]; - glpoly_t *p; + extern cvar_t gl_maxdist; + float time = cl.gametime+realtime-cl.gametimemark; - // calculate vertex values for sky box - for (p=fa->polys ; p ; p=p->next) - { - for (i=0 ; inumverts ; i++) + float skydist = gl_maxdist.value; + if (skydist<1) + skydist=gl_skyboxdist.value; + skydist/=16; + + //scale sky sphere and place around view origin. + qglPushMatrix(); + qglTranslatef(r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2]); + qglScalef(skydist, skydist, skydist); + +//draw in bulk? this is eeevil +//FIXME: We should use the skybox clipping code and split the sphere into 6 sides. +#ifdef Q3SHADERS + if (fa->texinfo->texture->shader) + { //the shader route. + meshbuffer_t mb; + skyspherecalc(2); + mb.sortkey = 0; + mb.infokey = -1; + mb.dlightbits = 0; + mb.entity = &r_worldentity; + mb.shader = fa->texinfo->texture->shader; + mb.fog = NULL; + mb.mesh = &skymesh; + R_PushMesh(mb.mesh, mb.shader->features); + R_RenderMeshBuffer(&mb, false); + } + else +#endif + { //the boring route. + skyspherecalc(1); + qglMatrixMode(GL_TEXTURE); + qglPushMatrix(); + qglTranslatef(time*8/128, time*8/128, 0); + GL_DrawAliasMesh(&skymesh, solidskytexture); + qglColor4f(1,1,1,0.5); + qglEnable(GL_BLEND); + qglTranslatef(time*8/128, time*8/128, 0); + GL_DrawAliasMesh(&skymesh, alphaskytexture); + qglDisable(GL_BLEND); + qglPopMatrix(); + qglMatrixMode(GL_MODELVIEW); + } + qglPopMatrix(); + + if (!cls.allow_skyboxes) //allow a little extra fps. + {//Draw the texture chain to only the depth buffer. + qglColorMask(0,0,0,0); + for (; fa; fa = fa->texturechain) { - VectorSubtract (p->verts[i], r_origin, verts[i]); + GL_DrawAliasMesh(fa->mesh, 0); } - ClipSkyPolygon (p->numverts, verts[0], 0); + qglColorMask(1,1,1,1); } } - /* ============== R_ClearSkyBox @@ -813,6 +725,12 @@ void R_ClearSkyBox (void) return; } if (gl_skyboxname.modified) + { + gl_skyboxname.modified = false; + reloadskybox = true; + } + + if (reloadskybox) R_LoadSkys(); if (!skyboxtex[0] || !skyboxtex[1] || !skyboxtex[2] || !skyboxtex[3] || !skyboxtex[4] || !skyboxtex[5]) @@ -881,18 +799,11 @@ int skytexorder[6] = {0,2,1,3,4,5}; void R_DrawSkyBox (msurface_t *s) { msurface_t *fa; - glpoly_t *poly; int i; if (!usingskybox) return; -#if 0 -qglEnable (GL_BLEND); -qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -qglColor4f (1,1,1,0.5); -qglDisable (GL_DEPTH_TEST); -#endif for (i=0 ; i<6 ; i++) { if (skymins[0][i] >= skymaxs[0][i] @@ -900,12 +811,7 @@ qglDisable (GL_DEPTH_TEST); continue; GL_Bind (skyboxtex[skytexorder[i]]); -#if 0 -skymins[0][i] = -1; -skymins[1][i] = -1; -skymaxs[0][i] = 1; -skymaxs[1][i] = 1; -#endif + qglBegin (GL_QUADS); MakeSkyVec (skymins[0][i], skymins[1][i], i); MakeSkyVec (skymins[0][i], skymaxs[1][i], i); @@ -913,31 +819,14 @@ skymaxs[1][i] = 1; MakeSkyVec (skymaxs[0][i], skymins[1][i], i); qglEnd (); } -#if 0 -qglDisable (GL_BLEND); -qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -qglColor4f (1,1,1,0.5); -qglEnable (GL_DEPTH_TEST); -#endif if (!cls.allow_skyboxes && s) //allow a little extra fps. { + //write the depth correctly qglColorMask(0, 0, 0, 0); //depth only. for (fa = s; fa; fa = fa->texturechain) - { - if (fa->mesh) - GL_DrawAliasMesh(fa->mesh, 1); - else - { - for (poly = fa->polys; poly; poly = poly->next) - { - qglBegin (GL_POLYGON); - for (i = 0; i < poly->numverts; i++) - qglVertex3fv (&poly->verts[0][0]+i*VERTEXSIZE); - qglEnd (); - } - } - } + GL_DrawAliasMesh(fa->mesh, 1); + qglColorMask(1, 1, 1, 1); } } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 2f4298597..54017c4e8 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -54,7 +54,7 @@ void GLR_DrawAlphaSurfaces (void); void GL_FlushSkinCache(void); void GL_GAliasFlushSkinCache(void); -void PPL_LoadSpecularFragmentProgram(void); +void PPL_CreateShaderObjects(void); void PPL_BaseBModelTextures(entity_t *e); #ifdef RUNTIMELIGHTING @@ -719,24 +719,25 @@ extern PFNGLBINDPROGRAMARBPROC qglBindProgramARB; extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB; //glslang - arb_shader_objects -extern PFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; -extern PFNGLDELETEOBJECTARBPROC qglDeleteObjectARB; -extern PFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; -extern PFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; -extern PFNGLSHADERSOURCEARBPROC qglShaderSourceARB; -extern PFNGLCOMPILESHADERARBPROC qglCompileShaderARB; -extern PFNGLGETOBJECTPARAMETERIVARBPROC qglGetObjectParameterivARB; -extern PFNGLATTACHOBJECTARBPROC qglAttachObjectARB; -extern PFNGLGETINFOLOGARBPROC qglGetInfoLogARB; -extern PFNGLLINKPROGRAMARBPROC qglLinkProgramARB; -extern PFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; -extern PFNGLUNIFORM4FARBPROC qglUniform4fARB; -extern PFNGLUNIFORM1IARBPROC qglUniform1iARB; -extern PFNGLUNIFORM1FARBPROC qglUniform1fARB; +extern PFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; +extern PFNGLDELETEOBJECTARBPROC qglDeleteObjectARB; +extern PFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; +extern PFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; +extern PFNGLSHADERSOURCEARBPROC qglShaderSourceARB; +extern PFNGLCOMPILESHADERARBPROC qglCompileShaderARB; +extern PFNGLGETOBJECTPARAMETERIVARBPROC qglGetObjectParameterivARB; +extern PFNGLATTACHOBJECTARBPROC qglAttachObjectARB; +extern PFNGLGETINFOLOGARBPROC qglGetInfoLogARB; +extern PFNGLLINKPROGRAMARBPROC qglLinkProgramARB; +extern PFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; +extern PFNGLUNIFORM4FARBPROC qglUniform4fARB; +extern PFNGLUNIFORM3FARBPROC qglUniform3fARB; +extern PFNGLUNIFORM3FVARBPROC qglUniform3fvARB; +extern PFNGLUNIFORM1IARBPROC qglUniform1iARB; +extern PFNGLUNIFORM1FARBPROC qglUniform1fARB; //glslang helper api -GLhandleARB GLSlang_CreateShader (char *shadersource, int shadertype); -GLhandleARB GLSlang_CreateProgram (GLhandleARB vert, GLhandleARB frag); +GLhandleARB GLSlang_CreateProgram (char *precompilerconstants, char *vert, char *frag); GLint GLSlang_GetUniformLocation (int prog, char *name); #define GLSlang_UseProgram(prog) qglUseProgramObjectARB(prog); #define GLSlang_SetUniform1i(uni, parm0) qglUniform1iARB(uni, parm0); diff --git a/engine/gl/model_hl.h b/engine/gl/model_hl.h index d5a57149c..5d19389b7 100644 --- a/engine/gl/model_hl.h +++ b/engine/gl/model_hl.h @@ -206,7 +206,7 @@ typedef struct int sequence; int frame; /* Current animation sequence and frame */ float frametime; /* Time of last frame drawn */ - qbyte controller[4]; /* Position of bone controllers */ + float controller[4]; /* Position of bone controllers */ vec4_t adjust; /* Static pointers */ diff --git a/engine/gl/shader.h b/engine/gl/shader.h index bc67c875c..4125a45dc 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -176,6 +176,14 @@ typedef struct shaderpass_s { } flags; } shaderpass_t; +typedef struct +{ + mesh_t meshes[5]; + + int farbox_textures[6]; + int nearbox_textures[6]; +} skydome_t; + typedef struct shader_s { int numpasses; //careful... 0 means it's not loaded... and not actually a proper shader. struct shader_s *next; @@ -209,6 +217,8 @@ typedef struct shader_s { shadersort_t sort; + skydome_t *skydome; + meshfeatures_t features; int registration_sequence; @@ -217,11 +227,6 @@ typedef struct shader_s { -void GLR_MeshInit(void); -void GL_DrawMesh(mesh_t *mesh, shader_t *shader, int texturenum, int lmtexturenum); -void GL_DrawMeshBump(mesh_t *mesh, int texturenum, int lmtexturenum, int bumpnum, int deluxnum); - - void R_RenderMeshGeneric ( meshbuffer_t *mb, shaderpass_t *pass ); void R_RenderMeshCombined ( meshbuffer_t *mb, shaderpass_t *pass ); void R_RenderMeshMultitextured ( meshbuffer_t *mb, shaderpass_t *pass ); diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index d0d243f29..48a2a4029 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -466,6 +466,7 @@ qboolean HTTP_CL_Get(char *url, char *localfile) httpcl = con; + HTTP_CL_Think(); return true; } diff --git a/engine/http/iwebiface.c b/engine/http/iwebiface.c index 69e825f6a..fb1c660ac 100644 --- a/engine/http/iwebiface.c +++ b/engine/http/iwebiface.c @@ -68,8 +68,6 @@ int main(int argc, char **argv) { FTP_ServerRun(1); HTTP_ServerPoll(1); -// SV_POP3(1); -// SV_SMTP(1); Sleep(1); } } @@ -312,8 +310,6 @@ IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb"); #ifndef CLIENTONLY cvar_t ftpserver = {"sv_ftp", "0"}; cvar_t httpserver = {"sv_http", "0"}; -cvar_t pop3server = {"sv_pop3", "0"}; -cvar_t smtpserver = {"sv_smtp", "0"}; cvar_t sv_readlevel = {"sv_readlevel", "0"}; //default to allow anyone cvar_t sv_writelevel = {"sv_writelevel", "35"}; //allowed to write to uploads/uname cvar_t sv_fulllevel = {"sv_fulllevel", "51"}; //allowed to write anywhere, replace any file... @@ -368,11 +364,6 @@ void IWebInit(void) Cvar_Register(&ftpserver, "Internet Server Access"); Cvar_Register(&httpserver, "Internet Server Access"); #endif - -#ifdef EMAILSERVER - Cvar_Register(&pop3server, "Internet Server Access"); - Cvar_Register(&smtpserver, "Internet Server Access"); -#endif } void IWebRun(void) { @@ -380,10 +371,6 @@ void IWebRun(void) FTP_ServerRun(ftpserver.value!= 0); HTTP_ServerPoll(httpserver.value!=0); #endif -#ifdef EMAILSERVER - SV_POP3(pop3server.value!=0); - SV_SMTP(smtpserver.value!=0); -#endif } void IWebShutdown(void) { diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 6925d3c67..53e784d3b 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -704,6 +704,7 @@ enum { #define FLAG_ASDEFAULT 2 #define FLAG_SETINGUI 4 #define FLAG_HIDDENINGUI 8 +#define FLAG_MIDCOMPILE 16 //option can be changed mid-compile with the special pragma typedef struct { pbool *enabled; char *abbrev; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 0d242622f..fc4d5bfa2 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -4492,6 +4492,29 @@ void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname) num_gotos++; } +pbool QCC_PR_StatementBlocksMatch(QCC_dstatement_t *p1, int p1count, QCC_dstatement_t *p2, int p2count) +{ + if (p1count != p2count) + return false; + + while(p1count>0) + { + if (p1->op != p2->op) + return false; + if (p1->a != p2->a) + return false; + if (p1->b != p2->b) + return false; + if (p1->c != p2->c) + return false; + p1++; + p2++; + p1count--; + } + + return true; +} + /* ============ PR_ParseStatement @@ -4870,7 +4893,7 @@ void QCC_PR_ParseStatement (void) int lastwasreturn; lastwasreturn = statements[numstatements-1].op == OP_RETURN || statements[numstatements-1].op == OP_DONE; - //nothing jumped to it, so it's not a problem! + //the last statement of the if was a return, so we don't need the goto at the end if (lastwasreturn && opt_compound_jumps && !QCC_AStatementJumpsTo(numstatements, patch1-statements, numstatements)) { // QCC_PR_ParseWarning(0, "optimised the else"); @@ -4885,6 +4908,9 @@ void QCC_PR_ParseStatement (void) patch1->b = &statements[numstatements] - patch1; QCC_PR_ParseStatement (); patch2->a = &statements[numstatements] - patch2; + + if (QCC_PR_StatementBlocksMatch(patch1+1, patch2-patch1, patch2+1, &statements[numstatements] - patch2)) + QCC_PR_ParseWarning(0, "Two identical blocks each side of an else"); } } else diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 5bcb64216..d61cb5af8 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -526,36 +526,44 @@ pbool QCC_PR_Precompiler(void) } else if (!strncmp(directive, "include", 7)) { + byte sm; + pr_file_p=directive+7; while(*pr_file_p <= ' ') pr_file_p++; - *msg = '\0'; + strncpy(msg, compilingfile, sizeof(msg)); + msg[sizeof(msg)-1] = '\0'; if (*pr_file_p == '\"') - { - pr_file_p++; - for (a=0;a<1023;a++) - { - if (*pr_file_p == '\"') - break; - msg[a] = *pr_file_p++; - } - msg[a] = '\0'; - } + sm = '\"'; else if (*pr_file_p == '<') - { - pr_file_p++; - for (a=0;a<1023;a++) - { - if (*pr_file_p == '>') - break; - msg[a] = *pr_file_p++; - } - msg[a] = '\0'; - } + sm = '>'; else + { QCC_PR_ParseError(0, "Not a string literal"); + sm = 0; + } + + //msg already contains the current file name + for (a = strlen(msg)-1; a > 0; a--) + { + if (msg[a] == '/' || msg[a] == '\\') //eeeevil windows. + { + a++; + break; + } + } + + pr_file_p++; + for (;a<1023;a++) + { + if (*pr_file_p == sm) + break; + msg[a] = *pr_file_p++; + } + msg[a] = '\0'; + printf("Including: %s\n", msg); QCC_Include(msg); @@ -709,6 +717,43 @@ pbool QCC_PR_Precompiler(void) strcpy(destfile, qcc_token); printf("Outputfile: %s\n", destfile); } + else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag")) + { + char *s; + int st; + s = QCC_COM_Parse(msg); + if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on")) + st = 0; + else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off")) + st = 1; + else + { + QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised"); + st = -1; + } + if (st < 0) + QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised"); + else + { + int f; + s = QCC_COM_Parse(s); + + for (f = 0; compiler_flag[f].enabled; f++) + { + if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token)) + { + if (compiler_flag[f].flags & FLAG_MIDCOMPILE) + *compiler_flag[f].enabled = st; + else + QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma"); + break; + } + } + if (!compiler_flag[f].enabled) + QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag not recognised"); + + } + } else if (!QC_strcasecmp(qcc_token, "warning")) { int st; @@ -721,7 +766,10 @@ pbool QCC_PR_Precompiler(void) else if (!stricmp(qcc_token, "toggle")) st = 2; else + { + QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning state not recognised"); st = -1; + } if (st>=0) { int wn; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 07d3c0c02..61e833c75 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -175,37 +175,39 @@ optimisations_t optimisations[] = {NULL} }; - +#define defaultkeyword FLAG_HIDDENINGUI|FLAG_ASDEFAULT|FLAG_MIDCOMPILE +#define nondefaultkeyword FLAG_HIDDENINGUI|0|FLAG_MIDCOMPILE +//global to store useage to, flags, codename, human-readable name, help text compiler_flag_t compiler_flag[] = { //keywords - {&keyword_asm, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "asm", "Keyword: asm", "Disables the 'asm' keyword."}, - {&keyword_break, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "break", "Keyword: break", "Disables the 'break' keyword."}, - {&keyword_case, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "case", "Keyword: case", "Disables the 'case' keyword."}, - {&keyword_class, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "class", "Keyword: class", "Disables the 'class' keyword."}, - {&keyword_const, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "const", "Keyword: const", "Disables the 'const' keyword."}, - {&keyword_continue, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "continue", "Keyword: continue", "Disables the 'continue' keyword."}, - {&keyword_default, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "default", "Keyword: default", "Disables the 'default' keyword."}, - {&keyword_entity, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "entity", "Keyword: entity", "Disables the 'entity' keyword."}, - {&keyword_enum, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "enum", "Keyword: enum", "Disables the 'enum' keyword."}, //kinda like in c, but typedef not supported. - {&keyword_enumflags, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "enumflags", "Keyword: enumflags", "Disables the 'enumflags' keyword."}, //like enum, but doubles instead of adds 1. - {&keyword_extern, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "extern", "Keyword: extern", "Disables the 'extern' keyword."}, //function is external, don't error or warn if the body was not found - {&keyword_float, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "float", "Keyword: float", "Disables the 'float' keyword."}, - {&keyword_for, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "for", "Keyword: for", "Disables the 'for' keyword."}, - {&keyword_goto, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "goto", "Keyword: goto", "Disables the 'goto' keyword."}, - {&keyword_int, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "int", "Keyword: int", "Disables the 'int' keyword."}, - {&keyword_integer, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "integer", "Keyword: integer", "Disables the 'integer' keyword."}, - {&keyword_noref, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't strip it. - {&keyword_nosave, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output. - {&keyword_shared, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "shared", "Keyword: shared", "Disables the 'shared' keyword."}, //mark global to be copied over when progs changes (part of FTE_MULTIPROGS) - {&keyword_state, FLAG_HIDDENINGUI|0, "state", "Keyword: state", "Disables the 'state' keyword."}, - {&keyword_string, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "string", "Keyword: string", "Disables the 'string' keyword."}, - {&keyword_struct, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "struct", "Keyword: struct", "Disables the 'struct' keyword."}, - {&keyword_switch, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "switch", "Keyword: switch", "Disables the 'switch' keyword."}, - {&keyword_thinktime, FLAG_HIDDENINGUI|0, "thinktime", "Keyword: thinktime", "Disables the 'thinktime' keyword."}, - {&keyword_typedef, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "typedef", "Keyword: typedef", "Disables the 'typedef' keyword."}, //fixme - {&keyword_union, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "union", "Keyword: union", "Disables the 'union' keyword."}, //you surly know what a union is! - {&keyword_var, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "var", "Keyword: var", "Disables the 'var' keyword."}, - {&keyword_vector, FLAG_HIDDENINGUI|FLAG_ASDEFAULT, "vector", "Keyword: vector", "Disables the 'vector' keyword."}, + {&keyword_asm, defaultkeyword, "asm", "Keyword: asm", "Disables the 'asm' keyword. Use the writeasm flag to see an example of the asm."}, + {&keyword_break, defaultkeyword, "break", "Keyword: break", "Disables the 'break' keyword."}, + {&keyword_case, defaultkeyword, "case", "Keyword: case", "Disables the 'case' keyword."}, + {&keyword_class, defaultkeyword, "class", "Keyword: class", "Disables the 'class' keyword."}, + {&keyword_const, defaultkeyword, "const", "Keyword: const", "Disables the 'const' keyword."}, + {&keyword_continue, defaultkeyword, "continue", "Keyword: continue", "Disables the 'continue' keyword."}, + {&keyword_default, defaultkeyword, "default", "Keyword: default", "Disables the 'default' keyword."}, + {&keyword_entity, defaultkeyword, "entity", "Keyword: entity", "Disables the 'entity' keyword."}, + {&keyword_enum, defaultkeyword, "enum", "Keyword: enum", "Disables the 'enum' keyword."}, //kinda like in c, but typedef not supported. + {&keyword_enumflags, defaultkeyword, "enumflags", "Keyword: enumflags", "Disables the 'enumflags' keyword."}, //like enum, but doubles instead of adds 1. + {&keyword_extern, defaultkeyword, "extern", "Keyword: extern", "Disables the 'extern' keyword. Use only on functions inside addons."}, //function is external, don't error or warn if the body was not found + {&keyword_float, defaultkeyword, "float", "Keyword: float", "Disables the 'float' keyword. (Disables the float keyword without 'local' preceeding it)"}, + {&keyword_for, defaultkeyword, "for", "Keyword: for", "Disables the 'for' keyword. Syntax: for(assignment; while; increment) {codeblock;}"}, + {&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."}, + {&keyword_int, defaultkeyword, "int", "Keyword: int", "Disables the 'int' keyword."}, + {&keyword_integer, defaultkeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."}, + {&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't strip it. + {&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output. + {&keyword_shared, defaultkeyword, "shared", "Keyword: shared", "Disables the 'shared' keyword."}, //mark global to be copied over when progs changes (part of FTE_MULTIPROGS) + {&keyword_state, nondefaultkeyword,"state", "Keyword: state", "Disables the 'state' keyword."}, + {&keyword_string, defaultkeyword, "string", "Keyword: string", "Disables the 'string' keyword."}, + {&keyword_struct, defaultkeyword, "struct", "Keyword: struct", "Disables the 'struct' keyword."}, + {&keyword_switch, defaultkeyword, "switch", "Keyword: switch", "Disables the 'switch' keyword."}, + {&keyword_thinktime, nondefaultkeyword,"thinktime", "Keyword: thinktime", "Disables the 'thinktime' keyword which is used in HexenC"}, + {&keyword_typedef, defaultkeyword, "typedef", "Keyword: typedef", "Disables the 'typedef' keyword."}, //fixme + {&keyword_union, defaultkeyword, "union", "Keyword: union", "Disables the 'union' keyword."}, //you surly know what a union is! + {&keyword_var, defaultkeyword, "var", "Keyword: var", "Disables the 'var' keyword."}, + {&keyword_vector, defaultkeyword, "vector", "Keyword: vector", "Disables the 'vector' keyword."}, //options @@ -213,10 +215,10 @@ compiler_flag_t compiler_flag[] = { {&output_parms, 0, "parms", "Define offset parms", "if PARM0 PARM1 etc should be defined by the compiler. These are useful if you make use of the asm keyword for function calls, or you wish to create your own variable arguments. This is an easy way to break decompilers."}, //controls weather to define PARMx for the parms (note - this can screw over some decompilers) {&autoprototype, 0, "autoproto", "Automatic Prototyping","Causes compilation to take two passes instead of one. The first pass, only the definitions are read. The second pass actually compiles your code. This means you never have to remember to prototype functions again."}, //so you no longer need to prototype functions and things in advance. {&writeasm, 0, "wasm", "Dump Assembler", "Writes out a qc.asm which contains all your functions but in assembler. This is a great way to look for bugs in fteqcc, but can also be used to see exactly what your functions turn into, and thus how to optimise statements better."}, //spit out a qc.asm file, containing an assembler dump of the ENTIRE progs. (Doesn't include initialisation of constants) - {&flag_ifstring, 0, "ifstring", "if(string) fix", "Causes if(string) to behave identically to if(string!="") This is most useful with addons of course, but also has adverse effects with FRIK_FILE's fgets, where it becomes impossible to determin the end of the file. In such a case, you can still use asm {IF string 2;RETURN} to detect eof and leave the function."}, //correction for if(string) no-ifstring to get the standard behaviour. + {&flag_ifstring, FLAG_MIDCOMPILE,"ifstring", "if(string) fix", "Causes if(string) to behave identically to if(string!="") This is most useful with addons of course, but also has adverse effects with FRIK_FILE's fgets, where it becomes impossible to determin the end of the file. In such a case, you can still use asm {IF string 2;RETURN} to detect eof and leave the function."}, //correction for if(string) no-ifstring to get the standard behaviour. {&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows ¦ as EOF. Whilst case insensativity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files. {&flag_caseinsensative, 0, "caseinsens", "Case insensativity", "Causes fteqcc to become case insensative whilst compiling names. It's generally not advised to use this as it compiles a little more slowly and provides little benefit. However, it is required for full reacc support."}, //symbols will be matched to an insensative case if the specified case doesn't exist. This should b usable for any mod - {&flag_laxcasts, 0, "lax", "Lax type checks", "Disables many errors (generating warnings instead) when function calls or operations refer to two normally incompatable types. This is required for reacc support, and can also allow certain (evil) mods to compile that were origionally written for frikqcc."}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code. + {&flag_laxcasts, FLAG_MIDCOMPILE,"lax", "Lax type checks", "Disables many errors (generating warnings instead) when function calls or operations refer to two normally incompatable types. This is required for reacc support, and can also allow certain (evil) mods to compile that were origionally written for frikqcc."}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code. {&opt_logicops, 0, "lo", "Logic ops", "This changes the behaviour of your code. It generates additional if operations to early-out in if statements. With this flag, the line if (0 && somefunction()) will never call the function. It can thus be considered an optimisation. However, due to the change of behaviour, it is not considered so by fteqcc. Note that due to inprecisions with floats, this flag can cause runaway loop errors within the player walk and run functions. This code is advised:\nplayer_stand1:\n if (self.velocity_x || self.velocity_y)\nplayer_run\n if (!(self.velocity_x || self.velocity_y))"}, {NULL} }; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index f198e0cc0..d8f8f7fe1 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -62,6 +62,7 @@ evalc_t evalc_idealpitch, evalc_pitch_speed; int pr_teamfield; void PR_ClearThreads(void); +void PR_fclose_progs(progfuncs_t*); typedef struct { @@ -374,6 +375,7 @@ void Q_SetProgsParms(qboolean forcompiler) PR_RegisterSVBuiltins(); } PR_ClearThreads(); + PR_fclose_progs(svprogfuncs); // svs.numprogs = 0; @@ -382,6 +384,7 @@ void Q_SetProgsParms(qboolean forcompiler) void PR_Deinit(void) { PR_ClearThreads(); + PR_fclose_progs(svprogfuncs); if (svprogfuncs) CloseProgs(svprogfuncs); svprogfuncs=NULL; @@ -1809,6 +1812,7 @@ void PF_setmodel (progfuncs_t *prinst, struct globalvars_s *pr_globals) mod = sv.models[i]; if (mod) { + mod = Mod_ForName (m, false); VectorCopy (mod->mins, e->v->mins); VectorCopy (mod->maxs, e->v->maxs); VectorSubtract (mod->maxs, mod->mins, e->v->size); @@ -1834,7 +1838,7 @@ void PF_setmodel (progfuncs_t *prinst, struct globalvars_s *pr_globals) { if (sv.models[i]) { - mod = Mod_ForName (m, true); + mod = Mod_ForName (m, false); VectorCopy (mod->mins, e->v->mins); VectorCopy (mod->maxs, e->v->maxs); VectorSubtract (mod->maxs, mod->mins, e->v->size); @@ -1933,6 +1937,24 @@ void PF_sprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) SV_ClientPrintf (client, level, "%s", s); } +//When a client is backbuffered, it's generally not a brilliant plan to send a bazillion stuffcmds. You have been warned. +//This handy function will let the mod know when it shouldn't send more. (use instead of a timer, and you'll never get clients overflowing. yay.) +void PF_isbackbuffered (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int entnum; + client_t *client; + + entnum = G_EDICTNUM(prinst, OFS_PARM0); + if (entnum < 1 || entnum > sv.allocated_client_slots) + { + Con_Printf ("PF_isbackbuffered: Not a client\n"); + return; + } + client = &svs.clients[entnum-1]; + + G_FLOAT(OFS_RETURN) = client->num_backbuf>0; +} + /* ================= @@ -5158,8 +5180,9 @@ void PF_strstrofs (progfuncs_t *prinst, struct globalvars_s *pr_globals) else G_FLOAT(OFS_RETURN) = match - instr; } -//FTE_STRINGS +//FTE_STRINGS +//returns characture at position X void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *instr = PR_GetStringOfs(prinst, OFS_PARM0); @@ -5173,6 +5196,9 @@ void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals) else G_FLOAT(OFS_RETURN) = instr[ofs]; } + +//FTE_STRINGS +//returns a string containing one characture per parameter (up to the qc max params of 8). void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i; @@ -5255,6 +5281,8 @@ static int chrchar_alpha(int i, int basec, int baset, int convc, int convt) } return i + basec + baset; } +//FTE_STRINGS +//bulk convert a string. change case or colouring. void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper @@ -5300,6 +5328,39 @@ void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) *result = '\0'; } +//FTE_STRINGS +//C style strncmp (compare first n charactures - case sensative. Note that there is no strcmp provided) +void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + float len = G_FLOAT(OFS_PARM2); + + G_FLOAT(OFS_RETURN) = strncmp(a, b, len); +} + +//FTE_STRINGS +//C style strcasecmp (case insensative string compare) +void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + + G_FLOAT(OFS_RETURN) = stricmp(a, b); +} + +//FTE_STRINGS +//C style strncasecmp (compare first n charactures - case insensative) +void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + float len = G_FLOAT(OFS_PARM2); + + G_FLOAT(OFS_RETURN) = strnicmp(a, b, len); +} + +//uses qw style \key\value strings void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *info = PR_GetStringOfs(prinst, OFS_PARM0); @@ -5314,6 +5375,8 @@ void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_SSTRING(temp); } + +//uses qw style \key\value strings void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *info = PR_GetStringOfs(prinst, OFS_PARM0); @@ -5326,31 +5389,6 @@ void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) strcpy(temp, key); RETURN_SSTRING(temp); } -void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); - - G_FLOAT(OFS_RETURN) = strncmp(a, b, len); -} -void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - - G_FLOAT(OFS_RETURN) = stricmp(a, b); -} -void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); - - G_FLOAT(OFS_RETURN) = strnicmp(a, b, len); -} - - //back to frik_file support. @@ -5582,9 +5620,195 @@ void PF_fcloseall (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } -void PF_fclose_progs (progfuncs_t *prinst) + + +typedef struct prvmsearch_s { + int handle; + progfuncs_t *fromprogs; //share across menu/server + int entries; + char **names; + int *sizes; + + struct prvmsearch_s *next; +} prvmsearch_t; +prvmsearch_t *prvmsearches; +int prvm_nextsearchhandle; + +void search_close (progfuncs_t *prinst, int handle) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + return; + } + + prev = s; + s = s->next; + } +} +//a progs was closed... hunt down it's searches, and warn about any searches left open. +void search_close_progs(progfuncs_t *prinst, qboolean complain) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->fromprogs == prinst) + { //close it down. + + if (complain) + Con_Printf("Warning: Progs search was still active\n"); + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + if (prev) + s = prev->next; + else + s = prvmsearches; + continue; + } + + prev = s; + s = s->next; + } + + if (!prvmsearches) + prvm_nextsearchhandle = 0; //might as well. +} + +int search_enumerate(char *name, int fsize, void *parm) +{ + prvmsearch_t *s = parm; + + s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); + s->sizes = BZ_Realloc(s->sizes, ((s->entries+64)&~63) * sizeof(int)); + s->names[s->entries] = BZ_Malloc(strlen(name)+1); + strcpy(s->names[s->entries], name); + s->sizes[s->entries] = fsize; + + s->entries++; + return true; +} + +//float search_begin(string pattern, float caseinsensitive, float quiet) = #74; +void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ //< 0 for error, > 0 for handle. + char *pattern = PR_GetStringOfs(prinst, OFS_PARM0); +// qboolean caseinsensative = G_FLOAT(OFS_PARM1); +// qboolean quiet = G_FLOAT(OFS_PARM2); + prvmsearch_t *s; + + s = BZ_Malloc(sizeof(*s)); + s->fromprogs = prinst; + s->handle = prvm_nextsearchhandle++; + + COM_EnumerateFiles(pattern, search_enumerate, s); + + if (s->entries==0) + { + BZ_Free(s); + G_FLOAT(OFS_RETURN) = -1; + return; + } + s->next = prvmsearches; + prvmsearches = s; + G_FLOAT(OFS_RETURN) = s->handle; +} +//void search_end(float handle) = #75; +void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + search_close(prinst, handle); +} +//float search_getsize(float handle) = #76; +void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + prvmsearch_t *s; + G_FLOAT(OFS_RETURN) = -1; + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + + G_FLOAT(OFS_RETURN) = s->entries; + return; + } + } +} +//string search_getfilename(float handle, float num) = #77; +void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + int num = G_FLOAT(OFS_PARM1); + prvmsearch_t *s; + G_INT(OFS_RETURN) = 0; + + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Search handle wasn't valid with that progs\n"); + return; + } + + if (num < 0 || num >= s->entries) + return; + G_INT(OFS_RETURN) = (int)(s->names[num] - prinst->stringtable); + return; + } + } + + Con_Printf("Search handle wasn't valid\n"); +} + +//closes filesystem type stuff for when a progs has stopped needing it. +void PR_fclose_progs (progfuncs_t *prinst) { PF_fcloseall(prinst, PR_globals(prinst, PR_CURRENT)); + search_close_progs(prinst, true); } @@ -5665,6 +5889,7 @@ lh_extension_t QSG_Extensions[] = { {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, {"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}}, {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, + {"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}}, #ifndef NOMEDIA {"FTE_MEDIA_AVI"}, //playfilm supports avi files. {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. @@ -5910,7 +6135,14 @@ void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv; { char *dest = PF_TempStr(); - strcpy(dest, Cmd_Argv(G_FLOAT(OFS_PARM0))); + int i = G_FLOAT(OFS_PARM0); + if (i < 0) + { + PR_BIError(prinst, "pr_argv with i < 0"); + G_INT(OFS_RETURN) = 0; + return; + } + strcpy(dest, Cmd_Argv(i)); RETURN_CSTRING(dest); } @@ -7345,20 +7577,88 @@ void PF_te_beam(progfuncs_t *prinst, struct globalvars_s *pr_globals) //DP_TE_SPARK void PF_te_spark(progfuncs_t *prinst, struct globalvars_s *pr_globals) { -#pragma message("PF_te_spark not implemented yet.") + float *org = G_VECTOR(OFS_PARM0); + + if (G_FLOAT(OFS_PARM2) < 1) + return; + + MSG_WriteByte(&sv.multicast, svc_temp_entity); + MSG_WriteByte(&sv.multicast, DPTE_SPARK); + // origin + MSG_WriteCoord(&sv.multicast, org[0]); + MSG_WriteCoord(&sv.multicast, org[1]); + MSG_WriteCoord(&sv.multicast, org[2]); + // velocity + MSG_WriteByte(&sv.multicast, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.multicast, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.multicast, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + // count + MSG_WriteByte(&sv.multicast, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); + +//the nq version +#ifdef NQPROT + MSG_WriteByte(&sv.nqmulticast, svc_temp_entity); + MSG_WriteByte(&sv.nqmulticast, DPTE_SPARK); + // origin + MSG_WriteCoord(&sv.nqmulticast, org[0]); + MSG_WriteCoord(&sv.nqmulticast, org[1]); + MSG_WriteCoord(&sv.nqmulticast, org[2]); + // velocity + MSG_WriteByte(&sv.nqmulticast, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.nqmulticast, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.nqmulticast, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + // count + MSG_WriteByte(&sv.nqmulticast, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); +#endif + SV_Multicast(org, MULTICAST_PVS); } // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) void PF_te_smallflash(progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *org = G_VECTOR(OFS_PARM0); - SV_point_tempentity(org, 72, 0); + SV_point_tempentity(org, DPTE_SMALLFLASH, 0); } // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) void PF_te_customflash(progfuncs_t *prinst, struct globalvars_s *pr_globals) { -#pragma message("PF_te_customflash not implemented yet.") + float *org = G_VECTOR(OFS_PARM0); + + if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0)) + return; + MSG_WriteByte(&sv.multicast, svc_temp_entity); + MSG_WriteByte(&sv.multicast, DPTE_CUSTOMFLASH); + // origin + MSG_WriteCoord(&sv.multicast, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteCoord(&sv.multicast, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteCoord(&sv.multicast, G_VECTOR(OFS_PARM0)[2]); + // radius + MSG_WriteByte(&sv.multicast, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255)); + // lifetime + MSG_WriteByte(&sv.multicast, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255)); + // color + MSG_WriteByte(&sv.multicast, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255)); + MSG_WriteByte(&sv.multicast, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255)); + MSG_WriteByte(&sv.multicast, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255)); + +#ifdef NQPROT + MSG_WriteByte(&sv.nqmulticast, svc_temp_entity); + MSG_WriteByte(&sv.nqmulticast, DPTE_CUSTOMFLASH); + // origin + MSG_WriteCoord(&sv.nqmulticast, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteCoord(&sv.nqmulticast, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteCoord(&sv.nqmulticast, G_VECTOR(OFS_PARM0)[2]); + // radius + MSG_WriteByte(&sv.nqmulticast, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255)); + // lifetime + MSG_WriteByte(&sv.nqmulticast, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255)); + // color + MSG_WriteByte(&sv.nqmulticast, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255)); + MSG_WriteByte(&sv.nqmulticast, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255)); + MSG_WriteByte(&sv.nqmulticast, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255)); +#endif + SV_Multicast(org, MULTICAST_PVS); } //#408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) @@ -7716,27 +8016,6 @@ void PF_ChangePic(progfuncs_t *prinst, struct globalvars_s *pr_globals) } } -//DP_QC_FS_SEARCH -void PF_Search_Begin(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_INT(OFS_RETURN) = 0; -} -void PF_Search_End(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_INT(OFS_RETURN) = 0; -} -void PF_Search_GetSize(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_INT(OFS_RETURN) = 0; -} -void PF_SearchGetFileName(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_INT(OFS_RETURN) = 0; -} - - - - @@ -8139,6 +8418,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"clientstat", PF_clientstat, 0, 0, 0, 232}, {"runclientphys", PF_runclientphys, 0, 0, 0, 233}, //END EXT_CSQC + {"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234}, //end fte extras @@ -8194,10 +8474,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"setattachment", PF_setattachment, 0, 0, 0, 443},// #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) - {"search_begin", PF_Search_Begin, 0, 0, 0, 444}, - {"search_end", PF_Search_End, 0, 0, 0, 445}, - {"search_getsize", PF_Search_GetSize, 0, 0, 0, 446}, - {"search_getfilename", PF_SearchGetFileName,0, 0, 0, 447}, + {"search_begin", PF_search_begin, 0, 0, 0, 444}, + {"search_end", PF_search_end, 0, 0, 0, 445}, + {"search_getsize", PF_search_getsize, 0, 0, 0, 446}, + {"search_getfilename", PF_search_getfilename,0, 0, 0, 447}, //DP_QC_CVAR_STRING {"dp_cvar_string", PF_cvar_string, 0, 0, 0, 448},// #448 string(float n) cvar_string diff --git a/engine/server/progs.h b/engine/server/progs.h index 7d630d659..7db817926 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -73,8 +73,6 @@ typedef struct edict_s //the rest is free for adaption link_t area; // linked to a division node or leaf - int solidtype; - int num_leafs; short leafnums[MAX_ENT_LEAFS]; int areanum; //q2bsp @@ -83,6 +81,8 @@ typedef struct edict_s entity_state_t baseline; + qbyte solidtype; //relinks entities if thier solidity changed + unsigned short tagent; unsigned short tagindex; diff --git a/engine/server/q2game.h b/engine/server/q2game.h index b75149d24..8ed11a9e6 100644 --- a/engine/server/q2game.h +++ b/engine/server/q2game.h @@ -36,8 +36,8 @@ extern float pm_stepheight; struct trace_s; struct q2trace_s; -struct pmove_s; -typedef struct pmove_s pmove_t; +struct q2pmove_s; +typedef struct q2pmove_s q2pmove_t; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 5dfecb498..643a6f5a5 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -356,7 +356,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) //FIXME: Add a developer mode to write the length of each entity. SZ_Write(msg, csqcmsgbuffer.data, csqcmsgbuffer.cursize); - Con_Printf("Sending update packet %i\n", ent->entnum); +// Con_Printf("Sending update packet %i\n", ent->entnum); } else if (sv.csqcentversion[ent->entnum]) { //Don't want to send. @@ -368,7 +368,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) mask = (unsigned)ent->entnum | 0x8000; MSG_WriteShort(msg, mask); - Con_Printf("Sending remove 2 packet\n"); +// Con_Printf("Sending remove 2 packet\n"); } client->csqcentversions[ent->entnum] = sv.csqcentversion[ent->entnum]; client->csqcentsequence[ent->entnum] = currentsequence; @@ -392,7 +392,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) MSG_WriteByte(msg, svc_csqcentities); } - Con_Printf("Sending remove packet %i\n", en); +// Con_Printf("Sending remove packet %i\n", en); mask = (unsigned)en | 0x8000; MSG_WriteShort(msg, mask); @@ -1450,7 +1450,7 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size if (progstype != PROG_QW) { - if (progstype == PROG_H2 && (int)ent->v->effects & EF_NODRAW && ent != clent) + if (progstype == PROG_H2 && (int)ent->v->effects & H2EF_NODRAW && ent != clent) continue; if ((int)ent->v->effects & EF_MUZZLEFLASH) @@ -1502,7 +1502,7 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size clst.velocity = vent->v->velocity; clst.effects = ent->v->effects; - if (((int)vent->v->effects & EF_NODRAW) && progstype == PROG_H2) + if (progstype == PROG_H2 && ((int)vent->v->effects & H2EF_NODRAW)) { clst.effects = 0; clst.modelindex = 0; @@ -2095,7 +2095,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore state->fatness = clent->v->fatness; #endif - if (state->effects & EF_FLAG1) + if (state->effects & QWEF_FLAG1) { memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); state = &pack->entities[pack->num_entities]; @@ -2105,7 +2105,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore state->number++; state->skinnum = 0; } - else if (state->effects & EF_FLAG2) + else if (state->effects & QWEF_FLAG2) { memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); state = &pack->entities[pack->num_entities]; @@ -2131,7 +2131,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (progstype != PROG_QW) { - if (progstype == PROG_H2 && (int)ent->v->effects & EF_NODRAW) + if (progstype == PROG_H2 && (int)ent->v->effects & H2EF_NODRAW) continue; if ((int)ent->v->effects & EF_MUZZLEFLASH) { diff --git a/engine/sw/d_polysa.s b/engine/sw/d_polysa.s index 6b395a886..319897936 100644 --- a/engine/sw/d_polysa.s +++ b/engine/sw/d_polysa.s @@ -479,8 +479,8 @@ C(D_PolysetCalcGradientsAsm): #define lp2 8+16 #define lp3 12+16 -.globl C(D_PolysetRecursiveTriangle) -C(D_PolysetRecursiveTriangle): +.globl C(D_PolysetRecursiveTriangleAsm) +C(D_PolysetRecursiveTriangleAsm): pushl %ebp // preserve caller stack frame pointer pushl %esi // preserve register variables pushl %edi @@ -713,18 +713,18 @@ LDraw: LNoDraw: //// recursively continue -// D_PolysetRecursiveTriangle (lp3, lp1, new); +// D_PolysetRecursiveTriangleAsm (lp3, lp1, new); pushl %esp pushl %ebx pushl %edi - call C(D_PolysetRecursiveTriangle) + call C(D_PolysetRecursiveTriangleAsm) -// D_PolysetRecursiveTriangle (lp3, new, lp2); +// D_PolysetRecursiveTriangleAsm (lp3, new, lp2); movl %esp,%ebx pushl %esi pushl %ebx pushl %edi - call C(D_PolysetRecursiveTriangle) + call C(D_PolysetRecursiveTriangleAsm) addl $24,%esp LDone: @@ -1188,7 +1188,7 @@ Llooptop: #ifdef ONSEAMSTUFF // if (ptri[i].facesfront) // { -// D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); +// D_PolysetRecursiveTriangleAsm(index0->v, index1->v, index2->v); movl mtri_facesfront-16(%ebx,%ebp,),%eax testl %eax,%eax jz Lfacesback @@ -1197,7 +1197,7 @@ Llooptop: pushl %edx pushl %esi pushl %ecx - call C(D_PolysetRecursiveTriangle) + call C(D_PolysetRecursiveTriangleAsm) subl $16,%ebp jnz Llooptop @@ -1247,7 +1247,7 @@ Lp13: pushl %edx pushl %esi pushl %ecx - call C(D_PolysetRecursiveTriangle) + call C(D_PolysetRecursiveTriangleAsm) // index0->v[2] = s0; // index1->v[2] = s1; diff --git a/engine/sw/r_light.c b/engine/sw/r_light.c index f2ff365d0..e5296a157 100644 --- a/engine/sw/r_light.c +++ b/engine/sw/r_light.c @@ -166,7 +166,7 @@ void SWR_PushDlights (void) if (cl.worldmodel->fromgame == fg_quake2) { - for (i=0 ; iradius) continue; @@ -176,7 +176,7 @@ void SWR_PushDlights (void) } else { - for (i=0 ; iradius) continue; diff --git a/engine/sw/r_main.c b/engine/sw/r_main.c index 6f4955722..491168e4c 100644 --- a/engine/sw/r_main.c +++ b/engine/sw/r_main.c @@ -1191,7 +1191,7 @@ void R_DrawBEntitiesOnList (void) // instanced model if (clmodel->firstmodelsurface != 0) { - for (k=0 ; knumsurfaces ; i++) cl.worldmodel->surfaces[i].decal = NULL; +#endif } +#if MAX_DECALS + static vec3_t decalorg; static float decalradius; void SWR_AddSurfDecal (msurface_t *surf) @@ -598,9 +610,7 @@ void SWR_DrawDecal8(decal_t *dec) */ } - - - +#endif @@ -629,7 +639,7 @@ void SWR_AddDynamicLights (void) tmax = (surf->extents[1]>>4)+1; tex = surf->texinfo; - for (lnum=0 ; lnumdlightbits & (1<extents[1]>>4)+1; tex = surf->texinfo; - for (lnum=0 ; lnumdlightbits & (1<decal && !r_drawsurf.surfmip) { if (r_pixbytes == 1 || r_pixbytes == 4) @@ -1157,6 +1170,7 @@ void R_DrawSurface (void) } } } +#endif } void R_DrawSurface32 (void) diff --git a/engine/sw/sw_screen.c b/engine/sw/sw_screen.c index 9a0fd4f39..c56c6f253 100644 --- a/engine/sw/sw_screen.c +++ b/engine/sw/sw_screen.c @@ -67,8 +67,6 @@ void SWSCR_UpdateScreen (void) #ifdef _WIN32 { // don't suck up any cpu if minimized - extern int Minimized; - if (Minimized) return; } @@ -90,9 +88,6 @@ void SWSCR_UpdateScreen (void) oldfov = scr_fov.value; vid.recalc_refdef = true; } - - if (scr_chatmode != scr_chatmodecvar.value) - vid.recalc_refdef = true; if (oldsbar != cl_sbar.value) {