diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 8479ea6e..7dad8c84 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -135,7 +135,7 @@ void Cam_Lock(int pnum, int playernum) if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { - memcpy(&cl.stats[pnum], cl.players[playernum].stats, sizeof(cl.stats[pnum])); + memcpy(&cl.playerview[pnum].stats, cl.players[playernum].stats, sizeof(cl.playerview[pnum].stats)); } Sbar_Changed(); @@ -379,18 +379,18 @@ void Cam_SelfTrack(int pnum) vec3_t forward, right, up; trace_t tr; AngleVectors(r_refdef.viewangles, forward, right, up); - VectorMA(cl.simorg[pnum], -128, forward, desired_position[pnum]); - tr = Cam_DoTrace(cl.simorg[pnum], desired_position[pnum]); + VectorMA(cl.playerview[pnum].simorg, -128, forward, desired_position[pnum]); + tr = Cam_DoTrace(cl.playerview[pnum].simorg, desired_position[pnum]); VectorCopy(tr.endpos, desired_position[pnum]); } else { //view from a random wall - if (!locked[pnum] || !Cam_IsVisible(cl.simorg[pnum], desired_position[pnum])) + if (!locked[pnum] || !Cam_IsVisible(cl.playerview[pnum].simorg, desired_position[pnum])) { if (!locked[pnum] || realtime - cam_lastviewtime[pnum] > 0.1) { - if (!InitFlyby(pnum, desired_position[pnum], cl.simorg[pnum], cl.simangles[pnum], true)) - InitFlyby(pnum, desired_position[pnum], cl.simorg[pnum], cl.simangles[pnum], false); + if (!InitFlyby(pnum, desired_position[pnum], cl.playerview[pnum].simorg, cl.playerview[pnum].simangles, true)) + InitFlyby(pnum, desired_position[pnum], cl.playerview[pnum].simorg, cl.playerview[pnum].simangles, false); cam_lastviewtime[pnum] = realtime; } } @@ -408,7 +408,7 @@ void Cam_SelfTrack(int pnum) // move there locally immediately VectorCopy(desired_position[pnum], r_refdef.vieworg); - VectorSubtract(cl.simorg[pnum], desired_position[pnum], vec); + VectorSubtract(cl.playerview[pnum].simorg, desired_position[pnum], vec); VectorAngles(vec, NULL, r_refdef.viewangles); r_refdef.viewangles[0] = -r_refdef.viewangles[0]; } @@ -474,7 +474,7 @@ void Cam_Track(int pnum, usercmd_t *cmd) cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; - VectorCopy(player->viewangles, cl.viewangles[pnum]); + VectorCopy(player->viewangles, cl.playerview[pnum].viewangles); if (memcmp(player->origin, &self->origin, sizeof(player->origin)) != 0) { if (!cls.demoplayback) @@ -509,8 +509,8 @@ void Cam_Track(int pnum, usercmd_t *cmd) VectorCopy(desired_position[pnum], self->origin); VectorSubtract(player->origin, desired_position[pnum], vec); - VectorAngles(vec, NULL, cl.viewangles[pnum]); - cl.viewangles[pnum][0] = -cl.viewangles[pnum][0]; + VectorAngles(vec, NULL, cl.playerview[pnum].viewangles); + cl.playerview[pnum].viewangles[0] = -cl.playerview[pnum].viewangles[0]; } void Cam_SetAutoTrack(int userid) @@ -575,7 +575,7 @@ void Cam_FinishMove(int pnum, usercmd_t *cmd) if (autocam[pnum] > CAM_TRACK) { Cam_Unlock(pnum); - VectorCopy(cl.viewangles[pnum], cmd->angles); + VectorCopy(cl.playerview[pnum].viewangles, cmd->angles); return; } } diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 92de537b..49507b32 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -116,7 +116,7 @@ void CL_WriteDemoCmd (usercmd_t *pcmd) for (i=0 ; i<3 ; i++) { - fl = LittleFloat (cl.viewangles[0][i]); + fl = LittleFloat (cl.playerview[0].viewangles[i]); VFS_WRITE (cls.demooutfile, &fl, 4); } @@ -444,15 +444,15 @@ qboolean CL_GetDemoMessage (void) for (i=0 ; i<3 ; i++) { - a1 = cl.viewangles[2][i]; - a2 = cl.viewangles[1][i]; + a1 = cl.playerview[2].viewangles[i]; + a2 = cl.playerview[1].viewangles[i]; if (a1 - a2 > 180) a1 -= 360; if (a1 - a2 < -180) a1 += 360; - cl.simangles[0][i] = a2 + f * (a1 - a2); + cl.playerview[0].simangles[i] = a2 + f * (a1 - a2); } - VectorCopy(cl.simangles[0], cl.viewangles[0]); + VectorCopy(cl.playerview[0].simangles, cl.playerview[0].viewangles); } return 0; } @@ -464,13 +464,13 @@ qboolean CL_GetDemoMessage (void) } if (cls.demoplayback == DPB_NETQUAKE) { - VectorCopy (cl.viewangles[1], cl.viewangles[2]); + VectorCopy (cl.playerview[1].viewangles, cl.playerview[2].viewangles); for (i=0 ; i<3 ; i++) { readdemobytes(&demopos, &f, 4); - cl.simangles[0][i] = cl.viewangles[1][i] = LittleFloat (f); + cl.playerview[0].simangles[i] = cl.playerview[1].viewangles[i] = LittleFloat (f); } - VectorCopy (cl.viewangles[1], cl.viewangles[0]); + VectorCopy (cl.playerview[1].viewangles, cl.playerview[0].viewangles); } olddemotime = demtime; @@ -678,7 +678,7 @@ readnext: for (i=0 ; i<3 ; i++) { readdemobytes (&demopos, &f, 4); - cl.viewangles[0][i] = LittleFloat (f); + cl.playerview[0].viewangles[i] = LittleFloat (f); } goto readnext; /* }*/ @@ -1315,11 +1315,11 @@ void CL_Record_f (void) for (i = ((cls.fteprotocolextensions&PEXT_HEXEN2)?MAX_QW_STATS:MAX_CL_STATS); i >= 0; i--) { - if (!cl.stats[0][i]) + if (!cl.playerview[0].stats[i]) continue; MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, i); - MSG_WriteLong (&buf, cl.stats[0][i]); + MSG_WriteLong (&buf, cl.playerview[0].stats[i]); if (buf.cursize > MAX_QWMSGLEN/2) { CL_WriteRecordDemoMessage (&buf, seq++); diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 4eab73f5..8d4eb8b5 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -510,8 +510,8 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * else if (!olds) { /*reset got lost, probably the data will be filled in later - FIXME: we should probably ignore this entity*/ -// Con_DPrintf("New entity without reset\n"); - memset(news, 0, sizeof(*news)); + Con_DPrintf("New entity without reset\n"); + *news = nullentitystate; // *news = *baseline; } else @@ -661,6 +661,9 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * news->lightstyle = MSG_ReadByte(); news->lightpflags = MSG_ReadByte(); } + if (bits & UF_TRAILEFFECT) + news->u.q1.traileffectnum = MSG_ReadShort(); + if (bits & UF_COLORMOD) { news->colormod[0] = MSG_ReadByte(); @@ -673,9 +676,28 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * news->glowmod[1] = MSG_ReadByte(); news->glowmod[2] = MSG_ReadByte(); } - if (bits & UF_FATNESS) news->fatness = MSG_ReadByte(); + if (bits & UF_MODELINDEX2) + { + if (bits & UF_16BIT) + news->modelindex2 = MSG_ReadShort(); + else + news->modelindex2 = MSG_ReadByte(); + } + if (bits & UF_GRAVITYDIR) + { + news->u.q1.gravitydir[0] = MSG_ReadByte(); + news->u.q1.gravitydir[1] = MSG_ReadByte(); + } +} + +void CLFTE_ParseBaseline(entity_state_t *es, qboolean numberisimportant) +{ + int entnum = 0; + if (numberisimportant) + entnum = MSG_ReadShort(); + CLFTE_ReadDelta(entnum, es, &nullentitystate, &nullentitystate); } /* @@ -1550,8 +1572,8 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt { if (parenttagent == cl.playernum[0]+1) { - org = cl.simorg[0]; - ang = cl.simangles[0]; + org = cl.playerview[0].simorg; + ang = cl.playerview[0].simangles; } else { @@ -1873,8 +1895,63 @@ void CLQ1_AddVisibleBBoxes(void) #ifdef CSQC_DAT case 2: w = &csqc_world; - return; + break; #endif + case 3: + { + frame_t *frame; + packet_entities_t *pak; + entity_state_t *state; + model_t *mod; + s = R_RegisterShader("bboxshader", + "{\n" + "polygonoffset\n" + "{\n" + "map $whiteimage\n" + "blendfunc add\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "}\n" + "}\n"); + frame = &cl.frames[cl.parsecount & UPDATE_MASK]; + pak = &frame->packet_entities; + + for (i=0 ; inum_entities ; i++) + { + state = &pak->entities[i]; + + if (!state->solid && !state->skinnum) + continue; + + if (state->solid == ES_SOLID_BSP) + { /*bsp model size*/ + if (state->modelindex <= 0) + continue; + if (!cl.model_precache[state->modelindex]) + continue; + /*this makes non-inline bsp objects non-solid for prediction*/ + if ((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode) + { + mod = cl.model_precache[state->modelindex]; + VectorAdd(state->origin, mod->mins, min); + VectorAdd(state->origin, mod->maxs, max); + CLQ1_AddCube(s, min, max, 0.1, 0, 0, 1); + } + } + else + { + /*don't bother with angles*/ + max[0] = max[1] = 8*(state->solid & 31); + min[0] = min[1] = -max[0]; + min[2] = -8*((state->solid>>5) & 31); + max[2] = 8*((state->solid>>10) & 63) - 32; + VectorAdd(state->origin, min, min); + VectorAdd(state->origin, max, max); + CLQ1_AddCube(s, min, max, 0.1, 0, 0, 1); + } + } + } + return; } if (!w->progs) @@ -1898,6 +1975,8 @@ void CLQ1_AddVisibleBBoxes(void) if (r_showbboxes.ival & 4) { + //shows the hulls instead + /*mins is easy*/ VectorAdd(e->v->origin, e->v->mins, min); @@ -2339,6 +2418,8 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp a1 += 360; le->angles[i] = a1 + frac * (a2 - a1); } + VectorCopy(le->origin, le->neworigin); + VectorCopy(le->angles, le->newangle); le->orglerpdeltatime = 0.1; le->orglerpstarttime = oldpack->servertime; } @@ -2533,6 +2614,7 @@ void CL_LinkPacketEntities (void) vec3_t angles; static int flickertime; static int flicker; + int trailef; pack = cl.currentpackentities; if (!pack) @@ -2777,7 +2859,7 @@ void CL_LinkPacketEntities (void) CLQ1_AddPowerupShell(ent, false, state->effects); // add automatic particle trails - if (!model || (!(model->flags&~MF_ROTATE) && model->particletrail<0 && model->particleeffect<0)) + if (!model || (!(model->flags&~MF_ROTATE) && model->particletrail<0 && model->particleeffect<0 && state->u.q1.traileffectnum==0)) continue; if (!cls.allow_anyparticles && !(model->flags & ~MF_ROTATE)) @@ -2801,7 +2883,11 @@ void CL_LinkPacketEntities (void) } } - if (model->particletrail == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, model->particletrail, ent->keynum, &(le->trailstate))) + trailef = model->particletrail; + if (state->u.q1.traileffectnum) + trailef = CL_TranslateParticleFromServer(state->u.q1.traileffectnum); + + if (trailef == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, trailef, ent->keynum, &(le->trailstate))) if (model->traildefaultindex >= 0) pe->ParticleTrailIndex(old_origin, ent->origin, model->traildefaultindex, 0, &(le->trailstate)); @@ -3150,6 +3236,10 @@ void CL_ParsePlayerinfo (void) state->colourmod[1] = 32; state->colourmod[2] = 32; + state->gravitydir[0] = 0; + state->gravitydir[1] = 0; + state->gravitydir[2] = -1; + state->pm_type = PM_NORMAL; TP_ParsePlayerInfo(oldstate, state, info); @@ -3160,8 +3250,8 @@ void CL_ParsePlayerinfo (void) { if (cl.playernum[i] == num) { - cl.stats[i][STAT_WEAPONFRAME] = state->weaponframe; - cl.statsf[i][STAT_WEAPONFRAME] = state->weaponframe; + cl.playerview[i].stats[STAT_WEAPONFRAME] = state->weaponframe; + cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->weaponframe; } } @@ -3273,6 +3363,10 @@ void CL_ParsePlayerinfo (void) state->alpha = 255; state->fatness = 0; + state->gravitydir[0] = 0; + state->gravitydir[1] = 0; + state->gravitydir[2] = -1; + #ifdef PEXT_SCALE if (flags & PF_SCALE && cls.fteprotocolextensions & PEXT_SCALE) state->scale = (float)MSG_ReadByte()/50; @@ -3383,8 +3477,8 @@ guess_pm_type: { if (cl.playernum[i] == num) { - cl.stats[i][STAT_WEAPONFRAME] = state->weaponframe; - cl.statsf[i][STAT_WEAPONFRAME] = state->weaponframe; + cl.playerview[i].stats[STAT_WEAPONFRAME] = state->weaponframe; + cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->weaponframe; } } @@ -3626,7 +3720,7 @@ void CL_LinkPlayers (void) VectorCopy(state->origin, org); for (pnum = 0; pnum < cl.splitclients; pnum++) if (cl.playernum[pnum] == j) - VectorCopy(cl.simorg[pnum], org); + VectorCopy(cl.playerview[pnum].simorg, org); if (model) { org[2] += model->mins[2]; @@ -3710,12 +3804,12 @@ void CL_LinkPlayers (void) cl_numvisedicts--; continue; } -*/ angles[0] = -1*cl.viewangles[pnum][0] / 3; - angles[1] = cl.viewangles[pnum][1]; - angles[2] = cl.viewangles[pnum][2]; - ent->origin[0] = cl.simorg[pnum][0]; - ent->origin[1] = cl.simorg[pnum][1]; - ent->origin[2] = cl.simorg[pnum][2]+cl.crouch[pnum]; +*/ angles[0] = -1*cl.playerview[pnum].viewangles[0] / 3; + angles[1] = cl.playerview[pnum].viewangles[1]; + angles[2] = cl.playerview[pnum].viewangles[2]; + ent->origin[0] = cl.playerview[pnum].simorg[0]; + ent->origin[1] = cl.playerview[pnum].simorg[1]; + ent->origin[2] = cl.playerview[pnum].simorg[2]+cl.crouch[pnum]; break; } } @@ -3823,10 +3917,10 @@ void CL_LinkViewModel(void) if (!r_drawentities.ival) return; - if ((cl.stats[r_refdef.currentplayernum][STAT_ITEMS] & IT_INVISIBILITY) && r_drawviewmodelinvis.value <= 0) + if ((cl.playerview[r_refdef.currentplayernum].stats[STAT_ITEMS] & IT_INVISIBILITY) && r_drawviewmodelinvis.value <= 0) return; - if (cl.stats[r_refdef.currentplayernum][STAT_HEALTH] <= 0) + if (cl.playerview[r_refdef.currentplayernum].stats[STAT_HEALTH] <= 0) return; if (r_drawviewmodel.value > 0 && r_drawviewmodel.value < 1) @@ -3834,7 +3928,7 @@ void CL_LinkViewModel(void) else alpha = 1; - if ((cl.stats[r_refdef.currentplayernum][STAT_ITEMS] & IT_INVISIBILITY) + if ((cl.playerview[r_refdef.currentplayernum].stats[STAT_ITEMS] & IT_INVISIBILITY) && r_drawviewmodelinvis.value > 0 && r_drawviewmodelinvis.value < 1) alpha *= r_drawviewmodelinvis.value; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 2298b502..b1331719 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -33,7 +33,7 @@ cvar_t cl_nodelta = CVAR("cl_nodelta","0"); cvar_t cl_c2spps = CVAR("cl_c2spps", "0"); cvar_t cl_c2sImpulseBackup = SCVAR("cl_c2sImpulseBackup","3"); -cvar_t cl_netfps = CVAR("cl_netfps", "100"); +cvar_t cl_netfps = CVAR("cl_netfps", "150"); cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0"); cvar_t cl_smartjump = CVAR("cl_smartjump", "1"); @@ -274,7 +274,7 @@ void IN_JumpDown (void) KeyDown(&in_up); else #endif - if (condition && cl.stats[pnum][STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator && + if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator && cl.frames[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[pnum]].messagenum == cl.validsequence && cl.waterlevel[pnum] >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1)) ) KeyDown(&in_up); @@ -322,7 +322,7 @@ void IN_Impulse (void) if (Cmd_Argc() > 2) { - items = cl.stats[pnum][STAT_ITEMS]; + items = cl.playerview[pnum].stats[STAT_ITEMS]; best = 0; for (i = Cmd_Argc() - 1; i > 0; i--) @@ -338,31 +338,31 @@ void IN_Impulse (void) best = 1; break; case 2: - if (items & IT_SHOTGUN && cl.stats[pnum][STAT_SHELLS] >= 1) + if (items & IT_SHOTGUN && cl.playerview[pnum].stats[STAT_SHELLS] >= 1) best = 2; break; case 3: - if (items & IT_SUPER_SHOTGUN && cl.stats[pnum][STAT_SHELLS] >= 2) + if (items & IT_SUPER_SHOTGUN && cl.playerview[pnum].stats[STAT_SHELLS] >= 2) best = 3; break; case 4: - if (items & IT_NAILGUN && cl.stats[pnum][STAT_NAILS] >= 1) + if (items & IT_NAILGUN && cl.playerview[pnum].stats[STAT_NAILS] >= 1) best = 4; break; case 5: - if (items & IT_SUPER_NAILGUN && cl.stats[pnum][STAT_NAILS] >= 2) + if (items & IT_SUPER_NAILGUN && cl.playerview[pnum].stats[STAT_NAILS] >= 2) best = 5; break; case 6: - if (items & IT_GRENADE_LAUNCHER && cl.stats[pnum][STAT_ROCKETS] >= 1) + if (items & IT_GRENADE_LAUNCHER && cl.playerview[pnum].stats[STAT_ROCKETS] >= 1) best = 6; break; case 7: - if (items & IT_ROCKET_LAUNCHER && cl.stats[pnum][STAT_ROCKETS] >= 1) + if (items & IT_ROCKET_LAUNCHER && cl.playerview[pnum].stats[STAT_ROCKETS] >= 1) best = 7; break; case 8: - if (items & IT_LIGHTNING && cl.stats[pnum][STAT_CELLS] >= 1) + if (items & IT_LIGHTNING && cl.playerview[pnum].stats[STAT_CELLS] >= 1) best = 8; } } @@ -520,7 +520,7 @@ void CL_AdjustAngles (int pnum, double frametime) quant *= speed; in_rotate -= quant; if (ruleset_allow_frj.ival) - cl.viewanglechange[pnum][YAW] += quant; + cl.playerview[pnum].viewanglechange[YAW] += quant; } if (!(in_strafe.state[pnum] & 1)) @@ -528,8 +528,8 @@ void CL_AdjustAngles (int pnum, double frametime) quant = cl_yawspeed.ival; if (cl.fpd & FPD_LIMIT_YAW || !ruleset_allow_frj.ival) quant = bound(-900, quant, 900); - cl.viewanglechange[pnum][YAW] -= speed*quant * CL_KeyState (&in_right, pnum); - cl.viewanglechange[pnum][YAW] += speed*quant * CL_KeyState (&in_left, pnum); + cl.playerview[pnum].viewanglechange[YAW] -= speed*quant * CL_KeyState (&in_right, pnum); + cl.playerview[pnum].viewanglechange[YAW] += speed*quant * CL_KeyState (&in_left, pnum); } if (in_klook.state[pnum] & 1) { @@ -537,8 +537,8 @@ void CL_AdjustAngles (int pnum, double frametime) quant = cl_pitchspeed.ival; if (cl.fpd & FPD_LIMIT_PITCH || !ruleset_allow_frj.ival) quant = bound(-700, quant, 700); - cl.viewanglechange[pnum][PITCH] -= speed*quant * CL_KeyState (&in_forward, pnum); - cl.viewanglechange[pnum][PITCH] += speed*quant * CL_KeyState (&in_back, pnum); + cl.playerview[pnum].viewanglechange[PITCH] -= speed*quant * CL_KeyState (&in_forward, pnum); + cl.playerview[pnum].viewanglechange[PITCH] += speed*quant * CL_KeyState (&in_back, pnum); } up = CL_KeyState (&in_lookup, pnum); @@ -547,8 +547,8 @@ void CL_AdjustAngles (int pnum, double frametime) quant = cl_pitchspeed.ival; if (!ruleset_allow_frj.ival) quant = bound(-700, quant, 700); - cl.viewanglechange[pnum][PITCH] -= speed*cl_pitchspeed.ival * up; - cl.viewanglechange[pnum][PITCH] += speed*cl_pitchspeed.ival * down; + cl.playerview[pnum].viewanglechange[PITCH] -= speed*cl_pitchspeed.ival * up; + cl.playerview[pnum].viewanglechange[PITCH] += speed*cl_pitchspeed.ival * down; if (up || down) V_StopPitchDrift (pnum); @@ -612,7 +612,7 @@ void CL_ClampPitch (int pnum) static float oldtime; float timestep = realtime - oldtime; oldtime = realtime; - +#if 0 if (cl.pmovetype[pnum] == PM_WALLWALK) { AngleVectors(cl.viewangles[pnum], view[0], view[1], view[2]); @@ -644,11 +644,99 @@ void CL_ClampPitch (int pnum) return; } +#endif +#if 1 + if (1) + { + float surfm[16], invsurfm[16]; + float viewm[16]; + vec3_t view[4]; + vec3_t surf[3]; + vec3_t fwd, up; + vec3_t vang; + void PerpendicularVector( vec3_t dst, const vec3_t src ); - cl.viewangles[pnum][PITCH] += cl.viewanglechange[pnum][PITCH]; - cl.viewangles[pnum][YAW] += cl.viewanglechange[pnum][YAW]; - cl.viewangles[pnum][ROLL] += cl.viewanglechange[pnum][ROLL]; - VectorClear(cl.viewanglechange[pnum]); + /*calc current view matrix relative to the surface*/ + AngleVectors(cl.playerview[pnum].viewangles, view[0], view[1], view[2]); + VectorNegate(view[1], view[1]); + + /*calculate the surface axis with up from the pmove code and right/forwards relative to the player's directions*/ + if (!cl.playerview[pnum].gravitydir[0] && !cl.playerview[pnum].gravitydir[1] && !cl.playerview[pnum].gravitydir[2]) + { + VectorSet(surf[2], 0, 0, 1); + } + else + { + VectorNegate(cl.playerview[pnum].gravitydir, surf[2]); + } + VectorNormalize(surf[2]); + PerpendicularVector(surf[1], surf[2]); + VectorNormalize(surf[1]); + CrossProduct(surf[2], surf[1], surf[0]); + VectorNegate(surf[0], surf[0]); + VectorNormalize(surf[0]); + Matrix4x4_RM_FromVectors(surfm, surf[0], surf[1], surf[2], vec3_origin); + Matrix3x4_InvertTo4x4_Simple(surfm, invsurfm); + + /*calc current view matrix relative to the surface*/ + Matrix4x4_RM_FromVectors(viewm, view[0], view[1], view[2], vec3_origin); + Matrix4_Multiply(viewm, invsurfm, mat); + /*convert that back to angles*/ + Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]); + VectorAngles(view[0], view[2], vang); + vang[PITCH] *= -1; + + /*edit it*/ + if (vang[PITCH] < -180) + vang[PITCH] += 360; + if (vang[PITCH] > 180) + vang[PITCH] -= 360; + if (vang[ROLL] > 180) + vang[ROLL] -= 360; + vang[PITCH] += cl.playerview[pnum].viewanglechange[PITCH]; + vang[YAW] += cl.playerview[pnum].viewanglechange[YAW]; + /*keep the player looking relative to their ground (smoothlyish)*/ + if (!vang[ROLL]) + { + if (!cl.playerview[pnum].viewanglechange[PITCH] && !cl.playerview[pnum].viewanglechange[YAW] && !cl.playerview[pnum].viewanglechange[ROLL]) + return; + } + else + { + if (fabs(vang[ROLL]) < host_frametime*180) + vang[ROLL] = 0; + else if (vang[ROLL] > 0) + vang[ROLL] -= host_frametime*180; + else + vang[ROLL] += host_frametime*180; + } + VectorClear(cl.playerview[pnum].viewanglechange); + /*clamp pitch*/ + if (vang[PITCH] > cl.maxpitch) + vang[PITCH] = cl.maxpitch; + if (vang[PITCH] < cl.minpitch) + vang[PITCH] = cl.minpitch; + + /*turn those angles back to a matrix*/ + AngleVectors(vang, view[0], view[1], view[2]); + VectorNegate(view[1], view[1]); + Matrix4x4_RM_FromVectors(mat, view[0], view[1], view[2], vec3_origin); + /*rotate back into world space*/ + Matrix4_Multiply(mat, surfm, viewm); + /*and figure out the final result*/ + Matrix3x4_RM_ToVectors(viewm, view[0], view[1], view[2], view[3]); + VectorAngles(view[0], view[2], cl.playerview[pnum].viewangles); + cl.playerview[pnum].viewangles[PITCH] *= -1; + + if (cl.playerview[pnum].viewangles[PITCH] < -180) + cl.playerview[pnum].viewangles[PITCH] += 360; + return; + } +#endif + cl.playerview[pnum].viewangles[PITCH] += cl.playerview[pnum].viewanglechange[PITCH]; + cl.playerview[pnum].viewangles[YAW] += cl.playerview[pnum].viewanglechange[YAW]; + cl.playerview[pnum].viewangles[ROLL] += cl.playerview[pnum].viewanglechange[ROLL]; + VectorClear(cl.playerview[pnum].viewanglechange); #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) @@ -658,15 +746,15 @@ void CL_ClampPitch (int pnum) if (pitch > 180) pitch -= 360; - if (cl.viewangles[pnum][PITCH] + pitch < -360) - cl.viewangles[pnum][PITCH] += 360; // wrapped - if (cl.viewangles[pnum][PITCH] + pitch > 360) - cl.viewangles[pnum][PITCH] -= 360; // wrapped + if (cl.playerview[pnum].viewangles[PITCH] + pitch < -360) + cl.playerview[pnum].viewangles[PITCH] += 360; // wrapped + if (cl.playerview[pnum].viewangles[PITCH] + pitch > 360) + cl.playerview[pnum].viewangles[PITCH] -= 360; // wrapped - if (cl.viewangles[pnum][PITCH] + pitch > cl.maxpitch) - cl.viewangles[pnum][PITCH] = cl.maxpitch - pitch; - if (cl.viewangles[pnum][PITCH] + pitch < cl.minpitch) - cl.viewangles[pnum][PITCH] = cl.minpitch - pitch; + if (cl.playerview[pnum].viewangles[PITCH] + pitch > cl.maxpitch) + cl.playerview[pnum].viewangles[PITCH] = cl.maxpitch - pitch; + if (cl.playerview[pnum].viewangles[PITCH] + pitch < cl.minpitch) + cl.playerview[pnum].viewangles[PITCH] = cl.minpitch - pitch; } else #endif @@ -678,23 +766,23 @@ void CL_ClampPitch (int pnum) else #endif { - if (cl.fixangle[pnum]) + if (cl.playerview[pnum].fixangle) return; - if (cl.viewangles[pnum][PITCH] > cl.maxpitch) - cl.viewangles[pnum][PITCH] = cl.maxpitch; - if (cl.viewangles[pnum][PITCH] < cl.minpitch) - cl.viewangles[pnum][PITCH] = cl.minpitch; + if (cl.playerview[pnum].viewangles[PITCH] > cl.maxpitch) + cl.playerview[pnum].viewangles[PITCH] = cl.maxpitch; + if (cl.playerview[pnum].viewangles[PITCH] < cl.minpitch) + cl.playerview[pnum].viewangles[PITCH] = cl.minpitch; } // if (cl.viewangles[pnum][ROLL] > 50) // cl.viewangles[pnum][ROLL] = 50; // if (cl.viewangles[pnum][ROLL] < -50) // cl.viewangles[pnum][ROLL] = -50; - roll = timestep*cl.viewangles[pnum][ROLL]*30; - if ((cl.viewangles[pnum][ROLL]-roll < 0) != (cl.viewangles[pnum][ROLL]<0)) - cl.viewangles[pnum][ROLL] = 0; + roll = timestep*cl.playerview[pnum].viewangles[ROLL]*30; + if ((cl.playerview[pnum].viewangles[ROLL]-roll < 0) != (cl.playerview[pnum].viewangles[ROLL]<0)) + cl.playerview[pnum].viewangles[ROLL] = 0; else - cl.viewangles[pnum][ROLL] -= timestep*cl.viewangles[pnum][ROLL]*3; + cl.playerview[pnum].viewangles[ROLL] -= timestep*cl.playerview[pnum].viewangles[ROLL]*3; } /* @@ -738,7 +826,7 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum) cmd->msec = msecs; for (i=0 ; i<3 ; i++) - cmd->angles[i] = ((int)(cl.viewangles[pnum][i]*65536.0/360)&65535); + cmd->angles[i] = ((int)(cl.playerview[pnum].viewangles[i]*65536.0/360)&65535); if (in_impulsespending[pnum] && !cl.paused) { @@ -819,7 +907,7 @@ void CL_UpdatePrydonCursor(usercmd_t *from, float cursor_screen[2], vec3_t curso temp[2] = 1; VectorCopy(r_origin, cursor_start); - Matrix4x4_CM_UnProject(temp, cursor_end, cl.viewangles[0], cursor_start, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_UnProject(temp, cursor_end, cl.playerview[0].viewangles, cursor_start, r_refdef.fov_x, r_refdef.fov_y); CL_SetSolidEntities(); //don't bother with players, they don't exist in NQ... @@ -859,9 +947,9 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) for (i=0 ; i<3 ; i++) { if (cls.protocol_nq == CPNQ_FITZ666 || cls.protocol_nq == CPNQ_PROQUAKE3_4) - MSG_WriteAngle16 (buf, cl.viewangles[pnum][i]); + MSG_WriteAngle16 (buf, cl.playerview[pnum].viewangles[i]); else - MSG_WriteAngle (buf, cl.viewangles[pnum][i]); + MSG_WriteAngle (buf, cl.playerview[pnum].viewangles[i]); } MSG_WriteShort (buf, cmd->forwardmove); @@ -987,7 +1075,7 @@ void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...) return; //no point. va_start (argptr, format); - vsnprintf (string,sizeof(string)-1, format,argptr); + Q_vsnprintfz (string,sizeof(string), format,argptr); va_end (argptr); @@ -1250,7 +1338,7 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf) else MSG_WriteLong (buf, cl.q2frame.serverframe); - lightlev = R_LightPoint(cl.simorg[0]); + lightlev = R_LightPoint(cl.playerview[0].simorg); // msecs = msecs - (double)msecstouse; @@ -1561,7 +1649,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) VectorClear(mousemovements[plnum]); for (i=0 ; i<3 ; i++) - independantphysics[plnum].angles[i] = ((int)(cl.viewangles[plnum][i]*65536.0/360)&65535); + independantphysics[plnum].angles[i] = ((int)(cl.playerview[plnum].viewangles[i]*65536.0/360)&65535); if (!independantphysics[plnum].msec) { @@ -1745,7 +1833,7 @@ static char *VARGS vahunk(char *format, ...) char *ret; va_start (argptr, format); - vsnprintf (string,sizeof(string)-1, format,argptr); + Q_vsnprintfz (string,sizeof(string), format,argptr); va_end (argptr); ret = Hunk_Alloc(strlen(string)+1); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 9da6fb1a..21927b38 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1119,15 +1119,11 @@ void CL_ClearState (void) rtlights_first = rtlights_max = RTL_FIRST; - if (cl_baselines) - { - BZ_Free(cl_baselines); - cl_baselines = NULL; - } - cl_baselines_count = 0; - for (i = 0; i < MAX_SPLITS; i++) + { + VectorSet(cl.playerview[i].gravitydir, 0, 0, -1); cl.viewheight[i] = DEFAULT_VIEWHEIGHT; + } cl.minpitch = -70; cl.maxpitch = 80; @@ -1230,34 +1226,7 @@ void CL_Disconnect (void) cl.worldmodel = NULL; } - if (cls.downloadmethod <= DL_QWPENDING) - cls.downloadmethod = DL_NONE; - if (cls.downloadqw) - { - VFS_CLOSE(cls.downloadqw); - cls.downloadqw = NULL; - } - if (!cls.downloadmethod) - { - *cls.downloadlocalname = '\0'; - *cls.downloadremotename = '\0'; - } - - { - downloadlist_t *next; - while(cl.downloadlist) - { - next = cl.downloadlist->next; - Z_Free(cl.downloadlist); - cl.downloadlist = next; - } - while(cl.faileddownloads) - { - next = cl.faileddownloads->next; - Z_Free(cl.faileddownloads); - cl.faileddownloads = next; - } - } + CL_Parse_Disconnected(); COM_FlushTempoaryPacks(); @@ -1294,6 +1263,8 @@ void CL_Disconnect (void) #endif Cvar_ForceSet(&cl_servername, "none"); + + CL_ClearState(); } #undef serverrunning @@ -3665,9 +3636,9 @@ double Host_Frame (double time) SCR_UpdateScreen (); if (cls.state >= ca_active && r_viewleaf) - SNDDMA_SetUnderWater(r_viewleaf->contents <= Q1CONTENTS_WATER); + S_SetUnderWater(r_viewleaf->contents <= Q1CONTENTS_WATER); else - SNDDMA_SetUnderWater(false); + S_SetUnderWater(false); } if (host_speeds.ival) @@ -4015,6 +3986,8 @@ void Host_Shutdown(void) } host_initialized = false; + Plug_Shutdown(); + //disconnect server/client/etc CL_Disconnect_f(); //Kill renderer @@ -4037,12 +4010,12 @@ void Host_Shutdown(void) #else NET_Shutdown (); #endif - FS_Shutdown(); Cvar_Shutdown(); Validation_FlushFileList(); Cmd_Shutdown(); + Key_Unbindall_f(); Con_Shutdown(); Memory_DeInit(); @@ -4051,6 +4024,8 @@ void Host_Shutdown(void) memset(&svs, 0, sizeof(svs)); #endif Sys_Shutdown(); + + FS_Shutdown(); } #ifdef CLIENTONLY diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 53e3a1ee..f457391a 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -247,6 +247,41 @@ double parsecounttime; int cl_spikeindex, cl_playerindex, cl_h_playerindex, cl_flagindex, cl_rocketindex, cl_grenadeindex, cl_gib1index, cl_gib2index, cl_gib3index; +//called after disconnect, purges all memory that was allocated etc +void CL_Parse_Disconnected(void) +{ + if (cls.downloadmethod <= DL_QWPENDING) + cls.downloadmethod = DL_NONE; + if (cls.downloadqw) + { + VFS_CLOSE(cls.downloadqw); + cls.downloadqw = NULL; + } + if (!cls.downloadmethod) + { + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; + } + + { + downloadlist_t *next; + while(cl.downloadlist) + { + next = cl.downloadlist->next; + Z_Free(cl.downloadlist); + cl.downloadlist = next; + } + while(cl.faileddownloads) + { + next = cl.faileddownloads->next; + Z_Free(cl.faileddownloads); + cl.faileddownloads = next; + } + } + + CL_ClearParseState(); +} + //============================================================================= int packet_latency[NET_TIMINGS]; @@ -2190,6 +2225,20 @@ void CL_ClearParseState(void) cl_gib1index = -1; cl_gib2index = -1; cl_gib3index = -1; + + if (cl_baselines) + { + BZ_Free(cl_baselines); + cl_baselines = NULL; + } + cl_baselines_count = 0; + + cl_max_static_entities = 0; + if (cl_static_entities) + { + BZ_Free(cl_static_entities); + cl_static_entities = NULL; + } } /* @@ -3389,7 +3438,10 @@ void CL_ParseBaseline2 (void) { entity_state_t es; - CLQW_ParseDelta(&nullentitystate, &es, (unsigned short)MSG_ReadShort(), true); + if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + CLFTE_ParseBaseline(&es, true); + else + CLQW_ParseDelta(&nullentitystate, &es, (unsigned short)MSG_ReadShort(), true); if (!CL_CheckBaselines(es.number)) Host_EndGame("CL_ParseBaseline2: check baselines failed with size %i", es.number); memcpy(cl_baselines + es.number, &es, sizeof(es)); @@ -3455,7 +3507,10 @@ void CL_ParseStatic (int version) } else { - CLQW_ParseDelta(&nullentitystate, &es, MSG_ReadShort(), true); + if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + CLFTE_ParseBaseline(&es, false); + else + CLQW_ParseDelta(&nullentitystate, &es, MSG_ReadShort(), true); es.number+=MAX_EDICTS; for (i = 0; i < cl.num_statics; i++) @@ -4041,28 +4096,28 @@ CL_SetStat static void CL_SetStat_Internal (int pnum, int stat, int value) { int j; - if (cl.stats[pnum][stat] != value) + if (cl.playerview[pnum].stats[stat] != value) Sbar_Changed (); if (stat == STAT_ITEMS) { // set flash times for (j=0 ; j<32 ; j++) - if ( (value & (1<color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); break; @@ -4288,27 +4343,27 @@ void CLQ2_ParseMuzzleFlash (void) case Q2MZ_CHAINGUN1: dl->radius = 200 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.05;dl->color[2] = 0; - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); break; case Q2MZ_CHAINGUN2: dl->radius = 225 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.1;dl->color[2] = 0; dl->die = cl.time + 0.1; // long delay - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.05); break; case Q2MZ_CHAINGUN3: dl->radius = 250 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; dl->die = cl.time + 0.1; // long delay - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.033); - snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); + Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.066); break; @@ -5012,6 +5067,8 @@ void CL_ParsePrecache(void) else Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS); break; + case 0x4000: + break; case 0x8000: if (i >= 1 && i < MAX_SOUNDS) { @@ -5027,6 +5084,11 @@ void CL_ParsePrecache(void) else Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS); break; + case 0xC000: + if (i >= 1 && i < 1024) + { + } + break; } } @@ -5083,7 +5145,7 @@ void CLQW_ParseServerMessage (void) cl.last_servermessage = realtime; CL_ClearProjectiles (); for (i = 0; i < MAX_SPLITS; i++) - cl.fixangle[i] = false; + cl.playerview[i].fixangle = false; // // if recording demos, copy the message out @@ -5231,8 +5293,8 @@ void CLQW_ParseServerMessage (void) #endif case svcfte_setangledelta: for (i=0 ; i<3 ; i++) - cl.viewangles[destsplit][i] += MSG_ReadAngle16 (); - VectorCopy (cl.viewangles[destsplit], cl.simangles[destsplit]); + cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 (); + VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles); break; case svc_setangle: if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) @@ -5245,20 +5307,20 @@ void CLQW_ParseServerMessage (void) { if (Cam_TrackNum(j) == i) { - cl.fixangle[j]=true; - VectorCopy(ang, cl.simangles[j]); - VectorCopy(ang, cl.viewangles[j]); - VectorCopy(ang, cl.fixangles[j]); + cl.playerview[j].fixangle=true; + VectorCopy(ang, cl.playerview[j].simangles); + VectorCopy(ang, cl.playerview[j].viewangles); + VectorCopy(ang, cl.playerview[j].fixangles); } } break; } - cl.fixangle[destsplit]=true; + cl.playerview[destsplit].fixangle=true; for (i=0 ; i<3 ; i++) - cl.viewangles[destsplit][i] = cl.fixangles[destsplit][i] = MSG_ReadAngle (); + cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].fixangles[i] = MSG_ReadAngle (); - VectorCopy (cl.viewangles[destsplit], cl.simangles[destsplit]); -// cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0; + VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles); +// cl.playerview[destsplit].viewangles[PITCH] = cl.viewangles[ROLL] = 0; break; case svc_lightstyle: @@ -5372,11 +5434,11 @@ void CLQW_ParseServerMessage (void) break; case svc_killedmonster: - cl.stats[destsplit][STAT_MONSTERS]++; + cl.playerview[destsplit].stats[STAT_MONSTERS]++; break; case svc_foundsecret: - cl.stats[destsplit][STAT_SECRETS]++; + cl.playerview[destsplit].stats[STAT_SECRETS]++; break; case svc_updatestat: @@ -5420,18 +5482,18 @@ void CLQW_ParseServerMessage (void) cl.completed_time = cl.gametime; vid.recalc_refdef = true; // go to full screen for (i=0 ; i<3 ; i++) - cl.simorg[destsplit][i] = MSG_ReadCoord (); + cl.playerview[destsplit].simorg[i] = MSG_ReadCoord (); for (i=0 ; i<3 ; i++) - cl.simangles[destsplit][i] = MSG_ReadAngle (); - VectorCopy (cl.simangles[destsplit], cl.fixangles[destsplit]); - VectorClear (cl.simvel[destsplit]); + cl.playerview[destsplit].simangles[i] = MSG_ReadAngle (); + VectorCopy (cl.playerview[destsplit].simangles, cl.playerview[destsplit].fixangles); + VectorClear (cl.playerview[destsplit].simvel); break; case svc_finale: if (!cl.intermission) for (i = 0; i < MAX_SPLITS; i++) - cl.simorg[i][2] += cl.viewheight[i]; - VectorCopy (cl.fixangles[destsplit], cl.simangles[destsplit]); + cl.playerview[i].simorg[2] += cl.viewheight[i]; + VectorCopy (cl.playerview[destsplit].fixangles, cl.playerview[destsplit].simangles); cl.intermission = 2; cl.completed_time = cl.gametime; @@ -5575,13 +5637,13 @@ void CLQW_ParseServerMessage (void) break; case svcfte_trailparticles: - CLDP_ParseTrailParticles(); + CL_ParseTrailParticles(); break; case svcfte_pointparticles: - CLDP_ParsePointParticles(false); + CL_ParsePointParticles(false); break; case svcfte_pointparticles1: - CLDP_ParsePointParticles(true); + CL_ParsePointParticles(true); break; case svcfte_cgamepacket: @@ -6103,9 +6165,9 @@ void CLNQ_ParseServerMessage (void) break; case svc_time: - cl.oldfixangle[0] = cl.fixangle[0]; - VectorCopy(cl.fixangles[0], cl.oldfixangles[0]); - cl.fixangle[0] = false; + cl.playerview[0].oldfixangle = cl.playerview[0].fixangle; + VectorCopy(cl.playerview[0].fixangles, cl.playerview[0].oldfixangles); + cl.playerview[0].fixangle = false; cls.netchan.outgoing_sequence++; cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1; @@ -6208,9 +6270,9 @@ void CLNQ_ParseServerMessage (void) CL_SetStatFloat (0, i, j); break; case svc_setangle: - cl.fixangle[0]=true; + cl.playerview[0].fixangle=true; for (i=0 ; i<3 ; i++) - cl.viewangles[0][i] = cl.fixangles[0][i] = MSG_ReadAngle (); + cl.playerview[0].viewangles[i] = cl.playerview[0].fixangles[i] = MSG_ReadAngle (); // cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0; break; @@ -6235,11 +6297,11 @@ void CLNQ_ParseServerMessage (void) break; case svc_killedmonster: - cl.stats[0][STAT_MONSTERS]++; + cl.playerview[0].stats[STAT_MONSTERS]++; break; case svc_foundsecret: - cl.stats[0][STAT_SECRETS]++; + cl.playerview[0].stats[STAT_SECRETS]++; break; case svc_intermission: @@ -6328,13 +6390,13 @@ void CLNQ_ParseServerMessage (void) break; case svcdp_trailparticles: - CLDP_ParseTrailParticles(); + CL_ParseTrailParticles(); break; case svcdp_pointparticles: - CLDP_ParsePointParticles(false); + CL_ParsePointParticles(false); break; case svcdp_pointparticles1: - CLDP_ParsePointParticles(true); + CL_ParsePointParticles(true); break; } diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index b7b2f78c..3dc80dca 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -285,7 +285,7 @@ qintptr_t VARGS Plug_CL_GetStats(void *offset, quintptr_t mask, const qintptr_t max = MAX_CL_STATS; for (i = 0; i < max; i++) { //fill stats with the right player's stats - stats[i] = cl.stats[pnum][i]; + stats[i] = cl.playerview[pnum].stats[i]; } for (; i < pluginstats; i++) //plugin has too many stats (wow) stats[i] = 0; //fill the rest. diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index ca2f0ce0..14bc25d5 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -235,6 +235,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients. int oldz; #endif int i; + int pnum = 0; if (cls.state != ca_active) return; @@ -248,7 +249,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients. { // just set angles for (i=0 ; i<3 ; i++) { - cl.predicted_angles[i] = cl.viewangles[0][i] + SHORT2ANGLE(cl.q2frame.playerstate.pmove.delta_angles[i]); + cl.predicted_angles[i] = cl.playerview[pnum].viewangles[i] + SHORT2ANGLE(cl.q2frame.playerstate.pmove.delta_angles[i]); } return; } @@ -378,6 +379,7 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state VectorCopy (from->origin, pmove.origin); VectorCopy (u->angles, pmove.angles); VectorCopy (from->velocity, pmove.velocity); + VectorCopy (from->gravitydir, pmove.gravitydir); if (!(pmove.velocity[0] == 0) && !(pmove.velocity[0] != 0)) { @@ -413,6 +415,7 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state VectorCopy (pmove.origin, to->origin); VectorCopy (pmove.angles, to->viewangles); VectorCopy (pmove.velocity, to->velocity); + VectorCopy (pmove.gravitydir, to->gravitydir); to->onground = pmove.onground; to->weaponframe = from->weaponframe; @@ -432,7 +435,7 @@ void CL_CatagorizePosition (int pnum) return; } VectorClear (pmove.velocity); - VectorCopy (cl.simorg[pnum], pmove.origin); + VectorCopy (cl.playerview[pnum].simorg, pmove.origin); pmove.numtouch = 0; PM_CategorizePosition (); cl.onground[pnum] = pmove.onground; @@ -446,50 +449,50 @@ void CL_CalcCrouch (int pnum, float stepchange) static float oldz[MAX_SPLITS] = {0}, extracrouch[MAX_SPLITS] = {0}, crouchspeed[MAX_SPLITS] = {100,100}; vec3_t delta; - VectorSubtract(cl.simorg[pnum], oldorigin[pnum], delta); + VectorSubtract(cl.playerview[pnum].simorg, oldorigin[pnum], delta); teleported = Length(delta)>48; - VectorCopy (cl.simorg[pnum], oldorigin[pnum]); + VectorCopy (cl.playerview[pnum].simorg, oldorigin[pnum]); if (teleported) { // possibly teleported or respawned - oldz[pnum] = cl.simorg[pnum][2]; + oldz[pnum] = cl.playerview[pnum].simorg[2]; extracrouch[pnum] = 0; crouchspeed[pnum] = 100; cl.crouch[pnum] = 0; - VectorCopy (cl.simorg[pnum], oldorigin[pnum]); + VectorCopy (cl.playerview[pnum].simorg, oldorigin[pnum]); return; } - if (cl.onground[pnum] && cl.simorg[pnum][2] - oldz[pnum] > 0) + if (cl.onground[pnum] && cl.playerview[pnum].simorg[2] - oldz[pnum] > 0) { - if (cl.simorg[pnum][2] - oldz[pnum] > movevars.stepheight+2) + if (cl.playerview[pnum].simorg[2] - oldz[pnum] > movevars.stepheight+2) { // if on steep stairs, increase speed if (crouchspeed[pnum] < 160) { - extracrouch[pnum] = cl.simorg[pnum][2] - oldz[pnum] - host_frametime * 200 - 15; + extracrouch[pnum] = cl.playerview[pnum].simorg[2] - oldz[pnum] - host_frametime * 200 - 15; extracrouch[pnum] = min(extracrouch[pnum], 5); } crouchspeed[pnum] = 160; } oldz[pnum] += host_frametime * crouchspeed[pnum]; - if (oldz[pnum] > cl.simorg[pnum][2]) - oldz[pnum] = cl.simorg[pnum][2]; + if (oldz[pnum] > cl.playerview[pnum].simorg[2]) + oldz[pnum] = cl.playerview[pnum].simorg[2]; - if (cl.simorg[pnum][2] - oldz[pnum] > 15 + extracrouch[pnum]) - oldz[pnum] = cl.simorg[pnum][2] - 15 - extracrouch[pnum]; + if (cl.playerview[pnum].simorg[2] - oldz[pnum] > 15 + extracrouch[pnum]) + oldz[pnum] = cl.playerview[pnum].simorg[2] - 15 - extracrouch[pnum]; extracrouch[pnum] -= host_frametime * 200; extracrouch[pnum] = max(extracrouch[pnum], 0); - cl.crouch[pnum] = oldz[pnum] - cl.simorg[pnum][2]; + cl.crouch[pnum] = oldz[pnum] - cl.playerview[pnum].simorg[2]; } else { // in air or moving down - oldz[pnum] = cl.simorg[pnum][2]; + oldz[pnum] = cl.playerview[pnum].simorg[2]; cl.crouch[pnum] += host_frametime * 150; if (cl.crouch[pnum] > 0) cl.crouch[pnum] = 0; @@ -552,11 +555,11 @@ static void CL_LerpMove (int pnum, float msgtime) VectorCopy (lerp_origin[1], lerp_origin[2]); VectorCopy (lerp_origin[0], lerp_origin[1]); - VectorCopy (cl.simorg[pnum], lerp_origin[0]); + VectorCopy (cl.playerview[pnum].simorg, lerp_origin[0]); VectorCopy (lerp_angles[1], lerp_angles[2]); VectorCopy (lerp_angles[0], lerp_angles[1]); - VectorCopy (cl.simangles[pnum], lerp_angles[0]); + VectorCopy (cl.playerview[pnum].simangles, lerp_angles[0]); nolerp[1] = nolerp[0]; nolerp[0] = false; @@ -608,9 +611,9 @@ static void CL_LerpMove (int pnum, float msgtime) for (i=0 ; i<3 ; i++) { - cl.simorg[pnum][i] = lerp_origin[from][i] + + cl.playerview[pnum].simorg[i] = lerp_origin[from][i] + frac * (lerp_origin[to][i] - lerp_origin[from][i]); - cl.simangles[pnum][i] = LerpAngles360(lerp_angles[from][i], lerp_angles[to][i], frac); + cl.playerview[pnum].simangles[i] = LerpAngles360(lerp_angles[from][i], lerp_angles[to][i], frac); } // LerpVector (lerp_origin[from], lerp_origin[to], frac, cl.simorg); @@ -776,6 +779,7 @@ static void CL_DecodeStateSize(unsigned short solid, int modelindex, vec3_t mins void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence) { /*update the prediction info*/ + vec3_t a; int pmtype, i; switch(state->u.q1.pmovetype) { @@ -812,14 +816,19 @@ void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int s VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity); plstate->messagenum = sequence; + a[0] = ((-192-state->u.q1.gravitydir[0])/256.0f) * 360; + a[1] = (state->u.q1.gravitydir[1]/256.0f) * 360; + a[2] = 0; + AngleVectors(a, plstate->gravitydir, NULL, NULL); + cl.players[state->number-1].stats[STAT_WEAPONFRAME] = state->u.q1.weaponframe; cl.players[state->number-1].statsf[STAT_WEAPONFRAME] = state->u.q1.weaponframe; for (i = 0; i < cl.splitclients; i++) { if (cl.playernum[i] == state->number-1) { - cl.stats[i][STAT_WEAPONFRAME] = state->u.q1.weaponframe; - cl.statsf[i][STAT_WEAPONFRAME] = state->u.q1.weaponframe; + cl.playerview[i].stats[STAT_WEAPONFRAME] = state->u.q1.weaponframe; + cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->u.q1.weaponframe; } } @@ -926,7 +935,7 @@ void CL_PredictMovePNum (int pnum) if (cls.netchan.outgoing_sequence - cl.ackedinputsequence >= UPDATE_BACKUP-1) { //lagging like poo. if (!cl.intermission) //keep the angles working though. - VectorCopy (cl.viewangles[pnum], cl.simangles[pnum]); + VectorCopy (cl.playerview[pnum].viewangles, cl.playerview[pnum].simangles); return; } @@ -935,7 +944,7 @@ void CL_PredictMovePNum (int pnum) if (!cl.intermission) { - VectorCopy (cl.viewangles[pnum], cl.simangles[pnum]); + VectorCopy (cl.playerview[pnum].viewangles, cl.playerview[pnum].simangles); } vel = from->playerstate[cl.playernum[pnum]].velocity; @@ -968,7 +977,7 @@ void CL_PredictMovePNum (int pnum) } - if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.fixangle[pnum] || cl.paused)) + if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.playerview[pnum].fixangle || cl.paused)) { if (cl_lerp_players.ival && !cls.demoplayback) { @@ -978,8 +987,8 @@ void CL_PredictMovePNum (int pnum) } fixedorg: - VectorCopy (vel, cl.simvel[pnum]); - VectorCopy (org, cl.simorg[pnum]); + VectorCopy (vel, cl.playerview[pnum].simvel); + VectorCopy (org, cl.playerview[pnum].simorg); to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; @@ -1004,7 +1013,7 @@ fixedorg: lerpents_t *le = &cl.lerpplayers[spec_track[pnum]]; org = le->origin; vel = vec3_origin; - VectorCopy(le->angles, cl.simangles[pnum]); + VectorCopy(le->angles, cl.playerview[pnum].simangles); goto fixedorg; } @@ -1032,7 +1041,7 @@ fixedorg: lrpv[i] = to->playerstate[spec_track[pnum]].velocity[i] + f * (from->playerstate[spec_track[pnum]].velocity[i] - to->playerstate[spec_track[pnum]].velocity[i]); - cl.simangles[pnum][i] = LerpAngles16(to->playerstate[spec_track[pnum]].command.angles[i], from->playerstate[spec_track[pnum]].command.angles[i], f)*360.0f/65535; + cl.playerview[pnum].simangles[i] = LerpAngles16(to->playerstate[spec_track[pnum]].command.angles[i], from->playerstate[spec_track[pnum]].command.angles[i], f)*360.0f/65535; } org = lrp; @@ -1048,8 +1057,8 @@ fixedorg: to = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK]; to->playerstate->pm_type = PM_SPECTATOR; - VectorCopy (cl.simvel[pnum], from->playerstate[cl.playernum[pnum]].velocity); - VectorCopy (cl.simorg[pnum], from->playerstate[cl.playernum[pnum]].origin); + VectorCopy (cl.playerview[pnum].simvel, from->playerstate[cl.playernum[pnum]].velocity); + VectorCopy (cl.playerview[pnum].simorg, from->playerstate[cl.playernum[pnum]].origin); CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]], &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); } @@ -1094,8 +1103,8 @@ fixedorg: if (1)//!independantphysics.msec) { - VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.simvel[pnum]); - VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.simorg[pnum]); + VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.playerview[pnum].simvel); + VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.playerview[pnum].simorg); } else { @@ -1115,16 +1124,16 @@ fixedorg: for (i=0 ; i<3 ; i++) if ( fabs(org[i] - to->playerstate[cl.playernum[pnum]].origin[i]) > 128) { // teleported, so don't lerp - VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.simvel[pnum]); - VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.simorg[pnum]); + VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.playerview[pnum].simvel); + VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.playerview[pnum].simorg); goto out; } for (i=0 ; i<3 ; i++) { - cl.simorg[pnum][i] = org[i] + cl.playerview[pnum].simorg[i] = org[i] + f*(to->playerstate[cl.playernum[pnum]].origin[i] - org[i]); - cl.simvel[pnum][i] = vel[i] + cl.playerview[pnum].simvel[i] = vel[i] + f*(to->playerstate[cl.playernum[pnum]].velocity[i] - vel[i]); } CL_CatagorizePosition(pnum); @@ -1137,6 +1146,7 @@ fixedorg: out: CL_CalcCrouch (pnum, stepheight); cl.waterlevel[pnum] = pmove.waterlevel; + VectorCopy(pmove.gravitydir, cl.playerview[pnum].gravitydir); } void CL_PredictMove (void) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 3c47b461..21ee1cd2 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1021,8 +1021,8 @@ void SCR_CalcRefdef (void) } r_refdef.fov_x = scr_fov.value; - if (cl.stats[0][STAT_VIEWZOOM]) - r_refdef.fov_x *= cl.stats[0][STAT_VIEWZOOM]/255.0f; + if (cl.playerview[r_refdef.currentplayernum].stats[STAT_VIEWZOOM]) + r_refdef.fov_x *= cl.playerview[r_refdef.currentplayernum].stats[STAT_VIEWZOOM]/255.0f; if (r_refdef.fov_x < 1) r_refdef.fov_x = 1; @@ -1055,9 +1055,9 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) vec3_t start; vec3_t right, up, fwds; - AngleVectors(cl.simangles[pnum], fwds, right, up); + AngleVectors(cl.playerview[pnum].simangles, fwds, right, up); - VectorCopy(cl.simorg[pnum], start); + VectorCopy(cl.playerview[pnum].simorg, start); start[2]+=16; VectorMA(start, 100000, fwds, end); @@ -1082,7 +1082,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) adj+=v_viewheight.value; start[2]+=adj; - Matrix4x4_CM_Project(tr.endpos, end, cl.simangles[pnum], start, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(tr.endpos, end, cl.playerview[pnum].simangles, start, r_refdef.fov_x, r_refdef.fov_y); *x = rect.x+rect.width*end[0]; *y = rect.y+rect.height*(1-end[1]); return; @@ -1349,7 +1349,7 @@ void SCR_DrawUPS (void) if (track != -1) vel = cl.frames[cl.validsequence&UPDATE_MASK].playerstate[track].velocity; else - vel = cl.simvel[0]; + vel = cl.playerview[0].simvel; lastups = sqrt((vel[0]*vel[0]) + (vel[1]*vel[1])); lastupstime = t; } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index d7733be4..182271b3 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1780,7 +1780,21 @@ void CL_ClearCustomTEnts(void) customtenttype[i].particleeffecttype = -1; } -void CLDP_ParseTrailParticles(void) +int CL_TranslateParticleFromServer(int sveffect) +{ + if (cl.maxparticleprecaches) + { + /*proper precaches*/ + return cl.particle_precache[sveffect].num; + } + else + { + /*server and client must share an identical effectinfo list file (just "effect $name\n" lines)*/ + return P_FindParticleType(COM_Effectinfo_ForNumber(sveffect)); + } +} + +void CL_ParseTrailParticles(void) { int entityindex; int effectindex; @@ -1797,7 +1811,7 @@ void CLDP_ParseTrailParticles(void) end[1] = MSG_ReadCoord(); end[2] = MSG_ReadCoord(); - effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex)); + effectindex = CL_TranslateParticleFromServer(effectindex); if (entityindex && (unsigned int)entityindex < MAX_EDICTS) ts = &cl.lerpents[entityindex].trailstate; @@ -1808,7 +1822,7 @@ void CLDP_ParseTrailParticles(void) P_ParticleTrail(start, end, rt_blood, entityindex, ts); } -void CLDP_ParsePointParticles(qboolean compact) +void CL_ParsePointParticles(qboolean compact) { vec3_t org, dir; unsigned int count, effectindex; @@ -1830,7 +1844,7 @@ void CLDP_ParsePointParticles(qboolean compact) count = (unsigned short)MSG_ReadShort(); } - effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex)); + effectindex = CL_TranslateParticleFromServer(effectindex); if (P_RunParticleEffectType(org, dir, count, effectindex)) P_RunParticleEffect (org, dir, 15, 15); @@ -2106,6 +2120,10 @@ void CLQ2_ParseTEnt (void) color = splash_color[r]; P_RunParticleEffect (pos, dir, color, cnt); + if (r == Q2SPLASH_BLUE_WATER || r == Q2SPLASH_BROWN_WATER) + { + P_RunParticleEffectTypeString(pos, dir, 1, "te_watersplash"); + } if (r == Q2SPLASH_SPARKS) { r = rand() & 3; @@ -2922,7 +2940,7 @@ void CL_UpdateBeams (void) vieworg = pl->origin; } else - vieworg = cl.simorg[j]; + vieworg = cl.playerview[j].simorg; VectorCopy (vieworg, b->start); b->start[2] += cl.crouch[j] + bound(-7, v_viewheight.value, 4); @@ -2941,10 +2959,10 @@ void CL_UpdateBeams (void) ang[0] = -ang[0]; if (ang[0] < -180) ang[0] += 360; - ang[0] += (cl.simangles[j][0] - ang[0]) * f; + ang[0] += (cl.playerview[j].simangles[0] - ang[0]) * f; // lerp yaw - delta = cl.simangles[j][1] - ang[1]; + delta = cl.playerview[j].simangles[1] - ang[1]; if (delta > 180) delta -= 360; if (delta < -180) @@ -2955,7 +2973,7 @@ void CL_UpdateBeams (void) AngleVectors (ang, fwd, ang, ang); VectorCopy(fwd, ang); VectorScale (fwd, len, fwd); - VectorCopy (cl.simorg[j], org); + VectorCopy (cl.playerview[j].simorg, org); org[2] += 16; VectorAdd (org, fwd, b->end); diff --git a/engine/client/clhl_game.c b/engine/client/clhl_game.c index aed20444..a3b2cf0a 100644 --- a/engine/client/clhl_game.c +++ b/engine/client/clhl_game.c @@ -1,12 +1,29 @@ #include "quakedef.h" -#include "glquake.h" +#include "shader.h" + +#ifdef _WIN32 +#include "winquake.h" +#endif #ifdef HLCLIENT +extern unsigned int r2d_be_flags; struct hlcvar_s *QDECL GHL_CVarGetPointer(char *varname); -#define notimp(l) Con_Printf("halflife cl builtin not implemented on line %i\n", l) +#if defined(_MSC_VER) + #if _MSC_VER >= 1300 + #define __func__ __FUNCTION__ + #else + #define __func__ "unknown" + #endif +#else + //I hope you're c99 and have a __func__ +#endif + +#define ignore(s) Con_Printf("Fixme: " s "\n") +#define notimpl(l) Con_Printf("halflife cl builtin not implemented on line %i\n", l) +#define notimpf(f) Con_Printf("halflife cl builtin %s not implemented\n", f) #if HLCLIENT >= 1 #define HLCL_API_VERSION HLCLIENT @@ -16,6 +33,27 @@ struct hlcvar_s *QDECL GHL_CVarGetPointer(char *varname); +void *vgui_panel; +qboolean VGui_Setup(void) +{ + void *vguidll; + int (QDECL *init)(void); + + dllfunction_t funcs[] = + { + {(void*)&init, "init"}, + {NULL} + }; + + vguidll = Sys_LoadLibrary("vguiwrap", funcs); + + if (vguidll) + vgui_panel = init(); + return !!vgui_panel; +} + + + #define HLPIC model_t* typedef struct @@ -179,7 +217,7 @@ typedef struct int (QDECL *movetypeisnoclip)(void); struct hlclent_s *(QDECL *getlocalplayer)(void); struct hlclent_s *(QDECL *getviewent)(void); - struct hlclent_s *(QDECL *getentidx)(void); + struct hlclent_s *(QDECL *getentidx)(int idx); float (QDECL *getlocaltime)(void); void (QDECL *calcshake)(void); void (QDECL *applyshake)(float *,float *,float); @@ -368,7 +406,7 @@ static mpic_t *getspritepic(HLPIC pic, int frame) mspriteframe_t *f; f = getspriteframe(pic, frame); if (f) - return &f->p; + return f->shader; return NULL; } @@ -380,7 +418,7 @@ int QDECL CLGHL_pic_getheight (HLPIC pic, int frame) if (!pframe) return 0; - return pframe->p.width; + return pframe->shader->width; } int QDECL CLGHL_pic_getwidth (HLPIC pic, int frame) { @@ -390,7 +428,7 @@ int QDECL CLGHL_pic_getwidth (HLPIC pic, int frame) if (!pframe) return 0; - return pframe->p.height; + return pframe->shader->height; } void QDECL CLGHL_pic_select (HLPIC pic, int r, int g, int b) { @@ -432,8 +470,7 @@ void QDECL CLGHL_pic_drawcuradditive (int frame, int x, int y, hlsubrect_t *loc) if (!pic) return; - qglEnable (GL_BLEND); - qglBlendFunc(GL_ONE, GL_ONE); + r2d_be_flags = BEF_FORCEADDITIVE; //use some kind of alpha pic->flags |= 1; @@ -453,7 +490,7 @@ void QDECL CLGHL_pic_drawcuradditive (int frame, int x, int y, hlsubrect_t *loc) 1, 1, pic); } - qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + r2d_be_flags = 0; } void QDECL CLGHL_pic_enablescissor (int x, int y, int width, int height) { @@ -563,7 +600,7 @@ char *QDECL CLGHL_cvar_getstring (char *name) void QDECL CLGHL_cmd_register (char *name, xcommand_t func) { - Cmd_AddRemCommand(name, func); + Cmd_AddCommand(name, func); } void QDECL CLGHL_hooknetmsg (char *msgname, void *func) { @@ -630,7 +667,7 @@ void QDECL CLGHL_startsound_name (char *name, float vol) Con_Printf ("CLGHL_startsound_name: can't cache %s\n", name); return; } - S_StartSound (-1, -1, sfx, vec3_origin, vol, 1); + S_StartSound (-1, -1, sfx, vec3_origin, vol, 1, 0, 0); } void QDECL CLGHL_startsound_idx (int idx, float vol) { @@ -640,7 +677,7 @@ void QDECL CLGHL_startsound_idx (int idx, float vol) Con_Printf ("CLGHL_startsound_name: index not precached %s\n", name); return; } - S_StartSound (-1, -1, sfx, vec3_origin, vol, 1); + S_StartSound (-1, -1, sfx, vec3_origin, vol, 1, 0, 0); } void QDECL CLGHL_anglevectors (float *ina, float *outf, float *outr, float *outu) @@ -703,14 +740,14 @@ int QDECL CLGHL_getwindowcentery(void) } void QDECL CLGHL_getviewnangles(float*ang) { - VectorCopy(cl.viewangles[0], ang); + VectorCopy(cl.playerview[0].viewangles, ang); } void QDECL CLGHL_setviewnangles(float*ang) { - VectorCopy(ang, cl.viewangles[0]); + VectorCopy(ang, cl.playerview[0].viewangles); } -void QDECL CLGHL_getmaxclients(float*ang){notimp(__LINE__);} -void QDECL CLGHL_cvar_setvalue(char *cvarname, char *value){notimp(__LINE__);} +void QDECL CLGHL_getmaxclients(float*ang){notimpf(__func__);} +void QDECL CLGHL_cvar_setvalue(char *cvarname, char *value){notimpf(__func__);} int QDECL CLGHL_cmd_argc(void) { @@ -722,10 +759,10 @@ char *QDECL CLGHL_cmd_argv(int i) } #define CLGHL_con_printf Con_Printf//void CLGHL_con_printf(char *fmt, ...){notimp(__LINE__);} #define CLGHL_con_dprintf Con_DPrintf//void CLGHL_con_dprintf(char *fmt, ...){notimp(__LINE__);} -void QDECL CLGHL_con_notificationprintf(int pos, char *fmt, ...){notimp(__LINE__);} -void QDECL CLGHL_con_notificationprintfex(void *info, char *fmt, ...){notimp(__LINE__);} -char *QDECL CLGHL_physkey(char *key){notimp(__LINE__);return NULL;} -char *QDECL CLGHL_serverkey(char *key){notimp(__LINE__);return NULL;} +void QDECL CLGHL_con_notificationprintf(int pos, char *fmt, ...){notimpf(__func__);} +void QDECL CLGHL_con_notificationprintfex(void *info, char *fmt, ...){notimpf(__func__);} +char *QDECL CLGHL_physkey(char *key){notimpf(__func__);return NULL;} +char *QDECL CLGHL_serverkey(char *key){notimpf(__func__);return NULL;} float QDECL CLGHL_getclientmaxspeed(void) { return 320; @@ -751,35 +788,42 @@ int QDECL CLGHL_keyevent(int key, int down) Con_Printf("CLGHL_keyevent: Unrecognised HL key code\n"); return true; //fixme: check the return type } -void QDECL CLGHL_getmousepos(int *outx, int *outy){notimp(__LINE__);} -int QDECL CLGHL_movetypeisnoclip(void){notimp(__LINE__);return 0;} -struct hlclent_s *QDECL CLGHL_getlocalplayer(void){notimp(__LINE__);return NULL;} -struct hlclent_s *QDECL CLGHL_getviewent(void){notimp(__LINE__);return NULL;} -struct hlclent_s *QDECL CLGHL_getentidx(void){notimp(__LINE__);return NULL;} +void QDECL CLGHL_getmousepos(int *outx, int *outy){notimpf(__func__);} +int QDECL CLGHL_movetypeisnoclip(void){notimpf(__func__);return 0;} +struct hlclent_s *QDECL CLGHL_getlocalplayer(void){notimpf(__func__);return NULL;} +struct hlclent_s *QDECL CLGHL_getviewent(void){notimpf(__func__);return NULL;} +struct hlclent_s *QDECL CLGHL_getentidx(int idx) +{ + notimpf(__func__);return NULL; +} float QDECL CLGHL_getlocaltime(void){return cl.time;} -void QDECL CLGHL_calcshake(void){notimp(__LINE__);} -void QDECL CLGHL_applyshake(float *origin, float *angles, float factor){notimp(__LINE__);} -int QDECL CLGHL_pointcontents(float *point, float *truecon){notimp(__LINE__);return 0;} -int QDECL CLGHL_entcontents(float *point){notimp(__LINE__);return 0;} -void QDECL CLGHL_traceline(float *start, float *end, int flags, int hull, int forprediction){notimp(__LINE__);} +void QDECL CLGHL_calcshake(void){notimpf(__func__);} +void QDECL CLGHL_applyshake(float *origin, float *angles, float factor){notimpf(__func__);} +int QDECL CLGHL_pointcontents(float *point, float *truecon){notimpf(__func__);return 0;} +int QDECL CLGHL_entcontents(float *point){notimpf(__func__);return 0;} +void QDECL CLGHL_traceline(float *start, float *end, int flags, int hull, int forprediction){notimpf(__func__);} -model_t *QDECL CLGHL_loadmodel(char *modelname, int *mdlindex){notimp(__LINE__);return Mod_ForName(modelname, false);} -int QDECL CLGHL_addrentity(int type, void *ent){notimp(__LINE__);return 0;} +model_t *QDECL CLGHL_loadmodel(char *modelname, int *mdlindex){notimpf(__func__);return Mod_ForName(modelname, false);} +int QDECL CLGHL_addrentity(int type, void *ent){notimpf(__func__);return 0;} -model_t *QDECL CLGHL_modelfrompic(HLPIC pic){notimp(__LINE__);return NULL;} -void QDECL CLGHL_soundatloc(char*sound, float volume, float *org){notimp(__LINE__);} +model_t *QDECL CLGHL_modelfrompic(HLPIC pic){notimpf(__func__);return NULL;} +void QDECL CLGHL_soundatloc(char*sound, float volume, float *org){notimpf(__func__);} -unsigned short QDECL CLGHL_precacheevent(int evtype, char *name){notimp(__LINE__);return 0;} -void QDECL CLGHL_playevent(int flags, struct hledict_s *ent, unsigned short evindex, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2){notimp(__LINE__);} +unsigned short QDECL CLGHL_precacheevent(int evtype, char *name){notimpf(__func__);return 0;} +void QDECL CLGHL_playevent(int flags, struct hledict_s *ent, unsigned short evindex, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2){notimpf(__func__);} void QDECL CLGHL_weaponanimate(int newsequence, int body) { hl_viewmodelsequencetime = cl.time; hl_viewmodelsequencecur = newsequence; hl_viewmodelsequencebody = body; } -float QDECL CLGHL_randfloat(float minv, float maxv){notimp(__LINE__);return minv;} -long QDECL CLGHL_randlong(long minv, long maxv){notimp(__LINE__);return minv;} -void QDECL CLGHL_hookevent(char *name, void (*func)(struct hlevent_s *event)){notimp(__LINE__);} +float QDECL CLGHL_randfloat(float minv, float maxv){notimpf(__func__);return minv;} +long QDECL CLGHL_randlong(long minv, long maxv){notimpf(__func__);return minv;} +void QDECL CLGHL_hookevent(char *name, void (*func)(struct hlevent_s *event)) +{ + Con_Printf("CLGHL_hookevent: not implemented. %s\n", name); +// notimpf(__func__); +} int QDECL CLGHL_con_isshown(void) { return scr_con_current > 0; @@ -799,12 +843,20 @@ char *QDECL CLGHL_lookupbinding(char *command) } char *QDECL CLGHL_getlevelname(void) { - return cl.levelname; + if (!cl.worldmodel) + return ""; + return cl.worldmodel->name; +} +void QDECL CLGHL_getscreenfade(struct hlsfade_s *fade){notimpf(__func__);} +void QDECL CLGHL_setscreenfade(struct hlsfade_s *fade){notimpf(__func__);} +void *QDECL CLGHL_vgui_getpanel(void) +{ + return vgui_panel; +} +void QDECL CLGHL_vgui_paintback(int extents[4]) +{ + notimpf(__func__); } -void QDECL CLGHL_getscreenfade(struct hlsfade_s *fade){notimp(__LINE__);} -void QDECL CLGHL_setscreenfade(struct hlsfade_s *fade){notimp(__LINE__);} -void *QDECL CLGHL_vgui_getpanel(void){notimp(__LINE__);return NULL;} -void QDECL CLGHL_vgui_paintback(int extents[4]){notimp(__LINE__);} void *QDECL CLGHL_loadfile(char *path, int alloctype, int *length) { @@ -815,7 +867,7 @@ void *QDECL CLGHL_loadfile(char *path, int alloctype, int *length) flen = FS_LoadFile(path, &ptr); } else - notimp(__LINE__); //don't leak, just fail + notimpf(__func__); //don't leak, just fail if (length) *length = flen; @@ -839,19 +891,19 @@ int QDECL CLGHL_forcedspectator(void) } model_t *QDECL CLGHL_loadmapsprite(char *name) { - notimp(__LINE__);return NULL; + notimpf(__func__);return NULL; } -void QDECL CLGHL_fs_addgamedir(char *basedir, char *appname){notimp(__LINE__);} -int QDECL CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimp(__LINE__);return false;} +void QDECL CLGHL_fs_addgamedir(char *basedir, char *appname){notimpf(__func__);} +int QDECL CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimpf(__func__);return false;} -char *QDECL CLGHL_player_key(int pnum, char *key){notimp(__LINE__);return NULL;} -void QDECL CLGHL_player_setkey(char *key, char *value){notimp(__LINE__);return;} +char *QDECL CLGHL_player_key(int pnum, char *key){notimpf(__func__);return NULL;} +void QDECL CLGHL_player_setkey(char *key, char *value){notimpf(__func__);return;} -qboolean QDECL CLGHL_getcdkey(int playernum, char key[16]){notimp(__LINE__);return false;} -int QDECL CLGHL_trackerfromplayer(int pslot){notimp(__LINE__);return 0;} -int QDECL CLGHL_playerfromtracker(int tracker){notimp(__LINE__);return 0;} -int QDECL CLGHL_sendcmd_unreliable(char *cmd){notimp(__LINE__);return 0;} +qboolean QDECL CLGHL_getcdkey(int playernum, char key[16]){notimpf(__func__);return false;} +int QDECL CLGHL_trackerfromplayer(int pslot){notimpf(__func__);return 0;} +int QDECL CLGHL_playerfromtracker(int tracker){notimpf(__func__);return 0;} +int QDECL CLGHL_sendcmd_unreliable(char *cmd){notimpf(__func__);return 0;} void QDECL CLGHL_getsysmousepos(long *xandy) { #ifdef _WIN32 @@ -887,7 +939,7 @@ int QDECL CLGHL_demo_istimedemo(void) } void QDECL CLGHL_demo_writedata(int size, void *data) { - notimp(__LINE__); + notimpf(__func__); } struct hl_demo_api_s hl_demo_api = @@ -1114,15 +1166,19 @@ void CLHL_LoadClientGame(void) memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs)); - path = NULL; - while((path = COM_NextPath (path))) + clg = Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/cl_dll/Debug/client", funcs); + if (!clg) { - if (!path) - return; // couldn't find one anywhere - snprintf (fullname, sizeof(fullname), "%s/%s", path, "cl_dlls/client"); - clg = Sys_LoadLibrary(fullname, funcs); - if (clg) - break; + path = NULL; + while((path = COM_NextPath (path))) + { + if (!path) + return; // couldn't find one anywhere + snprintf (fullname, sizeof(fullname), "%s/%s", path, "cl_dlls/client"); + clg = Sys_LoadLibrary(fullname, funcs); + if (clg) + break; + } } if (!clg) @@ -1149,6 +1205,8 @@ void CLHL_LoadClientGame(void) CLHL_cgamefuncs.IN_MouseEvent = (void*)Sys_GetAddressForName(clg, "IN_MouseEvent"); #endif + VGui_Setup(); + if (CLHL_cgamefuncs.HUD_Init) CLHL_cgamefuncs.HUD_Init(); if (CLHL_cgamefuncs.HUD_VidInit) @@ -1202,7 +1260,7 @@ int CLHL_DrawHud(void) state.mousesens = 0; state.keys = (in_attack.state[0]&3)?1:0; #endif - state.weapons = cl.stats[0][STAT_ITEMS]; + state.weapons = cl.playerview[0].stats[STAT_ITEMS]; state.fov = 90; V_StopPitchDrift(0); @@ -1226,6 +1284,8 @@ int CLHL_AnimateViewEntity(entity_t *ent) return true; } +explosion_t *CL_AllocExplosion (void); + int CLHL_ParseGamePacket(void) { int subcode; @@ -1286,7 +1346,7 @@ int CLHL_ParseGamePacket(void) if (!(flags & 8)) P_RunParticleEffectType(startp, NULL, 1, pt_explosion); if (!(flags & 4)) - S_StartSound(0, 0, S_PrecacheSound("explosion"), startp, 1, 1); + S_StartSound(0, 0, S_PrecacheSound("explosion"), startp, 1, 1, 0, 0); if (!(flags & 2)) CL_NewDlight(0, startp, 200, 1, 2.0,2.0,2.0); @@ -1409,7 +1469,7 @@ int CLHL_ParseGamePacket(void) break; case 37: //svc_roomtype tempi = MSG_ReadShort(); - SNDDMA_SetUnderWater(tempi==14||tempi==15||tempi==16); + S_SetUnderWater(tempi==14||tempi==15||tempi==16); break; default: Con_Printf("Unrecognised gamecode packet %i (%s)\n", subcode, usermsgs[subcode].name); diff --git a/engine/client/client.h b/engine/client/client.h index 258a736e..49aa4e6e 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -74,6 +74,7 @@ typedef struct qboolean jump_held; int jump_msec; // hack for fixing bunny-hop flickering on non-ZQuake servers vec3_t szmins, szmaxs; + vec3_t gravitydir; float lerpstarttime; int oldframe; @@ -530,20 +531,64 @@ typedef struct int lerpentssequence; lerpents_t lerpplayers[MAX_CLIENTS]; -// information for local display - int stats[MAX_SPLITS][MAX_CL_STATS]; // health, etc - float statsf[MAX_SPLITS][MAX_CL_STATS]; // health, etc - char *statsstr[MAX_SPLITS][MAX_CL_STATS]; // health, etc - float item_gettime[MAX_SPLITS][32]; // cl.time of aquiring item, for blinking - float faceanimtime[MAX_SPLITS]; // use anim frame if cl.time < this - cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups and content types -// the client maintains its own idea of view angles, which are -// sent to the server each frame. And only reset at level change -// and teleport times - vec3_t viewangles[MAX_SPLITS]; - vec3_t viewanglechange[MAX_SPLITS]; + //when running splitscreen, we have multiple viewports all active at once + int splitclients; //we are running this many clients split screen. + struct playerview_s + { + // information for local display + int stats[MAX_CL_STATS]; // health, etc + float statsf[MAX_CL_STATS]; // health, etc + char *statsstr[MAX_CL_STATS]; // health, etc + float item_gettime[32]; // cl.time of aquiring item, for blinking + float faceanimtime; // use anim frame if cl.time < this + + + // the client maintains its own idea of view angles, which are + // sent to the server each frame. And only reset at level change + // and teleport times + vec3_t viewangles; + vec3_t viewanglechange; + vec3_t gravitydir; + + // pitch drifting vars + float pitchvel; + qboolean nodrift; + float driftmove; + double laststop; + + vec3_t simorg; + vec3_t simvel; + vec3_t simangles; + float rollangle; + + qboolean fixangle; //received a fixangle - so disable prediction till the next packet. + qboolean oldfixangle; //received a fixangle - so disable prediction till the next packet. + vec3_t fixangles; //received a fixangle - so disable prediction till the next packet. + vec3_t oldfixangles; //received a fixangle - so disable prediction till the next packet. + } playerview[MAX_SPLITS]; + + float crouch[MAX_SPLITS]; // local amount for smoothing stepups + qboolean onground[MAX_SPLITS]; + float viewheight[MAX_SPLITS]; + + entity_t viewent[MAX_SPLITS]; // weapon model + float punchangle[MAX_SPLITS]; // temporary view kick from weapon firing + + int playernum[MAX_SPLITS]; + qboolean nolocalplayer[MAX_SPLITS]; + + #ifdef PEXT_SETVIEW + int viewentity[MAX_SPLITS]; + #endif + int waterlevel[MAX_SPLITS]; //for smartjump + + // localized movement vars + float entgravity[MAX_SPLITS]; + float maxspeed[MAX_SPLITS]; + float bunnyspeedcap; + int pmovetype[MAX_SPLITS]; // the client simulates or interpolates movement to get these values double time; // this is the time value that the client @@ -558,29 +603,11 @@ typedef struct float oldgametime; //used as the old time to lerp cl.time from. float oldgametimemark; //if it's 0, cl.time will casually increase. - vec3_t simorg[MAX_SPLITS]; - vec3_t simvel[MAX_SPLITS]; - vec3_t simangles[MAX_SPLITS]; - float rollangle[MAX_SPLITS]; - float minpitch; float maxpitch; -// pitch drifting vars - float pitchvel[MAX_SPLITS]; - qboolean nodrift[MAX_SPLITS]; - float driftmove[MAX_SPLITS]; - double laststop[MAX_SPLITS]; - - - float crouch[MAX_SPLITS]; // local amount for smoothing stepups - qboolean onground[MAX_SPLITS]; - float viewheight[MAX_SPLITS]; - qboolean paused; // send over by server - float punchangle[MAX_SPLITS]; // temporar yview kick from weapon firing - int intermission; // don't change view angle, full screen, etc float completed_time; // latched ffrom time at intermission start @@ -605,6 +632,14 @@ typedef struct qboolean model_precaches_added; + struct + { + int num; + char *name; + } *particle_precache; + unsigned int maxparticleprecaches; + + //used for q2 sky/configstrings char skyname[MAX_QPATH]; float skyrotate; @@ -614,9 +649,6 @@ typedef struct vec3_t fog_colour; char levelname[40]; // for display on solo scoreboard - int playernum[MAX_SPLITS]; - qboolean nolocalplayer[MAX_SPLITS]; - int splitclients; //we are running this many clients split screen. // refresh related state struct model_s *worldmodel; // cl_entitites[0].model @@ -625,8 +657,6 @@ typedef struct int cdtrack; // cd audio - entity_t viewent[MAX_SPLITS]; // weapon model - // all player information unsigned int allocated_client_slots; player_info_t players[MAX_CLIENTS]; @@ -635,13 +665,8 @@ typedef struct downloadlist_t *downloadlist; downloadlist_t *faileddownloads; -#ifdef PEXT_SETVIEW - int viewentity[MAX_SPLITS]; -#endif qboolean gamedirchanged; - int waterlevel[MAX_SPLITS]; //for smartjump - char q2statusbar[1024]; char q2layout[1024]; int parse_entities; @@ -655,15 +680,6 @@ typedef struct packet_entities_t *currentpackentities; float currentpacktime; - // localized movement vars - float entgravity[MAX_SPLITS]; - float maxspeed[MAX_SPLITS]; - float bunnyspeedcap; - qboolean fixangle[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. - qboolean oldfixangle[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. - vec3_t fixangles[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. - vec3_t oldfixangles[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. - int pmovetype[MAX_SPLITS]; int teamplay; int deathmatch; @@ -941,6 +957,7 @@ void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result); extern int packet_latency[NET_TIMINGS]; int CL_CalcNet (void); void CL_ClearParseState(void); +void CL_Parse_Disconnected(void); void CL_DumpPacket(void); void CL_ParseEstablished(void); void CLQW_ParseServerMessage (void); @@ -1003,8 +1020,9 @@ void CL_ParseParticleEffect2 (void); void CL_ParseParticleEffect3 (void); void CL_ParseParticleEffect4 (void); -void CLDP_ParseTrailParticles(void); -void CLDP_ParsePointParticles(qboolean compact); +int CL_TranslateParticleFromServer(int sveffect); +void CL_ParseTrailParticles(void); +void CL_ParsePointParticles(qboolean compact); void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, struct model_s *model, int startframe, int framecount, float framerate, float alpha, float randspin, float gravity); /*called from the particlesystem*/ // @@ -1019,6 +1037,7 @@ void CL_ClearProjectiles (void); void CL_ParseProjectiles (int modelindex, qboolean nails2); void CL_ParsePacketEntities (qboolean delta); void CLFTE_ParseEntities (void); +void CLFTE_ParseBaseline(entity_state_t *es, qboolean numberisimportant); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_ParseClientPersist(void); @@ -1055,6 +1074,7 @@ char *CG_GetConfigString(int num); // #ifdef CSQC_DAT qboolean CSQC_Inited(void); +void CSQC_RendererRestarted(void); qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum); void CSQC_RegisterCvarsAndThings(void); qboolean CSQC_DrawView(void); @@ -1220,6 +1240,20 @@ void CLQ2_RunMuzzleFlash2 (int ent, int flash_number); int CLQ2_RegisterTEntModels (void); #endif +#ifdef HLCLIENT +//networking +void CLHL_LoadClientGame(void); +int CLHL_ParseGamePacket(void); +int CLHL_AnimateViewEntity(entity_t *ent); +//screen +int CLHL_DrawHud(void); +//inputs +int CLHL_GamecodeDoesMouse(void); +int CLHL_MouseEvent(unsigned int buttonmask); +void CLHL_SetMouseActive(int activate); +int CLHL_BuildUserInput(int msecs, usercmd_t *cmd); +#endif + #ifdef NQPROT void CLNQ_ParseEntity(unsigned int bits); void NQ_P_ParseParticleEffect (void); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 3f489cbb..b43c529d 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1762,8 +1762,8 @@ void CLQ2_AddViewWeapon (q2player_state_t *ps, q2player_state_t *ops) //generate root matrix.. view = &cl.viewent[0]; - VectorCopy(cl.simorg[0], view->origin); - AngleVectors(cl.simangles[0], view->axis[0], view->axis[1], view->axis[2]); + VectorCopy(cl.playerview[0].simorg, view->origin); + AngleVectors(cl.playerview[0].simangles, view->axis[0], view->axis[1], view->axis[2]); VectorInverse(view->axis[1]); memset (&gun, 0, sizeof(gun)); @@ -1888,8 +1888,8 @@ void CLQ2_CalcViewValues (void) for (i=0 ; i<3 ; i++) r_refdef.viewangles[i] += v_gunkick_q2.value * LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp); - VectorCopy(r_refdef.vieworg, cl.simorg[0]); - VectorCopy(r_refdef.viewangles, cl.simangles[0]); + VectorCopy(r_refdef.vieworg, cl.playerview[0].simorg); + VectorCopy(r_refdef.viewangles, cl.playerview[0].simangles); // VectorCopy(r_refdef.viewangles, cl.viewangles); // AngleVectors (r_refdef.viewangles, v_forward, v_right, v_up); diff --git a/engine/client/console.c b/engine/client/console.c index 3148565c..ca9013fd 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -114,7 +114,9 @@ void Con_Destroy (console_t *con) if (con == &con_main) { - Con_Finit(con); + /*main console is never destroyed, only cleared (unless shutting down)*/ + if (con_initialized) + Con_Finit(con); return; } @@ -541,8 +543,8 @@ void Con_Shutdown(void) { Con_Destroy(con_main.next); } - Con_Destroy(&con_main); con_initialized = false; + Con_Destroy(&con_main); } void TTS_SayConString(conchar_t *stringtosay); diff --git a/engine/client/in_droid.c b/engine/client/in_droid.c index 42f9d0a6..ad4f4eb7 100644 --- a/engine/client/in_droid.c +++ b/engine/client/in_droid.c @@ -251,8 +251,8 @@ void IN_Move (float *movements, int pnum) V_StopPitchDrift (pnum); /*handle looks*/ - cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x * sensitivity.value; - cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y * sensitivity.value; + cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x * sensitivity.value; + cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y * sensitivity.value; mouse_x = mouse_y = 0.0; } diff --git a/engine/client/in_win.c b/engine/client/in_win.c index fc69e2e6..f005db4e 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -290,7 +290,7 @@ Force_CenterView_f */ void Force_CenterView_f (void) { - cl.viewangles[0][PITCH] = 0; + cl.playerview[0].viewangles[PITCH] = 0; } /* @@ -1367,10 +1367,10 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) mouse_y *= sensitivity.value*in_sensitivityscale; } - if (cl.stats[pnum][STAT_VIEWZOOM]) + if (cl.playerview[pnum].stats[STAT_VIEWZOOM]) { - mouse_x *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f; - mouse_y *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f; + mouse_x *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f; + mouse_y *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f; } @@ -1389,7 +1389,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) { // if ((int)((cl.viewangles[pnum][PITCH]+89.99)/180) & 1) // mouse_x *= -1; - cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x; + cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x; } if (in_mlook.state[pnum] & 1) @@ -1397,7 +1397,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1)) { - cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y; + cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y; } else { @@ -2150,11 +2150,11 @@ void IN_JoyMove (float *movements, int pnum) // only absolute control support here (joy_advanced is false) if (m_pitch.value < 0.0) { - cl.viewanglechange[pnum][PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + cl.playerview[pnum].viewanglechange[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; } else { - cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + cl.playerview[pnum].viewanglechange[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; } V_StopPitchDrift(pnum); } @@ -2201,11 +2201,11 @@ void IN_JoyMove (float *movements, int pnum) { if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) { - cl.viewanglechange[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; + cl.playerview[pnum].viewanglechange[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; } else { - cl.viewanglechange[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; + cl.playerview[pnum].viewanglechange[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; } } @@ -2220,11 +2220,11 @@ void IN_JoyMove (float *movements, int pnum) // pitch movement detected and pitch movement desired by user if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) { - cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + cl.playerview[pnum].viewanglechange[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; } else { - cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; + cl.playerview[pnum].viewanglechange[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; } V_StopPitchDrift(pnum); } diff --git a/engine/client/keys.h b/engine/client/keys.h index 6cdc3b2d..4ce83ef0 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -183,6 +183,7 @@ void Key_Init (void); void Key_WriteBindings (vfsfile_t *f); void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel); void Key_ClearStates (void); +void Key_Unbindall_f (void); //aka: Key_Shutdown qboolean Key_GetConsoleSelectionBox(int *sx, int *sy, int *ex, int *ey); qboolean Key_MouseShouldBeFree(void); diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 50b9421a..a50a1f6b 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -3186,7 +3186,10 @@ typedef struct void S_MP3_Abort(sfx_t *sfx) { mp3decoder_t *dec = sfx->decoder.buf; + sfx->decoder.buf = NULL; + sfx->decoder.abort = NULL; + sfx->decoder.decodedata = NULL; qacmStreamClose(dec->acm, 0); diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 0a5e938e..8cd65ebe 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -192,6 +192,7 @@ typedef struct part_type_s { float veladd; //scale the incoming velocity by this much float orgadd; //spawn the particle this far along its velocity direction float spawnvel, spawnvelvert; //spawn the particle with a velocity based upon its spawn type (generally so it flies outwards) + vec3_t orgbias; //static 3d world-coord bias float s1, t1, s2, t2; //texture coords float texsstride; //addition for s for each random slot. @@ -251,6 +252,8 @@ typedef struct part_type_s { float dl_radius; float dl_time; vec4_t dl_decay; + //PT_NODLSHADOW + int dl_cubemapnum; vec3_t stain_rgb; float stain_radius; @@ -275,6 +278,9 @@ typedef struct part_type_s { #define PT_NOSTATE 0x040 // don't use trailstate for this emitter (careful with assoc...) #define PT_NOSPREADFIRST 0x080 // don't randomize org/vel for first generated particle #define PT_NOSPREADLAST 0x100 // don't randomize org/vel for last generated particle +#define PT_TROVERWATER 0x200 // don't spawn if underwater +#define PT_TRUNDERWATER 0x400 // don't spawn if overwater +#define PT_NODLSHADOW 0x800 // dlights from this effect don't cast shadows. unsigned int state; #define PS_INRUNLIST 0x1 // particle type is currently in execution list @@ -516,7 +522,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) for (i = 0; i < ptype->nummodels; i++) ptype->models[i].model = NULL; - if (*ptype->texname) + if (*ptype->texname && ptype->looks.blendmode == BM_BLEND) { /*try and load the shader, fail if we would need to generate one*/ ptype->looks.shader = R_RegisterCustom(ptype->texname, NULL, NULL); @@ -586,7 +592,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "nomipmaps\n" "{\n" "map $diffuse\n" - "blendfunc GL_ZERO GL_ONE_MINUS_SRC_COLOR\n" + "blendfunc GL_ZERO GL_ONE_MINUS_SRC_ALPHA\n" "rgbgen vertex\n" "alphagen vertex\n" "}\n" @@ -1520,6 +1526,18 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) Q_strncatz(outstr, va("rotationstart %g %g\n", ptype->rotationstartmin*180/M_PI, (ptype->rotationstartmin+ptype->rotationstartrand)*180/M_PI), outstrlen); Q_strncatz(outstr, va("rotationspeed %g %g\n", ptype->rotationmin*180/M_PI, (ptype->rotationmin+ptype->rotationrand)*180/M_PI), outstrlen); + + if (ptype->dl_radius) + { + Q_strncatz(outstr, va("lightradius %g %g\n", ptype->dl_radius), outstrlen); + Q_strncatz(outstr, va("lightradiusfade %g \n", ptype->dl_decay[3]), outstrlen); + Q_strncatz(outstr, va("lightrgb %g %g %g\n", ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]), outstrlen); + Q_strncatz(outstr, va("lightrgbfade %g %g %g\n", ptype->dl_decay[0], ptype->dl_decay[1], ptype->dl_decay[2]), outstrlen); + Q_strncatz(outstr, va("lighttime %g\n", ptype->dl_time), outstrlen); + Q_strncatz(outstr, va("lightshadows %g\n", (ptype->flags & PT_NODLSHADOW)?0.0f:1.0f), outstrlen); + Q_strncatz(outstr, va("lightcubemap %i\n", ptype->dl_cubemapnum), outstrlen); + } + return true; #if 0 @@ -1569,10 +1587,6 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) float clipbounce; int stainonimpact; - vec3_t dl_rgb; - float dl_radius; - float dl_time; - vec4_t dl_decay; vec3_t stain_rgb; float stain_radius; @@ -1600,6 +1614,36 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) return false; } +static void P_ExportAllEffects_f(void) +{ + char effect[8192]; + int i; + vfsfile_t *outf; + char fname[64] = "particles/export.cfg"; + FS_CreatePath("particles/", FS_GAMEONLY); + outf = FS_OpenVFS(fname, "wb", FS_GAMEONLY); + if (!outf) + { + FS_NativePath(fname, FS_GAMEONLY, effect, sizeof(effect)); + Con_Printf("Unable to open file %s\n", effect); + return; + } + for (i = 0; i < numparticletypes; i++) + { + PScript_Query(i, 0, effect, sizeof(effect)); + VFS_PUTS(outf, "r_part "); + VFS_PUTS(outf, effect); + VFS_PUTS(outf, "\n{\n"); + PScript_Query(i, 1, effect, sizeof(effect)); + VFS_PUTS(outf, effect); + VFS_PUTS(outf, "}\n"); + } + VFS_CLOSE(outf); + + FS_NativePath(fname, FS_GAMEONLY, effect, sizeof(effect)); + Con_Printf("Written %s\n", effect); +} + #if _DEBUG // R_BeamInfo_f - debug junk static void P_BeamInfo_f (void) @@ -1751,6 +1795,8 @@ static void P_ImportEffectInfo_f(void) if (ptype) { + if (ptype->looks.type == PT_CDECAL) + ptype->scale *= 0.25; FinishParticleType(ptype); } @@ -1780,7 +1826,7 @@ static void P_ImportEffectInfo_f(void) ptype->alpharand = 1; ptype->alphachange = -1; ptype->die = 9999; - strcpy(ptype->texname, "particles/particlefont.tga"); + strcpy(ptype->texname, "particles/particlefont"); ptype->rgb[0] = 1; ptype->rgb[1] = 1; ptype->rgb[2] = 1; @@ -1845,17 +1891,19 @@ static void P_ImportEffectInfo_f(void) { ptype->looks.type = PT_NORMAL; ptype->looks.blendmode = BM_INVMOD; + ptype->gravity = 800*1; } else if (!strcmp(arg[1], "beam")) { ptype->looks.type = PT_BEAM; ptype->looks.blendmode = BM_ADD; } -// else if (!strcmp(arg[1], "snow")) -// { -// ptype->looks.type = PT_NORMAL; -// ptype->looks.blendmode = BM_BLEND; -// } + else if (!strcmp(arg[1], "snow")) + { + ptype->looks.type = PT_NORMAL; + ptype->looks.blendmode = BM_ADD; + //should have some sort of wind/flutter with it + } else { Con_Printf("effectinfo type %s not supported\n", arg[1]); @@ -1878,11 +1926,11 @@ static void P_ImportEffectInfo_f(void) else if (!strcmp(arg[0], "size") && args == 3) { float s1 = atof(arg[1]), s2 = atof(arg[2]); - ptype->scale = s1; - ptype->scalerand = s2-s1; + ptype->scale = s1 * 4; + ptype->scalerand = (s2-s1) * 4; } else if (!strcmp(arg[0], "sizeincrease") && args == 2) - ptype->scaledelta = atof(arg[1]); + ptype->scaledelta = atof(arg[1]) * 4; else if (!strcmp(arg[0], "color") && args == 3) { unsigned int rgb1 = strtoul(arg[1], NULL, 0), rgb2 = strtoul(arg[2], NULL, 0); @@ -1890,7 +1938,8 @@ static void P_ImportEffectInfo_f(void) for (i = 0; i < 3; i++) { ptype->rgb[i] = ((rgb1>>(16-i*8)) & 0xff)/255.0; - ptype->rgbrandsync[i] = (((rgb2>>(16-i*8)) & 0xff) - ((rgb1>>(16-i*8)) & 0xff))/255.0; + ptype->rgbrand[i] = (int)(((rgb2>>(16-i*8)) & 0xff) - ((rgb1>>(16-i*8)) & 0xff))/255.0; + ptype->rgbrandsync[i] = 1; } } else if (!strcmp(arg[0], "alpha") && args == 4) @@ -1908,7 +1957,11 @@ static void P_ImportEffectInfo_f(void) ptype->spawnvelvert = atof(arg[3]); } else if (!strcmp(arg[0], "originoffset") && args == 4) - ; /*a 3d world-coord addition*/ + { /*a 3d world-coord addition*/ + ptype->orgbias[0] = atof(arg[1]); + ptype->orgbias[1] = atof(arg[2]); + ptype->orgbias[2] = atof(arg[3]); + } else if (!strcmp(arg[0], "originjitter") && args == 4) { ptype->areaspread = (atof(arg[1]) + atof(arg[2]))*0.5; @@ -1928,19 +1981,11 @@ static void P_ImportEffectInfo_f(void) else if (!strcmp(arg[0], "liquidfriction") && args == 2) ; else if (!strcmp(arg[0], "underwater") && args == 1) - ; + ptype->flags |= PT_TRUNDERWATER; else if (!strcmp(arg[0], "notunderwater") && args == 1) - ; + ptype->flags |= PT_TROVERWATER; else if (!strcmp(arg[0], "velocitymultiplier") && args == 2) ptype->veladd = atof(arg[1]); - else if (!strcmp(arg[0], "lightradius") && args == 2) - ; - else if (!strcmp(arg[0], "lightradiusfade") && args == 2) - ; - else if (!strcmp(arg[0], "lightcolor") && args == 4) - ; - else if (!strcmp(arg[0], "lighttime") && args == 2) - ; else if (!strcmp(arg[0], "trailspacing") && args == 2) ptype->count = 1 / atof(arg[1]); else if (!strcmp(arg[0], "time") && args == 3) @@ -1955,15 +2000,47 @@ static void P_ImportEffectInfo_f(void) } else if (!strcmp(arg[0], "stretchfactor") && args == 2) ptype->looks.stretch = atof(arg[1]); -#if 0 else if (!strcmp(arg[0], "blend") && args == 2) - ; /*overrides blendmode*/ + { + if (!strcmp(arg[1], "invmod")) + ptype->looks.blendmode = BM_INVMOD; + else if (!strcmp(arg[1], "alpha")) + ptype->looks.blendmode = BM_BLEND; + else if (!strcmp(arg[1], "add")) + ptype->looks.blendmode = BM_ADD; + else + Con_Printf("effectinfo 'blend %s' not supported\n", arg[1]); + } else if (!strcmp(arg[0], "orientation") && args == 2) - ; /*overrides type*/ + { +// if (!strcmp(arg[1], "billboard")) +// ; +// else if (!strcmp(arg[1], "spark")) +// ; +// else if (!strcmp(arg[1], "oriented")) +// ; +// else if (!strcmp(arg[1], "beam")) +// ; +// else + Con_Printf("effectinfo 'orientation %s' not supported\n", arg[1]); + } + else if (!strcmp(arg[0], "lightradius") && args == 2) + ptype->dl_radius = atof(arg[1]); + else if (!strcmp(arg[0], "lightradiusfade") && args == 2) + ptype->dl_decay[3] = atof(arg[1]); + else if (!strcmp(arg[0], "lightcolor") && args == 4) + { + ptype->dl_rgb[0] = atof(arg[1]); + ptype->dl_rgb[1] = atof(arg[2]); + ptype->dl_rgb[2] = atof(arg[3]); + } + else if (!strcmp(arg[0], "lighttime") && args == 2) + ptype->dl_time = atof(arg[1]); else if (!strcmp(arg[0], "lightshadow") && args == 2) - ; + ptype->flags = (ptype->flags & ~PT_NODLSHADOW) | (!atoi(arg[1])?PT_NODLSHADOW:0); else if (!strcmp(arg[0], "lightcubemapnum") && args == 2) - ; + ptype->dl_cubemapnum = atoi(arg[1]); +#if 0 else if (!strcmp(arg[0], "staincolor") && args == 2) ; else if (!strcmp(arg[0], "stainalpha") && args == 2) @@ -1986,6 +2063,8 @@ static void P_ImportEffectInfo_f(void) if (ptype) { + if (ptype->looks.type == PT_CDECAL) + ptype->scale *= 0.25; FinishParticleType(ptype); } @@ -2044,6 +2123,7 @@ static qboolean PScript_InitParticles (void) Cmd_AddCommand("r_exportbuiltinparticles", P_ExportBuiltinSet_f); Cmd_AddCommand("r_importeffectinfo", P_ImportEffectInfo_f); + Cmd_AddCommand("r_exportalleffects", P_ExportAllEffects_f); #if _DEBUG Cmd_AddCommand("r_partinfo", P_PartInfo_f); @@ -2860,6 +2940,10 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir, in dl->channelfade[1] = ptype->dl_decay[1]; dl->channelfade[2] = ptype->dl_decay[2]; dl->decay = ptype->dl_decay[3]; + if (ptype->flags & PT_NODLSHADOW) + dl->flags |= LFLAG_NOSHADOWS; + if (ptype->dl_cubemapnum) + snprintf(dl->cubemapname, sizeof(dl->cubemapname), "cubemaps/%i", ptype->dl_cubemapnum); } if (ptype->stain_radius) R_AddStain(org, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2], ptype->stain_radius); @@ -2891,7 +2975,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int cont; cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, org); - if (cont & FTECONTENTS_WATER) + if (cont & FTECONTENTS_FLUID) ptype = &part_type[ptype->inwater]; } @@ -3388,6 +3472,8 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, p->org[2] -= ptype->orgadd; } + VectorAdd(p->org, ptype->orgbias, p->org); + p->die = particletime + ptype->die - p->die; } @@ -3702,6 +3788,7 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype beamseg_t *b; beamseg_t *bfirst; trailstate_t *ts; + int count; float veladd = -ptype->veladd; float randvel = ptype->randomvel; @@ -3751,6 +3838,17 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype P_ParticleTrail(start, end, ptype->assoc, dlkey, NULL); } + if (r_part_contentswitch.ival && (ptype->flags & (PT_TRUNDERWATER | PT_TROVERWATER)) && cl.worldmodel) + { + int cont; + cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, startpos); + + if ((ptype->flags & PT_TROVERWATER) && (cont & FTECONTENTS_FLUID)) + return; + if ((ptype->flags & PT_TRUNDERWATER) && !(cont & FTECONTENTS_FLUID)) + return; + } + // time limit for trails if (ptype->spawntime && ts) { @@ -3835,7 +3933,17 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype b = bfirst = NULL; - while (len < stop) + if (len < stop) + count = (stop-len) / step; + else + { + count = 0; + step = 0; + VectorClear(vstep); + } + count += ptype->countextra; + + while (count-->0)//len < stop) { len += step; @@ -4086,6 +4194,7 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype p->org[1] += vec[1]*ptype->orgadd; p->org[2] += vec[2]*ptype->orgadd; } + VectorAdd(p->org, ptype->orgbias, p->org); } VectorAdd (start, vstep, start); @@ -4178,12 +4287,12 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlk return 1; // inwater check, switch only once - if (r_part_contentswitch.ival && ptype->inwater >= 0) + if (r_part_contentswitch.ival && ptype->inwater >= 0 && cl.worldmodel) { int cont; cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, startpos); - if (cont & FTECONTENTS_WATER) + if (cont & FTECONTENTS_FLUID) ptype = &part_type[ptype->inwater]; } diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index c20b0b7f..6f89b821 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -205,23 +205,23 @@ static void CSQC_ChangeLocalPlayer(int lplayernum) if (csqcg.view_angles) { - csqcg.view_angles[0] = cl.viewangles[csqc_lplayernum][0]; - csqcg.view_angles[1] = cl.viewangles[csqc_lplayernum][1]; - csqcg.view_angles[2] = cl.viewangles[csqc_lplayernum][2]; + csqcg.view_angles[0] = cl.playerview[csqc_lplayernum].viewangles[0]; + csqcg.view_angles[1] = cl.playerview[csqc_lplayernum].viewangles[1]; + csqcg.view_angles[2] = cl.playerview[csqc_lplayernum].viewangles[2]; } if (dpcompat_corruptglobals.ival) { if (csqcg.pmove_org) { - csqcg.pmove_org[0] = cl.simorg[csqc_lplayernum][0]; - csqcg.pmove_org[1] = cl.simorg[csqc_lplayernum][1]; - csqcg.pmove_org[2] = cl.simorg[csqc_lplayernum][2]; + csqcg.pmove_org[0] = cl.playerview[csqc_lplayernum].simorg[0]; + csqcg.pmove_org[1] = cl.playerview[csqc_lplayernum].simorg[1]; + csqcg.pmove_org[2] = cl.playerview[csqc_lplayernum].simorg[2]; } if (csqcg.input_angles) { - csqcg.input_angles[0] = cl.viewangles[csqc_lplayernum][0]; - csqcg.input_angles[1] = cl.viewangles[csqc_lplayernum][1]; - csqcg.input_angles[2] = cl.viewangles[csqc_lplayernum][2]; + csqcg.input_angles[0] = cl.playerview[csqc_lplayernum].viewangles[0]; + csqcg.input_angles[1] = cl.playerview[csqc_lplayernum].viewangles[1]; + csqcg.input_angles[2] = cl.playerview[csqc_lplayernum].viewangles[2]; } } } @@ -1197,12 +1197,12 @@ static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s break; case VF_CL_VIEWANGLES_V: - VectorCopy(cl.viewangles[csqc_lplayernum], r); + VectorCopy(cl.playerview[csqc_lplayernum].viewangles, r); break; case VF_CL_VIEWANGLES_X: case VF_CL_VIEWANGLES_Y: case VF_CL_VIEWANGLES_Z: - *r = cl.viewangles[csqc_lplayernum][parametertype-VF_CL_VIEWANGLES_X]; + *r = cl.playerview[csqc_lplayernum].viewangles[parametertype-VF_CL_VIEWANGLES_X]; break; case VF_CARTESIAN_ANGLES: @@ -1320,12 +1320,12 @@ static void QCBUILTIN PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s break; case VF_CL_VIEWANGLES_V: - VectorCopy(p, cl.viewangles[csqc_lplayernum]); + VectorCopy(p, cl.playerview[csqc_lplayernum].viewangles); break; case VF_CL_VIEWANGLES_X: case VF_CL_VIEWANGLES_Y: case VF_CL_VIEWANGLES_Z: - cl.viewangles[csqc_lplayernum][parametertype-VF_CL_VIEWANGLES_X] = *p; + cl.playerview[csqc_lplayernum].viewangles[parametertype-VF_CL_VIEWANGLES_X] = *p; break; case VF_CARTESIAN_ANGLES: @@ -1429,13 +1429,13 @@ static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s static void QCBUILTIN PF_cs_getstati(progfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); - G_INT(OFS_RETURN) = cl.stats[csqc_lplayernum][stnum]; + G_INT(OFS_RETURN) = cl.playerview[csqc_lplayernum].stats[stnum]; } static void QCBUILTIN PF_cs_getstatbits(progfuncs_t *prinst, struct globalvars_s *pr_globals) { //convert an int stat into a qc float. int stnum = G_FLOAT(OFS_PARM0); - int val = cl.stats[csqc_lplayernum][stnum]; + int val = cl.playerview[csqc_lplayernum].stats[stnum]; if (*prinst->callargc > 1) { int first, count; @@ -1447,23 +1447,23 @@ static void QCBUILTIN PF_cs_getstatbits(progfuncs_t *prinst, struct globalvars_s G_FLOAT(OFS_RETURN) = (((unsigned int)val)&(((1<>first; } else - G_FLOAT(OFS_RETURN) = cl.statsf[csqc_lplayernum][stnum]; + G_FLOAT(OFS_RETURN) = cl.playerview[csqc_lplayernum].statsf[stnum]; } static void QCBUILTIN PF_cs_getstats(progfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); - RETURN_TSTRING(cl.statsstr[csqc_lplayernum][stnum]); + RETURN_TSTRING(cl.playerview[csqc_lplayernum].statsstr[stnum]); /* char out[17]; //the network protocol byteswaps - ((unsigned int*)out)[0] = LittleLong(cl.stats[csqc_lplayernum][stnum+0]); - ((unsigned int*)out)[1] = LittleLong(cl.stats[csqc_lplayernum][stnum+1]); - ((unsigned int*)out)[2] = LittleLong(cl.stats[csqc_lplayernum][stnum+2]); - ((unsigned int*)out)[3] = LittleLong(cl.stats[csqc_lplayernum][stnum+3]); + ((unsigned int*)out)[0] = LittleLong(cl.playerview[csqc_lplayernum].stats[stnum+0]); + ((unsigned int*)out)[1] = LittleLong(cl.playerview[csqc_lplayernum].stats[stnum+1]); + ((unsigned int*)out)[2] = LittleLong(cl.playerview[csqc_lplayernum].stats[stnum+2]); + ((unsigned int*)out)[3] = LittleLong(cl.playerview[csqc_lplayernum].stats[stnum+3]); ((unsigned int*)out)[4] = 0; //make sure it's null terminated RETURN_TSTRING(out);*/ @@ -1913,7 +1913,7 @@ static void QCBUILTIN PF_cs_trailparticles (progfuncs_t *prinst, struct globalva efnum = G_FLOAT(OFS_PARM1); ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); - efnum = pe->FindParticleType(COM_Effectinfo_ForNumber(efnum)); + efnum = CL_TranslateParticleFromServer(efnum); } else { @@ -1951,7 +1951,7 @@ static void QCBUILTIN PF_cs_particleeffectquery (progfuncs_t *prinst, struct glo if (csqc_isdarkplaces) { //keep the effectinfo synced between server and client. - id = COM_Effectinfo_ForName(COM_Effectinfo_ForNumber(id)); + id = CL_TranslateParticleFromServer(id); } else id = id - 1; @@ -2098,7 +2098,7 @@ static void QCBUILTIN PF_cs_getinputstate (progfuncs_t *prinst, struct globalvar { cmd = &independantphysics[csqc_lplayernum]; for (f=0 ; f<3 ; f++) - cmd->angles[f] = ((int)(cl.viewangles[csqc_lplayernum][f]*65536.0/360)&65535); + cmd->angles[f] = ((int)(cl.playerview[csqc_lplayernum].viewangles[f]*65536.0/360)&65535); } else cmd = &cl.frames[f&UPDATE_MASK].cmd[csqc_lplayernum]; @@ -4782,6 +4782,38 @@ void CSQC_Event_Think(world_t *w, wedict_t *s) PR_ExecuteProgram (w->progs, s->v->think); } +void CSQC_Event_Sound (wedict_t *wentity, int channel, char *sample, int volume, float attenuation, int pitchadj) +{ + int i; + vec3_t origin; + if (wentity->v->solid == SOLID_BSP) + { + for (i=0 ; i<3 ; i++) + origin[i] = wentity->v->origin[i]+0.5*(wentity->v->mins[i]+wentity->v->maxs[i]); + } + else + { + VectorCopy (wentity->v->origin, origin); + } + + S_StartSound(NUM_FOR_EDICT(csqcprogs, (edict_t*)wentity), channel, S_PrecacheSound(sample), origin, volume, attenuation, 0, pitchadj); +} + +qboolean CSQC_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) +{ + if (ent->xv->contentstransition) + { + void *pr_globals = PR_globals(w->progs, PR_CURRENT); + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); + pr_global_struct->time = w->physicstime; + G_FLOAT(OFS_PARM0) = oldwatertype; + G_FLOAT(OFS_PARM1) = newwatertype; + PR_ExecuteProgram (w->progs, ent->xv->contentstransition); + return true; + } + return false; //do legacy behaviour +} + model_t *CSQC_World_ModelForIndex(world_t *w, int modelindex) { return CSQC_GetModelForIndex(modelindex); @@ -5035,6 +5067,8 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) csqc_world.worldmodel = cl.worldmodel; csqc_world.Event_Touch = CSQC_Event_Touch; csqc_world.Event_Think = CSQC_Event_Think; + csqc_world.Event_Sound = CSQC_Event_Sound; + csqc_world.Event_ContentsTransition = CSQC_Event_ContentsTransition; csqc_world.Get_CModel = CSQC_World_ModelForIndex; csqc_world.Get_FrameState = CSQC_World_GetFrameState; csqc_world.defaultgravityscale = 1; @@ -5140,6 +5174,22 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) return true; //success! } +void CSQC_RendererRestarted(void) +{ + int i; + if (!csqcprogs) + return; + + csqc_world.worldmodel = cl.worldmodel; + + for (i = 0; i < MAX_CSQCMODELS; i++) + { + cl.model_csqcprecache[i] = NULL; + } + + //FIXME: registered shaders +} + void CSQC_WorldLoaded(void) { csqcedict_t *worldent; @@ -5347,11 +5397,9 @@ void CSQC_CvarChanged(cvar_t *var) qboolean CSQC_DrawView(void) { -#ifdef USEODE int ticlimit = 10; - float ft; float mintic = 0.01; -#endif + double clframetime = host_frametime; if (!csqcg.draw_function || !csqcprogs || !cl.worldmodel) return false; @@ -5361,28 +5409,28 @@ qboolean CSQC_DrawView(void) if (csqcg.frametime) *csqcg.frametime = host_frametime; -#ifdef USEODE while(1) { - ft = cl.servertime - csqc_world.physicstime; - if (ft < mintic) + host_frametime = cl.servertime - csqc_world.physicstime; + if (host_frametime < mintic) break; if (!--ticlimit) { csqc_world.physicstime = cl.servertime; break; } - if (ft > mintic) - ft = mintic; - csqc_world.physicstime += ft; + if (host_frametime > mintic) + host_frametime = mintic; + csqc_world.physicstime += host_frametime; - World_ODE_Frame(&csqc_world, ft, 800); +#ifdef USEODE + World_ODE_Frame(&csqc_world, host_frametime, 800); +#endif World_Physics_Frame(&csqc_world); } -#else - csqc_world.physicstime = cl.servertime; -#endif + + host_frametime = clframetime; if (csqcg.frametime) *csqcg.frametime = host_frametime; diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index fcaaf16d..d8d432aa 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -183,6 +183,11 @@ extern "C" { #define min(a,b) ((a) < (b) ? (a) : (b)) #endif +#ifdef USE_MSVCRT_DEBUG +#define USE_MSVCRT_DEBUG +#define _CRTDBG_MAP_ALLOC +#include +#endif #ifdef _WIN32 #if (_MSC_VER >= 1400) diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 48a7995b..c9f68fb7 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -81,6 +81,19 @@ qbyte GetPaletteIndex(int red, int green, int blue) } } +void R2D_Shutdown(void) +{ + Cvar_Unhook(&gl_font); + Cvar_Unhook(&vid_conautoscale); + Cvar_Unhook(&gl_screenangle); + Cvar_Unhook(&vid_conheight); + Cvar_Unhook(&vid_conwidth); + + Cvar_Unhook(&crosshair); + Cvar_Unhook(&crosshairimage); + Cvar_Unhook(&crosshaircolor); +} + /* Iniitalise the 2d rendering functions (including font). Image loading code must be ready for use at this point. diff --git a/engine/client/r_d3.c b/engine/client/r_d3.c index 91b9c215..5facc833 100644 --- a/engine/client/r_d3.c +++ b/engine/client/r_d3.c @@ -90,7 +90,10 @@ qboolean Mod_LoadMap_Proc(model_t *model, char *data) return false; b[surf].meshes = 1; b[surf].mesh = (mesh_t**)&m[surf]; - b[surf].lightmap = -1; + b[surf].lightmap[0] = -1; + b[surf].lightmap[1] = -1; + b[surf].lightmap[2] = -1; + b[surf].lightmap[3] = -1; data = COM_ParseOut(data, token, sizeof(token)); b[surf].shader = R_RegisterShader_Vertex(token); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 8d149150..59b82293 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.h" #include "shader.h" #include "renderque.h" +#include "com_mesh.h" #include extern cvar_t r_ambient; @@ -36,9 +37,6 @@ model_t *currentmodel; int lightmap_bytes; // 1, 3 or 4 qboolean lightmap_bgra; -texid_t *lightmap_textures; -texid_t *deluxmap_textures; - #define MAX_LIGHTMAP_SIZE LMBLOCK_WIDTH vec3_t blocknormals[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; @@ -85,6 +83,7 @@ void Surf_StainSurf (msurface_t *surf, float *parms) int lim; mtexinfo_t *tex; stmap *stainbase; + lightmapinfo_t *lm; lim = 255 - (r_stains.value*255); @@ -92,15 +91,16 @@ void Surf_StainSurf (msurface_t *surf, float *parms) change = stainbase[(s)*3+x] + amm*parms[4+x]; \ stainbase[(s)*3+x] = bound(lim, change, 255); - if (surf->lightmaptexturenum < 0) + if (surf->lightmaptexturenums[0] < 0) return; + lm = lightmap[surf->lightmaptexturenums[0]]; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; tex = surf->texinfo; - stainbase = lightmap[surf->lightmaptexturenum]->stainmaps; - stainbase += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; + stainbase = lm->stainmaps; + stainbase += (surf->light_t[0] * lm->width + surf->light_s[0]) * 3; rad = *parms; dist = DotProduct ((parms+1), surf->plane->normal) - surf->plane->dist; @@ -145,7 +145,7 @@ void Surf_StainSurf (msurface_t *surf, float *parms) surf->stained = true; } } - stainbase += 3*LMBLOCK_WIDTH; + stainbase += 3*lm->width; } if (surf->stained) @@ -245,7 +245,7 @@ void Surf_WipeStains(void) { if (!lightmap[i]) break; - memset(lightmap[i]->stainmaps, 255, sizeof(lightmap[i]->stainmaps)); + memset(lightmap[i]->stainmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3*sizeof(stmap)); } } @@ -260,6 +260,7 @@ void Surf_LessenStains(void) int stride; int ammount; int limit; + lightmapinfo_t *lm; static float time; @@ -279,15 +280,17 @@ void Surf_LessenStains(void) { if (surf->stained) { + lm = lightmap[surf->lightmaptexturenums[0]]; + surf->cached_dlight=-1;//nice hack here... smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; - stain = lightmap[surf->lightmaptexturenum]->stainmaps; - stain += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; + stain = lm->stainmaps; + stain += (surf->light_t[0] * lm->width + surf->light_s[0]) * 3; - stride = (LMBLOCK_WIDTH-smax)*3; + stride = (lm->width-smax)*3; surf->stained = false; @@ -1164,9 +1167,10 @@ void Surf_RenderDynamicLightmaps (msurface_t *fa) int maps; glRect_t *theRect; int smax, tmax; + lightmapinfo_t *lm; //surfaces without lightmaps - if (fa->lightmaptexturenum<0) + if (fa->lightmaptexturenums[0]<0) return; // check for lightmap modification @@ -1192,58 +1196,60 @@ void Surf_RenderDynamicLightmaps (msurface_t *fa) dynamic: RSpeedRemark(); - lightmap[fa->lightmaptexturenum]->modified = true; + lm = lightmap[fa->lightmaptexturenums[0]]; + + lm->modified = true; smax = (fa->extents[0]>>4)+1; tmax = (fa->extents[1]>>4)+1; - theRect = &lightmap[fa->lightmaptexturenum]->rectchange; - if (fa->light_t < theRect->t) { + theRect = &lm->rectchange; + if (fa->light_t[0] < theRect->t) { if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; + theRect->h += theRect->t - fa->light_t[0]; + theRect->t = fa->light_t[0]; } - if (fa->light_s < theRect->l) { + if (fa->light_s[0] < theRect->l) { if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; + theRect->w += theRect->l - fa->light_s[0]; + theRect->l = fa->light_s[0]; } - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s-theRect->l)+smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t-theRect->t)+tmax; + if ((theRect->w + theRect->l) < (fa->light_s[0] + smax)) + theRect->w = (fa->light_s[0]-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) + theRect->h = (fa->light_t[0]-theRect->t)+tmax; if (r_deluxemapping.ival) { - lightmap[fa->lightmaptexturenum]->deluxmodified = true; - theRect = &lightmap[fa->lightmaptexturenum]->deluxrectchange; - if (fa->light_t < theRect->t) { + lm->deluxmodified = true; + theRect = &lm->deluxrectchange; + if (fa->light_t[0] < theRect->t) { if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; + theRect->h += theRect->t - fa->light_t[0]; + theRect->t = fa->light_t[0]; } - if (fa->light_s < theRect->l) { + if (fa->light_s[0] < theRect->l) { if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; + theRect->w += theRect->l - fa->light_s[0]; + theRect->l = fa->light_s[0]; } - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s-theRect->l)+smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t-theRect->t)+tmax; + if ((theRect->w + theRect->l) < (fa->light_s[0] + smax)) + theRect->w = (fa->light_s[0]-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) + theRect->h = (fa->light_t[0]-theRect->t)+tmax; - luxbase = lightmap[fa->lightmaptexturenum]->deluxmaps; - luxbase += fa->light_t * LMBLOCK_WIDTH * 3 + fa->light_s * 3; + luxbase = lm->deluxmaps; + luxbase += fa->light_t[0] * lm->width * 3 + fa->light_s[0] * 3; } else luxbase = NULL; - base = lightmap[fa->lightmaptexturenum]->lightmaps; - base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; - stainbase = lightmap[fa->lightmaptexturenum]->stainmaps; - stainbase += (fa->light_t * LMBLOCK_WIDTH + fa->light_s) * 3; + base = lm->lightmaps; + base += fa->light_t[0] * lm->width * lightmap_bytes + fa->light_s[0] * lightmap_bytes; + stainbase = lm->stainmaps; + stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; Surf_BuildLightMap (fa, base, luxbase, stainbase, lightmap_shift, r_ambient.value*255); RSpeedEnd(RSPEED_DYNAMIC); @@ -1256,12 +1262,13 @@ void Surf_RenderAmbientLightmaps (msurface_t *fa, int ambient) stmap *stainbase; glRect_t *theRect; int smax, tmax; + lightmapinfo_t *lm; if (!fa->mesh) return; //surfaces without lightmaps - if (fa->lightmaptexturenum<0) + if (fa->lightmaptexturenums[0]<0) return; if (fa->cached_light[0] != ambient || fa->cached_colour[0] != 0xff) @@ -1274,58 +1281,64 @@ void Surf_RenderAmbientLightmaps (msurface_t *fa, int ambient) dynamic: RSpeedRemark(); - lightmap[fa->lightmaptexturenum]->modified = true; + lm = lightmap[fa->lightmaptexturenums[0]]; + + lm->modified = true; smax = (fa->extents[0]>>4)+1; tmax = (fa->extents[1]>>4)+1; - theRect = &lightmap[fa->lightmaptexturenum]->rectchange; - if (fa->light_t < theRect->t) { + theRect = &lm->rectchange; + if (fa->light_t[0] < theRect->t) + { if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; + theRect->h += theRect->t - fa->light_t[0]; + theRect->t = fa->light_t[0]; } - if (fa->light_s < theRect->l) { + if (fa->light_s[0] < theRect->l) + { if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; + theRect->w += theRect->l - fa->light_s[0]; + theRect->l = fa->light_s[0]; } - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s-theRect->l)+smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t-theRect->t)+tmax; + if ((theRect->w + theRect->l) < (fa->light_s[0] + smax)) + theRect->w = (fa->light_s[0]-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) + theRect->h = (fa->light_t[0]-theRect->t)+tmax; if (r_deluxemapping.ival) { - lightmap[fa->lightmaptexturenum]->deluxmodified = true; - theRect = &lightmap[fa->lightmaptexturenum]->deluxrectchange; - if (fa->light_t < theRect->t) { + lm->deluxmodified = true; + theRect = &lm->deluxrectchange; + if (fa->light_t[0] < theRect->t) + { if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; + theRect->h += theRect->t - fa->light_t[0]; + theRect->t = fa->light_t[0]; } - if (fa->light_s < theRect->l) { + if (fa->light_s[0] < theRect->l) + { if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; + theRect->w += theRect->l - fa->light_s[0]; + theRect->l = fa->light_s[0]; } - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s-theRect->l)+smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t-theRect->t)+tmax; + if ((theRect->w + theRect->l) < (fa->light_s[0] + smax)) + theRect->w = (fa->light_s[0]-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) + theRect->h = (fa->light_t[0]-theRect->t)+tmax; - luxbase = lightmap[fa->lightmaptexturenum]->deluxmaps; - luxbase += fa->light_t * LMBLOCK_WIDTH * 3 + fa->light_s * 3; + luxbase = lm->deluxmaps; + luxbase += fa->light_t[0] * lm->width * 3 + fa->light_s[0] * 3; } else luxbase = NULL; - base = lightmap[fa->lightmaptexturenum]->lightmaps; - base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; - stainbase = lightmap[fa->lightmaptexturenum]->stainmaps; - stainbase += (fa->light_t * LMBLOCK_WIDTH + fa->light_s) * 3; + base = lm->lightmaps; + base += fa->light_t[0] * lm->width * lightmap_bytes + fa->light_s[0] * lightmap_bytes; + stainbase = lm->stainmaps; + stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; Surf_BuildLightMap (fa, base, luxbase, stainbase, lightmap_shift, -1-ambient); RSpeedEnd(RSPEED_DYNAMIC); @@ -1516,11 +1529,10 @@ static void Surf_OrthoRecursiveWorldNode (mnode_t *node, unsigned int clipflags) { //when rendering as ortho the front and back sides are technically equal. the only culling comes from frustum culling. - int c, side, clipped; - mplane_t *plane, *clipplane; + int c, clipped; + mplane_t *clipplane; msurface_t *surf, **mark; mleaf_t *pleaf; - double dot; if (node->contents == Q1CONTENTS_SOLID) return; // solid @@ -1528,7 +1540,7 @@ static void Surf_OrthoRecursiveWorldNode (mnode_t *node, unsigned int clipflags) if (node->visframe != r_visframecount) return; - for (c = 0, clipplane = frustum; c < FRUSTUMPLANES; c++, clipplane++) + for (c = 0, clipplane = frustum; c < 4; c++, clipplane++) { if (!(clipflags & (1 << c))) continue; // don't need to clip against it @@ -1887,7 +1899,7 @@ static void Surf_CleanChains(void) void Surf_SetupFrame(void) { mleaf_t *leaf; - vec3_t temp; + vec3_t temp, pvsorg; R_AnimateLight(); r_framecount++; @@ -1948,19 +1960,23 @@ void Surf_SetupFrame(void) } else { - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; if (r_refdef.recurse) - r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_refdef.pvsorigin); + { + VectorCopy(r_refdef.pvsorigin, pvsorg); + } else - r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_origin); + { + VectorCopy(r_origin, pvsorg); + } + + r_viewleaf = RMod_PointInLeaf (cl.worldmodel, pvsorg); if (!r_viewleaf) { } else if (r_viewleaf->contents == Q1CONTENTS_EMPTY) { //look down a bit - VectorCopy (r_origin, temp); + VectorCopy (pvsorg, temp); temp[2] -= 16; leaf = RMod_PointInLeaf (cl.worldmodel, temp); if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA) @@ -1971,7 +1987,7 @@ void Surf_SetupFrame(void) else if (r_viewleaf->contents <= Q1CONTENTS_WATER && r_viewleaf->contents >= Q1CONTENTS_LAVA) { //in water, look up a bit. - VectorCopy (r_origin, temp); + VectorCopy (pvsorg, temp); temp[2] += 16; leaf = RMod_PointInLeaf (cl.worldmodel, temp); if (leaf->contents == Q1CONTENTS_EMPTY) @@ -2263,8 +2279,6 @@ void Surf_DrawWorld (void) } } - - /* ============================================================================= @@ -2272,7 +2286,7 @@ void Surf_DrawWorld (void) ============================================================================= */ - +#ifdef TERRAIN // returns a texture number and the position inside it int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) { @@ -2290,22 +2304,21 @@ int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) lightmap[numlightmaps+2] = NULL; lightmap[numlightmaps+3] = NULL; - lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); - memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); +// lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); +// memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); - deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); - memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); +// deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); +// memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); numlightmaps+=4; } if (!lightmap[texnum]) { lightmap[texnum] = Z_Malloc(sizeof(*lightmap[texnum])); - lightmap[texnum]->meshchain = NULL; lightmap[texnum]->modified = true; - lightmap[texnum]->shader = shader; +// lightmap[texnum]->shader = shader; lightmap[texnum]->external = true; // reset stainmap since it now starts at 255 - memset(lightmap[texnum]->stainmaps, 255, sizeof(lightmap[texnum]->stainmaps)); + memset(lightmap[texnum]->stainmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3*sizeof(stmap)); //clear out the deluxmaps incase there is none on the map. for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3; j+=3) @@ -2317,13 +2330,13 @@ int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) } /*not required, but using one lightmap per texture can result in better texture unit switching*/ - if (lightmap[texnum]->shader != shader) - continue; +// if (lightmap[texnum]->shader != shader) +// continue; if (lightmap[texnum]->external) { - TEXASSIGN(lightmap_textures[texnum], R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); - TEXASSIGN(deluxmap_textures[texnum], R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + TEXASSIGN(lightmap[texnum]->lightmap_texture, R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + TEXASSIGN(lightmap[texnum]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); lightmap[texnum]->external = false; } @@ -2359,6 +2372,9 @@ int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) Sys_Error ("AllocBlock: full"); return 0; } +#endif + +#if 0 //quake3 maps have their lightmaps in gl style already. //rather than forgetting that and redoing it, let's just keep the data. @@ -2385,7 +2401,6 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) if (!lightmap[i]) { lightmap[i] = BZ_Malloc(sizeof(*lightmap[i])); - lightmap[i]->meshchain = NULL; lightmap[i]->modified = true; lightmap[i]->external = true; for (l=0 ; lnumedges; } +#if 0 /* ================ BuildSurfaceDisplayList @@ -2581,13 +2598,15 @@ void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa, void **mem) mesh->colors4f_array[i][3] = 1; } } +#endif +#if 0 /* ======================== GL_CreateSurfaceLightmap ======================== */ -static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) +void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) { int smax, tmax; qbyte *base, *luxbase; stmap *stainbase; @@ -2634,6 +2653,7 @@ static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) Surf_BuildLightMap (surf, base, luxbase, stainbase, shift, r_ambient.value*255); } +#endif @@ -2641,26 +2661,15 @@ void Surf_DeInit(void) { int i; - if (lightmap_textures) - { - for (i = 0; i < numlightmaps; i++) - { - if (!lightmap[i] || lightmap[i]->external) - { - R_DestroyTexture(lightmap_textures[i]); - R_DestroyTexture(deluxmap_textures[i]); - } - } - BZ_Free(lightmap_textures); - BZ_Free(deluxmap_textures); - } - lightmap_textures=NULL; - deluxmap_textures = NULL; - for (i = 0; i < numlightmaps; i++) { if (!lightmap[i]) break; + if (lightmap[i]->external) + { + R_DestroyTexture(lightmap[i]->lightmap_texture); + R_DestroyTexture(lightmap[i]->deluxmap_texture); + } BZ_Free(lightmap[i]); lightmap[i] = NULL; } @@ -2670,6 +2679,8 @@ void Surf_DeInit(void) lightmap=NULL; numlightmaps=0; + + Alias_Shutdown(); } void Surf_Clear(model_t *mod) @@ -2679,16 +2690,6 @@ void Surf_Clear(model_t *mod) int i; if (mod->fromgame == fg_doom3) return;/*they're on the hunk*/ - for (i = 0; i < SHADER_SORT_COUNT; i++) - { - while ((b = mod->batches[i])) - { - mod->batches[i] = b->next; - - BZ_Free(b->mesh); - Z_Free(b); - } - } while(mod->vbos) { vbo = mod->vbos; @@ -2758,7 +2759,7 @@ Groups surfaces into their respective batches (based on the lightmap number). */ void Surf_BuildLightmaps (void) { - int i, j, t; + int i, j, k, t; model_t *m; int shift; msurface_t *surf; @@ -2784,6 +2785,154 @@ void Surf_BuildLightmaps (void) if (cl.worldmodel->fromgame == fg_doom) return; //no lightmaps. + numlightmaps = 0; + + for (j=1 ; jtype != mod_brush) + continue; + + if (!m->lightmaps.count) + continue; + if (m->needload) + continue; + + currentmodel = m; + shift = Surf_LightmapShift(currentmodel); + + i = numlightmaps + m->lightmaps.count; + lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i)); + while(i > numlightmaps) + { + i--; + + lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*m->lightmaps.width*m->lightmaps.height); + lightmap[i]->width = m->lightmaps.width; + lightmap[i]->height = m->lightmaps.height; + lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); + lightmap[i]->deluxmaps = (qbyte*)(lightmap[i]->lightmaps+4*lightmap[i]->width*lightmap[i]->height); + lightmap[i]->stainmaps = (stmap*)(lightmap[i]->deluxmaps+4*lightmap[i]->width*lightmap[i]->height); + + lightmap[i]->modified = true; +// lightmap[i]->shader = NULL; + lightmap[i]->external = false; + // reset stainmap since it now starts at 255 + memset(lightmap[i]->stainmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3*sizeof(stmap)); + + //clear out the deluxmaps incase there is none on the map. + for (k = 0; k < lightmap[i]->width*lightmap[i]->height*3; k+=3) + { + lightmap[i]->deluxmaps[k+0] = 128; + lightmap[i]->deluxmaps[k+1] = 128; + lightmap[i]->deluxmaps[k+2] = 255; + } + + TEXASSIGN(lightmap[i]->lightmap_texture, R_AllocNewTexture("***lightmap***", lightmap[i]->width, lightmap[i]->height)); + TEXASSIGN(lightmap[i]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", lightmap[i]->width, lightmap[i]->height)); + } + + //fixup batch lightmaps + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) + { + for (i = 0; i < MAXLIGHTMAPS; i++) + { + if (batch->lightmap[i] < 0) + continue; + batch->lightmap[i] = batch->lightmap[i] - m->lightmaps.first + numlightmaps; + } + } + + + /*particle emision based upon texture. this is lazy code*/ + if (m == cl.worldmodel) + { + for (t = m->numtextures-1; t >= 0; t--) + { + ptype = P_FindParticleType(va("tex_%s", m->textures[t]->name)); + + if (ptype != P_INVALID) + { + for (i=0; inummodelsurfaces; i++) + { + surf = m->surfaces + i + m->firstmodelsurface; + if (surf->texinfo->texture == m->textures[t]) + P_EmitSkyEffectTris(m, surf, ptype); + } + } + } + } + + + if (m->fromgame == fg_quake3) + { + int j; + unsigned char *src; + unsigned char *dst; + for (i = 0; i < m->lightmaps.count; i++) + { + dst = lightmap[numlightmaps+i]->lightmaps; + src = m->lightdata + i*m->lightmaps.width*m->lightmaps.height*3; + if (lightmap_bytes == 4) + { + if (lightmap_bgra) + { + for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 4, src += 3) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = 255; + } + } + else + { + for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 4, src += 3) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 255; + } + } + } + } + } + else + { + int j; + lightmapinfo_t *lm; + //fixup surface lightmaps, and paint + for (i=0; inummodelsurfaces; i++) + { + surf = m->surfaces + i + m->firstmodelsurface; + for (j = 0; j < 4; j++) + { + if (surf->lightmaptexturenums[j] < m->lightmaps.first) + { + surf->lightmaptexturenums[j] = -1; + continue; + } + surf->lightmaptexturenums[j] = surf->lightmaptexturenums[0] - m->lightmaps.first + numlightmaps; + + lm = lightmap[surf->lightmaptexturenums[j]]; + + Surf_BuildLightMap (surf, + lm->lightmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * lightmap_bytes, + lm->deluxmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * 3, + lm->stainmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * 3, + shift, r_ambient.value*255); + } + } + } + m->lightmaps.first = numlightmaps; + + numlightmaps += m->lightmaps.count; + } +#if 0 for (j=1 ; jbatches[sortid]; batch != NULL; batch = batch->next) { @@ -2907,7 +3057,7 @@ void Surf_BuildLightmaps (void) batch->meshes = 0; } } - +#endif BE_UploadAllLightmaps(); } #endif diff --git a/engine/client/render.h b/engine/client/render.h index b5942e78..9034db80 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -163,11 +163,14 @@ typedef struct vrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/ qboolean externalview; /*draw external models and not viewmodels*/ qboolean recurse; /*in a mirror/portal/half way through drawing something else*/ + qboolean forcevis; /*if true, vis comes from the forcedvis field instead of recalculated*/ qboolean flipcull; /*reflected/flipped view, requires inverted culling*/ qboolean useperspective; /*not orthographic*/ int postprocshader; /*if set, renders to texture then invokes this shader*/ int postproccube; /*postproc shader wants a cubemap, this is the mask of sides required*/ + + qbyte *forcedvis; } refdef_t; extern refdef_t r_refdef; @@ -210,22 +213,26 @@ typedef struct glRect_s { typedef unsigned char stmap; struct mesh_s; typedef struct { - struct mesh_s *meshchain; + texid_t lightmap_texture; + texid_t deluxmap_texture; qboolean modified; qboolean deluxmodified; qboolean external; + int width; + int height; glRect_t rectchange; glRect_t deluxrectchange; +#ifdef TERRAIN int allocated[LMBLOCK_WIDTH]; - qbyte lightmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; - qbyte deluxmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //fixme: make seperate structure for easy disabling with less memory usage. - stmap stainmaps[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. - shader_t *shader; +#endif + qbyte *lightmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; + qbyte *deluxmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //fixme: make seperate structure for easy disabling with less memory usage. + stmap *stainmaps;//[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. } lightmapinfo_t; extern lightmapinfo_t **lightmap; extern int numlightmaps; -extern texid_t *lightmap_textures; -extern texid_t *deluxmap_textures; +//extern texid_t *lightmap_textures; +//extern texid_t *deluxmap_textures; extern int lightmap_bytes; // 1, 3, or 4 extern qboolean lightmap_bgra; /*true=bgra, false=rgba*/ #endif @@ -299,6 +306,15 @@ texid_t D3D9_AllocNewTexture(char *ident, int width, int height); void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); void D3D9_DestroyTexture (texid_t tex); void D3D_Image_Shutdown(void); + +texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); +texid_t D3D11_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); +texid_t D3D11_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); +texid_t D3D11_LoadCompressed (char *name); +texid_t D3D11_FindTexture (char *identifier); +texid_t D3D11_AllocNewTexture(char *ident, int width, int height); +void D3D11_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); +void D3D11_DestroyTexture (texid_t tex); #endif extern int image_width, image_height; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 8e2fff21..14895f2e 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -213,6 +213,9 @@ extern cvar_t r_waterwarp; cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0.05"); cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "25"); +cvar_t r_polygonoffset_stencil_factor = SCVAR("r_polygonoffset_stencil_factor", "0.01"); +cvar_t r_polygonoffset_stencil_offset = SCVAR("r_polygonoffset_stencil_offset", "1"); + rendererstate_t currentrendererstate; #if defined(GLQUAKE) @@ -457,9 +460,10 @@ void R_InitTextures (void) { int x,y, m; qbyte *dest; + static char r_notexture_mip_mem[(sizeof(texture_t) + 16*16+8*8+4*4+2*2)]; // create a simple checkerboard texture for the default - r_notexture_mip = Z_Malloc (sizeof(texture_t) + 16*16+8*8+4*4+2*2); + r_notexture_mip = (texture_t*)r_notexture_mip_mem; r_notexture_mip->width = r_notexture_mip->height = 16; r_notexture_mip->offsets[0] = sizeof(texture_t); @@ -649,6 +653,8 @@ void Renderer_Init(void) Cvar_Register (&r_showbboxes, GLRENDEREROPTIONS); Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS); Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS); + Cvar_Register (&r_polygonoffset_stencil_factor, GLRENDEREROPTIONS); + Cvar_Register (&r_polygonoffset_stencil_offset, GLRENDEREROPTIONS); // misc Cvar_Register(&con_ocranaleds, "Console controls"); @@ -939,6 +945,11 @@ void R_ShutdownRenderer(void) COM_FlushTempoaryPacks(); + W_Shutdown(); + if (host_basepal) + BZ_Free(host_basepal); + host_basepal = NULL; + S_Shutdown(); } @@ -1296,6 +1307,10 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n")); } Skin_FlushPlayers(); + +#ifdef CSQC_DAT + CSQC_RendererRestarted(); +#endif } else { @@ -1829,35 +1844,47 @@ qbyte *R_MarkLeaves_Q2 (void) int c; - if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2) - return vis; + if (r_refdef.forcevis) + { + vis = r_refdef.forcedvis; - r_oldviewcluster = r_viewcluster; - r_oldviewcluster2 = r_viewcluster2; + r_oldviewcluster = 0; + r_oldviewcluster2 = 0; + } + else + { + if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2) + return vis; + + r_oldviewcluster = r_viewcluster; + r_oldviewcluster2 = r_viewcluster2; + + if (r_novis.ival == 2) + return vis; + + if (r_novis.ival || r_viewcluster == -1 || !cl.worldmodel->vis) + { + // mark everything + for (i=0 ; inumleafs ; i++) + cl.worldmodel->leafs[i].visframe = r_visframecount; + for (i=0 ; inumnodes ; i++) + cl.worldmodel->nodes[i].visframe = r_visframecount; + return vis; + } + + vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, curframevis, sizeof(curframevis)); + // may have to combine two clusters because of solid water boundaries + if (r_viewcluster2 != r_viewcluster) + { + vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster2, NULL, sizeof(curframevis)); + c = (cl.worldmodel->numleafs+31)/32; + for (i=0 ; ivis) - { - // mark everything - for (i=0 ; inumleafs ; i++) - cl.worldmodel->leafs[i].visframe = r_visframecount; - for (i=0 ; inumnodes ; i++) - cl.worldmodel->nodes[i].visframe = r_visframecount; - return vis; - } - - vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, curframevis, sizeof(curframevis)); - // may have to combine two clusters because of solid water boundaries - if (r_viewcluster2 != r_viewcluster) - { - vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster2, NULL, sizeof(curframevis)); - c = (cl.worldmodel->numleafs+31)/32; - for (i=0 ; ileafs ; inumleafs ; i++, leaf++) { @@ -1922,35 +1949,45 @@ qbyte *R_MarkLeaves_Q1 (void) int i; qbyte solid[4096]; - if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2) - return vis; - - r_visframecount++; - - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; - - if (r_novis.ival) + if (r_refdef.forcevis) { - vis = solid; - memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); - } - else if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) - { - int c; - Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis, sizeof(fatvis)); - vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); - c = (cl.worldmodel->numleafs+31)/32; - for (i=0 ; inumleafs+7)>>3); + } + else if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) + { + int c; + Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis, sizeof(fatvis)); + vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); + c = (cl.worldmodel->numleafs+31)/32; + for (i=0 ; inumleafs ; i++) { if (vis[i>>3] & (1<<(i&7))) diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 9af8a8ed..effbbdb5 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -406,7 +406,7 @@ void Sbar_ExecuteLayoutString (char *s) s = COM_Parse (s); time = atoi(com_token); -// DrawAltString (x+32, y, ci->name); + Draw_AltFunString (x+32, y, cl.players[value].name); Draw_FunString (x+32, y+8, "Score: "); Draw_AltFunString (x+32+7*8, y+8, va("%i", score)); Draw_FunString (x+32, y+16, va("Ping: %i", ping)); @@ -685,7 +685,7 @@ void Sbar_Hexen2InvLeft_f(void) if (sb_hexen2_cur_item[pnum] < 0) sb_hexen2_cur_item[pnum] = 14; - if (cl.stats[pnum][STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) + if (cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) break; } } @@ -707,7 +707,7 @@ void Sbar_Hexen2InvRight_f(void) if (sb_hexen2_cur_item[pnum] > 14) sb_hexen2_cur_item[pnum] = 0; - if (cl.stats[pnum][STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) + if (cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) break; } } @@ -1432,11 +1432,12 @@ void Sbar_CoopScoreboard (void) char str[80]; int minutes, seconds, tens, units; int l; + int pnum = 0; //doesn't matter, should all be the same - sprintf (str,"Monsters:%3i /%3i", cl.stats[0][STAT_MONSTERS], cl.stats[0][STAT_TOTALMONSTERS]); + sprintf (str,"Monsters:%3i /%3i", cl.playerview[pnum].stats[STAT_MONSTERS], cl.playerview[pnum].stats[STAT_TOTALMONSTERS]); Sbar_DrawString (8, 4, str); - sprintf (str,"Secrets :%3i /%3i", cl.stats[0][STAT_SECRETS], cl.stats[0][STAT_TOTALSECRETS]); + sprintf (str,"Secrets :%3i /%3i", cl.playerview[pnum].stats[STAT_SECRETS], cl.playerview[pnum].stats[STAT_TOTALSECRETS]); Sbar_DrawString (8, 12, str); // time @@ -1477,7 +1478,7 @@ void Sbar_DrawInventory (int pnum) { if (sbar_rogue) { - if ( cl.stats[pnum][STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) + if ( cl.playerview[pnum].stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[0]); else Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[1]); @@ -1488,15 +1489,15 @@ void Sbar_DrawInventory (int pnum) // weapons for (i=0 ; i<7 ; i++) { - if (cl.stats[pnum][STAT_ITEMS] & (IT_SHOTGUN<= 10) { - if ( cl.stats[pnum][STAT_ACTIVEWEAPON] == (IT_SHOTGUN<= RIT_LAVA_NAILGUN ) + if ( cl.playerview[pnum].stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) { for (i=0;i<5;i++) { - if (cl.stats[pnum][STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) + if (cl.playerview[pnum].stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) { if (headsup) { @@ -1551,7 +1552,7 @@ void Sbar_DrawInventory (int pnum) } for (i=0 ; i<4 ; i++) { - snprintf (num, sizeof(num), "%3i",cl.stats[pnum][STAT_SHELLS+i] ); + snprintf (num, sizeof(num), "%3i",cl.playerview[pnum].stats[STAT_SHELLS+i] ); numc[0] = CON_WHITEMASK|0xe000|((num[0]!=' ')?(num[0] + 18-'0'):' '); numc[1] = CON_WHITEMASK|0xe000|((num[1]!=' ')?(num[1] + 18-'0'):' '); numc[2] = CON_WHITEMASK|0xe000|((num[2]!=' ')?(num[2] + 18-'0'):' '); @@ -1570,9 +1571,9 @@ void Sbar_DrawInventory (int pnum) // items for (i=0 ; i<6 ; i++) { - if (cl.stats[pnum][STAT_ITEMS] & (1<<(17+i))) + if (cl.playerview[pnum].stats[STAT_ITEMS] & (1<<(17+i))) { - time = cl.item_gettime[pnum][17+i]; + time = cl.playerview[pnum].item_gettime[17+i]; if (time && time > cl.time - 2 && flashon ) { // flash frame sb_updates = 0; @@ -1589,9 +1590,9 @@ void Sbar_DrawInventory (int pnum) // new rogue items for (i=0 ; i<2 ; i++) { - if (cl.stats[pnum][STAT_ITEMS] & (1<<(29+i))) + if (cl.playerview[pnum].stats[STAT_ITEMS] & (1<<(29+i))) { - time = cl.item_gettime[pnum][29+i]; + time = cl.playerview[pnum].item_gettime[29+i]; if (time && time > cl.time - 2 && flashon ) { // flash frame @@ -1612,9 +1613,9 @@ void Sbar_DrawInventory (int pnum) // sigils for (i=0 ; i<4 ; i++) { - if (cl.stats[pnum][STAT_ITEMS] & (1<<(28+i))) + if (cl.playerview[pnum].stats[STAT_ITEMS] & (1<<(28+i))) { - time = cl.item_gettime[pnum][28+i]; + time = cl.playerview[pnum].item_gettime[28+i]; if (time && time > cl.time - 2 && flashon ) { // flash frame sb_updates = 0; @@ -1704,37 +1705,37 @@ void Sbar_DrawFace (int pnum) { int f, anim; - if ( (cl.stats[pnum][STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) + if ( (cl.playerview[pnum].stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) ) { Sbar_DrawPic (112, 0, 24, 24, sb_face_invis_invuln); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_QUAD) + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_QUAD) { Sbar_DrawPic (112, 0, 24, 24, sb_face_quad ); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_INVISIBILITY) + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_INVISIBILITY) { Sbar_DrawPic (112, 0, 24, 24, sb_face_invis ); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_INVULNERABILITY) + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_INVULNERABILITY) { Sbar_DrawPic (112, 0, 24, 24, sb_face_invuln); return; } - if (cl.stats[pnum][STAT_HEALTH] >= 100) + if (cl.playerview[pnum].stats[STAT_HEALTH] >= 100) f = 4; else - f = cl.stats[pnum][STAT_HEALTH] / 20; + f = cl.playerview[pnum].stats[STAT_HEALTH] / 20; if (f < 0) f=0; - if (cl.time <= cl.faceanimtime[pnum]) + if (cl.time <= cl.playerview[pnum].faceanimtime) { anim = 1; sb_updates = 0; // make sure the anim gets drawn over @@ -1755,7 +1756,7 @@ void Sbar_DrawNormal (int pnum) Sbar_DrawPic (0, 0, 320, 24, sb_sbar); // armor - if (cl.stats[pnum][STAT_ITEMS] & IT_INVULNERABILITY) + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_INVULNERABILITY) { Sbar_DrawNum (24, 0, 666, 3, 1); Sbar_DrawPic (0, 0, 24, 24, draw_disc); @@ -1764,24 +1765,24 @@ void Sbar_DrawNormal (int pnum) { if (sbar_rogue) { - Sbar_DrawNum (24, 0, cl.stats[pnum][STAT_ARMOR], 3, - cl.stats[pnum][STAT_ARMOR] <= 25); - if (cl.stats[pnum][STAT_ITEMS] & RIT_ARMOR3) + Sbar_DrawNum (24, 0, cl.playerview[pnum].stats[STAT_ARMOR], 3, + cl.playerview[pnum].stats[STAT_ARMOR] <= 25); + if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_ARMOR3) Sbar_DrawPic (0, 0, 24, 24, sb_armor[2]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_ARMOR2) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_ARMOR2) Sbar_DrawPic (0, 0, 24, 24, sb_armor[1]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_ARMOR1) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_ARMOR1) Sbar_DrawPic (0, 0, 24, 24, sb_armor[0]); } else { - Sbar_DrawNum (24, 0, cl.stats[pnum][STAT_ARMOR], 3, - cl.stats[pnum][STAT_ARMOR] <= 25); - if (cl.stats[pnum][STAT_ITEMS] & IT_ARMOR3) + Sbar_DrawNum (24, 0, cl.playerview[pnum].stats[STAT_ARMOR], 3, + cl.playerview[pnum].stats[STAT_ARMOR] <= 25); + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_ARMOR3) Sbar_DrawPic (0, 0, 24, 24, sb_armor[2]); - else if (cl.stats[pnum][STAT_ITEMS] & IT_ARMOR2) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_ARMOR2) Sbar_DrawPic (0, 0, 24, 24, sb_armor[1]); - else if (cl.stats[pnum][STAT_ITEMS] & IT_ARMOR1) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_ARMOR1) Sbar_DrawPic (0, 0, 24, 24, sb_armor[0]); } } @@ -1790,41 +1791,41 @@ void Sbar_DrawNormal (int pnum) Sbar_DrawFace (pnum); // health - Sbar_DrawNum (136, 0, cl.stats[pnum][STAT_HEALTH], 3 - , cl.stats[pnum][STAT_HEALTH] <= 25); + Sbar_DrawNum (136, 0, cl.playerview[pnum].stats[STAT_HEALTH], 3 + , cl.playerview[pnum].stats[STAT_HEALTH] <= 25); // ammo icon if (sbar_rogue) { - if (cl.stats[pnum][STAT_ITEMS] & RIT_SHELLS) + if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_SHELLS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[0]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_NAILS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_NAILS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[1]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_ROCKETS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_ROCKETS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[2]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_CELLS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_CELLS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[3]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_LAVA_NAILS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_LAVA_NAILS) Sbar_DrawPic (224, 0, 24, 24, rsb_ammo[0]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_PLASMA_AMMO) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_PLASMA_AMMO) Sbar_DrawPic (224, 0, 24, 24, rsb_ammo[1]); - else if (cl.stats[pnum][STAT_ITEMS] & RIT_MULTI_ROCKETS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) Sbar_DrawPic (224, 0, 24, 24, rsb_ammo[2]); } else { - if (cl.stats[pnum][STAT_ITEMS] & IT_SHELLS) + if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_SHELLS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[0]); - else if (cl.stats[pnum][STAT_ITEMS] & IT_NAILS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_NAILS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[1]); - else if (cl.stats[pnum][STAT_ITEMS] & IT_ROCKETS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_ROCKETS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[2]); - else if (cl.stats[pnum][STAT_ITEMS] & IT_CELLS) + else if (cl.playerview[pnum].stats[STAT_ITEMS] & IT_CELLS) Sbar_DrawPic (224, 0, 24, 24, sb_ammo[3]); } - Sbar_DrawNum (248, 0, cl.stats[pnum][STAT_AMMO], 3 - , cl.stats[pnum][STAT_AMMO] <= 10); + Sbar_DrawNum (248, 0, cl.playerview[pnum].stats[STAT_AMMO], 3 + , cl.playerview[pnum].stats[STAT_AMMO] <= 10); } qboolean Sbar_ShouldDraw (void) @@ -1874,7 +1875,7 @@ void Sbar_DrawScoreboard (void) for (pnum = 0; pnum < cl.splitclients; pnum++) { - if (cl.stats[pnum][STAT_HEALTH] <= 0) + if (cl.playerview[pnum].stats[STAT_HEALTH] <= 0) deadcount++; } @@ -1901,7 +1902,7 @@ void Sbar_Hexen2DrawItem(int pnum, int x, int y, int itemnum) int num; Sbar_DrawPic(x, y, 29, 28, R2D_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); - num = cl.stats[pnum][STAT_H2_CNT_TORCH+itemnum]; + num = cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+itemnum]; if(num > 0) { if (num >= 10) @@ -1920,7 +1921,7 @@ void Sbar_Hexen2DrawInventory(int pnum) /*always select an artifact that we actually have whether we are drawing the full bar or not.*/ for (i = 0; i < 15; i++) { - if (cl.stats[pnum][STAT_H2_CNT_TORCH+(i+sb_hexen2_cur_item[pnum])%15]) + if (cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+(i+sb_hexen2_cur_item[pnum])%15]) { sb_hexen2_cur_item[pnum] = (sb_hexen2_cur_item[pnum] + i)%15; break; @@ -1931,10 +1932,10 @@ void Sbar_Hexen2DrawInventory(int pnum) return; for (i = sb_hexen2_cur_item[pnum]; i < 15; i++) - if (sb_hexen2_cur_item[pnum] == i || cl.stats[pnum][STAT_H2_CNT_TORCH+i] > 0) + if (sb_hexen2_cur_item[pnum] == i || cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+i] > 0) activeright++; for (i = sb_hexen2_cur_item[pnum]-1; i >= 0; i--) - if (sb_hexen2_cur_item[pnum] == i || cl.stats[pnum][STAT_H2_CNT_TORCH+i] > 0) + if (sb_hexen2_cur_item[pnum] == i || cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+i] > 0) activeleft++; if (activeleft > 3 + (activeright<=3?(4-activeright):0)) @@ -1942,7 +1943,7 @@ void Sbar_Hexen2DrawInventory(int pnum) x=320/2-114 + (activeleft-1)*33; for (i = sb_hexen2_cur_item[pnum]-1; x>=320/2-114; i--) { - if (!cl.stats[pnum][STAT_H2_CNT_TORCH+i]) + if (!cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+i]) continue; if (i == sb_hexen2_cur_item[pnum]) @@ -1954,7 +1955,7 @@ void Sbar_Hexen2DrawInventory(int pnum) x=320/2-114 + activeleft*33; for (i = sb_hexen2_cur_item[pnum]; i < 15 && x < 320/2-114+7*33; i++) { - if (i != sb_hexen2_cur_item[pnum] && !cl.stats[pnum][STAT_H2_CNT_TORCH+i]) + if (i != sb_hexen2_cur_item[pnum] && !cl.playerview[pnum].stats[STAT_H2_CNT_TORCH+i]) continue; if (i == sb_hexen2_cur_item[pnum]) Sbar_DrawPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); @@ -1985,7 +1986,7 @@ void Sbar_Hexen2DrawExtra (int pnum) Con_Printf("Objectives:\n"); for (i = 0; i < 64; i++) { - if (cl.stats[pnum][STAT_H2_OBJECTIVE1 + i/32] & (1<<(i&31))) + if (cl.playerview[pnum].stats[STAT_H2_OBJECTIVE1 + i/32] & (1<<(i&31))) Con_Printf("%s\n", T_GetInfoString(i)); } sb_hexen2_infoplaque[pnum] = false; @@ -2011,44 +2012,44 @@ void Sbar_Hexen2DrawExtra (int pnum) Sbar_DrawTinyString (11, 48, pclassname[pclass]); Sbar_DrawTinyString (11, 58, va("int")); - Sbar_DrawTinyString (33, 58, va("%02d", cl.stats[pnum][STAT_H2_INTELLIGENCE])); + Sbar_DrawTinyString (33, 58, va("%02d", cl.playerview[pnum].stats[STAT_H2_INTELLIGENCE])); Sbar_DrawTinyString (11, 64, va("wis")); - Sbar_DrawTinyString (33, 64, va("%02d", cl.stats[pnum][STAT_H2_WISDOM])); + Sbar_DrawTinyString (33, 64, va("%02d", cl.playerview[pnum].stats[STAT_H2_WISDOM])); Sbar_DrawTinyString (11, 70, va("dex")); - Sbar_DrawTinyString (33, 70, va("%02d", cl.stats[pnum][STAT_H2_DEXTERITY])); + Sbar_DrawTinyString (33, 70, va("%02d", cl.playerview[pnum].stats[STAT_H2_DEXTERITY])); Sbar_DrawTinyString (58, 58, va("str")); - Sbar_DrawTinyString (80, 58, va("%02d", cl.stats[pnum][STAT_H2_STRENGTH])); + Sbar_DrawTinyString (80, 58, va("%02d", cl.playerview[pnum].stats[STAT_H2_STRENGTH])); Sbar_DrawTinyString (58, 64, va("lvl")); - Sbar_DrawTinyString (80, 64, va("%02d", cl.stats[pnum][STAT_H2_LEVEL])); + Sbar_DrawTinyString (80, 64, va("%02d", cl.playerview[pnum].stats[STAT_H2_LEVEL])); Sbar_DrawTinyString (58, 70, va("exp")); - Sbar_DrawTinyString (80, 70, va("%06d", cl.stats[pnum][STAT_H2_EXPERIENCE])); + Sbar_DrawTinyString (80, 70, va("%06d", cl.playerview[pnum].stats[STAT_H2_EXPERIENCE])); Sbar_DrawTinyString (11, 79, va("abilities")); - if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<22)) + if (cl.playerview[pnum].stats[STAT_H2_FLAGS] & (1<<22)) Sbar_DrawTinyString (8, 89, T_GetString(400 + 2*(pclass-1) + 0)); - if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<23)) + if (cl.playerview[pnum].stats[STAT_H2_FLAGS] & (1<<23)) Sbar_DrawTinyString (8, 96, T_GetString(400 + 2*(pclass-1) + 1)); for (i = 0; i < 4; i++) { - if (cl.stats[pnum][STAT_H2_ARMOUR1+i] > 0) + if (cl.playerview[pnum].stats[STAT_H2_ARMOUR1+i] > 0) { Sbar_DrawPic (164+i*40, 115, 28, 19, R2D_SafeCachePic(va("gfx/armor%d.lmp", i+1))); - Sbar_DrawTinyString (168+i*40, 136, va("+%d", cl.stats[pnum][STAT_H2_ARMOUR1+i])); + Sbar_DrawTinyString (168+i*40, 136, va("+%d", cl.playerview[pnum].stats[STAT_H2_ARMOUR1+i])); } } for (i = 0; i < 4; i++) { - if (cl.stats[pnum][STAT_H2_FLIGHT_T+i] > 0) + if (cl.playerview[pnum].stats[STAT_H2_FLIGHT_T+i] > 0) { Sbar_DrawPic (ringpos[i], 119, 32, 22, R2D_SafeCachePic(va("gfx/ring_f.lmp"))); - val = cl.stats[pnum][STAT_H2_FLIGHT_T+i]; + val = cl.playerview[pnum].stats[STAT_H2_FLIGHT_T+i]; if (val > 100) val = 100; if (val < 0) @@ -2061,9 +2062,9 @@ void Sbar_Hexen2DrawExtra (int pnum) slot = 0; for (i = 0; i < 8; i++) { - if (cl.statsstr[pnum][STAT_H2_PUZZLE1+i]) + if (cl.playerview[pnum].statsstr[STAT_H2_PUZZLE1+i]) { - Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, 26, 26, R2D_SafeCachePic(va("gfx/puzzle/%s.lmp", cl.statsstr[pnum][STAT_H2_PUZZLE1+i]))); + Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, 26, 26, R2D_SafeCachePic(va("gfx/puzzle/%s.lmp", cl.playerview[pnum].statsstr[STAT_H2_PUZZLE1+i]))); slot++; } } @@ -2095,10 +2096,10 @@ int Sbar_Hexen2ArmourValue(int pnum) classno--; for (i = 0; i < 4; i++) { - if (cl.stats[pnum][STAT_H2_ARMOUR1+i]) + if (cl.playerview[pnum].stats[STAT_H2_ARMOUR1+i]) { ac += acv[classno][i]; - ac += cl.stats[pnum][STAT_H2_ARMOUR1+i]/5.0; + ac += cl.playerview[pnum].stats[STAT_H2_ARMOUR1+i]/5.0; } } } @@ -2116,8 +2117,8 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_DrawPic(269, -23, 51, 23, R2D_SafeCachePic("gfx/topbumpr.lmp")); //mana1 - maxval = cl.stats[pnum][STAT_H2_MAXMANA]; - val = cl.stats[pnum][STAT_H2_BLUEMANA]; + maxval = cl.playerview[pnum].stats[STAT_H2_MAXMANA]; + val = cl.playerview[pnum].stats[STAT_H2_BLUEMANA]; val = bound(0, val, maxval); Sbar_DrawTinyString(201, 22, va("%03d", val)); if(val) @@ -2127,8 +2128,8 @@ void Sbar_Hexen2DrawBasic(int pnum) } //mana2 - maxval = cl.stats[pnum][STAT_H2_MAXMANA]; - val = cl.stats[pnum][STAT_H2_GREENMANA]; + maxval = cl.playerview[pnum].stats[STAT_H2_MAXMANA]; + val = cl.playerview[pnum].stats[STAT_H2_GREENMANA]; val = bound(0, val, maxval); Sbar_DrawTinyString(243, 22, va("%03d", val)); if(val) @@ -2139,7 +2140,7 @@ void Sbar_Hexen2DrawBasic(int pnum) //health - val = cl.stats[pnum][STAT_HEALTH]; + val = cl.playerview[pnum].stats[STAT_HEALTH]; if (val < -99) val = -99; Sbar_Hexen2DrawNum(58, 14, val, 3); @@ -2149,7 +2150,7 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_Hexen2DrawNum(105, 14, val, 2); // SetChainPosition(cl.v.health, cl.v.max_health); - chainpos = (195.0f*cl.stats[pnum][STAT_HEALTH]) / cl.stats[pnum][STAT_H2_MAXHEALTH]; + chainpos = (195.0f*cl.playerview[pnum].stats[STAT_HEALTH]) / cl.playerview[pnum].stats[STAT_H2_MAXHEALTH]; if (chainpos < 0) chainpos = 0; Sbar_DrawPic(45+((int)chainpos&7), 38, 222, 5, R2D_SafeCachePic("gfx/hpchain.lmp")); @@ -2168,10 +2169,10 @@ void Sbar_Hexen2DrawMinimal(int pnum) Sbar_DrawPic(3, y, 31, 17, R2D_SafeCachePic("gfx/bmmana.lmp")); Sbar_DrawPic(3, y+18, 31, 17, R2D_SafeCachePic("gfx/gmmana.lmp")); - Sbar_DrawTinyString(10, y+6, va("%03d", cl.stats[pnum][STAT_H2_BLUEMANA])); - Sbar_DrawTinyString(10, y+18+6, va("%03d", cl.stats[pnum][STAT_H2_GREENMANA])); + Sbar_DrawTinyString(10, y+6, va("%03d", cl.playerview[pnum].stats[STAT_H2_BLUEMANA])); + Sbar_DrawTinyString(10, y+18+6, va("%03d", cl.playerview[pnum].stats[STAT_H2_GREENMANA])); - Sbar_Hexen2DrawNum(38, y+18, cl.stats[pnum][STAT_HEALTH], 3); + Sbar_Hexen2DrawNum(38, y+18, cl.playerview[pnum].stats[STAT_HEALTH], 3); } @@ -2420,14 +2421,14 @@ void Sbar_Draw (void) if (sbarfailed) //files failed to load. { - if (cl.stats[pnum][STAT_HEALTH] <= 0) //when dead, show nothing + if (cl.playerview[pnum].stats[STAT_HEALTH] <= 0) //when dead, show nothing continue; // if (scr_viewsize.value != 120) // Cvar_Set(&scr_viewsize, "120"); - Sbar_DrawString (0, -8, va("Health: %i", cl.stats[pnum][STAT_HEALTH])); - Sbar_DrawString (0, -16, va(" Armor: %i", cl.stats[pnum][STAT_ARMOR])); + Sbar_DrawString (0, -8, va("Health: %i", cl.playerview[pnum].stats[STAT_HEALTH])); + Sbar_DrawString (0, -16, va(" Armor: %i", cl.playerview[pnum].stats[STAT_ARMOR])); Sbar_Voice(-24); continue; @@ -2457,7 +2458,7 @@ void Sbar_Draw (void) } else { - if (sb_showscores || sb_showteamscores || cl.stats[pnum][STAT_HEALTH] <= 0) + if (sb_showscores || sb_showteamscores || cl.playerview[pnum].stats[STAT_HEALTH] <= 0) Sbar_SoloScoreboard (); // else if (cls.gamemode != GAME_DEATHMATCH) // Sbar_CoopScoreboard (); @@ -2472,7 +2473,7 @@ void Sbar_Draw (void) } } } - else if (sb_showscores || sb_showteamscores || (cl.stats[pnum][STAT_HEALTH] <= 0 && cl.splitclients == 1)) + else if (sb_showscores || sb_showteamscores || (cl.playerview[pnum].stats[STAT_HEALTH] <= 0 && cl.splitclients == 1)) { if (!pnum) { @@ -3216,6 +3217,7 @@ void Sbar_CoopIntermission (void) mpic_t *pic; int dig; int num; + int pnum = 0; //should be the same for all players. sbar_rect.width = vid.width; sbar_rect.height = vid.height; @@ -3240,13 +3242,13 @@ void Sbar_CoopIntermission (void) R2D_ScalePic ((sbar_rect.width - 320)/2 + 266,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); //it is assumed that secrits/monsters are going to be constant for any player... - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 104, cl.stats[0][STAT_SECRETS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_SECRETS], 3, 0); R2D_ScalePic ((sbar_rect.width - 320)/2 + 232,(sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 104, cl.stats[0][STAT_TOTALSECRETS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_TOTALSECRETS], 3, 0); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 144, cl.stats[0][STAT_MONSTERS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_MONSTERS], 3, 0); R2D_ScalePic ((sbar_rect.width - 320)/2 + 232,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 144, cl.stats[0][STAT_TOTALMONSTERS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_TOTALMONSTERS], 3, 0); } /* ================== diff --git a/engine/client/snd_al.c b/engine/client/snd_al.c index 41da19a0..bfc06c1d 100644 --- a/engine/client/snd_al.c +++ b/engine/client/snd_al.c @@ -658,7 +658,7 @@ static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum) sc->GetDMAPos = OpenAL_GetDMAPos; sc->ChannelUpdate = OpenAL_ChannelUpdate; - snprintf(sc->name, sizeof(sc->name), "OpenAL device"); + Q_snprintfz(sc->name, sizeof(sc->name), "OpenAL device"); sc->openal = 1; sc->inactive_sound = true; diff --git a/engine/client/snd_directx.c b/engine/client/snd_directx.c index 802953b5..3d770abb 100644 --- a/engine/client/snd_directx.c +++ b/engine/client/snd_directx.c @@ -275,7 +275,7 @@ typedef struct { GUID SubFormat; } QWAVEFORMATEX; -const static GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, +const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, {0x80, 0x00, 0x00, @@ -574,7 +574,7 @@ int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum) { format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; format.Format.cbSize = 22; - memcpy(&format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); + memcpy(&format.SubFormat, &QKSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); format.dwChannelMask = KSAUDIO_SPEAKER_7POINT1; sc->sn.numchannels = 8; @@ -583,7 +583,7 @@ int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum) { format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; format.Format.cbSize = 22; - memcpy(&format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); + memcpy(&format.SubFormat, &QKSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); format.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; sc->sn.numchannels = 6; @@ -592,7 +592,7 @@ int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum) { format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; format.Format.cbSize = 22; - memcpy(&format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); + memcpy(&format.SubFormat, &QKSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); format.dwChannelMask = KSAUDIO_SPEAKER_QUAD; sc->sn.numchannels = 4; diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index ad9f9e24..612c5736 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -30,6 +30,7 @@ static void S_StopAllSounds_f (void); static void S_UpdateCard(soundcardinfo_t *sc); static void S_ClearBuffer (soundcardinfo_t *sc); +static sfx_t *S_FindName (char *name); // ======================================================================= // Internal sound data & structures @@ -883,7 +884,7 @@ void S_Startup (void) CL_InitTEntSounds(); } -void SNDDMA_SetUnderWater(qboolean underwater) +void S_SetUnderWater(qboolean underwater) { soundcardinfo_t *sc; @@ -895,6 +896,8 @@ void SNDDMA_SetUnderWater(qboolean underwater) //so that the video code can call it directly without flushing the models it's just loaded. void S_DoRestart (void) { + int i; + S_StopAllSounds (true); S_Shutdown(); @@ -907,6 +910,14 @@ void S_DoRestart (void) ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); S_StopAllSounds (true); + + + for (i=1 ; icache); + return ResampleSfx (s, rate, 1, 1, samples, -1, data); } #endif @@ -739,7 +737,7 @@ S_LoadSound_t AudioInputPlugins[10] = S_LoadWavSound, #ifdef DOOMWADS S_LoadDoomSound, - S_LoadDoomSpeakerSound, +// S_LoadDoomSpeakerSound, #endif }; @@ -784,7 +782,7 @@ qboolean S_LoadSound (sfx_t *s) FILE *f; #ifndef _WIN32 //convert from windows to a suitable alternative. char unixname[128]; - snprintf(unixname, sizeof(unixname), "/mnt/%c/%s", name[0]-'A'+'a', name+3); + Q_snprintfz(unixname, sizeof(unixname), "/mnt/%c/%s", name[0]-'A'+'a', name+3); name = unixname; while (*name) { diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index 69a87a6c..9acc710c 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -228,33 +228,24 @@ sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, } void OV_CancelDecoder(sfx_t *s) { - /* - sfxcache_t *src, *dest; ovdecoderbuffer_t *dec; - dec = s->decoder->buf; + dec = s->decoder.buf; + s->decoder.buf = NULL; + s->decoder.abort = NULL; + s->decoder.decodedata = NULL; p_ov_clear (&dec->vf); //close the decoder - //copy to new buffer - - src = s->cache.data; - s->cache.fake = false; - s->cache.data = NULL; - dest = Cache_Alloc(&s->cache, dec->mediaaswavpos, s->name); - memcpy(dest, src, dec->mediaaswavpos); - BZ_Free(src); - if (dec->tempbuffer) { BZ_Free(dec->tempbuffer); - dec->tempbufferbytes = NULL; + dec->tempbufferbytes = 0; } - Z_Free(s->decoder); - s->decoder = NULL; - */ + BZ_Free(dec->decodedbuffer); + dec->decodedbuffer = NULL; - //and it's now indistinguisable from a wav + BZ_Free(dec); } static size_t VARGS read_func (void *ptr, size_t size, size_t nmemb, void *datasource) diff --git a/engine/client/sound.h b/engine/client/sound.h index 2f55eacf..f4e61401 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -39,7 +39,6 @@ typedef struct } portable_samplegroup_t; typedef struct { - int decodedlen; struct sfxcache_s *(*decodedata) (struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length); //retrurn true when done. void (*abort) (struct sfx_s *sfx); //it's not playing elsewhere. free entirly void *buf; @@ -176,6 +175,7 @@ void SND_ResampleStream (void *in, int inrate, int inwidth, int inchannels, int // restart entire sound subsystem (doesn't flush old sounds, so make sure that happens) void S_DoRestart (void); +void S_SetUnderWater(qboolean underwater); void S_Restart_f (void); diff --git a/engine/client/sys_droid.c b/engine/client/sys_droid.c index 10b98bed..37dd735a 100644 --- a/engine/client/sys_droid.c +++ b/engine/client/sys_droid.c @@ -19,6 +19,7 @@ qboolean isDedicated = false; #endif void *sys_window; /*public so the renderer can attach to the correct place*/ static qboolean sys_running = false; +int sys_glesversion; #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, DISTRIBUTION"Droid", __VA_ARGS__)) @@ -48,11 +49,12 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject } JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject obj, - jint width, jint height, jstring japkpath, jstring jusrpath) + jint width, jint height, jint glesversion, jstring japkpath, jstring jusrpath) { char *tmp; vid.pixelwidth = width; vid.pixelheight = height; + sys_glesversion = glesversion; if (sys_running) Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); else diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 3d6acf4d..50b8947e 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -36,6 +36,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #endif +#ifdef GLQUAKE +#define PRINTGLARRAYS +#endif + #ifdef _DEBUG #if _MSC_VER >= 1300 #define CATCHCRASH @@ -53,6 +57,8 @@ unsigned int sys_parenttop; unsigned int sys_parentwidth; //valid if sys_parentwindow is set unsigned int sys_parentheight; +extern int fs_switchgame; + #ifdef RESTARTTEST jmp_buf restart_jmpbuf; @@ -362,7 +368,7 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP) ( PMINIDUMP_CALLBACK_INFORMATION CallbackParam ); -#if 0 +#ifdef PRINTGLARRAYS #include "glquake.h" #define GL_ARRAY_BUFFER 0x8892 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 @@ -390,7 +396,7 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception HMODULE hKernel; BOOL (WINAPI *pIsDebuggerPresent)(void); -#if 0 +#ifdef PRINTGLARRAYS int rval; void *ptr; int i; @@ -805,6 +811,14 @@ void Sys_Shutdown(void) VirtualFree(host_parms.membase, 0, MEM_RELEASE); host_parms.membase = 0; } + + if (tevent) + CloseHandle (tevent); + tevent = NULL; + + if (qwclsemaphore) + CloseHandle (qwclsemaphore); + qwclsemaphore = NULL; } @@ -844,6 +858,39 @@ void VARGS Sys_Error (const char *error, ...) #endif } +static wchar_t dequake(conchar_t chr) +{ + chr &= CON_CHARMASK; + + /*only this range are quake chars*/ + if (chr >= 0xe000 && chr < 0xe100) + { + chr &= 0xff; + if (chr >= 146 && chr < 156) + chr = chr - 146 + '0'; + if (chr >= 0x12 && chr <= 0x1b) + chr = chr - 0x12 + '0'; + if (chr == 143) + chr = '.'; + if (chr == 128 || chr == 129 || chr == 130 || chr == 157 || chr == 158 || chr == 159) + chr = '-'; + if (chr >= 128) + chr -= 128; + if (chr == 16) + chr = '['; + if (chr == 17) + chr = ']'; + if (chr == 0x1c) + chr = 249; + } + /*this range contains pictograms*/ + if (chr >= 0xe100 && chr < 0xe200) + { + chr = '?'; + } + return chr; +} + void VARGS Sys_Printf (char *fmt, ...) { va_list argptr; @@ -859,7 +906,19 @@ void VARGS Sys_Printf (char *fmt, ...) #ifdef _DEBUG if (debugout) - OutputDebugString(text); //msvc debug output + { + //msvc debug output + conchar_t msg[1024], *end; + wchar_t wide[1024]; + int i; + end = COM_ParseFunString(CON_WHITEMASK, text, msg, sizeof(msg), false); + for (i = 0; msg+i < end; i++) + { + wide[i] = dequake(msg[i] & CON_CHARMASK); + } + wide[i] = 0; + OutputDebugStringW(wide); + } #endif if (houtput) WriteFile (houtput, text, strlen(text), &dummy, NULL); @@ -872,17 +931,13 @@ void Sys_Quit (void) Host_Shutdown (); - if (tevent) - CloseHandle (tevent); - - if (qwclsemaphore) - CloseHandle (qwclsemaphore); - SetHookState(false); #else SV_Shutdown(); #endif + TL_Shutdown(); + #ifdef RESTARTTEST longjmp(restart_jmpbuf, 1); #endif @@ -894,6 +949,12 @@ void Sys_Quit (void) longjmp (host_abort, 1); } #else + +#ifdef USE_MSVCRT_DEBUG + if (_CrtDumpMemoryLeaks()) + OutputDebugStringA("Leaks detected\n"); +#endif + exit(1); #endif } @@ -1398,6 +1459,10 @@ HWND hwnd_dialog; #include "ntverp.h" #endif +#if defined(__MINGW64_VERSION_MAJOR) && (__MINGW64_VERSION_MAJOR >= 3) +#define SHARD_APPIDINFOLINK SHARD_APPIDINFOLINK +#endif + #ifndef SHARD_APPIDINFOLINK // SDK version 7600 = v7.0a & v7.1 @@ -1747,7 +1812,6 @@ void Win7_TaskListInit(void) } #endif - /* #ifdef _MSC_VER #include @@ -1773,7 +1837,6 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (hPrevInstance) return 0; - #ifndef MINGW #if _MSC_VER > 1200 Win7_Init(); @@ -2018,6 +2081,20 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin Sys_Error("wut?"); #endif } + +#ifndef SERVERONLY + if (fs_switchgame != -1) + { + SetHookState(false); + + Host_Shutdown (); + + COM_InitArgv (parms.argc, parms.argv); + if (!Sys_Startup_CheckMem(&parms)) + return 0; + Host_Init (&parms); + } +#endif } } #ifdef CATCHCRASH diff --git a/engine/client/view.c b/engine/client/view.c index 0a15b455..38cefa9f 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -165,7 +165,7 @@ float V_CalcBob (int pnum, qboolean queryold) // bob is proportional to simulated velocity in the xy plane // (don't count Z, or jumping messes it up) - bob[pnum] = sqrt(cl.simvel[pnum][0]*cl.simvel[pnum][0] + cl.simvel[pnum][1]*cl.simvel[pnum][1]) * cl_bob.value; + bob[pnum] = sqrt(cl.playerview[pnum].simvel[0]*cl.playerview[pnum].simvel[0] + cl.playerview[pnum].simvel[1]*cl.playerview[pnum].simvel[1]) * cl_bob.value; bob[pnum] = bob[pnum]*0.3 + bob[pnum]*0.7*sin(cycle); if (bob[pnum] > 4) bob[pnum] = 4; @@ -186,24 +186,24 @@ cvar_t v_centerspeed = SCVAR("v_centerspeed","500"); void V_StartPitchDrift (int pnum) { #if 1 - if (cl.laststop[pnum] == cl.time) + if (cl.playerview[pnum].laststop == cl.time) { return; // something else is keeping it from drifting } #endif - if (cl.nodrift || !cl.pitchvel) + if (cl.playerview[pnum].nodrift || !cl.playerview[pnum].pitchvel) { - cl.pitchvel[pnum] = v_centerspeed.value; - cl.nodrift[pnum] = false; - cl.driftmove[pnum] = 0; + cl.playerview[pnum].pitchvel = v_centerspeed.value; + cl.playerview[pnum].nodrift = false; + cl.playerview[pnum].driftmove = 0; } } void V_StopPitchDrift (int pnum) { - cl.laststop[pnum] = cl.time; - cl.nodrift[pnum] = true; - cl.pitchvel[pnum] = 0; + cl.playerview[pnum].laststop = cl.time; + cl.playerview[pnum].nodrift = true; + cl.playerview[pnum].pitchvel = 0; } /* @@ -225,36 +225,36 @@ void V_DriftPitch (int pnum) if (!cl.onground || cls.demoplayback ) { - cl.driftmove[pnum] = 0; - cl.pitchvel[pnum] = 0; + cl.playerview[pnum].driftmove = 0; + cl.playerview[pnum].pitchvel = 0; return; } // don't count small mouse motion - if (cl.nodrift[pnum]) + if (cl.playerview[pnum].nodrift) { if ( fabs(cl.frames[(cls.netchan.outgoing_sequence-1)&UPDATE_MASK].cmd[pnum].forwardmove) < 200) - cl.driftmove[pnum] = 0; + cl.playerview[pnum].driftmove = 0; else - cl.driftmove[pnum] += host_frametime; + cl.playerview[pnum].driftmove += host_frametime; - if ( cl.driftmove[pnum] > v_centermove.value) + if ( cl.playerview[pnum].driftmove > v_centermove.value) { V_StartPitchDrift (pnum); } return; } - delta = 0 - cl.viewangles[pnum][PITCH]; + delta = 0 - cl.playerview[pnum].viewangles[PITCH]; if (!delta) { - cl.pitchvel[pnum] = 0; + cl.playerview[pnum].pitchvel = 0; return; } - move = host_frametime * cl.pitchvel[pnum]; - cl.pitchvel[pnum] += host_frametime * v_centerspeed.value; + move = host_frametime * cl.playerview[pnum].pitchvel; + cl.playerview[pnum].pitchvel += host_frametime * v_centerspeed.value; //Con_Printf ("move: %f (%f)\n", move, host_frametime); @@ -262,19 +262,19 @@ void V_DriftPitch (int pnum) { if (move > delta) { - cl.pitchvel[pnum] = 0; + cl.playerview[pnum].pitchvel = 0; move = delta; } - cl.viewangles[pnum][PITCH] += move; + cl.playerview[pnum].viewangles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { - cl.pitchvel[pnum] = 0; + cl.playerview[pnum].pitchvel = 0; move = -delta; } - cl.viewangles[pnum][PITCH] -= move; + cl.playerview[pnum].viewangles[PITCH] -= move; } } @@ -395,7 +395,7 @@ void V_ParseDamage (int pnum) if (v_damagecshift.value >= 0) count *= v_damagecshift.value; - cl.faceanimtime[pnum] = cl.time + 0.2; // but sbar face into pain frame + cl.playerview[pnum].faceanimtime = cl.time + 0.2; // but sbar face into pain frame cl.cshifts[CSHIFT_DAMAGE].percent += 3*count; if (cl.cshifts[CSHIFT_DAMAGE].percent < 0) @@ -425,10 +425,10 @@ void V_ParseDamage (int pnum) // // calculate view angle kicks // - VectorSubtract (from, cl.simorg[pnum], from); + VectorSubtract (from, cl.playerview[pnum].simorg, from); VectorNormalize (from); - AngleVectors (cl.simangles[pnum], forward, right, up); + AngleVectors (cl.playerview[pnum].simangles, forward, right, up); side = DotProduct (from, right); v_dmg_roll[pnum] = count*side*v_kickroll.value; @@ -588,7 +588,7 @@ void V_CalcPowerupCshift (void) //we only have one palette, so combine the mask for (s = 0; s < cl.splitclients; s++) - im |= cl.stats[s][STAT_ITEMS]; + im |= cl.playerview[s].stats[STAT_ITEMS]; if (im & IT_QUAD) { @@ -879,18 +879,18 @@ void V_BoundOffsets (int pnum) // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall - if (r_refdef.vieworg[0] < cl.simorg[pnum][0] - 14) - r_refdef.vieworg[0] = cl.simorg[pnum][0] - 14; - else if (r_refdef.vieworg[0] > cl.simorg[pnum][0] + 14) - r_refdef.vieworg[0] = cl.simorg[pnum][0] + 14; - if (r_refdef.vieworg[1] < cl.simorg[pnum][1] - 14) - r_refdef.vieworg[1] = cl.simorg[pnum][1] - 14; - else if (r_refdef.vieworg[1] > cl.simorg[pnum][1] + 14) - r_refdef.vieworg[1] = cl.simorg[pnum][1] + 14; - if (r_refdef.vieworg[2] < cl.simorg[pnum][2] - 22) - r_refdef.vieworg[2] = cl.simorg[pnum][2] - 22; - else if (r_refdef.vieworg[2] > cl.simorg[pnum][2] + 30) - r_refdef.vieworg[2] = cl.simorg[pnum][2] + 30; + if (r_refdef.vieworg[0] < cl.playerview[pnum].simorg[0] - 14) + r_refdef.vieworg[0] = cl.playerview[pnum].simorg[0] - 14; + else if (r_refdef.vieworg[0] > cl.playerview[pnum].simorg[0] + 14) + r_refdef.vieworg[0] = cl.playerview[pnum].simorg[0] + 14; + if (r_refdef.vieworg[1] < cl.playerview[pnum].simorg[1] - 14) + r_refdef.vieworg[1] = cl.playerview[pnum].simorg[1] - 14; + else if (r_refdef.vieworg[1] > cl.playerview[pnum].simorg[1] + 14) + r_refdef.vieworg[1] = cl.playerview[pnum].simorg[1] + 14; + if (r_refdef.vieworg[2] < cl.playerview[pnum].simorg[2] - 22) + r_refdef.vieworg[2] = cl.playerview[pnum].simorg[2] - 22; + else if (r_refdef.vieworg[2] > cl.playerview[pnum].simorg[2] + 30) + r_refdef.vieworg[2] = cl.playerview[pnum].simorg[2] + 30; } /* @@ -946,7 +946,7 @@ void V_CalcViewRoll (int pnum) float side; float adjspeed; - side = V_CalcRoll (cl.simangles[pnum], cl.simvel[pnum]); + side = V_CalcRoll (cl.playerview[pnum].simangles, cl.playerview[pnum].simvel); adjspeed = fabs(cl_rollangle.value); if (adjspeed<1) @@ -954,19 +954,19 @@ void V_CalcViewRoll (int pnum) if (adjspeed>45) adjspeed = 45; adjspeed*=20; - if (side > cl.rollangle[pnum]) + if (side > cl.playerview[pnum].rollangle) { - cl.rollangle[pnum] += host_frametime * adjspeed; - if (cl.rollangle[pnum] > side) - cl.rollangle[pnum] = side; + cl.playerview[pnum].rollangle += host_frametime * adjspeed; + if (cl.playerview[pnum].rollangle > side) + cl.playerview[pnum].rollangle = side; } - else if (side < cl.rollangle[pnum]) + else if (side < cl.playerview[pnum].rollangle) { - cl.rollangle[pnum] -= host_frametime * adjspeed; - if (cl.rollangle[pnum] < side) - cl.rollangle[pnum] = side; + cl.playerview[pnum].rollangle -= host_frametime * adjspeed; + if (cl.playerview[pnum].rollangle < side) + cl.playerview[pnum].rollangle = side; } - r_refdef.viewangles[ROLL] += cl.rollangle[pnum]; + r_refdef.viewangles[ROLL] += cl.playerview[pnum].rollangle; if (v_dmg_time[pnum] > 0) { @@ -992,8 +992,8 @@ void V_CalcIntermissionRefdef (int pnum) // view is the weapon model view = &cl.viewent[pnum]; - VectorCopy (cl.simorg[pnum], r_refdef.vieworg); - VectorCopy (cl.simangles[pnum], r_refdef.viewangles); + VectorCopy (cl.playerview[pnum].simorg, r_refdef.vieworg); + VectorCopy (cl.playerview[pnum].simangles, r_refdef.viewangles); view->model = NULL; // always idle in intermission @@ -1039,7 +1039,7 @@ void V_CalcRefdef (int pnum) bob = V_CalcBob (pnum, false); // refresh position from simulated origin - VectorCopy (cl.simorg[pnum], r_refdef.vieworg); + VectorCopy (cl.playerview[pnum].simorg, r_refdef.vieworg); r_refdef.useperspective = true; @@ -1050,9 +1050,9 @@ void V_CalcRefdef (int pnum) r_refdef.vieworg[1] += 1.0/16; r_refdef.vieworg[2] += 1.0/16; - if (cl.fixangle[pnum]) + if (cl.playerview[pnum].fixangle) { - if (cl.oldfixangle[pnum]) + if (cl.playerview[pnum].oldfixangle) { float frac, move; if (cl.gametime <= cl.oldgametime) @@ -1064,22 +1064,22 @@ void V_CalcRefdef (int pnum) } for (i = 0; i < 3; i++) { - move = cl.fixangles[pnum][i] - cl.oldfixangles[pnum][i]; + move = cl.playerview[pnum].fixangles[i] - cl.playerview[pnum].oldfixangles[i]; if (move >= 180) move -= 360; if (move <= -180) move += 360; - r_refdef.viewangles[i] = cl.oldfixangles[pnum][i] + frac * move; + r_refdef.viewangles[i] = cl.playerview[pnum].oldfixangles[i] + frac * move; } } else { - VectorCopy (cl.fixangles[pnum], r_refdef.viewangles); + VectorCopy (cl.playerview[pnum].fixangles, r_refdef.viewangles); } } else { - VectorCopy (cl.simangles[pnum], r_refdef.viewangles); + VectorCopy (cl.playerview[pnum].simangles, r_refdef.viewangles); } V_CalcViewRoll (pnum); V_AddIdle (pnum); @@ -1112,14 +1112,14 @@ void V_CalcRefdef (int pnum) // set up gun position V_CalcGunPositionAngle (pnum, bob); - if (cl.stats[pnum][STAT_HEALTH] > 0 && (unsigned int)cl.stats[pnum][STAT_WEAPON] >= MAX_MODELS) + if (cl.playerview[pnum].stats[STAT_HEALTH] > 0 && (unsigned int)cl.playerview[pnum].stats[STAT_WEAPON] >= MAX_MODELS) view->model = NULL; else - view->model = cl.model_precache[cl.stats[pnum][STAT_WEAPON]]; + view->model = cl.model_precache[cl.playerview[pnum].stats[STAT_WEAPON]]; #ifdef HLCLIENT if (!CLHL_AnimateViewEntity(view)) #endif - view->framestate.g[FS_REG].frame[0] = cl.stats[pnum][STAT_WEAPONFRAME]; + view->framestate.g[FS_REG].frame[0] = cl.playerview[pnum].stats[STAT_WEAPONFRAME]; // set up the refresh position if (v_gunkick.value) @@ -1241,8 +1241,8 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) } r_refdef.fov_x = scr_fov.value; - if (cl.stats[pnum][STAT_VIEWZOOM]) - r_refdef.fov_x *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f; + if (cl.playerview[pnum].stats[STAT_VIEWZOOM]) + r_refdef.fov_x *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f; if (vrect->width < (vrect->height*640)/432) { @@ -1364,7 +1364,7 @@ void V_RenderPlayerViews(int plnum) for (viewnum = 0; viewnum < SIDEVIEWS; viewnum++) if (vsec_scalex[viewnum].value>0&&vsec_scaley[viewnum].value>0 && ((vsec_enabled[viewnum].value && vsec_enabled[viewnum].value != 2 && cls.allow_rearview) //rearview if v2_enabled = 1 and not 2 - || (vsec_enabled[viewnum].value && cl.stats[plnum][STAT_VIEW2]&&viewnum==0))) //v2 enabled if v2_enabled is non-zero + || (vsec_enabled[viewnum].value && cl.playerview[plnum].stats[STAT_VIEW2]&&viewnum==0))) //v2 enabled if v2_enabled is non-zero { vrect_t oldrect; vec3_t oldangles; @@ -1401,9 +1401,9 @@ void V_RenderPlayerViews(int plnum) #ifdef PEXT_VIEW2 //secondary view entity. e=NULL; - if (viewnum==0&&cl.stats[plnum][STAT_VIEW2]) + if (viewnum==0&&cl.playerview[plnum].stats[STAT_VIEW2]) { - e = CL_EntityNum (cl.stats[plnum][STAT_VIEW2]); + e = CL_EntityNum (cl.playerview[plnum].stats[STAT_VIEW2]); } if (e) { diff --git a/engine/client/wad.c b/engine/client/wad.c index 888b24ac..dc741292 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -59,6 +59,12 @@ void W_CleanupName (const char *in, char *out) } +void W_Shutdown (void) +{ + if (wad_base) + Z_Free(wad_base); + wad_base = NULL; +} /* ==================== @@ -111,7 +117,6 @@ void W_LoadWadFile (char *filename) } } - /* ============= W_GetLumpinfo @@ -380,7 +385,7 @@ qbyte *W_ConvertWAD3Texture(miptex_t *tex, int *width, int *height, qboolean *us alpha = 2; //use malloc here if you want, but you'll have to free it again... NUR! - data = out = Hunk_TempAllocMore(tex->width * tex->height * 4); + data = out = BZ_Malloc(tex->width * tex->height * 4); if (!data) return NULL; @@ -467,7 +472,7 @@ qbyte *W_GetTexture(char *name, int *width, int *height, qboolean *usesalpha)//r for (j = 0;j < MIPLEVELS;j++) tex->offsets[j] = LittleLong(tex->offsets[j]); - data = W_ConvertWAD3Texture(tex, width, height, usesalpha); //this will add to the temp + data = W_ConvertWAD3Texture(tex, width, height, usesalpha); BZ_Free(tex); return data; } diff --git a/engine/client/wad.h b/engine/client/wad.h index 31a47d40..34992174 100644 --- a/engine/client/wad.h +++ b/engine/client/wad.h @@ -98,6 +98,7 @@ extern int wad_numlumps; extern lumpinfo_t *wad_lumps; extern qbyte *wad_base; +void W_Shutdown (void); void W_LoadWadFile (char *filename); void W_CleanupName (const char *in, char *out); lumpinfo_t *W_GetLumpinfo (char *name); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 9cadd0c2..32da1846 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -317,43 +317,43 @@ static char *Macro_Gamedir (void) static char *Macro_Health (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_HEALTH]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_HEALTH]); return macro_buf; } static char *Macro_Armor (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_ARMOR]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_ARMOR]); return macro_buf; } static char *Macro_Shells (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_SHELLS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_SHELLS]); return macro_buf; } static char *Macro_Nails (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_NAILS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_NAILS]); return macro_buf; } static char *Macro_Rockets (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_ROCKETS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_ROCKETS]); return macro_buf; } static char *Macro_Cells (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_CELLS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_CELLS]); return macro_buf; } static char *Macro_Ammo (void) { - sprintf(macro_buf, "%i", cl.stats[SP][STAT_AMMO]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_AMMO]); return macro_buf; } @@ -375,7 +375,7 @@ static char *Weapon_NumToString (int wnum) static char *Macro_Weapon (void) { - return Weapon_NumToString(cl.stats[SP][STAT_ACTIVEWEAPON]); + return Weapon_NumToString(cl.playerview[SP].stats[STAT_ACTIVEWEAPON]); } static char *Macro_DroppedWeapon (void) @@ -386,21 +386,21 @@ static char *Macro_DroppedWeapon (void) static char *Macro_Weapons (void) { macro_buf[0] = 0; - if (cl.stats[SP][STAT_ITEMS] & IT_LIGHTNING) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_LIGHTNING) strcpy(macro_buf, tp_name_lg.string); - if (cl.stats[SP][STAT_ITEMS] & IT_ROCKET_LAUNCHER) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER) MacroBuf_strcat_with_separator (tp_name_rl.string); - if (cl.stats[SP][STAT_ITEMS] & IT_GRENADE_LAUNCHER) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER) MacroBuf_strcat_with_separator (tp_name_gl.string); - if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_NAILGUN) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_NAILGUN) MacroBuf_strcat_with_separator (tp_name_sng.string); - if (cl.stats[SP][STAT_ITEMS] & IT_NAILGUN) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_NAILGUN) MacroBuf_strcat_with_separator (tp_name_ng.string); - if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_SHOTGUN) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_SHOTGUN) MacroBuf_strcat_with_separator (tp_name_ssg.string); - if (cl.stats[SP][STAT_ITEMS] & IT_SHOTGUN) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SHOTGUN) MacroBuf_strcat_with_separator (tp_name_sg.string); - if (cl.stats[SP][STAT_ITEMS] & IT_AXE) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_AXE) MacroBuf_strcat_with_separator (tp_name_axe.string); // if (!macro_buf[0]) // strlcpy(macro_buf, tp_name_none.string, sizeof(macro_buf)); @@ -418,7 +418,7 @@ static char *Macro_WeaponAndAmmo (void) static char *Macro_WeaponNum (void) { - switch (cl.stats[SP][STAT_ACTIVEWEAPON]) + switch (cl.playerview[SP].stats[STAT_ACTIVEWEAPON]) { case IT_AXE: return "1"; case IT_SHOTGUN: return "2"; @@ -443,14 +443,14 @@ static int _Macro_BestWeapon (void) for (i = 0 ; i < strlen(*s) ; i++) { switch ((*s)[i]) { - case '1': if (cl.stats[SP][STAT_ITEMS] & IT_AXE) return IT_AXE; break; - case '2': if (cl.stats[SP][STAT_ITEMS] & IT_SHOTGUN) return IT_SHOTGUN; break; - case '3': if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_SHOTGUN) return IT_SUPER_SHOTGUN; break; - case '4': if (cl.stats[SP][STAT_ITEMS] & IT_NAILGUN) return IT_NAILGUN; break; - case '5': if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_NAILGUN) return IT_SUPER_NAILGUN; break; - case '6': if (cl.stats[SP][STAT_ITEMS] & IT_GRENADE_LAUNCHER) return IT_GRENADE_LAUNCHER; break; - case '7': if (cl.stats[SP][STAT_ITEMS] & IT_ROCKET_LAUNCHER) return IT_ROCKET_LAUNCHER; break; - case '8': if (cl.stats[SP][STAT_ITEMS] & IT_LIGHTNING) return IT_LIGHTNING; break; + case '1': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_AXE) return IT_AXE; break; + case '2': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SHOTGUN) return IT_SHOTGUN; break; + case '3': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_SHOTGUN) return IT_SUPER_SHOTGUN; break; + case '4': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_NAILGUN) return IT_NAILGUN; break; + case '5': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_NAILGUN) return IT_SUPER_NAILGUN; break; + case '6': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER) return IT_GRENADE_LAUNCHER; break; + case '7': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER) return IT_ROCKET_LAUNCHER; break; + case '8': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_LIGHTNING) return IT_LIGHTNING; break; } } } @@ -467,19 +467,19 @@ static char *Macro_BestAmmo (void) switch (_Macro_BestWeapon()) { case IT_SHOTGUN: case IT_SUPER_SHOTGUN: - sprintf(macro_buf, "%i", cl.stats[0][STAT_SHELLS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_SHELLS]); return macro_buf; case IT_NAILGUN: case IT_SUPER_NAILGUN: - sprintf(macro_buf, "%i", cl.stats[0][STAT_NAILS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_NAILS]); return macro_buf; case IT_GRENADE_LAUNCHER: case IT_ROCKET_LAUNCHER: - sprintf(macro_buf, "%i", cl.stats[0][STAT_ROCKETS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_ROCKETS]); return macro_buf; case IT_LIGHTNING: - sprintf(macro_buf, "%i", cl.stats[0][STAT_CELLS]); + sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_CELLS]); return macro_buf; default: @@ -498,11 +498,11 @@ static char *Macro_BestWeaponAndAmmo (void) static char *Macro_ArmorType (void) { - if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR1) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR1) return tp_name_armortype_ga.string; - else if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR2) + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR2) return tp_name_armortype_ya.string; - else if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR3) + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR3) return tp_name_armortype_ra.string; else return tp_name_none.string; // no armor at all @@ -514,18 +514,18 @@ static char *Macro_Powerups (void) macro_buf[0] = 0; - if (cl.stats[SP][STAT_ITEMS] & IT_QUAD) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_QUAD) MacroBuf_strcat_with_separator (tp_name_quad.string); - if (cl.stats[SP][STAT_ITEMS] & IT_INVULNERABILITY) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVULNERABILITY) MacroBuf_strcat_with_separator (tp_name_pent.string); - if (cl.stats[SP][STAT_ITEMS] & IT_INVISIBILITY) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVISIBILITY) MacroBuf_strcat_with_separator (tp_name_ring.string); effects = cl.frames[cl.parsecount&UPDATE_MASK].playerstate[cl.playernum[SP]].effects; if ( (effects & (QWEF_FLAG1|QWEF_FLAG2)) || // CTF - (cl.teamfortress && cl.stats[SP][STAT_ITEMS] & (IT_KEY1|IT_KEY2)) ) // TF + (cl.teamfortress && cl.playerview[SP].stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2)) ) // TF MacroBuf_strcat_with_separator (tp_name_flag.string); return macro_buf; @@ -533,7 +533,7 @@ static char *Macro_Powerups (void) static char *Macro_Location (void) { - return TP_LocationName (cl.simorg[SP]); + return TP_LocationName (cl.playerview[SP].simorg); } static char *Macro_LastDeath (void) @@ -624,15 +624,15 @@ static char *Macro_Need (void) macro_buf[0] = 0; // check armor - if ( ((cl.stats[SP][STAT_ITEMS] & IT_ARMOR1) && cl.stats[SP][STAT_ARMOR] < tp_need_ga.value) - || ((cl.stats[SP][STAT_ITEMS] & IT_ARMOR2) && cl.stats[SP][STAT_ARMOR] < tp_need_ya.value) - || ((cl.stats[SP][STAT_ITEMS] & IT_ARMOR3) && cl.stats[SP][STAT_ARMOR] < tp_need_ra.value) - || (!(cl.stats[SP][STAT_ITEMS] & (IT_ARMOR1|IT_ARMOR2|IT_ARMOR3)) + if ( ((cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR1) && cl.playerview[SP].stats[STAT_ARMOR] < tp_need_ga.value) + || ((cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR2) && cl.playerview[SP].stats[STAT_ARMOR] < tp_need_ya.value) + || ((cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR3) && cl.playerview[SP].stats[STAT_ARMOR] < tp_need_ra.value) + || (!(cl.playerview[SP].stats[STAT_ITEMS] & (IT_ARMOR1|IT_ARMOR2|IT_ARMOR3)) && (tp_need_ga.value || tp_need_ya.value || tp_need_ra.value))) strcpy (macro_buf, tp_name_armor.string); // check health - if (tp_need_health.value && cl.stats[SP][STAT_HEALTH] < tp_need_health.value) { + if (tp_need_health.value && cl.playerview[SP].stats[STAT_HEALTH] < tp_need_health.value) { MacroBuf_strcat_with_separator (tp_name_health.string); } @@ -640,13 +640,13 @@ static char *Macro_Need (void) { // in TF, we have all weapons from the start, // and ammo is checked differently - if (cl.stats[SP][STAT_ROCKETS] < tp_need_rockets.value) + if (cl.playerview[SP].stats[STAT_ROCKETS] < tp_need_rockets.value) MacroBuf_strcat_with_separator (tp_name_rockets.string); - if (cl.stats[SP][STAT_SHELLS] < tp_need_shells.value) + if (cl.playerview[SP].stats[STAT_SHELLS] < tp_need_shells.value) MacroBuf_strcat_with_separator (tp_name_shells.string); - if (cl.stats[SP][STAT_NAILS] < tp_need_nails.value) + if (cl.playerview[SP].stats[STAT_NAILS] < tp_need_nails.value) MacroBuf_strcat_with_separator (tp_name_nails.string); - if (cl.stats[SP][STAT_CELLS] < tp_need_cells.value) + if (cl.playerview[SP].stats[STAT_CELLS] < tp_need_cells.value) MacroBuf_strcat_with_separator (tp_name_cells.string); goto done; } @@ -655,13 +655,13 @@ static char *Macro_Need (void) weapon = 0; for (i=strlen(tp_need_weapon.string)-1 ; i>=0 ; i--) { switch (tp_need_weapon.string[i]) { - case '2': if (cl.stats[SP][STAT_ITEMS] & IT_SHOTGUN) weapon = 2; break; - case '3': if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_SHOTGUN) weapon = 3; break; - case '4': if (cl.stats[SP][STAT_ITEMS] & IT_NAILGUN) weapon = 4; break; - case '5': if (cl.stats[SP][STAT_ITEMS] & IT_SUPER_NAILGUN) weapon = 5; break; - case '6': if (cl.stats[SP][STAT_ITEMS] & IT_GRENADE_LAUNCHER) weapon = 6; break; - case '7': if (cl.stats[SP][STAT_ITEMS] & IT_ROCKET_LAUNCHER) weapon = 7; break; - case '8': if (cl.stats[SP][STAT_ITEMS] & IT_LIGHTNING) weapon = 8; break; + case '2': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SHOTGUN) weapon = 2; break; + case '3': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_SHOTGUN) weapon = 3; break; + case '4': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_NAILGUN) weapon = 4; break; + case '5': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_SUPER_NAILGUN) weapon = 5; break; + case '6': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER) weapon = 6; break; + case '7': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER) weapon = 7; break; + case '8': if (cl.playerview[SP].stats[STAT_ITEMS] & IT_LIGHTNING) weapon = 8; break; } if (weapon) break; @@ -670,15 +670,15 @@ static char *Macro_Need (void) if (!weapon) { MacroBuf_strcat_with_separator (tp_name_weapon.string); } else { - if (tp_need_rl.value && !(cl.stats[SP][STAT_ITEMS] & IT_ROCKET_LAUNCHER)) { + if (tp_need_rl.value && !(cl.playerview[SP].stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER)) { MacroBuf_strcat_with_separator (tp_name_rl.string); } switch (weapon) { - case 2: case 3: if (cl.stats[SP][STAT_SHELLS] < tp_need_shells.value) needammo = tp_name_shells.string; break; - case 4: case 5: if (cl.stats[SP][STAT_NAILS] < tp_need_nails.value) needammo = tp_name_nails.string; break; - case 6: case 7: if (cl.stats[SP][STAT_ROCKETS] < tp_need_rockets.value) needammo = tp_name_rockets.string; break; - case 8: if (cl.stats[SP][STAT_CELLS] < tp_need_cells.value) needammo = tp_name_cells.string; break; + case 2: case 3: if (cl.playerview[SP].stats[STAT_SHELLS] < tp_need_shells.value) needammo = tp_name_shells.string; break; + case 4: case 5: if (cl.playerview[SP].stats[STAT_NAILS] < tp_need_nails.value) needammo = tp_name_nails.string; break; + case 6: case 7: if (cl.playerview[SP].stats[STAT_ROCKETS] < tp_need_rockets.value) needammo = tp_name_rockets.string; break; + case 8: if (cl.playerview[SP].stats[STAT_CELLS] < tp_need_cells.value) needammo = tp_name_cells.string; break; } if (needammo) { MacroBuf_strcat_with_separator (needammo); @@ -1037,16 +1037,16 @@ char *Macro_CombinedHealth(void) //total health = health+armour*armourfrac //however,you're dead if health drops below 0 rather than the entire equation. - if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR1) + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR1) t = 0.3; - else if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR2) + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR2) t = 0.6; - else if (cl.stats[SP][STAT_ITEMS] & IT_ARMOR3) + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR3) t = 0.8; else t = 0; - a = cl.stats[SP][STAT_ARMOR]; - h = cl.stats[SP][STAT_HEALTH]; + a = cl.playerview[SP].stats[STAT_ARMOR]; + h = cl.playerview[SP].stats[STAT_HEALTH]; //work out the max useful armour //this will under-exagurate, due to usage of ceil based on damage @@ -1172,18 +1172,18 @@ static char *TP_ParseMacroString (char *s) macro_string = Macro_ArmorType(); if (!macro_string[0]) macro_string = "a"; - if (cl.stats[SP][STAT_ARMOR] < 30) - Q_snprintfz (mbuf, sizeof(mbuf), "\x10%s:%i\x11", macro_string, cl.stats[SP][STAT_ARMOR]); + if (cl.playerview[SP].stats[STAT_ARMOR] < 30) + Q_snprintfz (mbuf, sizeof(mbuf), "\x10%s:%i\x11", macro_string, cl.playerview[SP].stats[STAT_ARMOR]); else - Q_snprintfz (mbuf, sizeof(mbuf), "%s:%i", macro_string, cl.stats[SP][STAT_ARMOR]); + Q_snprintfz (mbuf, sizeof(mbuf), "%s:%i", macro_string, cl.playerview[SP].stats[STAT_ARMOR]); macro_string = mbuf; break; case 'h': - if (cl.stats[SP][STAT_HEALTH] >= 50) - Q_snprintfz (macro_buf, sizeof(macro_buf), "%i", cl.stats[SP][STAT_HEALTH]); + if (cl.playerview[SP].stats[STAT_HEALTH] >= 50) + Q_snprintfz (macro_buf, sizeof(macro_buf), "%i", cl.playerview[SP].stats[STAT_HEALTH]); else - Q_snprintfz (macro_buf, sizeof(macro_buf), "\x10%i\x11", cl.stats[SP][STAT_HEALTH]); + Q_snprintfz (macro_buf, sizeof(macro_buf), "\x10%i\x11", cl.playerview[SP].stats[STAT_HEALTH]); macro_string = macro_buf; break; @@ -2609,17 +2609,17 @@ more: if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount) { if (vars.items & ~vars.olditems & IT_LIGHTNING) - ExecTookTrigger (tp_name_lg.string, it_lg, cl.simorg[SP]); + ExecTookTrigger (tp_name_lg.string, it_lg, cl.playerview[SP].simorg); else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER) - ExecTookTrigger (tp_name_rl.string, it_rl, cl.simorg[SP]); + ExecTookTrigger (tp_name_rl.string, it_rl, cl.playerview[SP].simorg); else if (vars.items & ~vars.olditems & IT_GRENADE_LAUNCHER) - ExecTookTrigger (tp_name_gl.string, it_gl, cl.simorg[SP]); + ExecTookTrigger (tp_name_gl.string, it_gl, cl.playerview[SP].simorg); else if (vars.items & ~vars.olditems & IT_SUPER_NAILGUN) - ExecTookTrigger (tp_name_sng.string, it_sng, cl.simorg[SP]); + ExecTookTrigger (tp_name_sng.string, it_sng, cl.playerview[SP].simorg); else if (vars.items & ~vars.olditems & IT_NAILGUN) - ExecTookTrigger (tp_name_ng.string, it_ng, cl.simorg[SP]); + ExecTookTrigger (tp_name_ng.string, it_ng, cl.playerview[SP].simorg); else if (vars.items & ~vars.olditems & IT_SUPER_SHOTGUN) - ExecTookTrigger (tp_name_ssg.string, it_ssg, cl.simorg[SP]); + ExecTookTrigger (tp_name_ssg.string, it_ssg, cl.playerview[SP].simorg); } } return; @@ -2634,11 +2634,11 @@ more: armor_updated = (vars.stat_framecounts[STAT_ARMOR] == cls.framecount); armortype = FindNearestItem (it_armor, &item); - if (armortype == 1 || (!armortype && armor_updated && cl.stats[SP][STAT_ARMOR] == 100)) + if (armortype == 1 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 100)) ExecTookTrigger (tp_name_ga.string, it_ga, org); - else if (armortype == 2 || (!armortype && armor_updated && cl.stats[SP][STAT_ARMOR] == 150)) + else if (armortype == 2 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 150)) ExecTookTrigger (tp_name_ya.string, it_ya, org); - else if (armortype == 3 || (!armortype && armor_updated && cl.stats[SP][STAT_ARMOR] == 200)) + else if (armortype == 3 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 200)) ExecTookTrigger (tp_name_ra.string, it_ra, org); return; } @@ -2833,9 +2833,9 @@ static void TP_FindPoint (void) if (!cl.validsequence) goto nothing; - ang[0] = cl.viewangles[0][0]; ang[1] = cl.viewangles[0][1]; ang[2] = 0; + ang[0] = cl.playerview[SP].viewangles[0]; ang[1] = cl.playerview[SP].viewangles[1]; ang[2] = 0; AngleVectors (ang, visitem.forward, visitem.right, visitem.up); - VectorCopy (cl.simorg[0], visitem.vieworg); + VectorCopy (cl.playerview[SP].simorg, visitem.vieworg); visitem.vieworg[2] += 22 + (v_viewheight.value ? bound (-7, v_viewheight.value, 4) : 0); pointflags_dmm = pointflags; @@ -3058,7 +3058,7 @@ void TP_StatChanged (int stat, int value) else if (vars.health > 0) { // We have just died - vars.droppedweapon = cl.stats[SP][STAT_ACTIVEWEAPON]; + vars.droppedweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON]; vars.deathtrigger_time = realtime; strcpy (vars.lastdeathloc, Macro_Location()); @@ -3069,7 +3069,7 @@ void TP_StatChanged (int stat, int value) if (!cl.spectator && CountTeammates()) { - if (cl.teamfortress && (cl.stats[SP][STAT_ITEMS] & (IT_KEY1|IT_KEY2)) + if (cl.teamfortress && (cl.playerview[SP].stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2)) && Cmd_AliasExist("f_flagdeath", RESTRICT_LOCAL)) TP_ExecTrigger ("f_flagdeath"); else @@ -3101,9 +3101,9 @@ void TP_StatChanged (int stat, int value) } else if (stat == STAT_ACTIVEWEAPON) { - if (cl.stats[SP][STAT_ACTIVEWEAPON] != vars.activeweapon) + if (cl.playerview[SP].stats[STAT_ACTIVEWEAPON] != vars.activeweapon) TP_ExecTrigger ("f_weaponchange"); - vars.activeweapon = cl.stats[SP][STAT_ACTIVEWEAPON]; + vars.activeweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON]; } vars.stat_framecounts[stat] = cls.framecount; diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 74b0bed3..db34600f 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -176,8 +176,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define INTERQUAKEMODELS #define HUFFNETWORK //huffman network compression -// #define DOOMWADS //doom wad/sprite support -// #define MAP_DOOM //doom map support + #define DOOMWADS //doom wad/sprite support + #define MAP_DOOM //doom map support #define MAP_PROC //doom3/quake4 map support //#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet) #define Q2BSPS //quake 2 bsp support @@ -474,7 +474,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // per-level limits // #define MAX_EDICTS 32767 // FIXME: ouch! ouch! ouch! -#define MAX_LIGHTSTYLES 255 +#define MAX_LIGHTSTYLES 256 #define MAX_STANDARDLIGHTSTYLES 64 #define MAX_MODELS 1024 // these are sent over the net as bytes #define MAX_SOUNDS 1024 // so they cannot be blindly increased diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 83465d57..65041c78 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -497,52 +497,56 @@ typedef struct // a given brush can contribute multiple content bits // multiple brushes can be in a single leaf -// these definitions also need to be in q_shared.h! - -#define FTECONTENTS_EMPTY 0 -#define FTECONTENTS_SOLID 1 - //2 - //4 -#define FTECONTENTS_LAVA 8 -#define FTECONTENTS_SLIME 16 -#define FTECONTENTS_WATER 32 +#define FTECONTENTS_EMPTY 0x00000000 +#define FTECONTENTS_SOLID 0x00000001 + //0x00000002 + //0x00000004 +#define FTECONTENTS_LAVA 0x00000008 +#define FTECONTENTS_SLIME 0x00000010 +#define FTECONTENTS_WATER 0x00000020 #define FTECONTENTS_LADDER 0x00004000 #define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code. #define FTECONTENTS_PLAYERCLIP 0x00010000 +#define FTECONTENTS_MONSTERCLIP 0x00020000 #define FTECONTENTS_BODY 0x02000000 +#define FTECONTENTS_CORPSE 0x04000000 #define FTECONTENTS_SKY 0x80000000 // lower bits are stronger, and will eat weaker brushes completely -#define Q2CONTENTS_SOLID FTECONTENTS_SOLID //1 -#define Q2CONTENTS_WINDOW 2 // translucent, but not watery -#define Q2CONTENTS_AUX 4 -#define Q2CONTENTS_LAVA FTECONTENTS_LAVA //8 -#define Q2CONTENTS_SLIME FTECONTENTS_SLIME //16 -#define Q2CONTENTS_WATER FTECONTENTS_WATER //32 -#define Q2CONTENTS_MIST 64 - +#define Q2CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001 +#define Q2CONTENTS_WINDOW 0x00000002 // translucent, but not watery +#define Q2CONTENTS_AUX 0x00000004 +#define Q2CONTENTS_LAVA FTECONTENTS_LAVA //0x00000008 +#define Q2CONTENTS_SLIME FTECONTENTS_SLIME //0x00000010 +#define Q2CONTENTS_WATER FTECONTENTS_WATER //0x00000020 +#define Q2CONTENTS_MIST 0x00000040 + //0x00000080 + //0x00000100 + //0x00000200 + //0x00000400 + //0x00000800 + //0x00001000 + //0x00002000 + //FTECONTENTS_LADDER //0x00004000 // remaining contents are non-visible, and don't eat brushes - -#define Q2CONTENTS_AREAPORTAL 0x8000 - -#define Q2CONTENTS_PLAYERCLIP 0x10000 -#define Q2CONTENTS_MONSTERCLIP 0x20000 - +#define Q2CONTENTS_AREAPORTAL 0x00008000 +#define Q2CONTENTS_PLAYERCLIP FTECONTENTS_PLAYERCLIP //0x00010000 +#define Q2CONTENTS_MONSTERCLIP FTECONTENTS_MONSTERCLIP //0x00020000 // currents can be added to any other contents, and may be mixed -#define Q2CONTENTS_CURRENT_0 0x40000 -#define Q2CONTENTS_CURRENT_90 0x80000 -#define Q2CONTENTS_CURRENT_180 0x100000 -#define Q2CONTENTS_CURRENT_270 0x200000 -#define Q2CONTENTS_CURRENT_UP 0x400000 -#define Q2CONTENTS_CURRENT_DOWN 0x800000 - -#define Q2CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity - -#define Q2CONTENTS_MONSTER FTECONTENTS_BODY //0x2000000 // should never be on a brush, only in game -#define Q2CONTENTS_DEADMONSTER 0x4000000 -#define Q2CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs -#define Q2CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans -#define Q2CONTENTS_LADDER 0x20000000 +#define Q2CONTENTS_CURRENT_0 0x00040000 +#define Q2CONTENTS_CURRENT_90 0x00080000 +#define Q2CONTENTS_CURRENT_180 0x00100000 +#define Q2CONTENTS_CURRENT_270 0x00200000 +#define Q2CONTENTS_CURRENT_UP 0x00400000 +#define Q2CONTENTS_CURRENT_DOWN 0x00800000 +#define Q2CONTENTS_ORIGIN 0x01000000 // removed before bsping an entity +#define Q2CONTENTS_MONSTER FTECONTENTS_BODY //0x02000000 // should never be on a brush, only in game +#define Q2CONTENTS_DEADMONSTER FTECONTENTS_CORPSE //0x04000000 +#define Q2CONTENTS_DETAIL 0x08000000 // brushes to be added after vis leafs +#define Q2CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans +#define Q2CONTENTS_LADDER 0x20000000 + //0x40000000 + //0x80000000 #define Q3CONTENTS_SOLID FTECONTENTS_SOLID //1 // should never be on a brush, only in game @@ -559,10 +563,10 @@ typedef struct //0x00000800 //0x00001000 //0x00002000 - //0x00004000 + //FTECONTENTS_LADDER //0x00004000 #define Q3CONTENTS_AREAPORTAL 0x00008000 -#define Q3CONTENTS_PLAYERCLIP Q2CONTENTS_PLAYERCLIP //0x00010000 -#define Q3CONTENTS_MONSTERCLIP Q2CONTENTS_MONSTERCLIP //0x00020000 +#define Q3CONTENTS_PLAYERCLIP FTECONTENTS_PLAYERCLIP //0x00010000 +#define Q3CONTENTS_MONSTERCLIP FTECONTENTS_MONSTERCLIP //0x00020000 #define Q3CONTENTS_TELEPORTER 0x00040000 #define Q3CONTENTS_JUMPPAD 0x00080000 #define Q3CONTENTS_CLUSTERPORTAL 0x00100000 @@ -571,7 +575,7 @@ typedef struct #define Q3CONTENTS_MOVER 0x00800000 #define Q3CONTENTS_ORIGIN Q2CONTENTS_ORIGIN //0x01000000 #define Q3CONTENTS_BODY 0x02000000 -#define Q3CONTENTS_CORPSE Q2CONTENTS_DEADMONSTER //0x04000000 +#define Q3CONTENTS_CORPSE FTECONTENTS_CORPSE //0x04000000 #define Q3CONTENTS_DETAIL Q2CONTENTS_DETAIL //0x08000000 #define Q3CONTENTS_STRUCTURAL 0x10000000 #define Q3CONTENTS_TRANSLUCENT 0x20000000 diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 44e5fa6b..0747d18e 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2846,11 +2846,22 @@ void Cmd_Shutdown(void) { cmd_function_t *c; cmdalias_t *a; + int i; + //make sure we get no other execution int level; for (level = 0; level < sizeof(cmd_text)/sizeof(cmd_text[0]); level++) + { SZ_Clear (&cmd_text[level].buf); + if (cmd_text[level].buf.data) + { + BZ_Free(cmd_text[level].buf.data); + cmd_text[level].buf.data = NULL; + cmd_text[level].buf.maxsize = 0; + } + } + while(cmd_functions) { c = cmd_functions; @@ -2864,6 +2875,12 @@ void Cmd_Shutdown(void) Z_Free(a->value); Z_Free(a); } + + for (i=0 ; inumindexes = inf->numindexes; mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); - mesh->lmst_array = NULL; mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); mesh->colors4f_array = meshcache.colours; @@ -1507,7 +1524,6 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent #ifndef SERVERONLY mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); - mesh->lmst_array = NULL; mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); mesh->normals_array = meshcache.norm; mesh->snormals_array = meshcache.norm+meshcache.numnorm; @@ -1630,7 +1646,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent } - if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival) + if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival || qrenderer != QR_OPENGL) { mesh->xyz2_array = NULL; mesh->xyz_blendw[0] = 1; @@ -2230,26 +2246,62 @@ static dmdl_t *pq1inmodel; #define NUMVERTEXNORMALS 162 extern float r_avertexnormals[NUMVERTEXNORMALS][3]; // mdltype 0 = q1, 1 = qtest, 2 = rapo/h2 + +static void Alias_LoadPose(vecV_t *verts, vec3_t *normals, vec3_t *svec, vec3_t *tvec, dtrivertx_t *pinframe, int *seamremaps, int mdltype) +{ + int j; + if (mdltype == 2) + { + for (j = 0; j < galias->numverts; j++) + { + verts[j][0] = pinframe[seamremaps[j]].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[seamremaps[j]].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[seamremaps[j]].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[seamremaps[j]].lightnormalindex], normals[j]); +#endif + } + } + else + { + for (j = 0; j < pq1inmodel->numverts; j++) + { + verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); +#endif + if (seamremaps[j] != j) + { + VectorCopy(verts[j], verts[seamremaps[j]]); +#ifndef SERVERONLY + VectorCopy(normals[j], normals[seamremaps[j]]); +#endif + } + } + } +} static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps, int mdltype) { galiaspose_t *pose; - galiasgroup_t *frame; + galiasgroup_t *frame = (galiasgroup_t*)((char *)galias + galias->groupofs); dtrivertx_t *pinframe; daliasframe_t *frameinfo; - int i, j, k; + int i, k; daliasgroup_t *ingroup; daliasinterval_t *intervals; float sinter; -#ifndef SERVERONLY vec3_t *normals, *svec, *tvec; -#endif vecV_t *verts; - int aliasframesize; + int aliasframesize = (mdltype == 1) ? sizeof(daliasframe_t)-16 : sizeof(daliasframe_t); - aliasframesize = (mdltype == 1) ? sizeof(daliasframe_t)-16 : sizeof(daliasframe_t); - - frame = (galiasgroup_t*)((char *)galias + galias->groupofs); +#ifdef SERVERONLY + normals = NULL; + svec = NULL; + tvec = NULL; +#endif for (i = 0; i < pq1inmodel->numframes; i++) { @@ -2258,7 +2310,11 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap case ALIAS_SINGLE: frameinfo = (daliasframe_t*)((char *)(pframetype+1)); // qtest aliasframe is a subset pinframe = (dtrivertx_t*)((char*)frameinfo+aliasframesize); +#ifndef SERVERONLY pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + (sizeof(vecV_t)+sizeof(vec3_t)*3)*galias->numverts); +#else + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + (sizeof(vecV_t))*galias->numverts); +#endif frame->poseofs = (char *)pose - (char *)frame; frame->numposes = 1; galias->groups++; @@ -2277,43 +2333,9 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap pose->ofsnormals = (char *)normals - (char *)pose; pose->ofssvector = (char *)svec - (char *)pose; pose->ofstvector = (char *)tvec - (char *)pose; -#else -#ifdef warningmsg -#pragma warningmsg("wasted memory") -#endif #endif - if (mdltype == 2) - { - for (j = 0; j < galias->numverts; j++) - { - verts[j][0] = pinframe[seamremaps[j]].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[seamremaps[j]].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[seamremaps[j]].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[seamremaps[j]].lightnormalindex], normals[j]); -#endif - } - } - else - { - for (j = 0; j < pq1inmodel->numverts; j++) - { - verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); -#endif - if (seamremaps[j] != j) - { - VectorCopy(verts[j], verts[seamremaps[j]]); -#ifndef SERVERONLY - VectorCopy(normals[j], normals[seamremaps[j]]); -#endif - } - } - } + Alias_LoadPose(verts, normals, svec, tvec, pinframe, seamremaps, mdltype); // GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); @@ -2367,37 +2389,7 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); } - if (mdltype == 2) - { - for (j = 0; j < galias->numverts; j++) - { - verts[j][0] = pinframe[seamremaps[j]].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[seamremaps[j]].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[seamremaps[j]].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[seamremaps[j]].lightnormalindex], normals[j]); -#endif - } - } - else - { - for (j = 0; j < pq1inmodel->numverts; j++) - { - verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); -#endif - if (seamremaps[j] != j) - { - VectorCopy(verts[j], verts[seamremaps[j]]); -#ifndef SERVERONLY - VectorCopy(normals[j], normals[seamremaps[j]]); -#endif - } - } - } + Alias_LoadPose(verts, normals, svec, tvec, pinframe, seamremaps, mdltype); #ifndef SERVERONLY verts = (vecV_t*)&tvec[galias->numverts]; diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index eb5859f3..71bf88fd 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -131,6 +131,7 @@ void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weight #endif qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, entity_t *e, qboolean allowskel); void Alias_FlushCache(void); +void Alias_Shutdown(void); void Mod_DoCRC(model_t *mod, char *buffer, int buffersize); diff --git a/engine/common/common.c b/engine/common/common.c index db7d32cb..b31a52c3 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -185,6 +185,15 @@ void QDECL Q_strncpyz(char *d, const char *s, int n) *d='\0'; } +//windows/linux have inconsistant snprintf +//this is an attempt to get them consistant and safe +//size is the total size of the buffer +void VARGS Q_vsnprintfz (char *dest, size_t size, char *fmt, va_list argptr) +{ + vsnprintf (dest, size, fmt, argptr); + dest[size-1] = 0; +} + //windows/linux have inconsistant snprintf //this is an attempt to get them consistant and safe //size is the total size of the buffer @@ -193,10 +202,8 @@ void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) va_list argptr; va_start (argptr, fmt); - vsnprintf (dest, size, fmt, argptr); + Q_vsnprintfz(dest, size, fmt, argptr); va_end (argptr); - - dest[size-1] = 0; } @@ -3381,7 +3388,6 @@ void COM_Init (void) nullentitystate.glowmod[2] = 32; nullentitystate.trans = 255; nullentitystate.scale = 16; - nullentitystate.abslight = 255; nullentitystate.solid = 0;//ES_SOLID_BSP; } diff --git a/engine/common/common.h b/engine/common/common.h index d428af66..a59fb972 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -212,6 +212,7 @@ int wildcmp(const char *wild, const char *string); //1 if match #define Q_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) LIKEPRINTF(3); +void VARGS Q_vsnprintfz (char *dest, size_t size, char *fmt, va_list args); int VARGS Com_sprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3); #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 @@ -339,6 +340,9 @@ FTE_DEPRECATED void COM_CloseFile (FILE *h); typedef struct vfsfile_s { +#ifdef _DEBUG + char dbgname[MAX_QPATH]; +#endif int (*ReadBytes) (struct vfsfile_s *file, void *buffer, int bytestoread); int (*WriteBytes) (struct vfsfile_s *file, const void *buffer, int bytestoread); qboolean (*Seek) (struct vfsfile_s *file, unsigned long pos); //returns false for error @@ -451,6 +455,7 @@ char *version_string(void); void TL_InitLanguages(void); +void TL_Shutdown(void); void T_FreeStrings(void); char *T_GetString(int num); void T_FreeInfoStrings(void); diff --git a/engine/common/fs.c b/engine/common/fs.c index ea44dddc..8196f8b2 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -21,6 +21,8 @@ int active_fs_cachetype; static int fs_referencetype; int fs_finds; +int fs_switchgame = -1; + struct { const char *extension; @@ -1397,7 +1399,10 @@ static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam) return true; pak = funcs->OpenNew (vfs, pakfile); if (!pak) + { + VFS_CLOSE(vfs); return true; + } Q_snprintfz (pakfile, sizeof(pakfile), "%s%s/", param->parentdesc, descriptor); if (*param->puredesc) @@ -1804,10 +1809,10 @@ void COM_Gamedir (const char *dir) #define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\n" typedef struct { - const char *protocolname; //sent to the master server when this is the current gamemode. - const char *exename; //used if the exe name contains this const char *argname; //used if this was used as a parameter. - const char *auniquefile[4]; //used if this file is relative from the gamedir + const char *exename; //used if the exe name contains this + const char *protocolname; //sent to the master server when this is the current gamemode (Typically set for DP compat). + const char *auniquefile[4]; //used if this file is relative from the gamedir. needs just one file const char *customexec; @@ -1819,32 +1824,36 @@ const gamemode_info_t gamemode_info[] = { //this is to avoid having too many gamemodes anyway. //rogue/hipnotic have no special files - the detection conflicts and stops us from running regular quake - //protocol name(dpmaster) exename cmdline switch identifying file exec dir1 dir2 dir3 dir(fte) full name - {"DarkPlaces-Quake", "q1", "-quake", {"id1/pak0.pak"}, NULL, {"id1", "qw", "fte"}, "Quake"}, - {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", {NULL}, NULL, {"id1", "qw", "hipnotic", "fte"}, "Quake: Scourge of Armagon"}, - {"Darkplaces-Rogue", "rogue", "-rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"}, - {"Nexuiz", "nexuiz", "-nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"}, - {"Xonotic", "xonotic", "-xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"}, - {"Spark", "spark", "-spark", {"base/src/progs.src", - "base/qwprogs.dat", - "base/pak0.pak"}, DMFCFG, {"base", }, "Spark"}, + //cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name + {"-quake", "q1", "DarkPlaces-Quake", {"id1/pak0.pak" + "id1/quake.rc"}, NULL, {"id1", "qw", "fte"}, "Quake"}, + {"-hipnotic", "hipnotic", "Darkplaces-Hipnotic", {NULL}, NULL, {"id1", "qw", "hipnotic", "fte"}, "Quake: Scourge of Armagon"}, + {"-rogue", "rogue", "Darkplaces-Rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"}, + {"-nexuiz", "nexuiz", "Nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"}, + {"-xonotic", "xonotic", "Xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"}, + {"-spark", "spark", "Spark", {"base/src/progs.src", + "base/qwprogs.dat", + "base/pak0.pak"}, DMFCFG, {"base", }, "Spark"}, //supported commercial mods (some are currently only partially supported) - {"FTE-H2MP", "h2mp", "-portals", {"portals/hexen.rc", - "portals/pak3.pak"}, HEX2CFG,{"data1", "portals", "fteh2"}, "Hexen II MP"}, - {"FTE-Hexen2", "hexen2", "-hexen2", {"data1/pak0.pak"}, HEX2CFG,{"data1", "fteh2"}, "Hexen II"}, - {"FTE-Quake2", "q2", "-q2", {"baseq2/pak0.pak"}, NULL, {"baseq2", "fteq2"}, "Quake II"}, - {"FTE-Quake3", "q3", "-q3", {"baseq3/pak0.pk3"}, Q3CFG, {"baseq3", "fteq3"}, "Quake III Arena"}, + {"-portals", "h2mp", "FTE-H2MP", {"portals/hexen.rc", + "portals/pak3.pak"}, HEX2CFG,{"data1", "portals", "fteh2"}, "Hexen II MP"}, + {"-hexen2", "hexen2", "FTE-Hexen2", {"data1/pak0.pak"}, HEX2CFG,{"data1", "fteh2"}, "Hexen II"}, + {"-q2", "q2", "FTE-Quake2", {"baseq2/pak0.pak"}, NULL, {"baseq2", "fteq2"}, "Quake II"}, + {"-q3", "q3", "FTE-Quake3", {"baseq3/pak0.pk3"}, Q3CFG, {"baseq3", "fteq3"}, "Quake III Arena"}, - //the rest are not officially supported. - {"FTE-Quake4", "q4", "-q4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"}, - {"FTE-EnemyTerritory", "et", "-et", {"etmain/pak0.pk3"}, NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"}, + //can run in windows, needs + {"-halflife", "hl", "FTE-HalfLife", {"valve/liblist.gam"}, NULL, {"valve", "ftehl"}, "Half-Life"}, - {"FTE-JK2", "jk2", "-jk2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"}, + //the rest are not supported in any real way. maps-only mostly, if that + {"-q4", "q4", "FTE-Quake4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"}, + {"-et", "et", "FTE-EnemyTerritory", {"etmain/pak0.pk3"}, NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"}, - {"FTE-HalfLife", "hl", "-halflife", {"valve/liblist.gam"}, NULL, {"valve", "ftehl"}, "Half-Life"}, - {"FTE-Doom", "doom", "-doom", {"doom.wad"}, NULL, {"*doom.wad", "ftedoom"}, "Doom"}, - {"FTE-Doom2", "doom2", "-doom2", {"doom2.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"}, + {"-jk2", "jk2", "FTE-JK2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"}, + {"-warsow", "warsow", "FTE-Warsow", {"basewsw/pak0.pk3"}, NULL, {"basewsw", "fte"}, "Warsow"}, + + {"-doom", "doom", "FTE-Doom", {"doom.wad"}, NULL, {"*doom.wad", "ftedoom"}, "Doom"}, + {"-doom2", "doom2", "FTE-Doom2", {"doom2.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"}, {NULL} }; @@ -2430,6 +2439,13 @@ void FS_Shutdown(void) com_fschanged = true; + + if (filesystemhash.numbuckets) + { + BZ_Free(filesystemhash.bucket); + filesystemhash.bucket = NULL; + filesystemhash.numbuckets = 0; + } } void FS_AddGamePack(const char *pakname) @@ -2560,6 +2576,23 @@ void FS_StartupWithGame(int gamenum) Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL); } +void FS_ChangeGame_f(void) +{ + int i; + char *arg = Cmd_Argv(1); + + for (i = 0; gamemode_info[i].argname; i++) + { + if (!stricmp(gamemode_info[i].argname+1, arg)) + { + Con_Printf("Switching to %s\n", gamemode_info[i].argname+1); + fs_switchgame = i; + return; + } + } + Con_Printf("Game unknown\n"); +} + /* ================ COM_InitFilesystem @@ -2579,6 +2612,9 @@ void COM_InitFilesystem (void) FS_RegisterDefaultFileSystems(); Cmd_AddCommand("fs_restart", FS_ReloadPackFiles_f); +#ifdef _WIN32 + Cmd_AddCommand("fs_changegame", FS_ChangeGame_f); +#endif // // -basedir @@ -2635,7 +2671,7 @@ void COM_InitFilesystem (void) //use the game based on an parameter over all else. for (i = 0; gamemode_info[i].argname; i++) { - if (COM_CheckParm(gamemode_info[i].argname)) + if ((fs_switchgame != -1 && i == fs_switchgame) || (fs_switchgame == -1 && COM_CheckParm(gamemode_info[i].argname))) { gamenum = i; @@ -2675,6 +2711,7 @@ void COM_InitFilesystem (void) break; } } + fs_switchgame = -1; //still failed? find quake and use that one by default if (gamenum<0) diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index cbd1c3d2..6c23af9a 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -340,6 +340,9 @@ vfsfile_t *FSPAK_OpenVFS(void *handle, flocation_t *loc, const char *mode) vfs->length = loc->len; vfs->currentpos = vfs->startpos; +#ifdef _DEBUG + Q_strncpyz(vfs->funcs.dbgname, pack->files[loc->index].name, sizeof(vfs->funcs.dbgname)); +#endif vfs->funcs.Close = VFSPAK_Close; vfs->funcs.GetLen = VFSPAK_GetLen; vfs->funcs.ReadBytes = VFSPAK_ReadBytes; @@ -388,7 +391,7 @@ void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, const char *desc) { dwadheader_t header; int i; - packfile_t *newfiles; + mpackfile_t *newfiles; int numpackfiles; pack_t *pack; dwadfile_t info; @@ -423,7 +426,7 @@ void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, const char *desc) header.dirlen = LittleLong (header.dirlen); numpackfiles = header.dirlen; - newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); + newfiles = (mpackfile_t*)Z_Malloc (numpackfiles * sizeof(mpackfile_t)); VFS_SEEK(packhandle, header.dirofs); //doom wads are awkward. diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index 938bfacf..61c15d36 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -102,6 +102,9 @@ vfsfile_t *FSSTDIO_OpenTemp(void) file = Z_Malloc(sizeof(vfsstdiofile_t)); file->funcs.Close = VFSSTDIO_Close; +#endif +#ifdef _DEBUG + Q_strncpyz(file->funcs.dbgname, "FSSTDIO_OpenTemp", sizeof(file->funcs.dbgname)); #endif file->funcs.ReadBytes = VFSSTDIO_ReadBytes; file->funcs.WriteBytes = VFSSTDIO_WriteBytes; @@ -164,6 +167,9 @@ static vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean * } file = Z_Malloc(sizeof(vfsstdiofile_t)); +#ifdef _DEBUG + Q_strncpyz(file->funcs.dbgname, osname, sizeof(file->funcs.dbgname)); +#endif file->funcs.ReadBytes = strchr(mode, 'r')?VFSSTDIO_ReadBytes:NULL; file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSSTDIO_WriteBytes:NULL; file->funcs.Seek = VFSSTDIO_Seek; diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c index 846df8c9..1af80390 100644 --- a/engine/common/fs_win32.c +++ b/engine/common/fs_win32.c @@ -165,6 +165,9 @@ vfsfile_t *VFSW32_Open(const char *osname, const char *mode) } file = Z_Malloc(sizeof(vfsw32file_t)); +#ifdef _DEBUG + Q_strncpyz(file->funcs.dbgname, osname, sizeof(file->funcs.dbgname)); +#endif file->funcs.ReadBytes = read?VFSW32_ReadBytes:NULL; file->funcs.WriteBytes = (write||append)?VFSW32_WriteBytes:NULL; file->funcs.Seek = VFSW32_Seek; diff --git a/engine/common/fs_zip.c b/engine/common/fs_zip.c index 7d351bdb..ed3ea413 100644 --- a/engine/common/fs_zip.c +++ b/engine/common/fs_zip.c @@ -653,6 +653,9 @@ vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, const char *mode) vfsz->startpos = zip->files[loc->index].filepos; vfsz->length = loc->len; +#ifdef _DEBUG + Q_strncpyz(vfsz->funcs.dbgname, zip->files[loc->index].name, sizeof(vfsz->funcs.dbgname)); +#endif vfsz->funcs.Close = VFSZIP_Close; vfsz->funcs.GetLen = VFSZIP_GetLen; vfsz->funcs.ReadBytes = VFSZIP_ReadBytes; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index ff49b755..7be0c5f6 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -42,6 +42,7 @@ unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p); extern char loadname[32]; extern model_t *loadmodel; +void RMod_Batches_Build(mesh_t *meshlist, model_t *mod, void (*build)(model_t *mod, msurface_t *surf, void *cookie), void *buildcookie); float RadiusFromBounds (vec3_t mins, vec3_t maxs) { int i; @@ -351,7 +352,7 @@ static vecV_t *map_verts; //3points static int numvertexes; static vec2_t *map_vertstmexcoords; -static vec2_t *map_vertlstmexcoords; +static vec2_t *map_vertlstmexcoords[4]; static vec4_t *map_colors4f_array; static vec3_t *map_normals_array; static vec3_t *map_svector_array; @@ -2062,7 +2063,10 @@ qboolean CModQ3_LoadVertexes (lump_t *l) tout = Hunk_Alloc ( count*sizeof(*nout) ); map_verts = out; map_vertstmexcoords = stout; - map_vertlstmexcoords = lmout; + map_vertlstmexcoords[0] = lmout; + map_vertlstmexcoords[1] = lmout; + map_vertlstmexcoords[2] = lmout; + map_vertlstmexcoords[3] = lmout; map_colors4f_array = cout; map_normals_array = nout; map_svector_array = sout; @@ -2098,6 +2102,7 @@ qboolean CModRBSP_LoadVertexes (lump_t *l) int i, count, j; vec2_t *lmout, *stout; vec4_t *cout; + int sty; in = (void *)(cmod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -2115,14 +2120,15 @@ qboolean CModRBSP_LoadVertexes (lump_t *l) out = Hunk_Alloc ( count*sizeof(*out) ); stout = Hunk_Alloc ( count*sizeof(*stout) ); - lmout = Hunk_Alloc ( count*sizeof(*lmout) ); + lmout = Hunk_Alloc ( MAXLIGHTMAPS*count*sizeof(*lmout) ); cout = Hunk_Alloc ( count*sizeof(*cout) ); nout = Hunk_Alloc ( count*sizeof(*nout) ); sout = Hunk_Alloc ( count*sizeof(*sout) ); tout = Hunk_Alloc ( count*sizeof(*tout) ); map_verts = out; map_vertstmexcoords = stout; - map_vertlstmexcoords = lmout; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + map_vertlstmexcoords[sty] = lmout + sty*count; map_colors4f_array = cout; map_normals_array = nout; map_svector_array = sout; @@ -2139,7 +2145,8 @@ qboolean CModRBSP_LoadVertexes (lump_t *l) for ( j=0 ; j < 2 ; j++) { stout[i][j] = LittleFloat ( ((float *)in->texcoords)[j] ); - lmout[i][j] = LittleFloat ( ((float *)in->texcoords)[j+2] ); + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + map_vertlstmexcoords[sty][i][j] = LittleFloat ( ((float *)in->texcoords)[j+2*(sty+1)] ); } for ( j=0 ; j < 4 ; j++) { @@ -2354,22 +2361,54 @@ mfog_t *CM_FogForOrigin(vec3_t org) index_t tempIndexesArray[MAX_ARRAY_VERTS*6]; -//mesh_t *GL_CreateMeshForPatch ( model_t *mod, q3dface_t *surf ) -mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, int numverts, int firstvert) +void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert) { - int numindexes, patch_cp[2], step[2], size[2], flat[2], i, u, v, p; - mesh_t *mesh; - index_t *indexes; + int patch_cp[2], step[2], size[2], flat[2]; float subdivlevel; - char *allocbuf; - int sz; patch_cp[0] = patchwidth; patch_cp[1] = patchheight; if (patch_cp[0] <= 0 || patch_cp[1] <= 0 ) { - return NULL; + mesh->numindexes = 0; + mesh->numvertexes = 0; + return; + } + + subdivlevel = r_subdivisions.value; + if ( subdivlevel < 1 ) + subdivlevel = 1; + +// find the degree of subdivision in the u and v directions + Patch_GetFlatness ( subdivlevel, map_verts[firstvert], sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat ); + +// allocate space for mesh + step[0] = (1 << flat[0]); + step[1] = (1 << flat[1]); + size[0] = (patch_cp[0] / 2) * step[0] + 1; + size[1] = (patch_cp[1] / 2) * step[1] + 1; + + mesh->numvertexes = size[0] * size[1]; + mesh->numindexes = (size[0]-1) * (size[1]-1) * 6; +} + +//mesh_t *GL_CreateMeshForPatch ( model_t *mod, q3dface_t *surf ) +void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert) +{ + int numindexes, patch_cp[2], step[2], size[2], flat[2], i, u, v, p; + index_t *indexes; + float subdivlevel; + int sty; + + patch_cp[0] = patchwidth; + patch_cp[1] = patchheight; + + if (patch_cp[0] <= 0 || patch_cp[1] <= 0 ) + { + mesh->numindexes = 0; + mesh->numvertexes = 0; + return; } subdivlevel = r_subdivisions.value; @@ -2387,34 +2426,19 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in numverts = size[0] * size[1]; if ( numverts < 0 || numverts > MAX_ARRAY_VERTS ) - return NULL; + { + mesh->numindexes = 0; + mesh->numvertexes = 0; + return; + } - sz = sizeof(mesh_t) + numverts * ( - sizeof(vecV_t)+ - sizeof(vec3_t)+ - sizeof(vec3_t)+ - sizeof(vec3_t)+ - sizeof(vec2_t)+ - sizeof(vec2_t)+ - sizeof(vec4_t)); - allocbuf = Hunk_Alloc(sz); - sz-=sizeof(mesh_t); - mesh = (mesh_t *)(allocbuf+sz); - sz-=numverts*sizeof(vecV_t); - mesh->xyz_array = (vecV_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec3_t); - mesh->normals_array = (vec3_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec3_t); - mesh->snormals_array = (vec3_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec3_t); - mesh->tnormals_array = (vec3_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec2_t); - mesh->st_array = (vec2_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec2_t); - mesh->lmst_array = (vec2_t *)(allocbuf+sz); - sz-=numverts*sizeof(vec4_t); - mesh->colors4f_array = (vec4_t *)(allocbuf+sz); - mesh->numvertexes = numverts; + + if (mesh->numvertexes != numverts) + { + mesh->numindexes = 0; + mesh->numvertexes = 0; + return; + } // fill in @@ -2422,7 +2446,11 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in Patch_Evaluate ( map_colors4f_array[firstvert], patch_cp, step, mesh->colors4f_array[0], 4 ); Patch_Evaluate ( map_normals_array[firstvert], patch_cp, step, mesh->normals_array[0], 3 ); Patch_Evaluate ( map_vertstmexcoords[firstvert], patch_cp, step, mesh->st_array[0], 2 ); - Patch_Evaluate ( map_vertlstmexcoords[firstvert], patch_cp, step, mesh->lmst_array[0], 2 ); + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + if (mesh->lmst_array[sty]) + Patch_Evaluate ( map_vertlstmexcoords[sty][firstvert], patch_cp, step, mesh->lmst_array[sty][0], 2 ); + } // compute new indexes avoiding adding invalid triangles numindexes = 0; @@ -2435,9 +2463,10 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in indexes[1] = p + size[0]; indexes[2] = p + 1; - if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) && - !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) && - !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) ) { +// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) && +// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) && +// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) ) + { indexes += 3; numindexes += 3; } @@ -2446,9 +2475,10 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in indexes[1] = p + size[0]; indexes[2] = p + size[0] + 1; - if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) && - !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) && - !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) ) { +// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) && +// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) && +// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) ) + { indexes += 3; numindexes += 3; } @@ -2456,12 +2486,224 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in } // allocate and fill index table + if (mesh->numindexes != numindexes) + Con_Printf("DEBUGY\n"); + mesh->numindexes = numindexes; - mesh->indexes = (index_t *)Hunk_Alloc ( numindexes * sizeof(index_t)); memcpy (mesh->indexes, tempIndexesArray, numindexes * sizeof(index_t) ); +} + +void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, void *cookie) +{ + rbspface_t *in = cookie; + int idx = out - loadmodel->surfaces; + int sty; + in += idx; + + if (LittleLong(in->facetype) == MST_PATCH) + { +// out->mesh->numindexes = 0; +// out->mesh->numvertexes = 0; + //FIXME + GL_CreateMeshForPatch(loadmodel, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); +// if (out->mesh) +// { +// Mod_AccumulateMeshTextureVectors(out->mesh); +// Mod_NormaliseTextureVectors(out->mesh->normals_array, out->mesh->snormals_array, out->mesh->tnormals_array, out->mesh->numvertexes); +// } + } + else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) + { + unsigned int fv = LittleLong(in->firstvertex), i; + for (i = 0; i < out->mesh->numvertexes; i++) + { + VectorCopy(map_verts[fv + i], out->mesh->xyz_array[i]); + Vector2Copy(map_vertstmexcoords[fv + i], out->mesh->st_array[i]); + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + Vector2Copy(map_vertlstmexcoords[sty][fv + i], out->mesh->lmst_array[sty][i]); + } + Vector4Copy(map_colors4f_array[fv + i], out->mesh->colors4f_array[i]); + + VectorCopy(map_normals_array[fv + i], out->mesh->normals_array[i]); + } + fv = LittleLong(in->firstindex); + for (i = 0; i < out->mesh->numindexes; i++) + { + out->mesh->indexes[i] = map_surfindexes[fv + i]; + } + +/* numindexes = LittleLong(in->num_indexes); + numverts = LittleLong(in->num_vertices); + if (numindexes%3 || numindexes < 0 || numverts < 0) + { + Con_Printf(CON_ERROR "mesh indexes should be multiples of 3\n"); + return false; + } + + out->mesh = Hunk_Alloc(sizeof(mesh_t)); + out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); + out->mesh->snormals_array = map_svector_array + LittleLong(in->firstvertex); + out->mesh->tnormals_array = map_tvector_array + LittleLong(in->firstvertex); + + out->mesh->colors4f_array = map_colors4f_array + LittleLong(in->firstvertex); + out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); + out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); + out->mesh->st_array = map_vertstmexcoords + LittleLong(in->firstvertex); + out->mesh->lmst_array = map_vertlstmexcoords + LittleLong(in->firstvertex); + + out->mesh->numindexes = numindexes; + out->mesh->numvertexes = numverts; + + if (LittleLong(in->facetype) == MST_PLANAR) + if (out->mesh->numindexes == (out->mesh->numvertexes-2)*3) + out->mesh->istrifan = true; + + Mod_AccumulateMeshTextureVectors(out->mesh); +*/ + } + else + { +/* //flare + int r, g, b; + extern index_t r_quad_indexes[6]; + static vec2_t st[4] = {{0,0},{0,1},{1,1},{1,0}}; + + mesh = out->mesh = (mesh_t *)Hunk_Alloc(sizeof(mesh_t)); + mesh->xyz_array = (vecV_t *)Hunk_Alloc(sizeof(vecV_t)*4); + mesh->colors4b_array = (byte_vec4_t *)Hunk_Alloc(sizeof(byte_vec4_t)*4); + mesh->numvertexes = 4; + mesh->indexes = r_quad_indexes; + mesh->st_array = st; + mesh->numindexes = 6; + + VectorCopy (in->lightmap_origin, mesh->xyz_array[0]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[1]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[2]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[3]); + + r = LittleFloat(in->lightmap_vecs[0][0]) * 255.0f; + r = bound (0, r, 255); + g = LittleFloat(in->lightmap_vecs[0][1]) * 255.0f; + g = bound (0, g, 255); + b = LittleFloat(in->lightmap_vecs[0][2]) * 255.0f; + b = bound (0, b, 255); + + mesh->colors4b_array[0][0] = r; + mesh->colors4b_array[0][1] = g; + mesh->colors4b_array[0][2] = b; + mesh->colors4b_array[0][3] = 255; + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[1]); + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[2]); + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[3]); +*/ + } +} + +void CModQ3_BuildSurfMesh(model_t *mod, msurface_t *out, void *cookie) +{ + q3dface_t *in = cookie; + int idx = out - loadmodel->surfaces; + in += idx; + + if (LittleLong(in->facetype) == MST_PATCH) + { +// out->mesh->numindexes = 0; +// out->mesh->numvertexes = 0; + //FIXME + GL_CreateMeshForPatch(loadmodel, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); +// if (out->mesh) +// { +// Mod_AccumulateMeshTextureVectors(out->mesh); +// Mod_NormaliseTextureVectors(out->mesh->normals_array, out->mesh->snormals_array, out->mesh->tnormals_array, out->mesh->numvertexes); +// } + } + else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) + { + unsigned int fv = LittleLong(in->firstvertex), i; + for (i = 0; i < out->mesh->numvertexes; i++) + { + VectorCopy(map_verts[fv + i], out->mesh->xyz_array[i]); + Vector2Copy(map_vertstmexcoords[fv + i], out->mesh->st_array[i]); + Vector2Copy(map_vertlstmexcoords[0][fv + i], out->mesh->lmst_array[0][i]); + Vector4Copy(map_colors4f_array[fv + i], out->mesh->colors4f_array[i]); + + VectorCopy(map_normals_array[fv + i], out->mesh->normals_array[i]); + } + fv = LittleLong(in->firstindex); + for (i = 0; i < out->mesh->numindexes; i++) + { + out->mesh->indexes[i] = map_surfindexes[fv + i]; + } + +/* numindexes = LittleLong(in->num_indexes); + numverts = LittleLong(in->num_vertices); + if (numindexes%3 || numindexes < 0 || numverts < 0) + { + Con_Printf(CON_ERROR "mesh indexes should be multiples of 3\n"); + return false; + } + + out->mesh = Hunk_Alloc(sizeof(mesh_t)); + out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); + out->mesh->snormals_array = map_svector_array + LittleLong(in->firstvertex); + out->mesh->tnormals_array = map_tvector_array + LittleLong(in->firstvertex); + + out->mesh->colors4f_array = map_colors4f_array + LittleLong(in->firstvertex); + out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); + out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); + out->mesh->st_array = map_vertstmexcoords + LittleLong(in->firstvertex); + out->mesh->lmst_array = map_vertlstmexcoords + LittleLong(in->firstvertex); + + out->mesh->numindexes = numindexes; + out->mesh->numvertexes = numverts; + + if (LittleLong(in->facetype) == MST_PLANAR) + if (out->mesh->numindexes == (out->mesh->numvertexes-2)*3) + out->mesh->istrifan = true; + + Mod_AccumulateMeshTextureVectors(out->mesh); +*/ + } + else + { +/* //flare + int r, g, b; + extern index_t r_quad_indexes[6]; + static vec2_t st[4] = {{0,0},{0,1},{1,1},{1,0}}; + + mesh = out->mesh = (mesh_t *)Hunk_Alloc(sizeof(mesh_t)); + mesh->xyz_array = (vecV_t *)Hunk_Alloc(sizeof(vecV_t)*4); + mesh->colors4b_array = (byte_vec4_t *)Hunk_Alloc(sizeof(byte_vec4_t)*4); + mesh->numvertexes = 4; + mesh->indexes = r_quad_indexes; + mesh->st_array = st; + mesh->numindexes = 6; + + VectorCopy (in->lightmap_origin, mesh->xyz_array[0]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[1]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[2]); + VectorCopy (in->lightmap_origin, mesh->xyz_array[3]); + + r = LittleFloat(in->lightmap_vecs[0][0]) * 255.0f; + r = bound (0, r, 255); + g = LittleFloat(in->lightmap_vecs[0][1]) * 255.0f; + g = bound (0, g, 255); + b = LittleFloat(in->lightmap_vecs[0][2]) * 255.0f; + b = bound (0, b, 255); + + mesh->colors4b_array[0][0] = r; + mesh->colors4b_array[0][1] = g; + mesh->colors4b_array[0][2] = b; + mesh->colors4b_array[0][3] = 255; + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[1]); + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[2]); + Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[3]); +*/ + } + - return mesh; } qboolean CModQ3_LoadRFaces (lump_t *l) @@ -2473,8 +2715,8 @@ qboolean CModQ3_LoadRFaces (lump_t *l) int count; int surfnum; - int numverts, numindexes; int fv; + int sty; mesh_t *mesh; @@ -2487,6 +2729,7 @@ qboolean CModQ3_LoadRFaces (lump_t *l) count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadmodel->name ); pl = Hunk_AllocName (count*sizeof(*pl), loadmodel->name);//create a new array of planes for speed. + mesh = Hunk_AllocName (count*sizeof(*mesh), loadmodel->name); loadmodel->surfaces = out; loadmodel->numsurfaces = count; @@ -2495,13 +2738,22 @@ qboolean CModQ3_LoadRFaces (lump_t *l) { out->plane = pl; out->texinfo = loadmodel->texinfo + LittleLong(in->shadernum); - out->lightmaptexturenum = LittleLong(in->lightmapnum); - out->light_s = LittleLong(in->lightmap_x); - out->light_t = LittleLong(in->lightmap_y); + out->lightmaptexturenums[0] = LittleLong(in->lightmapnum); + out->light_s[0] = LittleLong(in->lightmap_x); + out->light_t[0] = LittleLong(in->lightmap_y); + out->styles[0] = 255; + for (sty = 1; sty < MAXLIGHTMAPS; sty++) + { + out->styles[sty] = 255; + out->lightmaptexturenums[sty] = -1; + } out->extents[0] = (LittleLong(in->lightmap_width)-1)<<4; out->extents[1] = (LittleLong(in->lightmap_height)-1)<<4; out->samples=NULL; + if (loadmodel->lightmaps.count < out->lightmaptexturenums[0]+1) + loadmodel->lightmaps.count = out->lightmaptexturenums[0]+1; + fv = LittleLong(in->firstvertex); { vec3_t v[3]; @@ -2511,10 +2763,6 @@ qboolean CModQ3_LoadRFaces (lump_t *l) PlaneFromPoints(v, pl); CategorizePlane(pl); } - /* - if (in->fognum!=-1) - continue; - */ if (map_surfaces[LittleLong(in->shadernum)].c.value == 0 || map_surfaces[LittleLong(in->shadernum)].c.value & Q3CONTENTS_TRANSLUCENT) //q3dm10's thingie is 0 @@ -2543,84 +2791,30 @@ qboolean CModQ3_LoadRFaces (lump_t *l) if (map_surfaces[LittleLong(in->shadernum)].c.flags & (Q3SURF_NODRAW | Q3SURF_SKIP)) { - out->mesh = &nullmesh; + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = 0; + out->mesh->numvertexes = 0; } else if (LittleLong(in->facetype) == MST_PATCH) { - out->mesh = GL_CreateMeshForPatch(loadmodel, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); - if (out->mesh) - { - Mod_AccumulateMeshTextureVectors(out->mesh); - Mod_NormaliseTextureVectors(out->mesh->normals_array, out->mesh->snormals_array, out->mesh->tnormals_array, out->mesh->numvertexes); - } + out->mesh = &mesh[surfnum]; + GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); } else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) { - numindexes = LittleLong(in->num_indexes); - numverts = LittleLong(in->num_vertices); - if (numindexes%3 || numindexes < 0 || numverts < 0) - { - Con_Printf(CON_ERROR "mesh indexes should be multiples of 3\n"); - return false; - } - - out->mesh = Hunk_Alloc(sizeof(mesh_t)); - out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); - out->mesh->snormals_array = map_svector_array + LittleLong(in->firstvertex); - out->mesh->tnormals_array = map_tvector_array + LittleLong(in->firstvertex); - - out->mesh->colors4f_array = map_colors4f_array + LittleLong(in->firstvertex); - out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); - out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); - out->mesh->st_array = map_vertstmexcoords + LittleLong(in->firstvertex); - out->mesh->lmst_array = map_vertlstmexcoords + LittleLong(in->firstvertex); - - out->mesh->numindexes = numindexes; - out->mesh->numvertexes = numverts; - - if (LittleLong(in->facetype) == MST_PLANAR) - if (out->mesh->numindexes == (out->mesh->numvertexes-2)*3) - out->mesh->istrifan = true; - + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = LittleLong(in->num_indexes); + out->mesh->numvertexes = LittleLong(in->num_vertices); +/* Mod_AccumulateMeshTextureVectors(out->mesh); +*/ } else { - //flare - int r, g, b; - extern index_t r_quad_indexes[6]; - static vec2_t st[4] = {{0,0},{0,1},{1,1},{1,0}}; - - mesh = out->mesh = (mesh_t *)Hunk_Alloc(sizeof(mesh_t)); - mesh->xyz_array = (vecV_t *)Hunk_Alloc(sizeof(vecV_t)*4); - mesh->colors4b_array = (byte_vec4_t *)Hunk_Alloc(sizeof(byte_vec4_t)*4); - mesh->numvertexes = 4; - mesh->indexes = r_quad_indexes; - mesh->st_array = st; - mesh->numindexes = 6; - - VectorCopy (in->lightmap_origin, mesh->xyz_array[0]); - VectorCopy (in->lightmap_origin, mesh->xyz_array[1]); - VectorCopy (in->lightmap_origin, mesh->xyz_array[2]); - VectorCopy (in->lightmap_origin, mesh->xyz_array[3]); - - r = LittleFloat(in->lightmap_vecs[0][0]) * 255.0f; - r = bound (0, r, 255); - g = LittleFloat(in->lightmap_vecs[0][1]) * 255.0f; - g = bound (0, g, 255); - b = LittleFloat(in->lightmap_vecs[0][2]) * 255.0f; - b = bound (0, b, 255); - - mesh->colors4b_array[0][0] = r; - mesh->colors4b_array[0][1] = g; - mesh->colors4b_array[0][2] = b; - mesh->colors4b_array[0][3] = 255; - Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[1]); - Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[2]); - Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[3]); + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = 6; + out->mesh->numvertexes = 4; } - if (out->mesh->numindexes == 0) - Con_Printf("foo\n"); } Mod_NormaliseTextureVectors(map_normals_array, map_svector_array, map_tvector_array, numvertexes); @@ -2641,6 +2835,7 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) int numverts, numindexes; int fv; + int j; mesh_t *mesh; @@ -2654,6 +2849,7 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadmodel->name ); pl = Hunk_AllocName (count*sizeof(*pl), loadmodel->name);//create a new array of planes for speed. + mesh = Hunk_AllocName (count*sizeof(*mesh), loadmodel->name); loadmodel->surfaces = out; loadmodel->numsurfaces = count; @@ -2663,11 +2859,20 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) out->plane = pl; out->texinfo = loadmodel->texinfo + LittleLong(in->shadernum); in->facetype = LittleLong(in->facetype); - out->lightmaptexturenum = in->lightmapnum[0]; - out->light_s = in->lightmap_offs[0][0]; - out->light_t = in->lightmap_offs[0][0]; - out->extents[0] = (in->lightmap_width-1)<<4; - out->extents[1] = (in->lightmap_height-1)<<4; + for (j = 0; j < 4 && j < MAXLIGHTMAPS; j++) + { + if (in->lightmapnum[j] >= 0 && j) + Con_Printf("lightstyled!\n"); + out->lightmaptexturenums[j] = LittleLong(in->lightmapnum[j]); + out->light_s[j] = LittleLong(in->lightmap_offs[0][j]); + out->light_t[j] = LittleLong(in->lightmap_offs[1][j]); + out->styles[j] = in->lm_styles[j]; + + if (loadmodel->lightmaps.count < out->lightmaptexturenums[j]+1) + loadmodel->lightmaps.count = out->lightmaptexturenums[j]+1; + } + out->extents[0] = (LittleLong(in->lightmap_width)-1)<<4; + out->extents[1] = (LittleLong(in->lightmap_height)-1)<<4; out->samples=NULL; fv = LittleLong(in->firstvertex); @@ -2679,10 +2884,6 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) PlaneFromPoints(v, pl); CategorizePlane(pl); } - /* - if (in->fognum!=-1) - continue; - */ if (map_surfaces[in->shadernum].c.value == 0 || map_surfaces[in->shadernum].c.value & Q3CONTENTS_TRANSLUCENT) //q3dm10's thingie is 0 @@ -2710,66 +2911,35 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) else out->fog = map_fogs + in->fognum; #endif - if (map_surfaces[in->shadernum].c.flags & (Q3SURF_NODRAW | Q3SURF_SKIP)) - { - if (map_surfaces[in->shadernum].c.flags & Q3SURF_SKIP) - Con_Printf("Surface skip\n"); - out->mesh = NULL; - } - else if (in->facetype == MST_PATCH) - { - out->mesh = GL_CreateMeshForPatch(loadmodel, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); - } - else if (in->facetype == MST_PLANAR || in->facetype == MST_TRIANGLE_SOUP) - { - numindexes = LittleLong(in->num_indexes); - numverts = LittleLong(in->num_vertices); - if (numindexes%3) - { - Con_Printf(CON_ERROR "mesh indexes should be multiples of 3\n"); - return false; - } - out->mesh = Hunk_Alloc(sizeof(mesh_t) + (sizeof(vec3_t)) * numverts); - out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); - out->mesh->colors4f_array = map_colors4f_array + LittleLong(in->firstvertex); - out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); - out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); - out->mesh->st_array = map_vertstmexcoords + LittleLong(in->firstvertex); - out->mesh->lmst_array = map_vertlstmexcoords + LittleLong(in->firstvertex); - - out->mesh->numindexes = numindexes; - out->mesh->numvertexes = numverts; + if (map_surfaces[LittleLong(in->shadernum)].c.flags & (Q3SURF_NODRAW | Q3SURF_SKIP)) + { + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = 0; + out->mesh->numvertexes = 0; + } + else if (LittleLong(in->facetype) == MST_PATCH) + { + out->mesh = &mesh[surfnum]; + GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); + } + else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) + { + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = LittleLong(in->num_indexes); + out->mesh->numvertexes = LittleLong(in->num_vertices); +/* + Mod_AccumulateMeshTextureVectors(out->mesh); +*/ } else { -// int r, g, b; - extern index_t r_quad_indexes[6]; - static vec2_t st[4] = {{0,0},{0,1},{1,1},{1,0}}; - - mesh = out->mesh = (mesh_t *)Hunk_Alloc ( sizeof(mesh_t)); - mesh->xyz_array = (vecV_t *)Hunk_Alloc ( sizeof(vecV_t)); - mesh->numvertexes = 1; - mesh->indexes = r_quad_indexes; - mesh->st_array = st; - mesh->numindexes = 6; - // VectorCopy ( out->origin, mesh->xyz_array[0] ); - -/* r = LittleFloat ( in->lightmapVecs[0][0] ) * 255.0f; - r = bound ( 0, r, 255 ); - - g = LittleFloat ( in->lightmapVecs[0][1] ) * 255.0f; - g = bound ( 0, g, 255 ); - - b = LittleFloat ( in->lightmapVecs[0][2] ) * 255.0f; - b = bound ( 0, b, 255 ); - - out->dlightbits = (unsigned int)COLOR_RGB ( r, g, b ); -*/ } + out->mesh = &mesh[surfnum]; + out->mesh->numindexes = 6; + out->mesh->numvertexes = 4; + } } - Mod_SortShaders(); - return true; } #endif @@ -3256,8 +3426,8 @@ qboolean CModRBSP_LoadLightgrid (lump_t *elements, lump_t *indexes) ecount = elements->filelen / sizeof(*ein); grid = Hunk_AllocName (sizeof(q3lightgridinfo_t) + ecount*sizeof(*eout) + icount*sizeof(*iout), loadmodel->name ); - grid->rbspelements = (rbspgridlight_t*)((char *)grid); - grid->rbspindexes = (unsigned short*)((char *)grid + ecount*sizeof(*eout)); + grid->rbspelements = (rbspgridlight_t*)((char *)grid + sizeof(q3lightgridinfo_t)); + grid->rbspindexes = (unsigned short*)((char *)grid + sizeof(q3lightgridinfo_t) + ecount*sizeof(*eout)); eout = grid->rbspelements; iout = grid->rbspindexes; @@ -3570,6 +3740,9 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c qboolean noerrors = true; int start; + void (*buildmeshes)(model_t *mod, msurface_t *surf, void *cookie) = NULL; + void *buildcookie = NULL; + // free old stuff numplanes = 0; numleafs = 0; @@ -3610,6 +3783,17 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c cmod_base = mod_base = (qbyte *)buf; start = Hunk_LowMark(); + if (header.ident == (('F'<<0)+('B'<<8)+('S'<<16)+('P'<<24))) + { + loadmodel->lightmaps.width = 512; + loadmodel->lightmaps.height = 512; + } + else + { + loadmodel->lightmaps.width = 128; + loadmodel->lightmaps.height = 128; + } + switch(header.version) { default: @@ -3618,7 +3802,7 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c return NULL; break; #if 1 - case 1: //rbsp + case 1: //rbsp/fbsp case Q3BSPVERSION+1: //rtcw case Q3BSPVERSION: mapisq3 = true; @@ -3703,10 +3887,17 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c else map_numfogs = 0; + buildcookie = (void *)(mod_base + header.lumps[Q3LUMP_SURFACES].fileofs); if (header.version == 1) + { noerrors = noerrors && CModRBSP_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); + buildmeshes = CModRBSP_BuildSurfMesh; + } else + { noerrors = noerrors && CModQ3_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); + buildmeshes = CModQ3_BuildSurfMesh; + } noerrors = noerrors && CModQ3_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFSURFACES]); //fixme: duplicated loading. /*make sure all textures have a shader*/ @@ -3923,6 +4114,13 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c loadmodel->checksum = loadmodel->checksum2 = *checksum; + loadmodel->nummodelsurfaces = loadmodel->numsurfaces; + memset(&loadmodel->batches, 0, sizeof(loadmodel->batches)); + loadmodel->vbos = NULL; +#ifndef SERVERONLY + if (qrenderer != QR_NONE) + RMod_Batches_Build(NULL, loadmodel, buildmeshes, buildcookie); +#endif loadmodel->numsubmodels = CM_NumInlineModels(loadmodel); { @@ -3965,6 +4163,13 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c mod->hulls[j].available = false; } + memset(&mod->batches, 0, sizeof(mod->batches)); + mod->vbos = NULL; +#ifndef SERVERONLY + if (qrenderer != QR_NONE) + RMod_Batches_Build(NULL, mod, buildmeshes, buildcookie); +#endif + VectorCopy (bm->maxs, mod->maxs); VectorCopy (bm->mins, mod->mins); #ifndef SERVERONLY diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 72a9e148..6485ff60 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -418,6 +418,16 @@ int VectorCompare (const vec3_t v1, const vec3_t v2) return 1; } +int Vector4Compare (const vec4_t v1, const vec4_t v2) +{ + int i; + + for (i=0 ; i<4 ; i++) + if (v1[i] != v2[i]) + return 0; + + return 1; +} void _VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc) { diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index e2ad7b65..5caa9547 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -190,6 +190,7 @@ void R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out); void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result); int VectorCompare (const vec3_t v1, const vec3_t v2); +int Vector4Compare (const vec4_t v1, const vec4_t v2); void VectorInverse (vec3_t v); void _VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc); float QDECL VectorNormalize (vec3_t v); // returns vector length diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 483b1c6e..aed771d1 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -1812,6 +1812,7 @@ void Plug_Close(plugin_t *plug) Plug_FreeConCommands(plug); Plug_Client_Close(plug); + Z_Free(plug); if (currentplug == plug) currentplug = NULL; @@ -1883,8 +1884,17 @@ void Plug_Shutdown(void) { while(plugs) { + plugs->blockcloses = 0; Plug_Close(plugs); } + + numplugbuiltins = 0; + BZ_Free(plugbuiltins); + plugbuiltins = NULL; + + plugincommandarraylen = 0; + BZ_Free(plugincommandarray); + plugincommandarray = NULL; } #endif diff --git a/engine/common/pmove.c b/engine/common/pmove.c index a644d170..fec5291b 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -372,6 +372,7 @@ void PM_Friction (void) speed = Length(pmove.velocity); if (speed < 1) { +//fixme: gravitydir fix needed pmove.velocity[0] = 0; pmove.velocity[1] = 0; if (pmove.pm_type == PM_FLY) @@ -1122,7 +1123,7 @@ void PM_PlayerMove (float gamespeed) if (pmove.waterlevel == 2 && pmove.pm_type != PM_FLY) PM_CheckWaterJump (); - if (pmove.velocity[2] < 0 || pmove.pm_type == PM_DEAD) + if (-DotProduct(pmove.gravitydir, pmove.velocity) < 0 || pmove.pm_type == PM_DEAD) pmove.waterjumptime = 0; if (pmove.waterjumptime) @@ -1157,7 +1158,7 @@ void PM_PlayerMove (float gamespeed) // this is to make sure landing sound is not played twice // and falling damage is calculated correctly - if (pmove.onground && pmove.velocity[2] < -300 + if (pmove.onground && -DotProduct(pmove.gravitydir, pmove.velocity) < -300 && DotProduct(pmove.velocity, groundplane.normal) < -0.1) { PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index bea1b41f..f26a7fb1 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -3707,6 +3707,7 @@ lh_extension_t QSG_Extensions[] = { {"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}}, {"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control {"FTE_CSQC_BASEFRAME"}, //control for all skeletal models + {"FTE_ENT_SKIN_CONTENTS"}, //self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder. {"FTE_ENT_UNIQUESPAWNID"}, {"FTE_EXTENDEDTEXTCODES"}, {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, @@ -3731,7 +3732,7 @@ lh_extension_t QSG_Extensions[] = { {"FTE_QC_PAUSED"}, {"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, {"FTE_QC_TRACETRIGGER"}, - {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) + {"FTE_SOLID_LADDER"}, //Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS #ifdef SQL // serverside SQL functions for managing an SQL database connection diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 1bee944c..af3c0e5f 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -543,15 +543,15 @@ enum clcq2_ops_e #define UF_DRAWFLAGS (1u<<19) #define UF_TAGINFO (1u<<20) #define UF_LIGHT (1u<<21) -#define UF_EFFECTS2 (1u<<22) +#define UF_TRAILEFFECT (1u<<22) #define UF_EXTEND3 (1u<<23) #define UF_COLORMOD (1u<<24) #define UF_GLOWMOD (1u<<25) #define UF_FATNESS (1u<<26) #define UF_MODELINDEX2 (1u<<27) -#define UF_UNUSED4 (1u<<28) -#define UF_UNUSED3 (1u<<29) +#define UF_GRAVITYDIR (1u<<28) +#define UF_EFFECTS2 (1u<<29) #define UF_UNUSED2 (1u<<30) #define UF_UNUSED1 (1u<<31) @@ -823,6 +823,8 @@ typedef struct entity_state_s unsigned short weaponframe; short movement[3]; short velocity[3]; // 1/8th + unsigned char gravitydir[2]; //pitch/yaw, no roll + unsigned short traileffectnum; } q1; } u; unsigned short modelindex2; //q2/vweps diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index bb0bc941..24c9305c 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -1832,7 +1832,6 @@ static qbyte mod_novis[MAX_MAP_LEAFS/8]; qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, qbyte *buffer, unsigned int buffersize) { - static qbyte decompressed[MAX_MAP_LEAFS/8]; if (leaf == model->leafs) diff --git a/engine/common/translate.c b/engine/common/translate.c index f45eaa2e..4f6e58a7 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -1,8 +1,5 @@ #include "quakedef.h" -#undef malloc -#undef free - static char *defaultlanguagetext = "STL_LANGUAGENAME \"English\"\n" "TL_NL \"\\n\"\n" @@ -686,6 +683,26 @@ void TL_WriteTLHeader(void) } #endif +void TL_Shutdown(void) +{ + int i, j, k; + + for (i = 0; i < STL_MAXSTL; i++) + { + for (j = 0; j < MAX_LANGUAGES; j++) + { + if (j) + free(langtext(i, j)); + for (k = j+1; k < MAX_LANGUAGES; k++) + { + if (langtext(i, k) == langtext(i, j)) + langtext(i, k) = NULL; + } + langtext(i, j) = NULL; + } + } +} + void TL_InitLanguages(void) { int i, j; diff --git a/engine/common/vm.h b/engine/common/vm.h index 35d299ad..028d6e00 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -71,6 +71,7 @@ void Plug_Command_f(void); int Plug_ConnectionlessClientPacket(char *buffer, int size); void Plug_DrawReloadImages(void); void Plug_Init(void); +void Plug_Shutdown(void); qboolean Plug_Menu_Event(int eventtype, int param); void Plug_ResChanged(void); void Plug_SBar(void); diff --git a/engine/common/world.h b/engine/common/world.h index 60094892..fce37636 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -151,6 +151,7 @@ struct world_s void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o); void (*Event_Think)(struct world_s *w, wedict_t *s); void (*Event_Sound) (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); + qboolean (*Event_ContentsTransition) (struct world_s *w, wedict_t *ent, int oldwatertype, int newwatertype); model_t *(*Get_CModel)(struct world_s *w, int modelindex); void (*Get_FrameState)(struct world_s *w, wedict_t *s, framestate_t *fstate); diff --git a/engine/common/zone.c b/engine/common/zone.c index 3b8026f4..cdc2cd9e 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -184,11 +184,24 @@ void *VARGS Z_TagMalloc(int size, int tag) return (void *)(zone + 1); } +#ifdef USE_MSVCRT_DEBUG +void *ZF_MallocNamed(int size, char *file, int line) +{ + return _calloc_dbg(size, 1, _NORMAL_BLOCK, file, line); +} +void *Z_MallocNamed(int size, char *file, int line) +{ + void *mem = ZF_MallocNamed(size, file, line); + if (!mem) + Sys_Error("Z_Malloc: Failed on allocation of %i bytes", size); + + return mem; +} +#else void *ZF_Malloc(int size) { return calloc(size, 1); } - void *Z_Malloc(int size) { void *mem = ZF_Malloc(size); @@ -197,6 +210,7 @@ void *Z_Malloc(int size) return mem; } +#endif void VARGS Z_TagFree(void *mem) { @@ -348,6 +362,19 @@ void *Z_Realloc(void *data, int newsize) } */ +#ifdef USE_MSVCRT_DEBUG +void *BZF_MallocNamed(int size, char *file, int line) //BZ_MallocNamed but allowed to fail - like straight malloc. +{ + void *mem; + mem = _malloc_dbg(size, _NORMAL_BLOCK, file, line); + if (mem) + { + zmemdelta += size; + zmemtotal += size; + } + return mem; +} +#else void *BZF_Malloc(int size) //BZ_Malloc but allowed to fail - like straight malloc. { void *mem; @@ -359,7 +386,18 @@ void *BZF_Malloc(int size) //BZ_Malloc but allowed to fail - like straight mallo } return mem; } +#endif +#ifdef USE_MSVCRT_DEBUG +void *BZ_MallocNamed(int size, char *file, int line) //BZ_MallocNamed but allowed to fail - like straight malloc. +{ + void *mem = BZF_MallocNamed(size, file, line); + if (!mem) + Sys_Error("BZ_Malloc: Failed on allocation of %i bytes", size); + + return mem; +} +#else void *BZ_Malloc(int size) //Doesn't clear. The expectation is a large file, rather than sensative data structures. { void *mem = BZF_Malloc(size); @@ -368,7 +406,24 @@ void *BZ_Malloc(int size) //Doesn't clear. The expectation is a large file, rath return mem; } +#endif +#ifdef USE_MSVCRT_DEBUG +void *BZF_ReallocNamed(void *data, int newsize, char *file, int line) +{ + return _realloc_dbg(data, newsize, _NORMAL_BLOCK, file, line); +} + +void *BZ_ReallocNamed(void *data, int newsize, char *file, int line) +{ + void *mem = BZF_ReallocNamed(data, newsize, file, line); + + if (!mem) + Sys_Error("BZ_Realloc: Failed on reallocation of %i bytes", newsize); + + return mem; +} +#else void *BZF_Realloc(void *data, int newsize) { return realloc(data, newsize); @@ -383,6 +438,7 @@ void *BZ_Realloc(void *data, int newsize) return mem; } +#endif void BZ_Free(void *data) { @@ -1776,6 +1832,17 @@ void Hunk_Print_f (void) Con_Printf("Zone: %i containing %iKB\n", zoneblocks, zoneused/1024); } #endif + +#ifdef USE_MSVCRT_DEBUG + { + static struct _CrtMemState savedstate; + static qboolean statesaved; + + _CrtMemDumpAllObjectsSince(statesaved?&savedstate:NULL); + _CrtMemCheckpoint(&savedstate); + statesaved = true; + } +#endif } void Cache_Init(void) { diff --git a/engine/common/zone.h b/engine/common/zone.h index 7f394c09..f3598f85 100644 --- a/engine/common/zone.h +++ b/engine/common/zone.h @@ -89,6 +89,8 @@ void Memory_DeInit(void); void VARGS Z_Free (void *ptr); void *Z_Malloc (int size); // returns 0 filled memory void *ZF_Malloc (int size); // allowed to fail +void *Z_MallocNamed (int size, char *file, int line); // returns 0 filled memory +void *ZF_MallocNamed (int size, char *file, int line); // allowed to fail //#define Z_Malloc(x) Z_MallocNamed2(x, __FILE__, __LINE__ ) void *VARGS Z_TagMalloc (int size, int tag); void VARGS Z_TagFree(void *ptr); @@ -99,17 +101,21 @@ void VARGS Z_FreeTags(int tag); //(this is a nicer name for malloc) void *BZ_Malloc(int size); void *BZF_Malloc(int size); +void *BZ_MallocNamed (int size, char *file, int line); // returns 0 filled memory +void *BZF_MallocNamed (int size, char *file, int line); // allowed to fail void *BZ_Realloc(void *ptr, int size); +void *BZ_ReallocNamed(void *data, int newsize, char *file, int line); void *BZF_Realloc(void *data, int newsize); +void *BZF_ReallocNamed(void *data, int newsize, char *file, int line); void BZ_Free(void *ptr); -#ifdef NAMEDMALLOCS -#define BZ_Malloc(size) Z_MallocNamed(size, __FILE__, __LINE__) - - +#ifdef USE_MSVCRT_DEBUG +#define BZ_Malloc(size) BZ_MallocNamed(size, __FILE__, __LINE__) #define Z_Malloc(size) Z_MallocNamed(size, __FILE__, __LINE__) - -#define BZ_Realloc(ptr, size) BZ_NamedRealloc(ptr, size, __FILE__, __LINE__) +#define BZ_Realloc(ptr, size) BZ_ReallocNamed(ptr, size, __FILE__, __LINE__) +#define BZF_Malloc(size) BZF_MallocNamed(size, __FILE__, __LINE__) +#define ZF_Malloc(size) ZF_MallocNamed(size, __FILE__, __LINE__) +#define BZF_Realloc(ptr, size) BZF_ReallocNamed(ptr, size, __FILE__, __LINE__) #endif void *Hunk_Alloc (int size); // returns 0 filled memory diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 5c6efe4c..ec34f31a 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -9,6 +9,33 @@ #endif #include +/* +Things to improve: + mmapping: + this code is fairly simple. the caller gives a series of batches/meshes, and this code pushes the data to the gpu in its entirety before moving on to the next batch + for the world, this is fast enough where its pretty much all vboed (except for weird shaders). + but for lightning beams and models etc, we're mmapping new data regions in the dynamic vbo for every single quad. + not just one mmap, but one mmap for every single individual attribute that is submitted + by using a single buffer for all dynamic data, and filling that buffer before flushing anything to the hardware we ought to get higher framerates + especially if this means D3DLOCK_NOOVERWRITE checks etc are not doing weird slow things. + This won't affect the world too much, but should stop everything else destroying the framerate. + + long story short, make this batch properly, and use D3DLOCK_DISCARD only. + + models: + models should already be in a buffer (with different offsets for different poses). This is a problem with gl too. + + hlsl: + we don't really use this as much as we should. Should be possible to use as a fast path to avoid having to do any weird shader/dynamic stuff. + currently used for water(required to mimic software rendering) and sky(because its muuuch faster than a skydome). + hlsl programs ought to have per-hlsl vertex declarations, and only one stream source. +*/ + + + + + + extern LPDIRECT3DDEVICE9 pD3DDev9; //#define d3dcheck(foo) foo @@ -169,6 +196,17 @@ typedef struct batch_t *wbatches; } d3dbackend_t; +typedef struct +{ + vecV_t coord; + vec2_t tex; + vec2_t lm; + vec3_t ndir; + vec3_t sdir; + vec3_t tdir; + byte_vec4_t colorsb; +} vbovdata_t; + #define DYNVBUFFSIZE 65536 #define DYNIBUFFSIZE 65536 @@ -1052,7 +1090,7 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX)) && (pass->alphagen == ALPHA_GEN_VERTEX))) { - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(byte_vec4_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(vbovdata_t))); } else { @@ -1537,9 +1575,9 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert vdec |= D3D_VDEC_ST0<texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t))); else if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_LIGHTMAP && !pass[passno].numtcmods) - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord.d3d.buff, shaderstate.batchvbo->lmcoord.d3d.offs, sizeof(vec2_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vbovdata_t))); else { allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec2_t)); @@ -1595,13 +1633,13 @@ static void BE_SubmitMeshChain(int idxfirst) for (++m; m < shaderstate.nummeshes; m++) { mesh = shaderstate.meshlist[m]; -/* if (endi == mesh->vbofirstelement) + if (endi == mesh->vbofirstelement) { endv = mesh->vbofirstvert+mesh->numvertexes; endi = mesh->vbofirstelement+mesh->numindexes; } else -*/ { + { break; } } @@ -1747,7 +1785,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i if (vdec & D3D_VDEC_COL4B) { if (shaderstate.batchvbo) - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(byte_vec4_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(vbovdata_t))); else { int mno,v; @@ -1783,7 +1821,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i if (vdec & D3D_VDEC_ST0) { if (shaderstate.batchvbo) - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t))); else { int mno; @@ -1805,7 +1843,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i if (vdec & D3D_VDEC_ST1) { if (shaderstate.batchvbo) - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.batchvbo->lmcoord.d3d.buff, shaderstate.batchvbo->lmcoord.d3d.offs, sizeof(vec2_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vbovdata_t))); else { int mno; @@ -1829,9 +1867,9 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i { if (shaderstate.batchvbo) { - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vec3_t))); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vec3_t))); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vec3_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vbovdata_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vbovdata_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vbovdata_t))); } else { @@ -1933,7 +1971,7 @@ static void BE_DrawMeshChain_Internal(void) /*vertex buffers are common to all passes*/ if (shaderstate.batchvbo && !shaderstate.curshader->numdeforms) { - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vecV_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vbovdata_t))); } else { @@ -2046,10 +2084,135 @@ void D3DBE_SelectEntity(entity_t *ent) BE_RotateForEntity(ent, ent->model); } +#if 1 +static void D3DBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) +{ + int maxvboelements; + int maxvboverts; + int vert = 0, idx = 0; + batch_t *batch; + vbo_t *vbo; + int i, j; + mesh_t *m; + IDirect3DVertexBuffer9 *vbuff; + IDirect3DIndexBuffer9 *ebuff; + index_t *vboedata; + vbovdata_t *vbovdata; + + vbo = Z_Malloc(sizeof(*vbo)); + + maxvboverts = 0; + maxvboelements = 0; + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + for (i=0 ; imaxmeshes ; i++) + { + m = batch->mesh[i]; + maxvboelements += m->numindexes; + maxvboverts += m->numvertexes; + } + } + + IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, sizeof(index_t) * maxvboelements, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &ebuff, NULL); + IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, sizeof(*vbovdata) * maxvboverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &vbuff, NULL); + + vbovdata = NULL; + vbo->coord.d3d.buff = vbuff; + vbo->coord.d3d.offs = (quintptr_t)&vbovdata->coord; + vbo->texcoord.d3d.buff = vbuff; + vbo->texcoord.d3d.offs = (quintptr_t)&vbovdata->tex; + vbo->lmcoord[0].d3d.buff = vbuff; + vbo->lmcoord[0].d3d.offs = (quintptr_t)&vbovdata->lm; + vbo->normals.d3d.buff = vbuff; + vbo->normals.d3d.offs = (quintptr_t)&vbovdata->ndir; + vbo->svector.d3d.buff = vbuff; + vbo->svector.d3d.offs = (quintptr_t)&vbovdata->sdir; + vbo->tvector.d3d.buff = vbuff; + vbo->tvector.d3d.offs = (quintptr_t)&vbovdata->tdir; + vbo->colours.d3d.buff = vbuff; + vbo->colours.d3d.offs = (quintptr_t)&vbovdata->colorsb; + vbo->indicies.d3d.buff = ebuff; + vbo->indicies.d3d.offs = 0; + + IDirect3DIndexBuffer9_Lock(ebuff, 0, sizeof(index_t) * maxvboelements, &vboedata, D3DLOCK_DISCARD); + IDirect3DVertexBuffer9_Lock(vbuff, 0, sizeof(*vbovdata) * maxvboverts, &vbovdata, D3DLOCK_DISCARD); + + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + batch->vbo = vbo; + for (j=0 ; jmaxmeshes ; j++) + { + m = batch->mesh[j]; + m->vbofirstvert = vert; + for (i = 0; i < m->numvertexes; i++) + { + VectorCopy(m->xyz_array[i], vbovdata->coord); + vbovdata->coord[3] = 1; + Vector2Copy(m->st_array[i], vbovdata->tex); + Vector2Copy(m->lmst_array[0][i], vbovdata->lm); + VectorCopy(m->normals_array[i], vbovdata->ndir); + VectorCopy(m->snormals_array[i], vbovdata->sdir); + VectorCopy(m->tnormals_array[i], vbovdata->tdir); + Vector4Scale(m->colors4f_array[i], 255, vbovdata->colorsb); + + vbovdata++; + } + + m->vbofirstelement = idx; + for (i = 0; i < m->numindexes; i++) + { + *vboedata++ = vert + m->indexes[i]; + } + idx += m->numindexes; + vert += m->numvertexes; + } + } + + IDirect3DIndexBuffer9_Unlock(ebuff); + IDirect3DVertexBuffer9_Unlock(vbuff); + + vbo->next = *vbochain; + *vbochain = vbo; +} + +void D3DBE_GenBrushModelVBO(model_t *mod) +{ + unsigned int vcount; + + + batch_t *batch, *fbatch; + int sortid; + int i; + + fbatch = NULL; + vcount = 0; + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + { + if (!mod->batches[sortid]) + continue; + + for (fbatch = batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + //firstmesh got reused as the number of verticies in each batch + if (vcount + batch->firstmesh > MAX_INDICIES) + { + D3DBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + fbatch = batch; + vcount = 0; + } + + for (i = 0; i < batch->maxmeshes; i++) + vcount += batch->mesh[i]->numvertexes; + } + + D3DBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + } +} +#else /*Generates an optimised vbo for each of the given model's textures*/ void D3DBE_GenBrushModelVBO(model_t *mod) { -#if 0 +#if 1 unsigned int maxvboverts; unsigned int maxvboelements; @@ -2101,7 +2264,7 @@ void D3DBE_GenBrushModelVBO(model_t *mod) maxvboverts += m->numvertexes; } #if sizeof_index_t == 2 - if (maxvboverts > (1<<(sizeof(index_t)*8))-1) + if (maxvboverts > (1u<<(sizeof(index_t)*8))-1) continue; #endif if (!maxvboverts) @@ -2231,53 +2394,58 @@ void D3DBE_GenBrushModelVBO(model_t *mod) } #endif } +#endif /*Wipes a vbo*/ void D3DBE_ClearVBO(vbo_t *vbo) { - IDirect3DVertexBuffer9 *vbuff = vbo->vertdata; + IDirect3DVertexBuffer9 *vbuff = vbo->coord.d3d.buff; IDirect3DIndexBuffer9 *ebuff = vbo->indicies.d3d.buff; if (vbuff) IDirect3DVertexBuffer9_Release(vbuff); if (ebuff) IDirect3DIndexBuffer9_Release(ebuff); - vbo->vertdata = NULL; + vbo->coord.d3d.buff = NULL; vbo->indicies.d3d.buff = NULL; + + free(vbo); } /*upload all lightmaps at the start to reduce lags*/ void BE_UploadLightmaps(qboolean force) { int i; + lightmapinfo_t *lm; for (i = 0; i < numlightmaps; i++) { - if (!lightmap[i]) + lm = lightmap[i]; + if (!lm) continue; if (force) { - lightmap[i]->rectchange.l = 0; - lightmap[i]->rectchange.t = 0; - lightmap[i]->rectchange.w = LMBLOCK_WIDTH; - lightmap[i]->rectchange.h = LMBLOCK_HEIGHT; + lm->rectchange.l = 0; + lm->rectchange.t = 0; + lm->rectchange.w = LMBLOCK_WIDTH; + lm->rectchange.h = LMBLOCK_HEIGHT; } if (lightmap[i]->modified) { - IDirect3DTexture9 *tex = lightmap_textures[i].ptr; + IDirect3DTexture9 *tex = lm->lightmap_texture.ptr; D3DLOCKED_RECT lock; RECT rect; - glRect_t *theRect = &lightmap[i]->rectchange; + glRect_t *theRect = &lm->rectchange; int r; if (!tex) { - lightmap_textures[i] = R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - tex = lightmap_textures[i].ptr; + lm->lightmap_texture = R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + tex = lm->lightmap_texture.ptr; if (!tex) continue; } - lightmap[i]->modified = 0; + lm->modified = 0; rect.left = theRect->l; rect.right = theRect->l + theRect->w; rect.top = theRect->t; @@ -2445,10 +2613,10 @@ void D3DBE_SubmitBatch(batch_t *batch) shaderstate.curshader = batch->shader; shaderstate.curtexnums = batch->skin; shaderstate.flags = batch->flags; - if (batch->lightmap < 0) + if (batch->lightmap[0] < 0) shaderstate.curlightmap = r_nulltex; else - shaderstate.curlightmap = lightmap_textures[batch->lightmap]; + shaderstate.curlightmap = lightmap[batch->lightmap[0]]->lightmap_texture; BE_DrawMeshChain_Internal(); } @@ -2891,7 +3059,7 @@ void D3DBE_DrawWorld (qbyte *vis) #ifdef RTLIGHTS RSpeedRemark(); D3DBE_SelectEntity(&r_worldentity); - Sh_DrawLights(vis, batches); + Sh_DrawLights(vis); RSpeedEnd(RSPEED_STENCILSHADOWS); #endif diff --git a/engine/d3d/d3d_image.c b/engine/d3d/d3d_image.c index 7e188c01..d74ccd5f 100644 --- a/engine/d3d/d3d_image.c +++ b/engine/d3d/d3d_image.c @@ -1,4 +1,5 @@ #include "quakedef.h" +#include "winquake.h" #ifdef D3DQUAKE #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #define HMONITOR_DECLARED @@ -27,6 +28,8 @@ void D3D_Image_Shutdown(void) tx = t->tex.ptr; if (tx) IDirect3DTexture9_Release(tx); + + free(t); } } diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index aff5d00e..3095f909 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -2,6 +2,7 @@ #ifdef D3DQUAKE #include "shader.h" +#include "winquake.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #define HMONITOR_DECLARED DECLARE_HANDLE(HMONITOR); diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index d9af98ed..c515e0d8 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -1120,6 +1120,7 @@ static void (D3D9_Draw_Init) (void) } static void (D3D9_Draw_Shutdown) (void) { + R2D_Shutdown(); } static void (D3D9_R_Init) (void) @@ -1202,7 +1203,7 @@ static void (D3D9_R_RenderView) (void) { D3D9_SetupViewPort(); if (r_clear.ival && !(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0)); + d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,0,0), 1, 0)); else d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0)); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 3188dfbd..5f5cd4ae 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -25,9 +25,6 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj", "{4735677B-6D5A-4BE6-A945-CB32A7282F56}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}" - ProjectSection(ProjectDependencies) = postProject - {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} = {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} - EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -175,7 +172,6 @@ Global {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|Win32.ActiveCfg = Debug {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|x64.ActiveCfg = Debug {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|Win32.ActiveCfg = Release - {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|Win32.Build.0 = Release {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|x64.ActiveCfg = Release {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|x64.Build.0 = Release {E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug Dedicated Server|Win32.ActiveCfg = Debug @@ -236,7 +232,6 @@ Global {2866F783-6B44-4655-A38D-D53874037454}.D3DDebug|Win32.Build.0 = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.D3DDebug|x64.ActiveCfg = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.D3DRelease|Win32.ActiveCfg = Release|Win32 - {2866F783-6B44-4655-A38D-D53874037454}.D3DRelease|Win32.Build.0 = Release|Win32 {2866F783-6B44-4655-A38D-D53874037454}.D3DRelease|x64.ActiveCfg = Release|Win32 {2866F783-6B44-4655-A38D-D53874037454}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 @@ -272,7 +267,6 @@ Global {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|Win32.Build.0 = Debug|Win32 {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|x64.ActiveCfg = Debug|Win32 {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DRelease|Win32.ActiveCfg = Release|Win32 - {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DRelease|Win32.Build.0 = Release|Win32 {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DRelease|x64.ActiveCfg = Release|Win32 {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 {62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 @@ -331,40 +325,31 @@ Global {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MRelease|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MRelease|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MRelease|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release Dedicated Server|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release Dedicated Server|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|Win32.ActiveCfg = Release|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|x64.ActiveCfg = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|Win32.ActiveCfg = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|Win32.Build.0 = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|x64.ActiveCfg = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|Win32.ActiveCfg = Release|Win32 - {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|Win32.Build.0 = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|x64.ActiveCfg = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 8de83499..9f987525 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -463,11 +463,11 @@ FloatingPointModel="2" UsePrecompiledHeader="2" PrecompiledHeaderThrough="quakedef.h" - BrowseInformation="1" BrowseInformationFile="$(IntDir)\" WarningLevel="3" SuppressStartupBanner="true" CallingConvention="1" + CompileAs="0" DisableSpecificWarnings="4996" /> @@ -23037,6 +23039,194 @@ RelativePath="..\gl\gl_font.c" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -25504,194 +25694,6 @@ /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/engine/droid/src/com/fteqw/FTEDroidActivity.java b/engine/droid/src/com/fteqw/FTEDroidActivity.java index e8faac27..4c6c4e84 100644 --- a/engine/droid/src/com/fteqw/FTEDroidActivity.java +++ b/engine/droid/src/com/fteqw/FTEDroidActivity.java @@ -1,7 +1,9 @@ package com.fteqw; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLConfig; -//import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.opengles.GL10; import android.app.Activity; @@ -26,6 +28,8 @@ import android.os.Environment; public class FTEDroidActivity extends Activity { + private static final int USE_GLES_VERSION = 1; //valid values: 1 or 2. If set to 2, it'll still fall back to 1 if gles2 isn't supported on this device. + private SensorManager sensorman; private Sensor sensoracc; private FTEView view; @@ -34,6 +38,7 @@ public class FTEDroidActivity extends Activity private class FTERenderer implements GLSurfaceView.Renderer { private boolean inited; + public int glesversion; private String basedir, userdir; FTEDroidActivity act; @@ -51,7 +56,7 @@ public class FTEDroidActivity extends Activity } // try // { - userdir = Environment.getExternalStorageDirectory().getPath(); + userdir = Environment.getExternalStorageDirectory().getPath() + "/fte"; // } // catch(foo) // { @@ -73,7 +78,7 @@ public class FTEDroidActivity extends Activity public void onSurfaceChanged(GL10 gl, int width, int height) { android.util.Log.i("FTEDroid", "Surface changed, now " + width + " by " + height + "."); - FTEDroidEngine.init(width, height, basedir, userdir); + FTEDroidEngine.init(width, height, glesversion, basedir, userdir); inited = true; } @Override @@ -81,32 +86,94 @@ public class FTEDroidActivity extends Activity { } } -/* + private class FTEEGLConfig implements GLSurfaceView.EGLConfigChooser { + public void setversion(FTEView view, int version) + { + view.setEGLContextClientVersion(version); + } + public boolean CheckGLES2Support() + { + EGL10 egl = (EGL10) EGLContext.getEGL(); + EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + EGLConfig cfg; + + int[] version = new int[2]; + egl.eglInitialize(display, version); + + cfg = chooseConfig(egl, display); + + int[] value = {0}; + egl.eglGetConfigAttrib(display, cfg, EGL10.EGL_RENDERABLE_TYPE, value); + egl.eglTerminate(display); + return ((value[0] & 4) == 4); + } + @Override - public EGLConfig chooseConfig (javax.microedition.khronos.egl.EGL10 egl, javax.microedition.khronos.egl.EGLDisplay display) + public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) { int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - EGLConfig[] cfg = new EGLConfig[1]; + EGLConfig[] cfg = new EGLConfig[64]; int[] num_configs = {0}; + int[] value = {0}; + int i; int[] attribs = { - EGL_CONTEXT_CLIENT_VERSION, 2, - egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT, + egl.EGL_RENDERABLE_TYPE, 4/*egl.EGL_OPENGL_ES2_BIT*/, +// egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT, egl.EGL_BLUE_SIZE, 5, egl.EGL_GREEN_SIZE, 6, egl.EGL_RED_SIZE, 5, egl.EGL_DEPTH_SIZE, 16, - egl.EGL_STENCIL_SIZE, 8, +// egl.EGL_STENCIL_SIZE, 8, egl.EGL_NONE, egl.EGL_NONE }; - egl.eglChooseConfig(display, attribs, cfg, 1, num_configs); + if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs)) + throw new IllegalArgumentException("eglChooseConfig failed"); + + if (num_configs[0] == 0) + { + attribs[1] = 1; //egl.EGL_RENDERABLE_TYPE, 1/*egl.EGL_OPENGL_ES_BIT*/, + if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs)) + throw new IllegalArgumentException("eglChooseConfig failed"); + + if (num_configs[0] == 0) + { + throw new IllegalArgumentException("eglChooseConfig didn't report any valid configs"); + } + } + + android.util.Log.i("FTEDroid", "Found " + num_configs[0] + " EGL configs."); + + for (i = 0; i < num_configs[0]; i++) + { + android.util.Log.i("FTEDroid", "Config " + i + ":"); + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RED_SIZE, value); + android.util.Log.i("FTEDroid", "EGL_RED_SIZE " + value[0]); + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_GREEN_SIZE, value); + android.util.Log.i("FTEDroid", "EGL_GREEN_SIZE " + value[0]); + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_BLUE_SIZE, value); + android.util.Log.i("FTEDroid", "EGL_BLUE_SIZE " + value[0]); + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_DEPTH_SIZE, value); + android.util.Log.i("FTEDroid", "EGL_DEPTH_SIZE " + value[0]); + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_STENCIL_SIZE, value); + android.util.Log.i("FTEDroid", "EGL_STENCIL_SIZE " + value[0]); + + egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RENDERABLE_TYPE, value); + android.util.Log.i("FTEDroid", "EGL_RENDERABLE_TYPE " + value[0]); + + if ((value[0] & 4) == 4) + { + android.util.Log.i("FTEDroid", "Found a GLES2 context!"); + return cfg[i]; + } + } return cfg[0]; } } -*/ + private class FTEView extends GLSurfaceView implements SensorEventListener { private final FTERenderer rndr; @@ -260,7 +327,35 @@ public class FTEDroidActivity extends Activity inputevent = new FTELegacyInputEvent(); rndr = new FTERenderer(context, context); -// setEGLConfigChooser(new FTEEGLConfig()); + + if (USE_GLES_VERSION < 2) + { + android.util.Log.i("FTEDroid", "GLES2 disabled at game compile time"); + rndr.glesversion = 1; + } + else if (android.os.Build.VERSION.SDK_INT >= 8) //could be 5 with setEGLContextFactory instead of setEGLContextClientVersion + { + FTEEGLConfig cfgchooser = new FTEEGLConfig(); + setEGLConfigChooser(cfgchooser); + + if (cfgchooser.CheckGLES2Support()) + { + android.util.Log.i("FTEDroid", "Support for GLES2 detected"); + rndr.glesversion = 2; + cfgchooser.setversion(this, rndr.glesversion); + } + else + { + android.util.Log.i("FTEDroid", "GLES2 not supported. Using GLES1."); + rndr.glesversion = 1; + } + } + else + { + android.util.Log.i("FTEDroid", "GLES2 requires android 2.2+"); + rndr.glesversion = 1; + } + setRenderer(rndr); setFocusable(true); setFocusableInTouchMode(true); @@ -372,7 +467,7 @@ public class FTEDroidActivity extends Activity if (runningintheemulator()) { - android.util.Log.i("FTEDroid", "emulator detected - skipping sensors to avoid emulator hangs"); + android.util.Log.i("FTEDroid", "emulator detected - skipping sensors to avoid emulator bugs"); sensorman = null; } else diff --git a/engine/droid/src/com/fteqw/FTEDroidEngine.java b/engine/droid/src/com/fteqw/FTEDroidEngine.java index 5ddc0a15..5264f090 100644 --- a/engine/droid/src/com/fteqw/FTEDroidEngine.java +++ b/engine/droid/src/com/fteqw/FTEDroidEngine.java @@ -2,7 +2,7 @@ package com.fteqw; public class FTEDroidEngine { - public static native void init(int w, int h, String apkpath, String usrpath); /* init/reinit */ + public static native void init(int w, int h, int gles2, String apkpath, String usrpath); /* init/reinit */ public static native void frame(float ax, float ay, float az); public static native void keypress(int down, int qkey, int unicode); public static native void motion(int act, int pointerid, float x, float y); diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index efc0952c..88860981 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -183,7 +183,8 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e *forcedtex = NULL; - if (e->skinnum >= 100 && e->skinnum < 110) + /*hexen2 feature: global skins */ + if (inf->numskins < 100 && e->skinnum >= 100 && e->skinnum < 110) { shader_t *s; s = R_RegisterSkin(va("gfx/skin%d.lmp", e->skinnum), NULL); @@ -224,31 +225,18 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e galiascolourmapped_t *cm; char hashname[512]; -// if (e->scoreboard->skin->cachedbpp - - /* if (cls.protocol == CP_QUAKE2) + if (e->scoreboard && e->scoreboard->skin) { - if (e->scoreboard && e->scoreboard->skin) - snprintf(hashname, sizeof(hashname), "%s$%s$%i", modelname, e->scoreboard->skin->name, surfnum); - else - snprintf(hashname, sizeof(hashname), "%s$%i", modelname, surfnum); + snprintf(hashname, sizeof(hashname), "%s$%s$%i", model->name, e->scoreboard->skin->name, surfnum); skinname = hashname; } - else */ + else if (surfnum) { - if (e->scoreboard && e->scoreboard->skin) - { - snprintf(hashname, sizeof(hashname), "%s$%s$%i", model->name, e->scoreboard->skin->name, surfnum); - skinname = hashname; - } - else if (surfnum) - { - snprintf(hashname, sizeof(hashname), "%s$%i", model->name, surfnum); - skinname = hashname; - } - else - skinname = model->name; + snprintf(hashname, sizeof(hashname), "%s$%i", model->name, surfnum); + skinname = hashname; } + else + skinname = model->name; if (!skincolourmapped.numbuckets) { @@ -291,6 +279,8 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum && cm->subframe == subframe && cm->pclass == pc) { *forcedtex = &cm->texnum; + if (!shader) + shader = R_RegisterSkin(skinname, NULL); return shader; } } @@ -706,7 +696,7 @@ static void R_DrawShadowVolume(mesh_t *mesh) #endif //true if no shading is to be used. -static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) +qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) { vec3_t lightdir; int i; @@ -1017,7 +1007,10 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) b->skin = skin; b->texture = NULL; b->shader = shader; - b->lightmap = -1; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->surf_first = surfnum; b->flags = 0; sort = shader->sort; @@ -1570,7 +1563,6 @@ static void R_DB_LightningBeam(batch_t *batch) mesh.indexes = indexarray; mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]); mesh.colors4f_array = (vec4_t*)colors; - mesh.lmst_array = NULL; mesh.normals_array = NULL; mesh.numvertexes = 4; mesh.st_array = texcoords; @@ -1641,11 +1633,9 @@ static void R_DB_RailgunBeam(batch_t *batch) mesh.indexes = indexarray; mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]); mesh.colors4f_array = (vec4_t*)colors; - mesh.lmst_array = NULL; mesh.normals_array = NULL; mesh.numvertexes = 4; mesh.st_array = texcoords; - } #endif static void R_DB_Sprite(batch_t *batch) @@ -1746,12 +1736,21 @@ static void R_DB_Sprite(batch_t *batch) spraxis[1][1]*=e->scale; spraxis[1][2]*=e->scale; - if (e->shaderRGBAf[0] > 1) + if (e->shaderRGBAf[0] != 0 || e->shaderRGBAf[1] != 0 || e->shaderRGBAf[2] != 0 || (batch->flags & BEF_FORCECOLOURMOD)) + { + if (e->shaderRGBAf[0] > 1) + e->shaderRGBAf[0] = 1; + if (e->shaderRGBAf[1] > 1) + e->shaderRGBAf[1] = 1; + if (e->shaderRGBAf[2] > 1) + e->shaderRGBAf[2] = 1; + } + else + { e->shaderRGBAf[0] = 1; - if (e->shaderRGBAf[1] > 1) e->shaderRGBAf[1] = 1; - if (e->shaderRGBAf[2] > 1) e->shaderRGBAf[2] = 1; + } Vector4Copy(e->shaderRGBAf, colours[0]); Vector4Copy(e->shaderRGBAf, colours[1]); @@ -1780,7 +1779,6 @@ static void R_DB_Sprite(batch_t *batch) mesh.indexes = indexes; mesh.numindexes = sizeof(indexes)/sizeof(indexes[0]); mesh.colors4f_array = colours; - mesh.lmst_array = NULL; mesh.normals_array = NULL; mesh.numvertexes = 4; mesh.st_array = texcoords; @@ -1851,7 +1849,10 @@ static void R_Sprite_GenerateBatch(entity_t *e, batch_t **batches, void (*drawfu b->skin = &shader->defaulttextures; b->texture = NULL; b->shader = shader; - b->lightmap = -1; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->surf_first = 0; b->flags |= BEF_NODLIGHT|BEF_NOSHADOWS; b->vbo = NULL; @@ -1899,7 +1900,10 @@ void BE_GenPolyBatches(batch_t **batches) b->skin = &shader->defaulttextures; b->texture = NULL; b->shader = shader; - b->lightmap = -1; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->surf_first = i; b->flags = BEF_NODLIGHT|BEF_NOSHADOWS; b->vbo = 0; @@ -1907,6 +1911,7 @@ void BE_GenPolyBatches(batch_t **batches) batches[shader->sort] = b; } } +void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches); void BE_GenModelBatches(batch_t **batches) { @@ -1975,9 +1980,13 @@ void BE_GenModelBatches(batch_t **batches) case mod_sprite: R_Sprite_GenerateBatch(ent, batches, R_DB_Sprite); break; + case mod_halflife: +#ifdef HALFLIFEMODELS + R_HalfLife_GenerateBatches(ent, batches); +#endif + break; // warning: enumeration value ‘mod_*’ not handled in switch case mod_dummy: - case mod_halflife: case mod_heightmap: break; } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 61b0ff1b..eff6b4a1 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -5,6 +5,8 @@ #ifdef GLQUAKE +#define r_refract_fboival 0 + #include "glquake.h" #include "shader.h" #ifdef _WIN32 @@ -141,6 +143,7 @@ struct { int currentprogram; int lastuniform; /*program which was last set, so using the same prog for multiple surfaces on the same ent (ie: world) does not require lots of extra uniform chnges*/ + batch_t dummybatch; vbo_t dummyvbo; int colourarraytype; int currentvbo; @@ -183,9 +186,8 @@ struct { vbo_t *sourcevbo; const shader_t *curshader; const entity_t *curentity; + const batch_t *curbatch; const texnums_t *curtexnums; - texid_t curlightmap; - texid_t curdeluxmap; float curtime; float updatetime; @@ -237,7 +239,7 @@ static void BE_PolyOffset(qboolean pushdepth) else { #ifndef FORCESTATE - if (*(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset || *(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset) + if (*(int*)&shaderstate.curpolyoffset.factor != *(int*)&shaderstate.curshader->polyoffset.factor || *(int*)&shaderstate.curpolyoffset.unit != *(int*)&shaderstate.curshader->polyoffset.unit) #endif { shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; @@ -350,6 +352,14 @@ void GL_SetShaderState2D(qboolean is2d) if (is2d) memcpy(shaderstate.modelviewmatrix, r_refdef.m_view, sizeof(shaderstate.modelviewmatrix)); BE_SelectMode(BEM_STANDARD); + + + if (cl.paused || cls.state < ca_active) + shaderstate.updatetime = r_refdef.time; + else + shaderstate.updatetime = cl.servertime; + BE_SelectEntity(&r_worldentity); + shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } void GL_SelectTexture(int target) @@ -371,14 +381,18 @@ void GL_SelectVBO(int vbo) qglBindBufferARB(GL_ARRAY_BUFFER_ARB, shaderstate.currentvbo); } } -void GL_SelectEBO(int vbo) +void GL_DeselectVAO(void) { - //EBO is part of the current VAO, so keep things matching that if (shaderstate.currentvao) { qglBindVertexArray(0); shaderstate.currentvao = 0; } +} +void GL_SelectEBO(int vbo) +{ + //EBO is part of the current VAO, so keep things matching that + GL_DeselectVAO(); #ifndef FORCESTATE if (shaderstate.currentebo != vbo) @@ -570,8 +584,20 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend qglVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); break; case VATTR_LMCOORD: - GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord.gl.addr); + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[0].gl.vbo); + qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[0].gl.addr); + break; + case VATTR_LMCOORD2: + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[1].gl.vbo); + qglVertexAttribPointer(VATTR_LMCOORD2, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[1].gl.addr); + break; + case VATTR_LMCOORD3: + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[2].gl.vbo); + qglVertexAttribPointer(VATTR_LMCOORD3, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[2].gl.addr); + break; + case VATTR_LMCOORD4: + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[3].gl.vbo); + qglVertexAttribPointer(VATTR_LMCOORD4, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[3].gl.addr); break; case VATTR_NORMALS: if (!shaderstate.sourcevbo->normals.gl.addr) @@ -661,6 +687,9 @@ void GLBE_SetupVAO(vbo_t *vbo, unsigned vaodynamic) (1u<<(gl_config.nofixedfunc?VATTR_VERTEX1:VATTR_LEG_VERTEX))| (1u<texgen) { @@ -946,10 +974,16 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) t = pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes]; break; case T_GEN_LIGHTMAP: - t = shaderstate.curlightmap; + if (shaderstate.curbatch->lightmap[0] < 0) + t = r_whiteimage; + else + t = lightmap[shaderstate.curbatch->lightmap[0]]->lightmap_texture; break; case T_GEN_DELUXMAP: - t = shaderstate.curdeluxmap; + if (shaderstate.curbatch->lightmap[0] < 0) + t = r_nulltex; //fixme + else + t = lightmap[shaderstate.curbatch->lightmap[0]]->deluxmap_texture; break; case T_GEN_DIFFUSE: if (shaderstate.curtexnums && TEXVALID(shaderstate.curtexnums->base)) @@ -1015,6 +1049,11 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) t = shaderstate.tex_reflection; break; case T_GEN_REFRACTION: + if (!r_refract_fboival) + { + T_Gen_CurrentRender(tmu); + return; + } t = shaderstate.tex_refraction; break; case T_GEN_RIPPLEMAP: @@ -1153,11 +1192,20 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale) R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP); } +void GLBE_Shutdown(void) +{ + BZ_Free(shaderstate.wbatches); + shaderstate.wbatches = NULL; + shaderstate.maxwbatches = 0; +} + void GLBE_Init(void) { int i; double t; + GLBE_Shutdown(); + memset(&shaderstate, 0, sizeof(shaderstate)); shaderstate.curentity = &r_worldentity; @@ -1187,6 +1235,8 @@ void GLBE_Init(void) } shaderstate.identitylighting = 1; + for (i = 0; i < MAXLIGHTMAPS; i++) + shaderstate.dummybatch.lightmap[i] = -1; /*normally we load these lazily, but if they're probably going to be used anyway, load them now to avoid stalls.*/ if (r_shadow_realtime_dlight.ival && !shaderstate.inited_shader_rtlight && gl_config.arb_shader_objects) @@ -2123,10 +2173,9 @@ static void GenerateColourMods(const shaderpass_t *pass) } } -static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) +static void BE_GeneratePassTC(const shaderpass_t *pass, int tmu) { - pass += passno; - qglClientActiveTextureARB(mtexid0 + passno); + qglClientActiveTextureARB(mtexid0 + tmu); if (!pass->numtcmods) { //if there are no tcmods, pass through here as fast as possible @@ -2137,15 +2186,15 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) } else if (pass->tcgen == TC_GEN_LIGHTMAP) { - if (!shaderstate.sourcevbo->lmcoord.gl.addr) + if (!shaderstate.sourcevbo->lmcoord[0].gl.addr) { GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord.gl.addr); } else { - GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); - qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord.gl.addr); + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[0].gl.vbo); + qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord[0].gl.addr); } } else if (pass->tcgen == TC_GEN_NORMAL) @@ -2166,12 +2215,12 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) else { //specular highlights and reflections have no fixed data, and must be generated. - GenerateTCMods(pass, passno); + GenerateTCMods(pass, tmu); } } else { - GenerateTCMods(pass, passno); + GenerateTCMods(pass, tmu); } } @@ -2180,11 +2229,11 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) unsigned int delta; /*2d mode doesn't depth test or depth write*/ + if (shaderstate.force2d) + { #ifdef warningmsg #pragma warningmsg("fixme: q3 doesn't seem to have this, why do we need it?") #endif - if (shaderstate.force2d) - { sbits &= ~(SBITS_MISC_DEPTHWRITE|SBITS_MISC_DEPTHEQUALONLY); sbits |= SBITS_MISC_NODEPTHTEST; } @@ -2239,17 +2288,17 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) case SBITS_SRCBLEND_ONE_MINUS_DST_ALPHA: src = GL_ONE_MINUS_DST_ALPHA; break; case SBITS_SRCBLEND_ALPHA_SATURATE: src = GL_SRC_ALPHA_SATURATE; break; } - switch(sbits & SBITS_DSTBLEND_BITS) + switch((sbits & SBITS_DSTBLEND_BITS)>>4) { - case SBITS_DSTBLEND_ZERO: dst = GL_ZERO; break; + case SBITS_DSTBLEND_ZERO>>4: dst = GL_ZERO; break; default: - case SBITS_DSTBLEND_ONE: dst = GL_ONE; break; - case SBITS_DSTBLEND_SRC_COLOR: dst = GL_SRC_COLOR; break; - case SBITS_DSTBLEND_ONE_MINUS_SRC_COLOR: dst = GL_ONE_MINUS_SRC_COLOR; break; - case SBITS_DSTBLEND_SRC_ALPHA: dst = GL_SRC_ALPHA; break; - case SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA: dst = GL_ONE_MINUS_SRC_ALPHA; break; - case SBITS_DSTBLEND_DST_ALPHA: dst = GL_DST_ALPHA; break; - case SBITS_DSTBLEND_ONE_MINUS_DST_ALPHA: dst = GL_ONE_MINUS_DST_ALPHA; break; + case SBITS_DSTBLEND_ONE>>4: dst = GL_ONE; break; + case SBITS_DSTBLEND_SRC_COLOR>>4: dst = GL_SRC_COLOR; break; + case SBITS_DSTBLEND_ONE_MINUS_SRC_COLOR>>4: dst = GL_ONE_MINUS_SRC_COLOR; break; + case SBITS_DSTBLEND_SRC_ALPHA>>4: dst = GL_SRC_ALPHA; break; + case SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA>>4: dst = GL_ONE_MINUS_SRC_ALPHA; break; + case SBITS_DSTBLEND_DST_ALPHA>>4: dst = GL_DST_ALPHA; break; + case SBITS_DSTBLEND_ONE_MINUS_DST_ALPHA>>4: dst = GL_ONE_MINUS_DST_ALPHA; break; } qglEnable(GL_BLEND); qglBlendFunc(src, dst); @@ -2438,7 +2487,8 @@ static void BE_SubmitMeshChain(void) static void DrawPass(const shaderpass_t *pass) { - int i; + extern cvar_t temp1; + int i, j, k; int tmu; int lastpass = pass->numMergedPasses; unsigned int attr = (1u<lightmap[j] >= 0; j++) + { + if (j == 1) + BE_SetPassBlendMode(tmu, PBM_REPLACE); + + /*make sure no textures linger*/ + for (k = tmu; k < shaderstate.lastpasstmus; k++) + { + GL_LazyBind(k, 0, r_nulltex); + } + shaderstate.lastpasstmus = tmu; + + /*push it*/ + BE_EnableShaderAttributes(attr); + BE_SubmitMeshChain(); + tmu = 0; + + /*bind the light texture*/ + GL_LazyBind(tmu, GL_TEXTURE_2D, lightmap[shaderstate.curbatch->lightmap[j]]->lightmap_texture); + + /*set up the colourmod for this style's lighting*/ + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; + + shaderstate.pendingcolourflat[0] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[j]]/256.0f; + shaderstate.pendingcolourflat[1] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[j]]/256.0f; + shaderstate.pendingcolourflat[2] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[j]]/256.0f; + shaderstate.pendingcolourflat[3] = 1; + + /*pick the correct st coords for this lightmap pass*/ + qglClientActiveTextureARB(mtexid0 + tmu); + GL_SelectVBO(shaderstate.sourcevbo->lmcoord[j].gl.vbo); + qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord[j].gl.addr); + + BE_SetPassBlendMode(tmu, PBM_ADD); + BE_SendPassBlendDepthMask((pass[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE); + + attr = (1u< 1 && i != lastpass) + { + for (k = tmu; k < shaderstate.lastpasstmus; k++) + { + GL_LazyBind(k, 0, r_nulltex); + } + shaderstate.lastpasstmus = tmu; + BE_EnableShaderAttributes(attr); + + BE_SubmitMeshChain(); + tmu = 0; + + BE_SendPassBlendDepthMask(pass[i+1].shaderbits); + GenerateColourMods(&pass[i+1]); + } + } } + if (!tmu) + return; + for (i = tmu; i < shaderstate.lastpasstmus; i++) { GL_LazyBind(i, 0, r_nulltex); @@ -2550,22 +2672,40 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, break; case SP_E_LMSCALE: + if (perm & PERMUTATION_LIGHTSTYLES) { - vec4_t colscale; + vec4_t colscale[MAXLIGHTMAPS]; + int j; + for (j = 0; j < MAXLIGHTMAPS ; j++) + { + if (shaderstate.curentity->model && shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) + { + float sc = (1<lightstyle[j]]/256.0f, colscale[j]); + } + qglUniform4fvARB(p->handle[perm], j, (GLfloat*)colscale); + } + else + { + vec4_t colscale[4]; if (shaderstate.curentity->model && shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) { float sc = (1<shaderRGBAf, sc, colscale); + VectorSet(colscale[0], sc, sc, sc); } - else if (shaderstate.identitylighting == 1) - { - VectorCopy(shaderstate.curentity->shaderRGBAf, colscale); - } else { - VectorScale(shaderstate.curentity->shaderRGBAf, shaderstate.identitylighting, colscale); + VectorSet(colscale[0], shaderstate.identitylighting, shaderstate.identitylighting, shaderstate.identitylighting); } - colscale[3] = shaderstate.curentity->shaderRGBAf[3]; + colscale[0][3] = 1; qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)colscale); } @@ -2759,6 +2899,8 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas perm |= PERMUTATION_FOG; if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET].glsl) perm |= PERMUTATION_OFFSET; + if (shaderstate.curbatch->lightmap[1] >= 0 && p->handle[perm|PERMUTATION_LIGHTSTYLES].glsl) + perm |= PERMUTATION_LIGHTSTYLES; if (shaderstate.currentvao != shaderstate.sourcevbo->vao) { @@ -2783,12 +2925,28 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas { Shader_BindTextureForPass(i, pass+i); } - //we need this loop to fix up fixed-function stuff - for (; i < shaderstate.lastpasstmus; i++) + if (perm & PERMUTATION_LIGHTSTYLES) { - GL_LazyBind(i, 0, r_nulltex); + GL_LazyBind(i++, GL_TEXTURE_2D, shaderstate.curbatch->lightmap[1] >= 0?lightmap[shaderstate.curbatch->lightmap[1]]->lightmap_texture:r_nulltex); + GL_LazyBind(i++, GL_TEXTURE_2D, shaderstate.curbatch->lightmap[2] >= 0?lightmap[shaderstate.curbatch->lightmap[2]]->lightmap_texture:r_nulltex); + GL_LazyBind(i++, GL_TEXTURE_2D, shaderstate.curbatch->lightmap[3] >= 0?lightmap[shaderstate.curbatch->lightmap[3]]->lightmap_texture:r_nulltex); + + //we need this loop to fix up fixed-function stuff + for (; i < shaderstate.lastpasstmus; i++) + { + GL_LazyBind(i, 0, r_nulltex); + } + shaderstate.lastpasstmus = pass->numMergedPasses+3; + } + else + { + //we need this loop to fix up fixed-function stuff + for (; i < shaderstate.lastpasstmus; i++) + { + GL_LazyBind(i, 0, r_nulltex); + } + shaderstate.lastpasstmus = pass->numMergedPasses; } - shaderstate.lastpasstmus = pass->numMergedPasses; } else { @@ -2796,7 +2954,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas for (i = 0; i < pass->numMergedPasses; i++) { Shader_BindTextureForPass(i, pass+i); - BE_GeneratePassTC(pass, i); + BE_GeneratePassTC(pass+i, i); } for (; i < shaderstate.lastpasstmus; i++) { @@ -2869,7 +3027,7 @@ void GLBE_SelectMode(backendmode_t mode) /*BEM_STENCIL doesn't support mesh writing*/ BE_PushOffsetShadow(false); - if (!shaderstate.allblackshader) + if (gl_config.nofixedfunc && !shaderstate.allblackshader) { char *defs[] = {NULL}; shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config.gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false); @@ -2993,6 +3151,7 @@ void GLBE_SelectEntity(entity_t *ent) } shaderstate.lastuniform = 0; + shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } void BE_SelectFog(vec3_t colour, float alpha, float density) @@ -3047,44 +3206,34 @@ void GLBE_SelectDLight(dlight_t *dl, vec3_t colour) void BE_PushOffsetShadow(qboolean pushdepth) { + extern cvar_t r_polygonoffset_stencil_offset, r_polygonoffset_stencil_factor; + polyoffset_t po; if (pushdepth) { /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; - polyoffset_t po; - po.factor = r_polygonoffset_submodel_factor.value; - po.unit = r_polygonoffset_submodel_offset.value; - -#ifndef FORCESTATE - if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) -#endif - { - shaderstate.curpolyoffset = po; - if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) - { - qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); - } - else - qglDisable(GL_POLYGON_OFFSET_FILL); - } + po.factor = r_polygonoffset_submodel_factor.value + r_polygonoffset_stencil_factor.value; + po.unit = r_polygonoffset_submodel_offset.value + r_polygonoffset_stencil_offset.value; } else { + po.factor = r_polygonoffset_stencil_factor.value; + po.unit = r_polygonoffset_stencil_offset.value; + } + #ifndef FORCESTATE - if (*(int*)&shaderstate.curpolyoffset != 0 || *(int*)&shaderstate.curpolyoffset != 0) + if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) #endif + { + shaderstate.curpolyoffset = po; + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) { - shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; - if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) - { - qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); - } - else - qglDisable(GL_POLYGON_OFFSET_FILL); + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); } + else + qglDisable(GL_POLYGON_OFFSET_FILL); } } @@ -3189,7 +3338,7 @@ static void BE_LegacyLighting(void) shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = coloursarray; - GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + GL_DeselectVAO(); GL_DeSelectProgram(); BE_EnableShaderAttributes(attr); @@ -3286,19 +3435,20 @@ static void DrawMeshes(void) BE_RenderMeshProgram(shaderstate.crepopaqueshader, shaderstate.crepopaqueshader->passes); break; case BEM_DEPTHONLY: + GL_DeselectVAO(); GL_DeSelectProgram(); #ifdef warningmsg #pragma warningmsg("fixme: support alpha test") #endif - GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); BE_EnableShaderAttributes((1u<indicies.gl.vbo); BE_EnableShaderAttributes((1u<flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright) && !gl_config.nofixedfunc) { //FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster. - GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + GL_DeselectVAO(); GL_DeSelectProgram(); shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = NULL; @@ -3334,7 +3484,7 @@ static void DrawMeshes(void) break; else { - GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + GL_DeselectVAO(); GL_DeSelectProgram(); while (passno < shaderstate.curshader->numpasses) { @@ -3352,6 +3502,7 @@ static void DrawMeshes(void) void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) { + shaderstate.curbatch = &shaderstate.dummybatch; if (!vbo) { mesh_t *m; @@ -3361,11 +3512,8 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ if (shaderstate.curentity != &r_worldentity) { BE_SelectEntity(&r_worldentity); - shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } shaderstate.curtexnums = texnums; - shaderstate.curlightmap = r_nulltex; - shaderstate.curdeluxmap = r_nulltex; while (nummeshes--) { @@ -3407,11 +3555,8 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ if (shaderstate.curentity != &r_worldentity) { BE_SelectEntity(&r_worldentity); - shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } shaderstate.curtexnums = texnums; - shaderstate.curlightmap = r_nulltex; - shaderstate.curdeluxmap = r_nulltex; shaderstate.meshcount = nummeshes; shaderstate.meshes = meshlist; @@ -3428,18 +3573,18 @@ void GLBE_SubmitBatch(batch_t *batch) { int lm; + shaderstate.curbatch = batch; if (batch->vbo) { shaderstate.sourcevbo = batch->vbo; shaderstate.colourarraytype = GL_FLOAT; - lm = batch->lightmap; } else { shaderstate.dummyvbo.coord.gl.addr = batch->mesh[0]->xyz_array; shaderstate.dummyvbo.coord2.gl.addr = batch->mesh[0]->xyz2_array; shaderstate.dummyvbo.texcoord.gl.addr = batch->mesh[0]->st_array; - shaderstate.dummyvbo.lmcoord.gl.addr = batch->mesh[0]->lmst_array; + shaderstate.dummyvbo.lmcoord[0].gl.addr = batch->mesh[0]->lmst_array[0]; shaderstate.dummyvbo.indicies.gl.addr = batch->mesh[0]->indexes; shaderstate.dummyvbo.normals.gl.addr = batch->mesh[0]->normals_array; shaderstate.dummyvbo.svector.gl.addr = batch->mesh[0]->snormals_array; @@ -3462,25 +3607,11 @@ void GLBE_SubmitBatch(batch_t *batch) lm = -1; } - if (lm < 0) - { - extern texid_t r_whiteimage; - /*FIXME: this doesn't compensate for overbrighting*/ - shaderstate.curlightmap = r_whiteimage; - shaderstate.curdeluxmap = r_nulltex; - } - else - { - shaderstate.curlightmap = lightmap_textures[lm]; - shaderstate.curdeluxmap = deluxmap_textures[lm]; - } - shaderstate.curshader = batch->shader; shaderstate.flags = batch->flags; if (shaderstate.curentity != batch->ent) { BE_SelectEntity(batch->ent); - shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; } if (batch->skin) shaderstate.curtexnums = batch->skin; @@ -3550,6 +3681,7 @@ static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) GL_ForceDepthWritable(); qglClear(GL_DEPTH_BUFFER_BIT); currententity = &r_worldentity; + shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } } } @@ -3598,7 +3730,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) { //these flags require rendering some view as an fbo if (r_refdef.recurse) - return; + continue; if (batch->shader->flags & SHADER_HASREFLECT) { @@ -3616,32 +3748,39 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, true); qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); GL_ForceDepthWritable(); - qglClear(GL_DEPTH_BUFFER_BIT); + qglClearColor(0, 0, 0, 0); + qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLR_DrawPortal(batch, cl.worldmodel->batches, 1); GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); } if (batch->shader->flags & SHADER_HASREFRACT) { - if (!shaderstate.tex_refraction.num) + if (r_refract_fboival) { - shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth/2, vid.pixelheight/2); - GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction); - qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - GL_ForceDepthWritable(); - GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, true); - qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); - GL_ForceDepthWritable(); - qglClear(GL_DEPTH_BUFFER_BIT); - GLR_DrawPortal(batch, cl.worldmodel->batches, 2); - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + if (!shaderstate.tex_refraction.num) + { + shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth/2, vid.pixelheight/2); + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + GL_ForceDepthWritable(); + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, true); + qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); + GL_ForceDepthWritable(); + qglClearColor(0, 0, 0, 0); + qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GLR_DrawPortal(batch, cl.worldmodel->batches, 2); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); - qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); + qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); + } + else + GLR_DrawPortal(batch, cl.worldmodel->batches, 2); } if (batch->shader->flags & SHADER_HASRIPPLEMAP) { @@ -3695,33 +3834,35 @@ void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop) static void BE_UpdateLightmaps(void) { - int lm; - for (lm = 0; lm < numlightmaps; lm++) + lightmapinfo_t *lm; + int lmidx; + for (lmidx = 0; lmidx < numlightmaps; lmidx++) { - if (!lightmap[lm]) + if (!lightmap[lmidx]) continue; - if (lightmap[lm]->modified) + lm = lightmap[lmidx]; + if (lm->modified) { glRect_t *theRect; - lightmap[lm]->modified = false; - theRect = &lightmap[lm]->rectchange; - GL_MTBind(0, GL_TEXTURE_2D, lightmap_textures[lm]); + lm->modified = false; + theRect = &lm->rectchange; + GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); switch (lightmap_bytes) { case 4: qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, - lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*4); + lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH*4); break; case 3: qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, - lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*3); + lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH*3); break; case 1: qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, LMBLOCK_WIDTH, theRect->h, GL_LUMINANCE, GL_UNSIGNED_BYTE, - lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH); + lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH); break; } theRect->l = LMBLOCK_WIDTH; @@ -3729,14 +3870,14 @@ static void BE_UpdateLightmaps(void) theRect->h = 0; theRect->w = 0; - if (lightmap[lm]->deluxmodified) + if (lm->deluxmodified) { - lightmap[lm]->deluxmodified = false; - theRect = &lightmap[lm]->deluxrectchange; - GL_MTBind(0, GL_TEXTURE_2D, deluxmap_textures[lm]); + lm->deluxmodified = false; + theRect = &lm->deluxrectchange; + GL_MTBind(0, GL_TEXTURE_2D, lm->deluxmap_texture); qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, - lightmap[lm]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); + lm->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); theRect->l = LMBLOCK_WIDTH; theRect->t = LMBLOCK_HEIGHT; theRect->h = 0; @@ -4002,7 +4143,10 @@ void GLBE_DrawWorld (qbyte *vis) BE_GenModelBatches(batches); R_GenDlightBatches(batches); shaderstate.curentity = &r_worldentity; - shaderstate.updatetime = cl.servertime; + if (cl.paused || cls.state < ca_active) + shaderstate.updatetime = r_refdef.time; + else + shaderstate.updatetime = cl.servertime; BE_SelectEntity(&r_worldentity); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 6e361e68..0ead0521 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -498,6 +498,8 @@ void GLDraw_DeInit (void) { Cmd_RemoveCommand ("r_imagelist"); + R2D_Shutdown(); + if (font_conchar) Font_Free(font_conchar); font_conchar = NULL; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index bee41c31..aa411fb7 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -315,7 +315,10 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) b = BE_GetTempBatch(); if (b) { - b->lightmap = -1; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->ent = e; b->shader = hm->skyshader; b->flags = 0; @@ -370,7 +373,7 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) { mesh->xyz_array = BZ_Malloc((sizeof(vecV_t)+sizeof(vec2_t)+sizeof(vec2_t)) * (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); mesh->st_array = (void*) (mesh->xyz_array + (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); - mesh->lmst_array = (void*) (mesh->st_array + (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); + mesh->lmst_array[0] = (void*) (mesh->st_array + (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); } mesh->numvertexes = 0; /*64 quads across requires 65 verticies*/ @@ -392,14 +395,14 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) mesh->st_array[v][1] = mesh->xyz_array[v][1] / 64; //calc the position in the range -0.5 to 0.5 - mesh->lmst_array[v][0] = (((float)vx / (SECTHEIGHTSIZE-1))-0.5); - mesh->lmst_array[v][1] = (((float)vy / (SECTHEIGHTSIZE-1))-0.5); + mesh->lmst_array[0][v][0] = (((float)vx / (SECTHEIGHTSIZE-1))-0.5); + mesh->lmst_array[0][v][1] = (((float)vy / (SECTHEIGHTSIZE-1))-0.5); //scale down to a half-texel - mesh->lmst_array[v][0] *= (SECTTEXSIZE-1.0f)/LMBLOCK_WIDTH; - mesh->lmst_array[v][1] *= (SECTTEXSIZE-1.0f)/LMBLOCK_HEIGHT; + mesh->lmst_array[0][v][0] *= (SECTTEXSIZE-1.0f)/LMBLOCK_WIDTH; + mesh->lmst_array[0][v][1] *= (SECTTEXSIZE-1.0f)/LMBLOCK_HEIGHT; //bias it - mesh->lmst_array[v][0] += ((float)SECTTEXSIZE/(LMBLOCK_WIDTH*2)) + ((float)(s->lmy) / LMBLOCK_WIDTH); - mesh->lmst_array[v][1] += ((float)SECTTEXSIZE/(LMBLOCK_HEIGHT*2)) + ((float)(s->lmx) / LMBLOCK_HEIGHT); + mesh->lmst_array[0][v][0] += ((float)SECTTEXSIZE/(LMBLOCK_WIDTH*2)) + ((float)(s->lmy) / LMBLOCK_WIDTH); + mesh->lmst_array[0][v][1] += ((float)SECTTEXSIZE/(LMBLOCK_HEIGHT*2)) + ((float)(s->lmx) / LMBLOCK_HEIGHT); //TODO: include colour tints } @@ -437,8 +440,8 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) GL_SelectVBO(0); s->vbo.texcoord.gl.addr = (void*)((char*)mesh->st_array - (char*)mesh->xyz_array); s->vbo.texcoord.gl.vbo = s->vbo.coord.gl.vbo; - s->vbo.lmcoord.gl.addr = (void*)((char*)mesh->lmst_array - (char*)mesh->xyz_array); - s->vbo.lmcoord.gl.vbo = s->vbo.coord.gl.vbo; + s->vbo.lmcoord[0].gl.addr = (void*)((char*)mesh->lmst_array - (char*)mesh->xyz_array); + s->vbo.lmcoord[0].gl.vbo = s->vbo.coord.gl.vbo; // Z_Free(mesh->xyz_array); // mesh->xyz_array = NULL; // mesh->st_array = NULL; @@ -476,7 +479,10 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) b->skin = &s->textures; b->texture = NULL; b->vbo = &s->vbo; - b->lightmap = s->lightmap; + b->lightmap[0] = s->lightmap; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->next = batches[b->shader->sort]; batches[b->shader->sort] = b; diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index e05d9aba..20ee9f10 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -2,7 +2,7 @@ #ifdef HALFLIFEMODELS -#include "glquake.h" +#include "shader.h" /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Half-Life Model Renderer (Experimental) Copyright (C) 2001 James 'Ender' Brown [ender@quakesrc.org] This program is @@ -83,7 +83,7 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer) hlmdl_tex_t *tex; hlmdl_bone_t *bones; hlmdl_bonecontroller_t *bonectls; - texid_t *texnums; + shader_t **shaders; int start, end, total; /*~~*/ @@ -198,11 +198,12 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer) model->bones = (char *)bones - (char *)model; model->bonectls = (char *)bonectls - (char *)model; - texnums = Hunk_Alloc(texheader->numtextures*sizeof(model->texnums)); - model->texnums = (char *)texnums - (char *)model; + shaders = Hunk_Alloc(texheader->numtextures*sizeof(shader_t)); + model->shaders = (char *)shaders - (char *)model; for(i = 0; i < texheader->numtextures; i++) { - texnums[i] = GL_LoadTexture8Pal24("", tex[i].w, tex[i].h, (qbyte *) texheader + tex[i].offset, (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset, IF_NOALPHA|IF_NOGAMMA); + shaders[i] = R_RegisterSkin(va("%s_%i.tga", mod->name, i), mod->name); + shaders[i]->defaulttextures.base = R_LoadTexture8Pal24("", tex[i].w, tex[i].h, (qbyte *) texheader + tex[i].offset, (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset, IF_NOALPHA|IF_NOGAMMA); } @@ -555,6 +556,8 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl } } + +#if 0 /* ======================================================================================================================= R_Draw_HL_AliasModel - main drawing function @@ -568,7 +571,6 @@ void R_DrawHLModel(entity_t *curent) int b, m, v; short *skins; int bgroup, cbone, lastbone; - float mmat[16], mvmat[16]; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ //general model @@ -577,7 +579,7 @@ void R_DrawHLModel(entity_t *curent) model.textures = (hlmdl_tex_t *) ((char *)modelc + modelc->textures); model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones); model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls); - model.texnums = (texid_t *) ((char *)modelc + modelc->texnums); + model.shaders = (shader_t **) ((char *)modelc + modelc->shaders); skins = (short *) ((qbyte *) model.texheader + model.texheader->skins); @@ -590,30 +592,9 @@ void R_DrawHLModel(entity_t *curent) for (b = 0; b < MAX_BONE_CONTROLLERS; b++) model.controller[b] = curent->framestate.bonecontrols[b]; - GL_TexEnv(GL_MODULATE); - - if (curent->shaderRGBAf[3]<1) - { - qglEnable(GL_BLEND); - } - else - { - qglDisable(GL_BLEND); - } - qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Con_Printf("%s %i\n", sequence->name, sequence->unknown1[0]); - qglPushMatrix(); - { - vec3_t difuse, ambient, ldir; - cl.worldmodel->funcs.LightPointValues(cl.worldmodel, curent->origin, difuse, ambient, ldir); - qglColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->shaderRGBAf[3]); - } - - R_RotateForEntity (mmat, mvmat, curent, curent->model); - qglLoadMatrixf(mvmat); cbone = 0; for (bgroup = 0; bgroup < FS_COUNT; bgroup++) @@ -684,16 +665,12 @@ void R_DrawHLModel(entity_t *curent) { tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w; tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h; - GL_LazyBind(0, GL_TEXTURE_2D, model.texnums[skins[mesh->skinindex]]); +// GL_LazyBind(0, GL_TEXTURE_2D, model.shaders[skins[mesh->skinindex]]->defaulttextures.base); } GL_Draw_HL_AliasFrame((short *) ((qbyte *) model.header + mesh->index), transformed, tex_w, tex_h); } } - - qglPopMatrix(); - - GL_TexEnv(GL_REPLACE); } /* @@ -734,6 +711,8 @@ void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float float *verts = transformed[order[0]]; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + //FIXME: what's order[1]? + /* texture coordinates come from the draw list */ qglTexCoord2f(order[2] * tex_w, order[3] * tex_h); order += 4; @@ -745,5 +724,246 @@ void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float qglEnd(); } } +#endif + +void R_HL_BuildFrame(hlmodel_t *model, hlmdl_model_t *amodel, entity_t *curent, short *order, float tex_s, float tex_t, mesh_t *mesh) +{ + static vecV_t xyz[2048]; + static vec3_t norm[2048]; + static vec2_t st[2048]; + static index_t index[4096]; + int count; + int b; + int cbone; + int bgroup; + int lastbone; + int v, i; + vec3_t *verts; + qbyte *bone; + vec3_t transformed[2048]; + + int idx = 0; + int vert = 0; + + mesh->xyz_array = xyz; + mesh->st_array = st; + mesh->normals_array = norm; //for lighting algos to not crash + mesh->snormals_array = norm; //for rtlighting + mesh->tnormals_array = norm; //for rtlighting + mesh->indexes = index; + + for (b = 0; b < MAX_BONE_CONTROLLERS; b++) + model->controller[b] = curent->framestate.bonecontrols[b]; + +// Con_Printf("%s %i\n", sequence->name, sequence->unknown1[0]); + + cbone = 0; + for (bgroup = 0; bgroup < FS_COUNT; bgroup++) + { + lastbone = curent->framestate.g[bgroup].endbone; + if (bgroup == FS_COUNT-1) + lastbone = model->header->numbones; + if (cbone >= lastbone) + continue; + HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0]); /* Setup the bones */ + cbone = lastbone; + } + + + verts = (vec3_t *) ((qbyte *) model->header + amodel->vertindex); + bone = ((qbyte *) model->header + amodel->vertinfoindex); + for(v = 0; v < amodel->numverts; v++) + { + VectorTransform(verts[v], (void *)transform_matrix[bone[v]], transformed[v]); + } + + for(;;) + { + count = *order++; /* get the vertex count and primitive type */ + if(!count) break; /* done */ + + if(count < 0) + { + count = -count; + + //emit (count-2)*3 indicies as a fan + + + + for (i = 0; i < count-2; i++) + { + index[idx++] = vert + 0; + index[idx++] = vert + i+1; + index[idx++] = vert + i+2; + } + } + else + { + //emit (count-2)*3 indicies as a strip + + for (i = 0; ; ) + { + if (i == count-2) + break; + index[idx++] = vert + i; + index[idx++] = vert + i+1; + index[idx++] = vert + i+2; + i++; + + if (i == count-2) + break; + index[idx++] = vert + i; + index[idx++] = vert + i+2; + index[idx++] = vert + i+1; + i++; + } + } + + do + { + VectorCopy(transformed[order[0]], xyz[vert]); + + //FIXME: what's order[1]? + + /* texture coordinates come from the draw list */ + st[vert][0] = order[2] * tex_s; + st[vert][1] = order[3] * tex_t; + + norm[vert][1] = 1; + + + order += 4; + vert++; + } while(--count); + } + + mesh->numindexes = idx; + mesh->numvertexes = vert; +} + +void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches); +void R_HL_BuildMesh(struct batch_s *b) +{ + R_HalfLife_WalkMeshes(b->ent, b, NULL); +} + +void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches) +{ + hlmodelcache_t *modelc = Mod_Extradata(rent->model); + hlmodel_t model; + int body, m, v; + short *skins; + int bgroup, cbone, lastbone; + int batchid = 0; + static mesh_t bmesh, *mptr = &bmesh; + + //general model + model.header = (hlmdl_header_t *) ((char *)modelc + modelc->header); + model.texheader = (hlmdl_header_t *) ((char *)modelc + modelc->texheader); + model.textures = (hlmdl_tex_t *) ((char *)modelc + modelc->textures); + model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones); + model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls); + model.shaders = (shader_t **) ((char *)modelc + modelc->shaders); + + skins = (short *) ((qbyte *) model.texheader + model.texheader->skins); + + for (body = 0; body < model.header->numbodyparts; body++) + { + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model.header + model.header->bodypartindex) + body; + int bodyindex = (0 / bodypart->base) % bodypart->nummodels; + hlmdl_model_t *amodel = (hlmdl_model_t *) ((qbyte *) model.header + bodypart->modelindex) + bodyindex; + qbyte *bone = ((qbyte *) model.header + amodel->vertinfoindex); + vec3_t *verts = (vec3_t *) ((qbyte *) model.header + amodel->vertindex); + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + + + /* Draw each mesh */ + for(m = 0; m < amodel->nummesh; m++) + { + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + hlmdl_mesh_t *mesh = (hlmdl_mesh_t *) ((qbyte *) model.header + amodel->meshindex) + m; + float tex_w; + float tex_h; + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + + + if (batches) + { + shader_t *shader; + int sort; + + b = BE_GetTempBatch(); + if (!b) + return; + + shader = model.shaders[skins[mesh->skinindex]]; + b->buildmeshes = R_HL_BuildMesh; + b->ent = rent; + b->mesh = NULL; + b->firstmesh = 0; + b->meshes = 1; + b->skin = &shader->defaulttextures; + b->texture = NULL; + b->shader = shader; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; + b->surf_first = batchid; + b->flags = 0; + sort = shader->sort; + //fixme: we probably need to force some blend modes based on the surface flags. + if (rent->flags & RF_FORCECOLOURMOD) + b->flags |= BEF_FORCECOLOURMOD; + if (rent->flags & Q2RF_ADDITIVE) + { + b->flags |= BEF_FORCEADDITIVE; + if (sort < SHADER_SORT_ADDITIVE) + sort = SHADER_SORT_ADDITIVE; + } + if (rent->flags & Q2RF_TRANSLUCENT) + { + b->flags |= BEF_FORCETRANSPARENT; + if (SHADER_SORT_PORTAL < sort && sort < SHADER_SORT_BLEND) + sort = SHADER_SORT_BLEND; + } + if (rent->flags & RF_NODEPTHTEST) + { + b->flags |= BEF_FORCENODEPTH; + if (sort < SHADER_SORT_NEAREST) + sort = SHADER_SORT_NEAREST; + } + if (rent->flags & RF_NOSHADOW) + b->flags |= BEF_NOSHADOWS; + b->vbo = NULL; + b->next = batches[sort]; + batches[sort] = b; + } + else + { + if (batchid == b->surf_first) + { + tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w; + tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h; + + b->mesh = &mptr; + R_HL_BuildFrame(&model, amodel, b->ent, (short *) ((qbyte *) model.header + mesh->index), tex_w, tex_h, b->mesh[0]); + return; + } + } + + batchid++; + } + } +} + +qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel); + +void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches) +{ + R_CalcModelLighting(e, e->model); + R_HalfLife_WalkMeshes(e, NULL, batches); +} #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index c092428c..d581fb25 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -96,18 +96,60 @@ void RMod_UpdateLightmap(int snum) #endif +void RMod_BatchList_f(void) +{ + int m, i; + model_t *mod; + batch_t *batch; + unsigned int count; + for (m=0 , mod=mod_known ; mtype == mod_brush && !mod->needload) + { + Con_Printf("%s:\n", mod->name); + count = 0; + for (i = 0; i < SHADER_SORT_COUNT; i++) + { + for (batch = mod->batches[i]; batch; batch = batch->next) + { + if (batch->lightmap[3] >= 0) + Con_Printf("%s lm=(%i:%i %i:%i %i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lightstyle[0], batch->lightmap[1], batch->lightstyle[1], batch->lightmap[2], batch->lightstyle[2], batch->lightmap[3], batch->lightstyle[3], batch->maxmeshes); + else if (batch->lightmap[2] >= 0) + Con_Printf("%s lm=(%i:%i %i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lightstyle[0], batch->lightmap[1], batch->lightstyle[1], batch->lightmap[2], batch->lightstyle[2], batch->maxmeshes); + else if (batch->lightmap[1] >= 0) + Con_Printf("%s lm=(%i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lightstyle[0], batch->lightmap[1], batch->lightstyle[1], batch->maxmeshes); + else if (batch->lightstyle[0] != 255) + Con_Printf("%s lm=(%i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lightstyle[0], batch->maxmeshes); + else + Con_Printf("%s lm=%i surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->maxmeshes); + count++; + } + } + Con_Printf("%u\n", count); + } + } +} + void RMod_TextureList_f(void) { int m, i; texture_t *tx; model_t *mod; - qboolean shownmodelname; + qboolean shownmodelname = false; + int count = 0; for (m=0 , mod=mod_known ; mtype == mod_brush && !mod->needload) { if (*mod->name == '*') continue;// inlines don't count + if (shownmodelname) + Con_Printf("%u\n", count); + count = 0; shownmodelname = false; for (i = 0; i < mod->numtextures; i++) { @@ -119,12 +161,16 @@ void RMod_TextureList_f(void) { shownmodelname = true; Con_Printf("%s\n", mod->name); + count = 0; } Con_Printf("%s\n", tx->name); + count++; } } } + if (shownmodelname) + Con_Printf("%u\n", count); } void RMod_BlockTextureColour_f (void) @@ -378,6 +424,7 @@ void RMod_Init (void) mod_numknown = 0; Q1BSP_Init(); + Cmd_AddCommand("mod_batchlist", RMod_BatchList_f); Cmd_AddCommand("mod_texturelist", RMod_TextureList_f); Cmd_AddCommand("mod_usetexture", RMod_BlockTextureColour_f); } @@ -387,6 +434,7 @@ void RMod_Shutdown (void) RMod_ClearAll(); mod_numknown = 0; + Cmd_RemoveCommand("mod_batchlist"); Cmd_RemoveCommand("mod_texturelist"); Cmd_RemoveCommand("mod_usetexture"); } @@ -1088,9 +1136,10 @@ void RMod_LoadMiptex(texture_t *tx, miptex_t *mt, texnums_t *tn, int maps) if (!TEXVALID(tn->base)) { tn->base = R_LoadReplacementTexture(mt->name, "bmodels", alphaed?0:IF_NOALPHA); - if (!TEXVALID(tn->base)) + if (base && !TEXVALID(tn->base)) tn->base = R_LoadTexture32 (mt->name, tx->width, tx->height, (unsigned int *)base, (alphaed?0:IF_NOALPHA)); } + BZ_Free(base); } *tx->name = *mt->name; @@ -1410,7 +1459,7 @@ void RMod_NowLoadExternal(void) data = W_GetTexture(tx->name, &width, &height, &alphaed); if (data) - { //data is from temp hunk, so no need to free. + { tx->alphaed = alphaed; } @@ -1421,6 +1470,7 @@ void RMod_NowLoadExternal(void) // if (!TEXVALID(tn.base)) // tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA|IF_MIPCAP); //a fallback. :/ } + BZ_Free(data); } if (!TEXVALID(tn.bump) && *tx->name != '{' && r_loadbumpmapping) { @@ -2110,7 +2160,7 @@ void CalcSurfaceExtents (msurface_t *s); Mod_LoadFaces ================= */ -qboolean RMod_LoadFaces (lump_t *l, qboolean lm) +qboolean RMod_LoadFaces (lump_t *l, qboolean lm, mesh_t **meshlist) { dsface_t *ins; dlface_t *inl; @@ -2143,6 +2193,7 @@ qboolean RMod_LoadFaces (lump_t *l, qboolean lm) } out = Hunk_AllocName ( count*sizeof(*out), loadname); + *meshlist = Hunk_AllocName(count*sizeof(**meshlist), loadname); loadmodel->surfaces = out; loadmodel->numsurfaces = count; for ( surfnum=0 ; surfnumlightofs); ins++; } +// (*meshlist)[surfnum].vbofirstvert = out->firstedge; +// (*meshlist)[surfnum].numvertexes = out->numedges; out->flags = 0; if (side) @@ -2234,6 +2287,499 @@ qboolean RMod_LoadFaces (lump_t *l, qboolean lm) return true; } +void RModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, void *cookie) +{ + int i, lindex; + mesh_t *mesh = surf->mesh; + medge_t *pedge; + float *vec; + float s, t, d; + int sty; + + //output the mesh's indicies + for (i=0 ; inumvertexes-2 ; i++) + { + mesh->indexes[i*3] = 0; + mesh->indexes[i*3+1] = i+1; + mesh->indexes[i*3+2] = i+2; + } + //output the renderable verticies + for (i=0 ; inumvertexes ; i++) + { + lindex = mod->surfedges[surf->firstedge + i]; + + if (lindex > 0) + { + pedge = &mod->edges[lindex]; + vec = mod->vertexes[pedge->v[0]].position; + } + else + { + pedge = &mod->edges[-lindex]; + vec = mod->vertexes[pedge->v[1]].position; + } + + s = DotProduct (vec, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; + t = DotProduct (vec, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; + + VectorCopy (vec, mesh->xyz_array[i]); + mesh->st_array[i][0] = s/surf->texinfo->texture->width; + mesh->st_array[i][1] = t/surf->texinfo->texture->height; + + for (sty = 0; sty < 1; sty++) + { + mesh->lmst_array[sty][i][0] = (s - surf->texturemins[0] + (surf->light_s[sty]*16) + 8) / (mod->lightmaps.width*16); + mesh->lmst_array[sty][i][1] = (t - surf->texturemins[1] + (surf->light_t[sty]*16) + 8) / (mod->lightmaps.height*16); + } + + //figure out the texture directions, for bumpmapping and stuff + if (surf->flags & SURF_PLANEBACK) + VectorNegate(surf->plane->normal, mesh->normals_array[i]); + else + VectorCopy(surf->plane->normal, mesh->normals_array[i]); + VectorNegate(surf->texinfo->vecs[0], mesh->snormals_array[i]); + VectorNegate(surf->texinfo->vecs[1], mesh->tnormals_array[i]); + //the s+t vectors are axis-aligned, so fiddle them so they're normal aligned instead + d = -DotProduct(mesh->normals_array[i], mesh->snormals_array[i]); + VectorMA(mesh->snormals_array[i], d, mesh->normals_array[i], mesh->snormals_array[i]); + d = -DotProduct(mesh->normals_array[i], mesh->tnormals_array[i]); + VectorMA(mesh->tnormals_array[i], d, mesh->normals_array[i], mesh->tnormals_array[i]); + VectorNormalize(mesh->snormals_array[i]); + VectorNormalize(mesh->tnormals_array[i]); + + //q1bsp has no colour information (fixme: sample from the lightmap) + mesh->colors4f_array[i][0] = 1; + mesh->colors4f_array[i][1] = 1; + mesh->colors4f_array[i][2] = 1; + mesh->colors4f_array[i][3] = 1; + } +} + +static void RMod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxindicies, void (*build)(model_t *mod, msurface_t *surf, void *cookie), void *buildcookie) +{ + batch_t *batch; + msurface_t *surf; + mesh_t *mesh; + int numverts = 0; + int numindicies = 0; + int j; + int sortid; + int sty; + vbo_t vbo; + int styles = MAXLIGHTMAPS; + + vbo.indicies.dummy = Hunk_AllocName(sizeof(index_t) * maxindicies, "indexdata"); + vbo.coord.dummy = Hunk_AllocName((sizeof(vecV_t)+sizeof(vec2_t)*(1+styles)+sizeof(vec3_t)*3+sizeof(vec4_t))* maxverts, "vertdata"); + vbo.texcoord.dummy = (vecV_t*)vbo.coord.dummy + maxverts; + vbo.lmcoord[0].dummy = (vec2_t*)vbo.texcoord.dummy + maxverts; + for (sty = 1; sty < styles; sty++) + vbo.lmcoord[sty].dummy = (vec2_t*)vbo.lmcoord[sty-1].dummy + maxverts; + vbo.normals.dummy = (vec2_t*)vbo.lmcoord[styles-1].dummy + maxverts; + vbo.svector.dummy = (vec3_t*)vbo.normals.dummy + maxverts; + vbo.tvector.dummy = (vec3_t*)vbo.svector.dummy + maxverts; + vbo.colours.dummy = (vec3_t*)vbo.tvector.dummy + maxverts; + + numindicies = 0; + numverts = 0; + + //build each mesh + for (sortid=0; sortidbatches[sortid]; batch; batch = batch->next) + { + for (j = 0; j < batch->maxmeshes; j++) + { + surf = (msurface_t*)batch->mesh[j]; + mesh = surf->mesh; + batch->mesh[j] = mesh; + + mesh->vbofirstvert = numverts; + mesh->vbofirstelement = numindicies; + numverts += mesh->numvertexes; + numindicies += mesh->numindexes; + + //set up the arrays. the arrangement is required for the backend to optimise vbos + mesh->xyz_array = (vecV_t*)vbo.coord.dummy + mesh->vbofirstvert; + mesh->st_array = (vec2_t*)vbo.texcoord.dummy + mesh->vbofirstvert; + for (sty = 0; sty < styles; sty++) + mesh->lmst_array[sty] = (vec2_t*)vbo.lmcoord[sty].dummy + mesh->vbofirstvert; + for ( ; sty < MAXLIGHTMAPS; sty++) + mesh->lmst_array[sty] = NULL; + mesh->normals_array = (vec3_t*)vbo.normals.dummy + mesh->vbofirstvert; + mesh->snormals_array = (vec3_t*)vbo.svector.dummy + mesh->vbofirstvert; + mesh->tnormals_array = (vec3_t*)vbo.tvector.dummy + mesh->vbofirstvert; + mesh->colors4f_array = (vec4_t*)vbo.colours.dummy + mesh->vbofirstvert; + mesh->indexes = (index_t*)vbo.indicies.dummy + mesh->vbofirstelement; + + mesh->vbofirstvert = 0; + mesh->vbofirstelement = 0; + + build(mod, surf, buildcookie); + } + batch->meshes = 0; + batch->firstmesh = 0; + } + } +} + +/* +batch->firstmesh is set only in and for this function, its cleared out elsewhere +*/ +static void RMod_Batches_Generate(model_t *mod) +{ + int i; + msurface_t *surf; + shader_t *shader; + int sortid; + batch_t *batch, *lbatch = NULL; + vec4_t plane; + + //for each surface, find a suitable batch to insert it into. + //we use 'firstmesh' to avoid chucking out too many verts in a single vbo (gl2 hardware tends to have a 16bit limit) + for (i=0; inummodelsurfaces; i++) + { + surf = mod->surfaces + mod->firstmodelsurface + i; + shader = surf->texinfo->texture->shader; + + if (shader) + { + sortid = shader->sort; + + //shaders that are portals need to be split into separate batches to have the same surface planes + if (sortid == SHADER_SORT_PORTAL || (shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT))) + { + if (surf->flags & SURF_PLANEBACK) + { + VectorNegate(surf->plane->normal, plane); + plane[3] = -surf->plane->dist; + } + else + { + VectorCopy(surf->plane->normal, plane); + plane[3] = surf->plane->dist; + } + } + else + { + VectorClear(plane); + plane[3] = 0; + } + } + else + { + sortid = SHADER_SORT_OPAQUE; + VectorClear(plane); + plane[3] = 0; + } + + if (lbatch && (lbatch->texture == surf->texinfo->texture && lbatch->lightmap[0] == surf->lightmaptexturenums[0] && Vector4Compare(plane, lbatch->plane) && lbatch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES) && + lbatch->lightmap[1] == surf->lightmaptexturenums[1] && + lbatch->lightmap[2] == surf->lightmaptexturenums[2] && + lbatch->lightmap[3] == surf->lightmaptexturenums[3]) + batch = lbatch; + else + { + for (batch = mod->batches[sortid]; batch; batch = batch->next) + { + if (batch->texture == surf->texinfo->texture && batch->lightmap[0] == surf->lightmaptexturenums[0] && Vector4Compare(plane, batch->plane) && batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES && + batch->lightmap[1] == surf->lightmaptexturenums[1] && + batch->lightmap[2] == surf->lightmaptexturenums[2] && + batch->lightmap[3] == surf->lightmaptexturenums[3]) + break; + } + } + if (!batch) + { + batch = Hunk_AllocName(sizeof(*batch), "batch"); + batch->lightmap[0] = surf->lightmaptexturenums[0]; + batch->lightmap[1] = surf->lightmaptexturenums[1]; + batch->lightmap[2] = surf->lightmaptexturenums[2]; + batch->lightmap[3] = surf->lightmaptexturenums[3]; + batch->texture = surf->texinfo->texture; + batch->next = mod->batches[sortid]; + batch->ent = &r_worldentity; + Vector4Copy(plane, batch->plane); + + mod->batches[sortid] = batch; + } + + surf->sbatch = batch; //let the surface know which batch its in + batch->maxmeshes++; + batch->firstmesh += surf->mesh->numvertexes; + + lbatch = batch; + } +} + +typedef struct +{ + int allocated[LMBLOCK_WIDTH]; + int lmnum; +} lmalloc_t; +static void RMod_LightmapAllocInit(lmalloc_t *lmallocator) +{ + memset(lmallocator, 0, sizeof(*lmallocator)); +} +static void RMod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod) +{ + mod->lightmaps.first = 1; + mod->lightmaps.count = lmallocator->lmnum; +} +static void RMod_LightmapAllocBlock(lmalloc_t *lmallocator, int w, int h, unsigned short *x, unsigned short *y, int *tnum) +{ + int best, best2; + int i, j; + + if (!lmallocator->lmnum) + lmallocator->lmnum = 1; + + for(;;) + { + best = LMBLOCK_HEIGHT; + + for (i = 0; i <= LMBLOCK_WIDTH - w; i++) + { + best2 = 0; + + for (j=0; j < w; j++) + { + if (lmallocator->allocated[i+j] >= best) + break; + if (lmallocator->allocated[i+j] > best2) + best2 = lmallocator->allocated[i+j]; + } + if (j == w) + { // this is a valid spot + *x = i; + *y = best = best2; + } + } + + if (best + h > LMBLOCK_HEIGHT) + { + memset(lmallocator->allocated, 0, sizeof(lmallocator->allocated)); + lmallocator->lmnum++; + continue; + } + + for (i=0; i < w; i++) + lmallocator->allocated[*x + i] = best + h; + + *tnum = lmallocator->lmnum; + break; + } +} + +static void RMod_LightmapAllocSurf(lmalloc_t *lmallocator, msurface_t *surf, int surfstyle) +{ + int smax, tmax; + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + + if (isDedicated || + (surf->texinfo->texture->shader && !(surf->texinfo->texture->shader->flags & SHADER_HASLIGHTMAP)) || //fte + (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) || //q1 + (surf->texinfo->flags & TEX_SPECIAL) || //the original 'no lightmap' + (surf->texinfo->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP)) || //q2 surfaces + smax > LMBLOCK_WIDTH || tmax > LMBLOCK_HEIGHT || smax < 0 || tmax < 0) //bugs/bounds/etc + { + surf->lightmaptexturenums[surfstyle] = -1; + return; + } + + RMod_LightmapAllocBlock (lmallocator, smax, tmax, &surf->light_s[surfstyle], &surf->light_t[surfstyle], &surf->lightmaptexturenums[surfstyle]); +} + +static void RMod_Batches_SplitLightmaps(model_t *mod) +{ + batch_t *batch; + batch_t *nb; + int i, j, sortid; + msurface_t *surf; + int sty; + + + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + surf = (msurface_t*)batch->mesh[0]; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + batch->lightmap[sty] = surf->lightmaptexturenums[sty]; + batch->lightstyle[sty] = surf->styles[sty]; + } + + for (j = 1; j < batch->maxmeshes; j++) + { + surf = (msurface_t*)batch->mesh[j]; + if (surf->lightmaptexturenums[0] != batch->lightmap[0] || + surf->lightmaptexturenums[1] != batch->lightmap[1] || + surf->lightmaptexturenums[2] != batch->lightmap[2] || + surf->lightmaptexturenums[3] != batch->lightmap[3] || + //fixme: we should merge later (reverted matching) surfaces into the prior batch + surf->styles[0] != batch->lightstyle[0] || + surf->styles[1] != batch->lightstyle[1] || + surf->styles[2] != batch->lightstyle[2] || + surf->styles[3] != batch->lightstyle[3] ) + { + nb = Hunk_AllocName(sizeof(*batch), "batch"); + *nb = *batch; + batch->next = nb; + + nb->mesh = batch->mesh + j*2; + nb->maxmeshes = batch->maxmeshes - j; + batch->maxmeshes = j; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + nb->lightmap[sty] = surf->lightmaptexturenums[sty]; + nb->lightstyle[sty] = surf->styles[sty]; + } + + memmove(nb->mesh, batch->mesh+j, sizeof(msurface_t*)*nb->maxmeshes); + + for (i = 0; i < nb->maxmeshes; i++) + { + surf = (msurface_t*)nb->mesh[i]; + surf->sbatch = nb; + } + + batch = nb; + j = 1; + } + } + } +} + +/* +allocates lightmaps and splits batches upon lightmap boundaries +*/ +static void RMod_Batches_AllocLightmaps(model_t *mod) +{ + batch_t *batch; + batch_t *nb; + lmalloc_t lmallocator; + int i, j, sortid; + msurface_t *surf; + int sty; + + RMod_LightmapAllocInit(&lmallocator); + + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + surf = (msurface_t*)batch->mesh[0]; + RMod_LightmapAllocSurf (&lmallocator, surf, 0); + for (sty = 1; sty < MAXLIGHTMAPS; sty++) + surf->lightmaptexturenums[sty] = -1; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + batch->lightmap[sty] = surf->lightmaptexturenums[sty]; + batch->lightstyle[sty] = 255;//don't do special backend rendering of lightstyles. + } + + for (j = 1; j < batch->maxmeshes; j++) + { + surf = (msurface_t*)batch->mesh[j]; + RMod_LightmapAllocSurf (&lmallocator, surf, 0); + for (sty = 1; sty < MAXLIGHTMAPS; sty++) + surf->lightmaptexturenums[sty] = -1; + if (surf->lightmaptexturenums[0] != batch->lightmap[0]) + { + nb = Hunk_AllocName(sizeof(*batch), "batch"); + *nb = *batch; + batch->next = nb; + + nb->mesh = batch->mesh + j*2; + nb->maxmeshes = batch->maxmeshes - j; + batch->maxmeshes = j; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + nb->lightmap[sty] = surf->lightmaptexturenums[sty]; + + memmove(nb->mesh, batch->mesh+j, sizeof(msurface_t*)*nb->maxmeshes); + + for (i = 0; i < nb->maxmeshes; i++) + { + surf = (msurface_t*)nb->mesh[i]; + surf->sbatch = nb; + } + + batch = nb; + j = 0; + } + } + } + + RMod_LightmapAllocDone(&lmallocator, mod); +} + +extern void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift); +//if build is NULL, uses q1/q2 surf generation, and allocates lightmaps +void RMod_Batches_Build(mesh_t *meshlist, model_t *mod, void (*build)(model_t *mod, msurface_t *surf, void *cookie), void *buildcookie) +{ + int i; + int numverts = 0, numindicies=0; + msurface_t *surf; + mesh_t *mesh; + mesh_t **bmeshes; + int sortid; + batch_t *batch; + + currentmodel = mod; + + if (meshlist) + meshlist += mod->firstmodelsurface; + else if (!build) + meshlist = Hunk_Alloc(sizeof(mesh_t) * mod->nummodelsurfaces); + + for (i=0; inummodelsurfaces; i++) + { + surf = mod->surfaces + i + mod->firstmodelsurface; + if (meshlist) + { + mesh = surf->mesh = &meshlist[i]; + mesh->numvertexes = surf->numedges; + mesh->numindexes = (surf->numedges-2)*3; + } + else + mesh = surf->mesh; + + numverts += mesh->numvertexes; + numindicies += mesh->numindexes; +// surf->lightmaptexturenum = -1; + } + + /*assign each mesh to a batch, generating as needed*/ + RMod_Batches_Generate(mod); + + bmeshes = Hunk_AllocName(sizeof(*bmeshes)*mod->nummodelsurfaces*2, "batchmeshes"); + + //we now know which batch each surface is in, and how many meshes there are in each batch. + //allocate the mesh-pointer-lists for each batch. *2 for recursion. + for (i = 0, sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + batch->mesh = bmeshes + i; + i += batch->maxmeshes*2; + } + //store the *surface* into the batch's mesh list (yes, this is an evil cast hack, but at least both are pointers) + for (i=0; inummodelsurfaces; i++) + { + surf = mod->surfaces + mod->firstmodelsurface + i; + surf->sbatch->mesh[surf->sbatch->meshes++] = (mesh_t*)surf; + } + if (build) + RMod_Batches_SplitLightmaps(mod); + else + RMod_Batches_AllocLightmaps(mod); + + if (!build) + build = RModQ1_Batches_BuildQ1Q2Poly; + RMod_Batches_BuildModelMeshes(mod, numverts, numindicies, build, buildcookie); + + if (BE_GenBrushModelVBO) + BE_GenBrushModelVBO(mod); +} + /* ================= @@ -3181,6 +3727,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) int start; qboolean noerrors; qboolean longm = false; + mesh_t *meshlist = NULL; #if (defined(ODE_STATIC) || defined(ODE_DYNAMIC)) qboolean ode = true; #else @@ -3223,6 +3770,9 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) return false; } + mod->lightmaps.width = LMBLOCK_WIDTH; + mod->lightmaps.height = LMBLOCK_HEIGHT; + // swap all the lumps mod_base = (qbyte *)header; @@ -3299,7 +3849,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) if (!isDedicated || ode) { noerrors = noerrors && RMod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); - noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm); + noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm, &meshlist); } if (!isDedicated) noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES], longm); @@ -3373,6 +3923,13 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) mod->numleafs = bm->visleafs; + memset(&mod->batches, 0, sizeof(mod->batches)); + mod->vbos = NULL; + if (meshlist) + { + RMod_Batches_Build(meshlist, mod, NULL, NULL); + } + if (i < mod->numsubmodels-1) { // duplicate the basic information char name[10]; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index c5f0acbf..cd53be11 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -69,7 +69,7 @@ typedef struct mesh_s vec3_t *snormals_array;/*required for rtlighting*/ vec3_t *tnormals_array;/*required for rtlighting*/ vec2_t *st_array; /*texture coords*/ - vec2_t *lmst_array; /*second texturecoord set (merely dubbed lightmap)*/ + vec2_t *lmst_array[MAXLIGHTMAPS]; /*second texturecoord set (merely dubbed lightmap, one for each potential lightstyle)*/ avec4_t *colors4f_array;/*floating point colours array*/ byte_vec4_t *colors4b_array;/*byte colours array*/ @@ -102,8 +102,10 @@ typedef struct batch_s shader_t *shader; struct vbo_s *vbo; - int lightmap; /*used for shader lightmap textures*/ entity_t *ent; /*used for shader properties*/ + int lightmap[MAXLIGHTMAPS]; /*used for shader lightmap textures*/ + + unsigned char lightstyle[MAXLIGHTMAPS]; struct texture_s *texture; /*is this used by the backend?*/ struct texnums_s *skin; @@ -120,7 +122,7 @@ typedef struct batch_s unsigned int surf_first; unsigned int surf_count; }; - vec3_t normal; /*used only at load (for portal surfaces, so multiple planes are not part of the same batch)*/ + vec4_t plane; /*used only at load (for portal surfaces, so multiple planes are not part of the same batch)*/ }; } batch_t; /* @@ -240,7 +242,7 @@ typedef struct vboarray_s { union { - int dummy; + void *dummy; #ifdef GLQUAKE struct @@ -278,7 +280,7 @@ typedef struct vbo_s vboarray_t coord; vboarray_t coord2; vboarray_t texcoord; - vboarray_t lmcoord; + vboarray_t lmcoord[MAXLIGHTMAPS]; vboarray_t normals; vboarray_t svector; @@ -395,15 +397,13 @@ typedef struct msurface_s short texturemins[2]; short extents[2]; - int light_s, light_t; // gl lightmap coordinates + unsigned short light_s[MAXLIGHTMAPS], light_t[MAXLIGHTMAPS]; // gl lightmap coordinates mfog_t *fog; mesh_t *mesh; - entity_t *ownerent; batch_t *sbatch; mtexinfo_t *texinfo; - struct msurface_s **mark; int visframe; // should be drawn when node is crossed int shadowframe; @@ -411,7 +411,7 @@ typedef struct msurface_s int dlightframe; int dlightbits; - int lightmaptexturenum; + int lightmaptexturenums[MAXLIGHTMAPS]; //rbsp+fbsp formats have multiple lightmaps qbyte styles[MAXLIGHTMAPS]; int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap qboolean cached_dlight; // true if dynamic light in cache @@ -957,6 +957,13 @@ typedef struct model_s vbo_t *vbos; void *terrain; batch_t *batches[SHADER_SORT_COUNT]; + struct + { + int first; + int count; + int width; + int height; + } lightmaps; unsigned checksum; unsigned checksum2; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index e1f978ce..b79959a6 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -28,7 +28,7 @@ extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; int r_dlightframecount; -int d_lightstylevalue[256]; // 8.8 fraction of base light value +int d_lightstylevalue[MAX_LIGHTSTYLES]; // 8.8 fraction of base light value /* ================== @@ -391,7 +391,10 @@ void R_GenDlightBatches(batch_t *batches[]) b->skin = &lpplight_shader->defaulttextures; b->texture = NULL; b->shader = lpplight_shader; - b->lightmap = -1; + b->lightmap[0] = -1; + b->lightmap[1] = -1; + b->lightmap[2] = -1; + b->lightmap[3] = -1; b->surf_first = i; b->flags |= BEF_NOSHADOWS; b->vbo = NULL; @@ -423,7 +426,7 @@ void R_PushDlights (void) #ifdef RTLIGHTS /*if we're doing full rtlighting only, then don't bother calculating old-style dlights as they won't be visible anyway*/ - if (r_shadow_realtime_world.value && r_shadow_realtime_world_lightmaps.value < 0.1) + if (r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value < 0.1) return; #endif @@ -817,12 +820,9 @@ void R_LoadRTLights(void) dl->coronascale = coronascale; dl->die = 0; dl->flags = flags; - if (ambientscale || diffusescale || specularscale) - { - dl->lightcolourscales[0] = ambientscale; - dl->lightcolourscales[1] = diffusescale; - dl->lightcolourscales[2] = specularscale; - } + dl->lightcolourscales[0] = ambientscale; + dl->lightcolourscales[1] = diffusescale; + dl->lightcolourscales[2] = specularscale; AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); Q_strncpyz(dl->cubemapname, cubename, sizeof(dl->cubemapname)); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 29a9e940..8e812d3c 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -106,6 +106,7 @@ texid_t scenepp_postproc_cube; // processing shaders void GL_InitSceneProcessingShaders_WaterWarp (void) { + scenepp_waterwarp = NULL; if (gl_config.arb_shader_objects) { scenepp_waterwarp = R_RegisterShader("waterwarp", @@ -645,6 +646,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype) refdef_t oldrefdef; mesh_t *mesh = batch->mesh[batch->firstmesh]; int sort; + qbyte newvis[(MAX_MAP_LEAFS+7)/8]; if (r_refdef.recurse) return; @@ -680,9 +682,54 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype) else if (portaltype == 2) { /*refraction image (same view, just with things culled*/ - r_refdef.externalview = false; + r_refdef.externalview = oldrefdef.externalview; VectorNegate(plane.normal, plane.normal); plane.dist = -plane.dist; + + //use the player's origin for r_viewleaf, because there's not much we can do anyway*/ + VectorCopy(r_origin, r_refdef.pvsorigin); + + if (cl.worldmodel && cl.worldmodel->funcs.LeafPVS && !r_novis.ival) + { + int lnum, i, j; + float d; + vec3_t point; + int pvsbytes = (cl.worldmodel->numleafs+7)>>3; + if (pvsbytes > sizeof(newvis)) + pvsbytes = sizeof(newvis); + r_refdef.forcevis = true; + r_refdef.forcedvis = NULL; + for (i = batch->firstmesh; i < batch->meshes; i++) + { + mesh = batch->mesh[i]; + VectorClear(point); + for (j = 0; j < mesh->numvertexes; j++) + VectorAdd(point, mesh->xyz_array[j], point); + VectorScale(point, 1.0f/mesh->numvertexes, point); + d = DotProduct(point, plane.normal) - plane.dist; + d += 0.1; //an epsilon on the far side + VectorMA(point, d, plane.normal, point); + + lnum = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, point); + if (i == batch->firstmesh) + r_refdef.forcedvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, lnum, newvis, sizeof(newvis)); + else + { + if (r_refdef.forcedvis != newvis) + { + memcpy(newvis, r_refdef.forcedvis, pvsbytes); + } + r_refdef.forcedvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, lnum, NULL, sizeof(newvis)); + + for (j = 0; j < pvsbytes; j+= 4) + { + *(int*)&newvis[j] |= *(int*)&r_refdef.forcedvis[j]; + } + r_refdef.forcedvis = newvis; + } + } + memset(newvis, 0xff, pvsbytes); + } } else if (!(view = R_NearestPortal(&plane)) || VectorCompare(view->origin, view->oldorigin)) { @@ -795,7 +842,10 @@ void R_Clear (void) GL_ForceDepthWritable(); { if (r_clear.ival && !r_secondaryview && !(r_refdef.flags & Q2RDF_NOWORLDMODEL)) + { + qglClearColor(1, 0, 0, 0); qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } else qglClear (GL_DEPTH_BUFFER_BIT); gldepthmin = 0; diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 5b62689e..cd14065f 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -28,15 +28,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void GLBE_ClearVBO(vbo_t *vbo) { - int vboh[7]; + int vboh[6 + MAXLIGHTMAPS]; int i, j; vboh[0] = vbo->indicies.gl.vbo; vboh[1] = vbo->coord.gl.vbo; vboh[2] = vbo->texcoord.gl.vbo; - vboh[3] = vbo->lmcoord.gl.vbo; - vboh[4] = vbo->normals.gl.vbo; - vboh[5] = vbo->svector.gl.vbo; - vboh[6] = vbo->tvector.gl.vbo; + vboh[3] = vbo->normals.gl.vbo; + vboh[4] = vbo->svector.gl.vbo; + vboh[5] = vbo->tvector.gl.vbo; + for (i = 0; i < MAXLIGHTMAPS; i++) + vboh[6+i] = vbo->lmcoord[i].gl.vbo; for (i = 0; i < 7; i++) { @@ -53,7 +54,7 @@ void GLBE_ClearVBO(vbo_t *vbo) if (vbo->vertdata) BZ_Free(vbo->vertdata); BZ_Free(vbo->meshlist); - memset(vbo, 0, sizeof(*vbo)); + BZ_Free(vbo); } void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic); @@ -61,6 +62,7 @@ void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic); static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize, unsigned int vaodynamic) { unsigned int vbos[2]; + int s; if (!qglGenBuffersARB) return false; @@ -84,10 +86,13 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int vbo->texcoord.gl.vbo = vbos[0]; vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata); } - if (vbo->lmcoord.gl.addr) + for (s = 0; s < MAXLIGHTMAPS; s++) { - vbo->lmcoord.gl.vbo = vbos[0]; - vbo->lmcoord.gl.addr = (vec2_t*)((char*)vbo->lmcoord.gl.addr - (char*)vdata); + if (vbo->lmcoord[s].gl.addr) + { + vbo->lmcoord[s].gl.vbo = vbos[0]; + vbo->lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata); + } } if (vbo->normals.gl.addr) { @@ -136,7 +141,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch unsigned int maxvboverts; unsigned int maxvboelements; - unsigned int i; + unsigned int i, s; unsigned int v; unsigned int vcount, ecount; unsigned int pervertsize; //erm, that name wasn't intentional @@ -148,7 +153,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch vecV_t *coord; vec2_t *texcoord; - vec2_t *lmcoord; + vec2_t *lmcoord[MAXLIGHTMAPS]; vec3_t *normals; vec3_t *svector; vec3_t *tvector; @@ -164,7 +169,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch meshes = 0; for(batch = firstbatch; batch != stopbatch; batch = batch->next) { - for (i=0 ; imeshes ; i++) + for (i=0 ; imaxmeshes ; i++) { m = batch->mesh[i]; meshes++; @@ -181,7 +186,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch pervertsize = sizeof(vecV_t)+ //coord sizeof(vec2_t)+ //tex - sizeof(vec2_t)+ //lm + sizeof(vec2_t)*MAXLIGHTMAPS+ //lm sizeof(vec3_t)+ //normal sizeof(vec3_t)+ //sdir sizeof(vec3_t)+ //tdir @@ -193,7 +198,8 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t)); vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); - vbo->lmcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + for (s = 0; s < MAXLIGHTMAPS; s++) + vbo->lmcoord[s].gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); @@ -202,7 +208,8 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch coord = vbo->coord.gl.addr; texcoord = vbo->texcoord.gl.addr; - lmcoord = vbo->lmcoord.gl.addr; + for (s = 0; s < 4; s++) + lmcoord[s] = vbo->lmcoord[s].gl.addr; normals = vbo->normals.gl.addr; svector = vbo->svector.gl.addr; tvector = vbo->tvector.gl.addr; @@ -218,7 +225,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch for(batch = firstbatch; batch != stopbatch; batch = batch->next) { batch->vbo = vbo; - for (i=0 ; imeshes ; i++) + for (i=0 ; imaxmeshes ; i++) { m = batch->mesh[i]; @@ -239,10 +246,13 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch texcoord[vcount+v][0] = m->st_array[v][0]; texcoord[vcount+v][1] = m->st_array[v][1]; } - if (m->lmst_array) + for (s = 0; s < MAXLIGHTMAPS; s++) { - lmcoord[vcount+v][0] = m->lmst_array[v][0]; - lmcoord[vcount+v][1] = m->lmst_array[v][1]; + if (m->lmst_array[s]) + { + lmcoord[s][vcount+v][0] = m->lmst_array[s][v][0]; + lmcoord[s][vcount+v][1] = m->lmst_array[s][v][1]; + } } if (m->normals_array) { @@ -291,6 +301,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) batch_t *batch, *fbatch; int sortid; + int i; fbatch = NULL; vcount = 0; @@ -308,11 +319,14 @@ void GLBE_GenBrushModelVBO(model_t *mod) fbatch = batch; vcount = 0; } - vcount += batch->firstmesh; + + for (i = 0; i < batch->maxmeshes; i++) + vcount += batch->mesh[i]->numvertexes; } - + GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch); } + #if 0 if (!mod->numsurfaces) return; @@ -455,6 +469,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) void GLBE_UploadAllLightmaps(void) { + lightmapinfo_t *lm; int i; // // upload all lightmaps that were filled @@ -463,48 +478,50 @@ void GLBE_UploadAllLightmaps(void) { if (!lightmap[i]) break; // no more used - lightmap[i]->rectchange.l = LMBLOCK_WIDTH; - lightmap[i]->rectchange.t = LMBLOCK_HEIGHT; - lightmap[i]->rectchange.w = 0; - lightmap[i]->rectchange.h = 0; - if (!lightmap[i]->modified) + lm = lightmap[i]; + lm->rectchange.l = lm->width; + lm->rectchange.t = lm->height; + lm->rectchange.w = 0; + lm->rectchange.h = 0; + if (!lm->modified) continue; - lightmap[i]->modified = false; - GL_MTBind(0, GL_TEXTURE_2D, lightmap_textures[i]); + lm->modified = false; + GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch (lightmap_bytes) { case 4: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, + lm->width, lm->height, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, lightmap[i]->lightmaps); break; case 3: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, + lm->width, lm->height, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break; case 1: qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, - LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + lm->width, lm->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break; } if (r_deluxemapping.ival) { lightmap[i]->deluxmodified = false; - lightmap[i]->deluxrectchange.l = LMBLOCK_WIDTH; - lightmap[i]->deluxrectchange.t = LMBLOCK_HEIGHT; + lightmap[i]->deluxrectchange.l = lm->width; + lightmap[i]->deluxrectchange.t = lm->height; lightmap[i]->deluxrectchange.w = 0; lightmap[i]->deluxrectchange.h = 0; - GL_MTBind(0, GL_TEXTURE_2D, deluxmap_textures[i]); + GL_MTBind(0, GL_TEXTURE_2D, lm->deluxmap_texture); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexImage2D (GL_TEXTURE_2D, 0, 3 - , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, + , lm->width, lm->height, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->deluxmaps); } } } + #endif diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index d9715d11..2bc2c079 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -811,6 +811,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip "#define SKELETAL\n", "#define FOG\n", "#define FRAMEBLEND\n", + "#define LIGHTSTYLED\n", NULL }; char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0]) + 64 + 1]; @@ -1599,6 +1600,9 @@ struct shader_field_names_s shader_attr_names[] = {"v_tvector", VATTR_TNORMALS}, {"v_bone", VATTR_BONENUMS}, {"v_weight", VATTR_BONEWEIGHTS}, + {"v_lmcoord2", VATTR_LMCOORD2}, + {"v_lmcoord3", VATTR_LMCOORD3}, + {"v_lmcoord4", VATTR_LMCOORD4}, {NULL} }; @@ -3147,6 +3151,8 @@ void Shader_Shutdown (void) } } + Shader_FlushGenerics(); + free(r_shaders); r_shaders = NULL; free(shader_hash); @@ -3448,6 +3454,8 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) } else return; + if (pass->texgen == T_GEN_LIGHTMAP && pass->blendmode == PBM_REPLACELIGHT && pass2->blendmode == PBM_MODULATE && config_tex_env_combine) + pass2->blendmode = PBM_OVERBRIGHT; if (pass2->texgen == T_GEN_LIGHTMAP && pass2->blendmode == PBM_MODULATE && config_tex_env_combine) pass2->blendmode = PBM_OVERBRIGHT; } @@ -4020,7 +4028,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) if (!builtin) builtin = ( "{\n" - "if $deluxmap\n" +/* "if $deluxmap\n" "[\n" "{\n" "map $normalmap\n" @@ -4032,21 +4040,25 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "tcgen lightmap\n" "}\n" "]\n" +*/// "if !r_fullbright\n" +// "[\n" + "{\n" + "map $lightmap\n" +// "if $deluxmap\n" +// "[\n" +// "blendfunc gl_dst_color gl_zero\n" +// "]\n" + "}\n" +// "]\n" "{\n" "map $diffuse\n" "tcgen base\n" - "if $deluxmap\n" - "[\n" - "blendfunc gl_one gl_zero\n" - "]\n" +// "if $deluxmap || !r_fullbright\n" +// "[\n" +// "blendfunc gl_dst_color gl_zero\n" + "blendfunc filter\n" +// "]\n" "}\n" - "if !r_fullbright\n" - "[\n" - "{\n" - "map $lightmap\n" - "blendfunc gl_dst_color gl_zero\n" - "}\n" - "]\n" "if gl_fb_bmodels\n" "[\n" "{\n" @@ -4086,6 +4098,115 @@ void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args) ); } +char *Shader_DefaultBSPWater(char *shortname) +{ + int wstyle; + if (r_wateralpha.value == 0) + wstyle = -1; + else if (r_fastturb.ival) + wstyle = 0; +#ifdef GLQUAKE + else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && r_waterstyle.ival>0 && !r_fastturb.ival && strncmp(shortname, "*lava", 5)) + wstyle = r_waterstyle.ival; //r_waterstyle does not apply to lava, and requires glsl and stuff +#endif + else + wstyle = 1; + + { + switch(wstyle) + { + case -1: //invisible + return ( + "{\n" + "sort blend\n" + "surfaceparm nodraw\n" + "surfaceparm nodlight\n" + "}\n" + ); + case 0: //fastturb + return ( + "{\n" + "sort blend\n" + "{\n" + "map $whiteimage\n" + "rgbgen const $r_fastturbcolour\n" + "}\n" + "surfaceparm nodlight\n" + "}\n" + ); + default: + case 1: //vanilla style + return ( + "{\n" + "sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/ + "program defaultwarp\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0.02 0.1 0.5 0.1\n" + "if r_wateralpha != 1\n" + "[\n" + "alphagen const $r_wateralpha\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" + "]\n" + "}\n" + "surfaceparm nodlight\n" + "}\n" + ); + case 2: //refraction of the underwater surface, with a fresnel + return ( + "{\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" + "program altwater#FRESNEL=4\n" + "}\n" + ); + case 3: //ripples + return ( + "{\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" + "{\n" + "map $ripplemap\n" + "}\n" + "program altwater#RIPPLEMAP#FRESNEL=4\n" + "}\n" + ); + case 4: //reflections + return ( + "{\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $reflection\n" + "}\n" + "{\n" + "map $ripplemap\n" + "}\n" + "program altwater#REFLECT#RIPPLEMAP#FRESNEL=4\n" + "}\n" + ); + } + } +} + void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args) { if (!strncmp(shortname, "sky/", 4)) @@ -4099,15 +4220,7 @@ void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args) } else if (!strncmp(shortname, "warp/", 5)) { - Shader_DefaultScript(shortname, s, - "{\n" - "program defaultwarp\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0 0.01 0.5 0\n" - "}\n" - "}\n" - ); + Shader_DefaultScript(shortname, s, Shader_DefaultBSPWater(shortname)); } else if (!strncmp(shortname, "warp33/", 7)) { @@ -4204,115 +4317,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) if (!builtin && (*shortname == '*')) { - int wstyle; - if (r_wateralpha.value == 0) - wstyle = -1; - else if (r_fastturb.ival) - wstyle = 0; - else if (gl_config.arb_shader_objects && r_waterstyle.ival>0 && !r_fastturb.ival && strncmp(shortname, "*lava", 5)) - wstyle = r_waterstyle.ival; //r_waterstyle does not apply to lava, and requires glsl and stuff - else - wstyle = 1; - - { - switch(wstyle) - { - case -1: //invisible - builtin = ( - "{\n" - "sort blend\n" - "surfaceparm nodraw\n" - "surfaceparm nodlight\n" - "}\n" - ); - break; - case 0: //fastturb - builtin = ( - "{\n" - "sort blend\n" - "{\n" - "map $whiteimage\n" - "rgbgen const $r_fastturbcolour\n" - "}\n" - "surfaceparm nodlight\n" - "}\n" - ); - break; - default: - case 1: //vanilla style - builtin = ( - "{\n" - "sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/ - "program defaultwarp\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0.02 0.1 0.5 0.1\n" - "if r_wateralpha != 1\n" - "[\n" - "alphagen const $r_wateralpha\n" - "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" - "]\n" - "}\n" - "surfaceparm nodlight\n" - "}\n" - ); - break; - case 2: //refraction of the underwater surface, with a fresnel - builtin = ( - "{\n" - "{\n" - "map $currentrender\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $diffuse\n" - "}\n" - "program altwater#FRESNEL=4\n" - "}\n" - ); - break; - case 3: //ripples - builtin = ( - "{\n" - "{\n" - "map $currentrender\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $diffuse\n" - "}\n" - "{\n" - "map $ripplemap\n" - "}\n" - "program altwater#RIPPLEMAP#FRESNEL=4\n" - "}\n" - ); - break; - case 4: //reflections - builtin = ( - "{\n" - "{\n" - "map $currentrender\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $reflection\n" - "}\n" - "{\n" - "map $ripplemap\n" - "}\n" - "program altwater#REFLECT#RIPPLEMAP#FRESNEL=4\n" - "}\n" - ); - break; - } - } + builtin = Shader_DefaultBSPWater(shortname); } if (!builtin && !strncmp(shortname, "sky", 3)) { diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 5786ae73..c16c15c0 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1,5 +1,11 @@ #include "quakedef.h" +/* +room for improvement: +There is no screen-space culling of lit surfaces. +model meshes are interpolated multiple times per frame +*/ + #if defined(GLQUAKE) || defined(D3DQUAKE) #ifdef RTLIGHTS @@ -1098,6 +1104,7 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) int i, e; mesh_t *sm; vec3_t ext; + float sc; cv.numedges = 0; cv.numpoints = 0; cv.numtris = 0; @@ -1107,7 +1114,7 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) sms = &sh_shmesh->batches[tno]; if (!sms->count) continue; - if ((cl.worldmodel->textures[tno]->shader->flags & (SHADER_BLEND|SHADER_NODRAW))) + if ((cl.worldmodel->shadowbatches[tno].tex->shader->flags & (SHADER_BLEND|SHADER_NODRAW))) continue; for (sno = 0; sno < sms->count; sno++) @@ -1150,12 +1157,13 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) ext[0] = cv.points[i][0]-dl->origin[0]; ext[1] = cv.points[i][1]-dl->origin[1]; ext[2] = cv.points[i][2]-dl->origin[2]; - VectorNormalize(ext); + + sc = dl->radius * VectorNormalize(ext); /*back face*/ - sh_shmesh->verts[(i * 2) + 1][0] = cv.points[i][0] + ext[0] * dl->radius; - sh_shmesh->verts[(i * 2) + 1][1] = cv.points[i][1] + ext[1] * dl->radius; - sh_shmesh->verts[(i * 2) + 1][2] = cv.points[i][2] + ext[2] * dl->radius; + sh_shmesh->verts[(i * 2) + 1][0] = cv.points[i][0] + ext[0] * sc; + sh_shmesh->verts[(i * 2) + 1][1] = cv.points[i][1] + ext[1] * sc; + sh_shmesh->verts[(i * 2) + 1][2] = cv.points[i][2] + ext[2] * sc; } sh_shmesh->numverts = i*2; @@ -1229,7 +1237,7 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi { case fg_quake: case fg_halflife: - if (!dl->die) + /*if (!dl->die) { SHM_BeginShadowMesh(dl, true); SHM_MarkLeavesQ1(dl, lvis); @@ -1237,7 +1245,7 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi if (!surfonly) SHM_ComposeVolume_BruteForce(dl); } - else + else*/ { SHM_BeginShadowMesh(dl, surfonly); SHM_MarkLeavesQ1(dl, lvis); @@ -1373,41 +1381,6 @@ typedef struct } srect_t; static void Sh_Scissor (srect_t r) { -#if 0 //visible scissors - extern cvar_t temp1; - if (temp1.ival) - { - qglMatrixMode(GL_PROJECTION); - qglPushMatrix(); - qglLoadIdentity(); - qglOrtho (0, vid.pixelwidth, vid.pixelheight, 0, -99999, 99999); - qglMatrixMode(GL_MODELVIEW); - qglPushMatrix(); - qglLoadIdentity(); - // GL_Set2D(); - - qglColor4f(1,1,1,1); - qglDisable(GL_DEPTH_TEST); - qglDisable(GL_SCISSOR_TEST); - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE ); - qglDisable(GL_TEXTURE_2D); - - qglBegin(GL_LINE_LOOP); - qglVertex2f(r.x, vid.pixelheight - (r.y + r.height)); - qglVertex2f(r.x+r.width, vid.pixelheight - (r.y + r.height)); - qglVertex2f(r.x+r.width, vid.pixelheight - (r.y)); - qglVertex2f(r.x, vid.pixelheight - (r.y)); - qglEnd(); - - qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - - qglMatrixMode(GL_PROJECTION); - qglPopMatrix(); - qglMatrixMode(GL_MODELVIEW); - qglPopMatrix(); - } -#endif - switch(qrenderer) { #ifdef GLQUAKE @@ -1516,7 +1489,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r) r->height = vid.pixelheight; r->dmin = 0; r->dmax = 1; - if (1)//!r_shadow_scissor.integer) + if (0)//!r_shadow_scissor.integer) { return false; } @@ -2332,11 +2305,6 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q struct shadowmesh_s *sm; entity_t *ent; -#ifdef GLQUAKE - if (qrenderer == QR_OPENGL) - BE_PushOffsetShadow(false); -#endif - sm = SHM_BuildShadowMesh(dl, lvis, vvis, false); if (!sm) Sh_DrawBrushModelShadow(dl, &r_worldentity); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 631ee427..1455ed59 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -592,8 +592,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglActiveStencilFaceEXT = (void *) getglext("glActiveStencilFaceEXT"); /*not enabled - its only useful for shadow volumes, but (on nvidia) it affects the depth values even when not clamped which results in shadow z-fighting. best rely upon infinite projection matricies instead*/ -// if (GL_CheckExtension("GL_ARB_depth_clamp") || GL_CheckExtension("GL_NV_depth_clamp")) -// gl_config.arb_depth_clamp = true; + if (GL_CheckExtension("GL_ARB_depth_clamp") || GL_CheckExtension("GL_NV_depth_clamp")) + gl_config.arb_depth_clamp = true; if (GL_CheckExtension("GL_ARB_texture_compression")) { @@ -608,14 +608,14 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) else gl_config.arb_texture_compression = true; } - +/* if (GL_CheckExtension("GL_EXT_depth_bounds_test")) qglDepthBoundsEXT = (void *)getglext("glDepthBoundsEXT"); else if (GL_CheckExtension("GL_NV_depth_bounds_test")) qglDepthBoundsEXT = (void *)getglext("glDepthBoundsNV"); else qglDepthBoundsEXT = NULL; - +*/ if (GL_CheckExtension("GL_ATI_pn_triangles")) { qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI"); @@ -666,10 +666,14 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB"); } + if (0 && !gl_config.nofixedfunc) + { + Con_Printf(CON_NOTICE "GLSL disabled\n"); + } // glslang //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //but our code kinda requires both for clean workings. - if (strstr(gl_renderer, " Mesa ") && Cvar_Get("gl_blacklist_mesa_glsl", "1", CVAR_RENDERERLATCH, "gl blacklists")->ival && (gl_config.glversion < 3 || gl_config.gles)) + else if (strstr(gl_renderer, " Mesa ") && (gl_config.glversion < 3 || gl_config.gles) && Cvar_Get("gl_blacklist_mesa_glsl", "1", CVAR_RENDERERLATCH, "gl blacklists")->ival) { //(9:12:33 PM) bigfoot: Spike, can you please blacklist your menu shader on Mesa? My machine just hard locked up again because I forgot that pressing escape in FTE is verboten //(11:51:42 PM) bigfoot: OpenGL vendor string: Tungsten Graphics, Inc @@ -936,7 +940,7 @@ static const char *glsl_hdrs[] = "{\n" "#if defined(RELIEFMAPPING) && !defined(GL_ES)\n" "float i, f;\n" - "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * vec2(1.0, -1.0), -1.0);\n" + "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * vec2(-1.0, 1.0), -1.0);\n" "vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n" "OffsetVector /= 10.0;\n" "for(i = 1.0; i < 10.0; ++i)\n" @@ -1073,6 +1077,10 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan length[strings] = strlen(prstrings[strings]); strings++; + //prstrings[strings] = "invariant gl_Position;\n"; + //length[strings] = strlen(prstrings[strings]); + //strings++; + switch (shadertype) { case GL_FRAGMENT_SHADER_ARB: @@ -1244,6 +1252,9 @@ GLhandleARB GLSlang_CreateProgramObject (char *name, GLhandleARB vert, GLhandleA qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour"); qglBindAttribLocationARB(program, VATTR_TEXCOORD, "v_texcoord"); qglBindAttribLocationARB(program, VATTR_LMCOORD, "v_lmcoord"); + qglBindAttribLocationARB(program, VATTR_LMCOORD2, "v_lmcoord2"); + qglBindAttribLocationARB(program, VATTR_LMCOORD3, "v_lmcoord3"); + qglBindAttribLocationARB(program, VATTR_LMCOORD4, "v_lmcoord4"); qglBindAttribLocationARB(program, VATTR_NORMALS, "v_normal"); qglBindAttribLocationARB(program, VATTR_SNORMALS, "v_svector"); qglBindAttribLocationARB(program, VATTR_TNORMALS, "v_tvector"); diff --git a/engine/gl/gl_viddroid.c b/engine/gl/gl_viddroid.c index f4f33626..d12febd1 100644 --- a/engine/gl/gl_viddroid.c +++ b/engine/gl/gl_viddroid.c @@ -20,11 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "glquake.h" -#ifdef GL_ES_VERSION_2_0 -qboolean gles2 = true; -#else -qboolean gles2 = false; -#endif +extern qboolean sys_glesversion; static dllhandle_t *sys_gl_module = NULL; @@ -89,11 +85,11 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) Cons: GL_EndRendering call will not swap buffers. Buffers will be swapped on return to java. */ - if (gles2) + if (sys_glesversion >= 2) Sys_Printf("Loading GLES2 driver\n"); else Sys_Printf("Loading GLES1 driver\n"); - sys_gl_module = Sys_LoadLibrary(gles2?"libGLESv2.so":"libGLESv1_CM.so", NULL); + sys_gl_module = Sys_LoadLibrary((sys_glesversion>=2)?"libGLESv2.so":"libGLESv1_CM.so", NULL); if (!sys_gl_module) { GLVID_DeInit(); @@ -143,7 +139,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) gl_canstencil = 0; const EGLint attribs[] = { - EGL_RENDERABLE_TYPE, gles2?EGL_OPENGL_ES2_BIT:EGL_OPENGL_ES_BIT, + EGL_RENDERABLE_TYPE, (sys_glesversion>=2)?EGL_OPENGL_ES2_BIT:EGL_OPENGL_ES_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, (info->bpp==16)?5:8, EGL_GREEN_SIZE, (info->bpp==16)?6:8, @@ -152,12 +148,12 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) // EGL_STENCIL_SIZE, 8, EGL_NONE }; - EGLint ctxattribs[] = {EGL_CONTEXT_CLIENT_VERSION, gles2?2:1, EGL_NONE}; + EGLint ctxattribs[] = {EGL_CONTEXT_CLIENT_VERSION, sys_glesversion, EGL_NONE}; EGLint w, h, dummy, format; EGLint numConfigs; EGLConfig config; - sys_gl_module = Sys_LoadLibrary(gles2?"libGLESv2.so":"libGLESv1_CM.so", NULL); + sys_gl_module = Sys_LoadLibrary((sys_glesversion>=2)?"libGLESv2.so":"libGLESv1_CM.so", NULL); if (!sys_gl_module) { GLVID_DeInit(); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 4b958686..d6c79afb 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.h" #include "winquake.h" #include "resource.h" +#include "shader.h" #include #ifndef SetWindowLongPtr //yes its a define, for unicode support @@ -1476,6 +1477,7 @@ void GLVID_Shutdown (void) gammaworks = false; + GLBE_Shutdown(); VID_UnSetMode(); } @@ -1715,11 +1717,13 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize) ****************************************************************************/ { static BOOL sound_active; + HWND foregroundwindow; if (ActiveApp == fActive && Minimized == minimize) return false; //so windows doesn't crash us over and over again. - ActiveApp = fActive; + foregroundwindow = GetForegroundWindow(); + ActiveApp = fActive;// && (foregroundwindow==mainwindow); Minimized = minimize; // enable/disable sound on focus gain/loss @@ -1954,7 +1958,7 @@ LONG WINAPI GLMainWndProc ( case WM_ACTIVATE: fActive = LOWORD(wParam); fMinimized = (BOOL) HIWORD(wParam); - if (!GLAppActivate(!(fActive == WA_INACTIVE), fMinimized)) +// if (!GLAppActivate(!(fActive == WA_INACTIVE), fMinimized)) break;//so, urm, tell me microsoft, what changed? if (modestate == MS_FULLDIB) ShowWindow(mainwindow, SW_SHOWNORMAL); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 48ffeb0f..3de7b1e5 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -89,7 +89,7 @@ void R_DrawSkyChain (batch_t *batch) return; } #if defined(GLQUAKE) && !defined(ANDROID) - if (*r_fastsky.string && qrenderer == QR_OPENGL && TEXVALID(batch->shader->defaulttextures.base)) + if (*r_fastsky.string && qrenderer == QR_OPENGL && TEXVALID(batch->shader->defaulttextures.base) && TEXVALID(batch->shader->defaulttextures.fullbright)) { R_CalcSkyChainBounds(batch); @@ -397,15 +397,15 @@ static void gl_skyspherecalc(int skytype) skymesh.indexes = skysphere_element3i; skymesh.st_array = (void*)skysphere_texcoord2f; - skymesh.lmst_array = (void*)skysphere_texcoord2f; + skymesh.lmst_array[0] = (void*)skysphere_texcoord2f; skymesh.xyz_array = (void*)skysphere_vertex3f; skymesh.numindexes = skysphere_numtriangles * 3; skymesh.numvertexes = skysphere_numverts; - dx = 16; - dy = 16; - dz = 16 / 3; + dx = 1; + dy = 1; + dz = 1 / 3.0; vertex = skysphere_vertex3f; texcoord2f = skysphere_texcoord2f; for (j = 0;j <= skygridy;j++) @@ -487,6 +487,7 @@ static void R_DrawSkyMesh(batch_t *batch, mesh_t *m, shader_t *shader) b.shader = shader; b.skin = &shader->defaulttextures; b.texture = NULL; + b.vbo = NULL; BE_SubmitBatch(&b); } diff --git a/engine/gl/glmod_doom.c b/engine/gl/glmod_doom.c index f410cf42..d6ec58a1 100644 --- a/engine/gl/glmod_doom.c +++ b/engine/gl/glmod_doom.c @@ -22,8 +22,6 @@ int Doom_SectorNearPoint(vec3_t p); //4. That ALL sectors are fully enclosed, and not made of two areas. //5. That no sectors are inside out. - - enum { THING_PLAYER = 1, THING_PLAYER2 = 2, @@ -162,8 +160,8 @@ typedef struct { typedef struct { int visframe; - shader_t *floortex; - shader_t *ceilingtex; + int floortex; + int ceilingtex; short floorheight; short ceilingheight; @@ -211,6 +209,21 @@ extern model_t *loadmodel; extern char loadname[]; +typedef struct +{ + char name[8]; + shader_t *shader; + unsigned short width; + unsigned short height; + batch_t batch; + mesh_t *meshptr; + mesh_t mesh; + int maxverts; + int maxindicies; +} gldoomtexture_t; +gldoomtexture_t *gldoomtextures; +int numgldoomtextures; + //////////////////////////////////////////////////////////////////////////////////////////// //physics @@ -696,47 +709,46 @@ void Doom_LoadPalette(void) } } -shader_t *Doom_LoadFlat(char *name) +int Doom_LoadFlat(char *flatname) { char *file; char texname[64]; - shader_t *shad; + int texnum; - Doom_LoadPalette(); + sprintf(texname, "flats/%-.8s", flatname); + + for (texnum = 0; texnum < numgldoomtextures; texnum++) + { + if (!strcmp(gldoomtextures[texnum].name, texname)) + return texnum; + } + + gldoomtextures = BZ_Realloc(gldoomtextures, sizeof(*gldoomtextures)*((numgldoomtextures+16)&~15)); + memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures])); + numgldoomtextures++; + + strncpy(gldoomtextures[texnum].name, texname, 8); + + gldoomtextures[texnum].shader = R_RegisterShader(texname, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n"); + + gldoomtextures[texnum].width = 64; + gldoomtextures[texnum].height = 64; + gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh; + gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr; + gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort]; + loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch; - sprintf(texname, "flats/%-.8s", name); - Q_strlwr(texname); - shad = R_RegisterShader(texname, "{\n{\nmap $diffuse\n}\n}\n"); file = FS_LoadMallocFile(texname); if (file) { - shad->defaulttextures.base = R_LoadTexture8Pal24(texname, 64, 64, file, doompalette, 0); + gldoomtextures[texnum].shader->defaulttextures.base = R_LoadTexture8Pal24(texname, 64, 64, file, doompalette, 0); Z_Free(file); } - else - { - Con_Printf("Flat %-0.8s not found\n", name); - } - return shad; + return texnum; } -typedef struct -{ - char name[8]; - shader_t *shader; - unsigned short width; - unsigned short height; - batch_t batch; - mesh_t *meshptr; - mesh_t mesh; - int maxverts; - int maxindicies; -} gldoomtexture_t; -gldoomtexture_t *gldoomtextures; -int numgldoomtextures; - -static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float frontfloor, float x2, float y2, float backfloor, qboolean unpegged, unsigned int colour4b) +static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float z1, float x2, float y2, float z2, qboolean unpegged, unsigned int colour4b) { gldoomtexture_t *tex = gldoomtextures+texnum; mesh_t *mesh = &tex->mesh; @@ -751,13 +763,15 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float fro if (unpegged) { t2 = t/tex->height; - t1 = t2 - (backfloor-frontfloor)/tex->height; + t1 = t2 - (z2-z1)/tex->height; } else { t1 = t/tex->height; - t2 = t1 + (backfloor-frontfloor)/tex->height; + t2 = t1 + (z2-z1)/tex->height; } + t1 = 0; + t2 = 1; if (mesh->numvertexes+4 > tex->maxverts) { @@ -773,19 +787,19 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float fro } col = colour4b * 0x01010101; - ((unsigned int*)&col)[3] = 0xff; + ((unsigned char*)&col)[3] = 0xff; *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+0] = col; *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+1] = col; *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+2] = col; *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+3] = col; - VectorSet(mesh->xyz_array[mesh->numvertexes+0], x1, y1, frontfloor); - VectorSet(mesh->xyz_array[mesh->numvertexes+1], x1, y1, backfloor); - VectorSet(mesh->xyz_array[mesh->numvertexes+2], x2, y2, backfloor); - VectorSet(mesh->xyz_array[mesh->numvertexes+3], x2, y2, frontfloor); + VectorSet(mesh->xyz_array[mesh->numvertexes+0], x1, y1, z1); + VectorSet(mesh->xyz_array[mesh->numvertexes+1], x1, y1, z2); + VectorSet(mesh->xyz_array[mesh->numvertexes+2], x2, y2, z2); + VectorSet(mesh->xyz_array[mesh->numvertexes+3], x2, y2, z1); Vector2Set(mesh->st_array[mesh->numvertexes+0], s1, t2); Vector2Set(mesh->st_array[mesh->numvertexes+1], s1, t1); Vector2Set(mesh->st_array[mesh->numvertexes+2], s2, t1); - Vector2Set(mesh->st_array[mesh->numvertexes+2], s2, t2); + Vector2Set(mesh->st_array[mesh->numvertexes+3], s2, t2); mesh->indexes[mesh->numindexes+0] = mesh->numvertexes+0; mesh->indexes[mesh->numindexes+1] = mesh->numvertexes+1; @@ -797,6 +811,93 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float fro mesh->numvertexes += 4; mesh->numindexes += 6; + + BE_DrawMesh_Single(tex->shader, mesh, NULL, &tex->shader->defaulttextures, 0); +} + +static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int ceilheight, int numverts, unsigned short *verts, unsigned int colour4b) +{ + mesh_t *mesh; + unsigned int col; + unsigned int v, i; + + //floor + { + gldoomtexture_t *floortex = gldoomtextures + floortexnum; + mesh = &floortex->mesh; + if (mesh->numvertexes+numverts > floortex->maxverts) + { + floortex->maxverts = mesh->numvertexes+numverts; + mesh->colors4b_array = BZ_Realloc(mesh->colors4b_array, sizeof(*mesh->colors4b_array) * floortex->maxverts); + mesh->xyz_array = BZ_Realloc(mesh->xyz_array, sizeof(*mesh->xyz_array) * floortex->maxverts); + mesh->st_array = BZ_Realloc(mesh->st_array, sizeof(*mesh->st_array) * floortex->maxverts); + } + if (mesh->numindexes+numverts > floortex->maxindicies) + { + floortex->maxindicies = mesh->numindexes+numverts; + mesh->indexes = BZ_Realloc(mesh->indexes, sizeof(*mesh->indexes) * floortex->maxindicies); + } + + col = colour4b * 0x01010101; + ((unsigned char*)&col)[3] = 0xff; + + for (i = 0; i < numverts; i++) + { + v = verts[i]; + VectorSet(mesh->xyz_array[mesh->numvertexes+i], vertexesl[v].xpos, vertexesl[v].ypos, floorheight); + Vector2Set(mesh->st_array[mesh->numvertexes+i], vertexesl[v].xpos/64.0f, vertexesl[v].ypos/64.0f); + *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+i] = col; + } + + for (i = 0; i < numverts; i++) + { + mesh->indexes[mesh->numindexes+i] = mesh->numvertexes+i; + } + + mesh->numvertexes += numverts; + mesh->numindexes += numverts; + + BE_DrawMesh_Single(floortex->shader, mesh, NULL, &floortex->shader->defaulttextures, 0); + } + + //ceiling + { + gldoomtexture_t *ceiltex = gldoomtextures + ceiltexnum; + mesh = &ceiltex->mesh; + if (mesh->numvertexes+numverts > ceiltex->maxverts) + { + ceiltex->maxverts = mesh->numvertexes+numverts; + mesh->colors4b_array = BZ_Realloc(mesh->colors4b_array, sizeof(*mesh->colors4b_array) * ceiltex->maxverts); + mesh->xyz_array = BZ_Realloc(mesh->xyz_array, sizeof(*mesh->xyz_array) * ceiltex->maxverts); + mesh->st_array = BZ_Realloc(mesh->st_array, sizeof(*mesh->st_array) * ceiltex->maxverts); + } + if (mesh->numindexes+numverts > ceiltex->maxindicies) + { + ceiltex->maxindicies = mesh->numindexes+numverts; + mesh->indexes = BZ_Realloc(mesh->indexes, sizeof(*mesh->indexes) * ceiltex->maxindicies); + } + + col = colour4b * 0x01010101; + ((unsigned char*)&col)[3] = 0xff; + + for (i = 0; i < numverts; i++) + { + v = verts[numverts-1-i]; + VectorSet(mesh->xyz_array[mesh->numvertexes+i], vertexesl[v].xpos, vertexesl[v].ypos, ceilheight); + Vector2Set(mesh->st_array[mesh->numvertexes+i], vertexesl[v].xpos/64.0f, vertexesl[v].ypos/64.0f); + *(unsigned int*)mesh->colors4b_array[mesh->numvertexes+i] = col; + } + + for (i = 0; i < numverts; i++) + { + mesh->indexes[mesh->numindexes+i] = mesh->numvertexes+i; + } + + mesh->numvertexes += numverts; + mesh->numindexes += numverts; + + BE_DrawMesh_Single(ceiltex->shader, mesh, NULL, &ceiltex->shader->defaulttextures, 0); + } } static void GLR_DrawSSector(unsigned int ssec) @@ -814,28 +915,8 @@ static void GLR_DrawSSector(unsigned int ssec) if (sec->visframe != r_visframecount) { -#if 0 - qglColor4ub(sectorm[i].lightlev, sectorm[i].lightlev, sectorm[i].lightlev, 255); - GL_Bind(sectorm[i].floortex); - qglBegin(GL_TRIANGLES); - for (v = 0; v < sectorm[i].numflattris*3; v++) - { - v1 = sectorm[i].flats[v]; - qglTexCoord2f(vertexesl[v1].xpos/64.0f, vertexesl[v1].ypos/64.0f); - qglVertex3f(vertexesl[v1].xpos, vertexesl[v1].ypos, sectorm[i].floorheight); - } - qglEnd(); + GLR_DrawFlats(sec->floortex, sec->floorheight, sec->ceilingtex, sec->ceilingheight, sec->numflattris*3, sec->flats, sec->lightlev); - GL_Bind(sectorm[i].ceilingtex); - qglBegin(GL_TRIANGLES); - for (v = sectorm[i].numflattris*3-1; v >= 0; v--) - { - v1 = sectorm[i].flats[v]; - qglTexCoord2f(vertexesl[v1].xpos/64.0f, vertexesl[v1].ypos/64.0f); - qglVertex3f(vertexesl[v1].xpos, vertexesl[v1].ypos, sectorm[i].ceilingheight); - } - qglEnd(); -#endif sec->visframe = r_visframecount; } for (seg = ssectorsl[ssec].first + ssectorsl[ssec].segcount-1; seg >= ssectorsl[ssec].first; seg--) @@ -1479,7 +1560,7 @@ static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth, } } -static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned short *width, unsigned short *height) +static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned short *width, unsigned short *height, qboolean *hasalpha) { char patch[32] = "patches/"; unsigned int *tex; @@ -1498,7 +1579,7 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor if (!strncmp(tx->name, name, 8)) { tex = BZ_Malloc(tx->width*tx->height*4); - memset(tex, 255, tx->width*tx->height*4); + memset(tex, 0, tx->width*tx->height*4); *width = tx->width; *height = tx->height; tc = (ddoomtexturecomponant_t*)(tx+1); @@ -1511,6 +1592,16 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor Doom_ExtractPName(tex, (doomimage_t *)COM_LoadTempFile(patch), tx->width, tx->height, tc->xoffset, tc->yoffset); } + *hasalpha = false; + for (i = 0; i < tx->width * tx->height; i++) + { + if (!(tex[i] & 0xff000000)) + { + *hasalpha = true; + break; + } + } + result = R_LoadTexture32(name, tx->width, tx->height, tex, 0); BZ_Free(tex); return result; @@ -1523,6 +1614,8 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor } static int Doom_LoadPatch(char *name) { + texid_t tex; + qboolean hasalpha = false; int texnum; for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. @@ -1541,27 +1634,28 @@ static int Doom_LoadPatch(char *name) strncpy(gldoomtextures[texnum].name, name, 8); - gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\n}\n}\n"); + tex = r_nulltex; + if (textures1 && !TEXVALID(tex)) + tex = Doom_LoadPatchFromTexWad(name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); + if (textures2 && !TEXVALID(tex)) + tex = Doom_LoadPatchFromTexWad(name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); + if (!TEXVALID(tex)) + { + //all else failed. + gldoomtextures[texnum].width = image_width; + gldoomtextures[texnum].height = image_height; + gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh; + gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr; + gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort]; + loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch; + } + + if (hasalpha) + gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\nalphafunc ge128\n}\n}\n"); + else + gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n"); + gldoomtextures[texnum].shader->defaulttextures.base = tex; - if (textures1) - { - gldoomtextures[texnum].shader->defaulttextures.base = Doom_LoadPatchFromTexWad(name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height); - if (TEXVALID(gldoomtextures[texnum].shader->defaulttextures.base)) - return texnum; - } - if (textures2) - { - gldoomtextures[texnum].shader->defaulttextures.base = Doom_LoadPatchFromTexWad(name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height); - if (TEXVALID(gldoomtextures[texnum].shader->defaulttextures.base)) - return texnum; - } - //all else failed. - gldoomtextures[texnum].width = image_width; - gldoomtextures[texnum].height = image_height; - gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh; - gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr; - gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort]; - loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch; return texnum; } static void Doom_Purge (struct model_s *mod) diff --git a/engine/gl/model_hl.h b/engine/gl/model_hl.h index 1535776c..51c6c343 100644 --- a/engine/gl/model_hl.h +++ b/engine/gl/model_hl.h @@ -213,7 +213,7 @@ typedef struct hlmdl_tex_t *textures; hlmdl_bone_t *bones; hlmdl_bonecontroller_t *bonectls; - texid_t *texnums; + shader_t **shaders; } hlmodel_t; typedef struct //this is stored as the cache. an hlmodel_t is generated when drawing @@ -223,7 +223,7 @@ typedef struct //this is stored as the cache. an hlmodel_t is generated when dra int textures; int bones; int bonectls; - int texnums; + int shaders; } hlmodelcache_t; /* HL mathlib prototypes: */ diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 5ccf5769..568ceb52 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -5,8 +5,25 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #ifdef GLQUAKE {QR_OPENGL, 110, "altwater", -//modifier: REFLECT +//modifier: REFLECT (s_t2 is a reflection instead of diffusemap) +//modifier: STRENGTH (0.1 = fairly gentle, 0.2 = big waves) //modifier: FRESNEL (5=water) +//modifier: TXSCALE (0.2 - wave strength) +//modifier: RIPPLEMAP (s_t3 contains a ripplemap +//modifier: TINT (some colour value) + +"#ifndef FRESNEL\n" +"#define FRESNEL 5.0\n" +"#endif\n" +"#ifndef STRENGTH\n" +"#define STRENGTH 0.1\n" +"#endif\n" +"#ifndef TXSCALE\n" +"#define TXSCALE 0.2\n" +"#endif\n" +"#ifndef TINT\n" +"#define TINT vec3(0.7, 0.8, 0.7)\n" +"#endif\n" "varying vec2 tc;\n" "varying vec4 tf;\n" @@ -28,9 +45,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D s_t0; //refract\n" "uniform sampler2D s_t1; //normalmap\n" -"uniform sampler2D s_t2; //diffuse\n" -"#ifdef REFLECT\n" -"uniform sampler2D s_t3; //reflect\n" +"uniform sampler2D s_t2; //diffuse/reflection\n" +"#ifdef RIPPLEMAP\n" +"uniform sampler2D s_t3; //ripplemap\n" "#endif\n" "uniform float e_time;\n" @@ -46,27 +63,29 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" //generate the two wave patterns from the normalmap -"n = (texture2D(s_t1, 0.2*tc + vec2(e_time*0.1, 0)).xyz);\n" -"n += (texture2D(s_t1, 0.2*tc - vec2(0, e_time*0.097)).xyz);\n" +"n = (texture2D(s_t1, TXSCALE*tc + vec2(e_time*0.1, 0)).xyz);\n" +"n += (texture2D(s_t1, TXSCALE*tc - vec2(0, e_time*0.097)).xyz);\n" "n -= 1.0 - 4.0/256.0;\n" -"n = normalize(n);\n" - -"#if 1//def REFRACT\n" -"refr = texture2D(s_t0, stc + n.st*0.2).rgb;\n" -"#else\n" -"refr = texture2D(s_t2, ntc).xyz;\n" -"#endif\n" -"#ifdef REFLECT\n" -"refl = texture2D(s_t3, stc - n.st*0.2).rgb;\n" -"#else\n" -"refl = texture2D(s_t2, ntc).xyz;\n" +"#ifdef RIPPLEMAP\n" +"n += texture2D(s_t3, stc)*3;\n" "#endif\n" //the fresnel term decides how transparent the water should be -"f = pow(1.0-abs(dot(n, normalize(eye))), float(FRESNEL));\n" +"f = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n" + +"refr = texture2D(s_t0, stc + n.st*STRENGTH).rgb * TINT;\n" +"#ifdef REFLECT\n" +"refl = texture2D(s_t2, stc - n.st*STRENGTH).rgb;\n" +"#else\n" +"refl = texture2D(s_t2, ntc).xyz;\n" +"#endif\n" +// refl += 0.1*pow(dot(n, vec3(0.0,0.0,1.0)), 64.0); + "fres = refr * (1.0-f) + refl*f;\n" +// fres = texture2D(s_t2, stc).xyz; + "gl_FragColor = vec4(fres, 1.0);\n" "}\n" "#endif\n" @@ -483,6 +502,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "!!permu OFFSETMAPPING\n" "!!permu FULLBRIGHT\n" "!!permu FOG\n" +"!!permu LIGHTSTYLED\n" "!!cvarf r_glsl_offsetmapping_scale\n" //this is what normally draws all of your walls, even with rtlights disabled @@ -492,10 +512,24 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#if defined(OFFSETMAPPING)\n" "varying vec3 eyevector;\n" "#endif\n" + +"varying vec2 tc;\n" +"#ifdef LIGHTSTYLED\n" +//we could use an offset, but that would still need to be per-surface which would break batches +//fixme: merge attributes? +"varying vec2 lm, lm2, lm3, lm4;\n" +"#else\n" +"varying vec2 lm;\n" +"#endif\n" + "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "attribute vec2 v_lmcoord;\n" -"varying vec2 tc, lm;\n" +"#ifdef LIGHTSTYLED\n" +"attribute vec2 v_lmcoord2;\n" +"attribute vec2 v_lmcoord3;\n" +"attribute vec2 v_lmcoord4;\n" +"#endif\n" "#if defined(OFFSETMAPPING)\n" "uniform vec3 e_eyepos;\n" "attribute vec3 v_normal;\n" @@ -506,16 +540,24 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "{\n" "#if defined(OFFSETMAPPING)\n" "vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n" -"eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n" -"eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n" +"eyevector.x = -dot(eyeminusvertex, v_svector.xyz);\n" +"eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n" "eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n" "#endif\n" "tc = v_texcoord;\n" "lm = v_lmcoord;\n" +"#ifdef LIGHTSTYLED\n" +"lm2 = v_lmcoord2;\n" +"lm3 = v_lmcoord3;\n" +"lm4 = v_lmcoord4;\n" +"#endif\n" "gl_Position = ftetransform();\n" "}\n" "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" +//samplers "uniform sampler2D s_t0;\n" "uniform sampler2D s_t1;\n" "#ifdef OFFSETMAPPING\n" @@ -524,8 +566,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FULLBRIGHT\n" "uniform sampler2D s_t4;\n" "#endif\n" -"varying vec2 tc, lm;\n" +"#ifdef LIGHTSTYLED\n" +"uniform sampler2D s_t5;\n" +"uniform sampler2D s_t6;\n" +"uniform sampler2D s_t7;\n" +"#endif\n" + +"#ifdef LIGHTSTYLED\n" +"uniform vec4 e_lmscale[4];\n" +"#else\n" "uniform vec4 e_lmscale;\n" +"#endif\n" "uniform vec4 e_colourident;\n" "#ifdef OFFSETMAPPING\n" "#include \"sys/offsetmapping.h\"\n" @@ -536,7 +587,18 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "vec2 tcoffsetmap = offsetmap(s_t2, tc, eyevector);\n" "#define tc tcoffsetmap\n" "#endif\n" -"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale;\n" +"gl_FragColor = texture2D(s_t0, tc);\n" +"#ifdef LIGHTSTYLED\n" +"vec4 lightmaps;\n" +"lightmaps = texture2D(s_t1, lm ) * e_lmscale[0];\n" +"lightmaps += texture2D(s_t5, lm2) * e_lmscale[1];\n" +"lightmaps += texture2D(s_t6, lm3) * e_lmscale[2];\n" +"lightmaps += texture2D(s_t7, lm4) * e_lmscale[3];\n" +"gl_FragColor.rgb *= lightmaps.rgb;\n" +"#else\n" +"gl_FragColor.rgb *= (texture2D(s_t1, lm) * e_lmscale).rgb;\n" +"#endif\n" + "#ifdef FULLBRIGHT\n" "gl_FragColor.rgb += texture2D(s_t4, tc).rgb;\n" "#endif\n" @@ -865,13 +927,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "gl_Position = skeletaltransform_wnst(w,n,s,t);\n" "tcbase = v_texcoord; //pass the texture coords straight through\n" "vec3 lightminusvertex = l_lightposition - w.xyz;\n" -"lightvector.x = dot(lightminusvertex, s.xyz);\n" +"lightvector.x = -dot(lightminusvertex, s.xyz);\n" "lightvector.y = dot(lightminusvertex, t.xyz);\n" "lightvector.z = dot(lightminusvertex, n.xyz);\n" "#if defined(SPECULAR)||defined(OFFSETMAPPING)\n" "vec3 eyeminusvertex = e_eyepos - w.xyz;\n" -"eyevector.x = dot(eyeminusvertex, s.xyz);\n" -"eyevector.y = -dot(eyeminusvertex, t.xyz);\n" +"eyevector.x = -dot(eyeminusvertex, s.xyz);\n" +"eyevector.y = dot(eyeminusvertex, t.xyz);\n" "eyevector.z = dot(eyeminusvertex, n.xyz);\n" "#endif\n" "#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE)\n" @@ -906,30 +968,37 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "void main ()\n" "{\n" +//read raw texture samples (offsetmapping munges the tex coords first) "#ifdef OFFSETMAPPING\n" "vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n" "#define tcbase tcoffsetmap\n" "#endif\n" "vec3 bases = vec3(texture2D(s_t0, tcbase));\n" "#if defined(BUMP) || defined(SPECULAR)\n" -"vec3 bumps = vec3(texture2D(s_t1, tcbase)) - 0.5;\n" +"vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n" "#endif\n" "#ifdef SPECULAR\n" "vec4 specs = texture2D(s_t2, tcbase);\n" "#endif\n" + "vec3 nl = normalize(lightvector);\n" -"float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n" +"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n" "vec3 diff;\n" "#ifdef BUMP\n" -"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(2.0*bumps, nl), 0.0));\n" +"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));\n" "#else\n" "diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n" "#endif\n" + + "#ifdef SPECULAR\n" -"vec3 halfdir = normalize(lightvector - normalize(eyevector));\n" -"float spec = pow(max(dot(halfdir, bumps), 0.0), 1.0 + 32.0 * specs.a);\n" -"diff += spec * specs.rgb * l_lightcolourscale.z;\n" +"vec3 halfdir = normalize(normalize(eyevector) + nl);\n" +"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n" +"diff += l_lightcolourscale.z * spec * specs.rgb;\n" "#endif\n" + + + "#ifdef CUBE\n" "diff *= textureCube(s_t3, vshadowcoord.xyz).rgb;\n" "#endif\n" diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 367bdd37..00aa80e2 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -268,7 +268,8 @@ enum{ PERMUTATION_SKELETAL = 32, PERMUTATION_FOG = 64, PERMUTATION_FRAMEBLEND = 128, - PERMUTATIONS = 256 + PERMUTATION_LIGHTSTYLES = 256, + PERMUTATIONS = 512 }; enum shaderattribs_e @@ -285,6 +286,9 @@ enum shaderattribs_e VATTR_TNORMALS, VATTR_BONENUMS, /*skeletal only*/ VATTR_BONEWEIGHTS, /*skeletal only*/ + VATTR_LMCOORD2, + VATTR_LMCOORD3, + VATTR_LMCOORD4, VATTR_LEG_COLOUR, VATTR_LEG_ELEMENTS, @@ -381,13 +385,13 @@ typedef struct { } polyoffset_t; struct shader_s { + char name[MAX_QPATH]; int uses; int width; int height; int numpasses; texnums_t defaulttextures; struct shader_s *next; - char name[MAX_QPATH]; //end of shared fields. byte_vec4_t fog_color; @@ -486,6 +490,7 @@ mfog_t *CM_FogForOrigin(vec3_t org); #ifdef GLQUAKE void GLBE_Init(void); +void GLBE_Shutdown(void); void GLBE_SelectMode(backendmode_t mode); void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); @@ -519,6 +524,27 @@ qboolean D3DShader_CreateProgram (program_t *prog, int permu, char **precompiler int D3DShader_FindUniform(union programhandle_u *h, int type, char *name); void D3DShader_Init(void); void D3DBE_Reset(qboolean before); + + + +void D3D11BE_Init(void); +void D3D11BE_SelectMode(backendmode_t mode); +void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D11BE_SubmitBatch(batch_t *batch); +batch_t *D3D11BE_GetTempBatch(void); +void D3D11BE_GenBrushModelVBO(model_t *mod); +void D3D11BE_ClearVBO(vbo_t *vbo); +void D3D11BE_UploadAllLightmaps(void); +void D3D11BE_DrawWorld (qbyte *vis); +qboolean D3D11BE_LightCullModel(vec3_t org, model_t *model); +void D3D11BE_SelectEntity(entity_t *ent); +void D3D11BE_SelectDLight(dlight_t *dl, vec3_t colour); + +qboolean D3D11Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); +int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name); +void D3D11Shader_Init(void); +void D3D11BE_Reset(qboolean before); #endif //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 323c5660..fb82d5d6 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -31,43 +31,64 @@ PR_PrintStatement ================= */ -/* -void PR_PrintStatement (progfuncs_t *progfuncs, dstatement16_t *s) +static void PR_PrintStatement (progfuncs_t *progfuncs, int statementnum) { int i; -printf("PR_PrintStatement is unsupported\n"); -return; - if ( (unsigned)s->op < OP_NUMOPS) + unsigned int op; + unsigned int arg[3]; + + switch(current_progstate->structtype) { - printf ("%s ", pr_opcodes[s->op].name); - i = strlen(pr_opcodes[s->op].name); + case PST_DEFAULT: + case PST_QTEST: + op = ((dstatement16_t*)current_progstate->statements + statementnum)->op; + arg[0] = ((dstatement16_t*)current_progstate->statements + statementnum)->a; + arg[1] = ((dstatement16_t*)current_progstate->statements + statementnum)->b; + arg[2] = ((dstatement16_t*)current_progstate->statements + statementnum)->c; + break; + case PST_KKQWSV: + case PST_FTE32: + op = ((dstatement32_t*)current_progstate->statements + statementnum)->op; + arg[0] = ((dstatement32_t*)current_progstate->statements + statementnum)->a; + arg[1] = ((dstatement32_t*)current_progstate->statements + statementnum)->b; + arg[2] = ((dstatement32_t*)current_progstate->statements + statementnum)->c; + break; + } + +#ifndef MINIMAL + if ( (unsigned)op < OP_NUMOPS) + { + printf ("%s ", pr_opcodes[op].name); + i = strlen(pr_opcodes[op].name); for ( ; i<10 ; i++) printf (" "); } + else +#endif + printf ("op%3i "); - if (s->op == OP_IF || s->op == OP_IFNOT) - printf ("%sbranch %i",PR_GlobalString(progfuncs, s->a),s->b); - else if (s->op == OP_GOTO) + if (op == OP_IF_F || op == OP_IFNOT_F) + printf ("%sbranch %i",PR_GlobalString(progfuncs, arg[0]),arg[1]); + else if (op == OP_GOTO) { - printf ("branch %i",s->a); + printf ("branch %i",arg[0]); } - else if ( (unsigned)(s->op - OP_STORE_F) < 6) + else if ( (unsigned)(op - OP_STORE_F) < 6) { - printf ("%s",PR_GlobalString(progfuncs, s->a)); - printf ("%s", PR_GlobalStringNoContents(progfuncs, s->b)); + printf ("%s",PR_GlobalString(progfuncs, arg[0])); + printf ("%s", PR_GlobalStringNoContents(progfuncs, arg[1])); } else { - if (s->a) - printf ("%s",PR_GlobalString(progfuncs, s->a)); - if (s->b) - printf ("%s",PR_GlobalString(progfuncs, s->b)); - if (s->c) - printf ("%s", PR_GlobalStringNoContents(progfuncs, s->c)); + if (arg[0]) + printf ("%s",PR_GlobalString(progfuncs, arg[0])); + if (arg[1]) + printf ("%s",PR_GlobalString(progfuncs, arg[1])); + if (arg[2]) + printf ("%s", PR_GlobalStringNoContents(progfuncs, arg[2])); } printf ("\n"); } -*/ /* ============ @@ -808,6 +829,12 @@ static char *lastfile = 0; int i; dfunction_t *f = pr_xfunction; + if (!externs->useeditor) + { + PR_PrintStatement(progfuncs, statement); + return statement; + } + if (f && pr_progstate[pn].linenums && externs->useeditor) { if (lastline == pr_progstate[pn].linenums[statement] && lastfile == f->s_file+progfuncs->stringtable) diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 0bb9f1a9..ae36e1ee 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -262,6 +262,7 @@ typedef union eval_s #define PR_AddString(pf, ed, len) (*pf->AddString) (pf, ed, len) #define PR_Alloc(pf,size,whatfor) (*pf->Tempmem) (pf, size, whatfor) #define PR_AddressableAlloc(pf,size) (*pf->AddressableAlloc) (pf, size) +#define PR_AddressableFree(pf,mem) (*pf->AddressableFree) (pf, mem) #define PROG_TO_EDICT(pf, ed) (*pf->ProgsToEdict) (pf, ed) #define EDICT_TO_PROG(pf, ed) (*pf->EdictToProgs) (pf, (struct edict_s*)ed) diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 86d50d7f..054796d5 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1450,7 +1450,7 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement newofs = 0; for (i = firststatement, st = &statements[i]; i < laststatement; i++, st++) { - if (pr_opcodes[st->op].type_a && st->a == t->ofs) + if (pr_opcodes[st->op].type_a && st->a >= t->ofs && st->a < t->ofs + t->size) { if (!newofs) { @@ -1467,9 +1467,9 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement #endif pr.localvars = def; } - st->a = newofs; + st->a = st->a - t->ofs + newofs; } - if (pr_opcodes[st->op].type_b && st->b == t->ofs) + if (pr_opcodes[st->op].type_b && st->b >= t->ofs && st->b < t->ofs + t->size) { if (!newofs) { @@ -1486,9 +1486,9 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement #endif pr.localvars = def; } - st->b = newofs; + st->b = st->b - t->ofs + newofs; } - if (pr_opcodes[st->op].type_c && st->c == t->ofs) + if (pr_opcodes[st->op].type_c && st->c >= t->ofs && st->c < t->ofs + t->size) { if (!newofs) { @@ -1505,7 +1505,7 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement #endif pr.localvars = def; } - st->c = newofs; + st->c = st->c - t->ofs + newofs; } } } @@ -4259,7 +4259,8 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) { allowarray = false; if (idx) - allowarray = t->arraysize>0; + allowarray = t->arraysize>0 || + (t->type == ev_vector); else if (!idx) { allowarray = d->arraysize || @@ -4285,7 +4286,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) { /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/ } - else if (!idx && d->type->type == ev_vector && !d->arraysize) + else if ((!idx && d->type->type == ev_vector && !d->arraysize) || (idx && t->type == ev_vector && !t->arraysize)) { if (tmp->constant) { @@ -4297,7 +4298,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) if (i < 0 || i >= 3) QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds"); } - else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) + else if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK])) { tmp = QCC_SupplyConversion(tmp, ev_integer, true); QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false); @@ -4320,13 +4321,14 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) } else { - if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) + if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK])) { tmp = QCC_SupplyConversion(tmp, ev_integer, true); QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false); } } - if (t->size != 1 && (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))) /*don't multiply by type size if the instruction/emulation will do that instead*/ + + if (t->size != 1) /*don't multiply by type size if the instruction/emulation will do that instead*/ { if (tmp->type->type == ev_float) tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL); @@ -4335,7 +4337,9 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) } /*calc the new index*/ - if (idx) + if (idx && idx->type->type == ev_float && tmp->type->type == ev_float) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, QCC_SupplyConversion(tmp, ev_float, true), NULL); + else if (idx) idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL); else idx = tmp; @@ -4356,11 +4360,22 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) if (!t) QCC_PR_ParseError(0, "%s is not a member", pr_token); - tmp = QCC_MakeIntConst(t->ofs); - if (idx) - idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); + if (QCC_OPCodeValid(&pr_opcodes[OP_ADD_I])) + { + tmp = QCC_MakeIntConst(t->ofs); + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); + else + idx = tmp; + } else - idx = tmp; + { + tmp = QCC_MakeFloatConst(t->ofs); + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, tmp, NULL); + else + idx = tmp; + } } else break; @@ -4479,7 +4494,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 0, false); rhs = QCC_PR_Expression(TOP_PRIORITY, 0); - if (rhs->type->type != d->type->type) + if (rhs->type->type != t->type) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); args[0] = QCC_SupplyConversion(idx, ev_float, true); @@ -4536,12 +4551,55 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) d->references++; /*make sure the function type that we're calling exists*/ - def_parms[0].type = type_float; - funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false); - args[0] = QCC_SupplyConversion(idx, ev_float, true); - d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); - d->type = t; + if (d->type->type == ev_vector) + { + def_parms[0].type = type_vector; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false); + + args[0] = QCC_SupplyConversion(idx, ev_float, true); + d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + d->type = t; + } + else + { + def_parms[0].type = type_float; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false); + + if (t->size > 1) + { + QCC_def_t *r; + unsigned int i; + int old_op = opt_assignments; + d = QCC_GetTemp(t); + idx = QCC_SupplyConversion(idx, ev_float, true); + + for (i = 0; i < t->size; i++) + { + if (i) + args[0] = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, QCC_MakeFloatConst(i), (QCC_dstatement_t **)0xffffffff); + else + { + args[0] = idx; + opt_assignments = false; + } + r = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + opt_assignments = old_op; + QCC_UnFreeTemp(idx); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], r, d, (QCC_dstatement_t **)0xffffffff)); + d->ofs++; + } + QCC_FreeTemp(idx); + d->ofs -= i; + QCC_UnFreeTemp(d); + } + else + { + args[0] = QCC_SupplyConversion(idx, ev_float, true); + d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + } + d->type = t; + } } /*parse recursively*/ @@ -7582,6 +7640,13 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi { QCC_dstatement_t *st; QCC_def_t *eq; + int stride; + + if (array->type->type == ev_vector) + stride = 3; + else + stride = 1; //struct arrays should be 1, so that every element can be accessed... + if (min == max || min+1 == max) { eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL); @@ -7589,7 +7654,7 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); - st->a = array->ofs + min*array->type->size; + st->a = array->ofs + min*stride; } else { @@ -7650,6 +7715,12 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) QCC_dfunction_t *df; QCC_def_t *temp, *index, *func; + int numslots; + + //array shouldn't ever be a vector array + numslots = array->arraysize*array->type->size; + numslots = (numslots+2)/3; + func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false); pr_scope = func; @@ -7674,7 +7745,7 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), temp, false); QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int - QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up + QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, numslots); QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); //err... we didn't find it, give up. QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); //err... we didn't find it, give up. @@ -7694,6 +7765,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) QCC_def_t *eq; QCC_def_t *fasttrackpossible; + int numslots; if (flag_fasttrackarrays) fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); @@ -7702,10 +7774,13 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false); - if (def->arraysize >= 15 && def->type->size == 1) - { + if (def->type->type == ev_vector) + numslots = def->arraysize; + else + numslots = def->arraysize*def->type->size; + + if (numslots >= 15 && def->type->type != ev_vector) vectortrick = QCC_PR_EmitArrayGetVector(def); - } else vectortrick = NULL; @@ -7733,7 +7808,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) //fetch_gbl takes: (float size, variant array[]), float index, variant pos //note that the array size is coded into the globals, one index before the array. - if (def->type->size >= 3) + if (def->type->type == ev_vector) QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_V], def, index, &def_ret, true); else QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], def, index, &def_ret, true); @@ -7755,7 +7830,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false); intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false); - eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule! + eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)numslots), NULL); //escape clause - should call some sort of error function instead.. that'd rule! QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, &st); @@ -7800,7 +7875,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) else { QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false); - QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize); + QCC_PR_ArrayRecurseDivideRegular(def, index, 0, numslots); } QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); @@ -7820,17 +7895,24 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t { QCC_dstatement_t *st; QCC_def_t *eq; + int stride; + + if (array->type->type == ev_vector) + stride = 3; + else + stride = 1; //struct arrays should be 1, so that every element can be accessed... + if (min == max || min+1 == max) { eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatConst((float)min), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 3; - if (array->type->size == 3) + if (stride == 3) QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st); else QCC_PR_Statement(pr_opcodes+OP_STORE_F, value, array, &st); - st->b = array->ofs + min*array->type->size; + st->b = array->ofs + min*stride; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); } else @@ -7858,6 +7940,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) QCC_def_t *def, *index, *value; QCC_def_t *fasttrackpossible; + int numslots; if (flag_fasttrackarrays) fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); @@ -7867,6 +7950,11 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false); pr_scope = scope; + if (def->type->type == ev_vector) + numslots = def->arraysize; + else + numslots = def->arraysize*def->type->size; + if (numfunctions >= MAX_FUNCTIONS) QCC_Error(ERR_INTERNAL, "Too many function defs"); @@ -7910,7 +7998,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) } QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false); - QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize); + QCC_PR_ArraySetRecurseDivide(def, index, value, 0, numslots); QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); @@ -8278,7 +8366,12 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool { //write the array size ofs = QCC_GetFreeOffsetSpace(1 + (type->size * arraysize)); - ((int *)qcc_pr_globals)[ofs] = arraysize-1; //An array needs the size written first. This is a hexen2 opcode thing. + //An array needs the size written first. This is a hexen2 opcode thing. + //note that for struct emulation, union and struct arrays, the size is the total size of global slots, rather than array elements + if (type->type == ev_vector) + ((int *)qcc_pr_globals)[ofs] = arraysize-1; + else + ((int *)qcc_pr_globals)[ofs] = (arraysize*type->size)-1; ofs++; } else diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 0a9f3100..89c1abc1 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -495,6 +495,21 @@ void SVPR_Event_Think(world_t *w, wedict_t *s) PR_ExecuteProgram (w->progs, s->v->think); } +qboolean SVPR_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) +{ + if (ent->xv->contentstransition) + { + void *pr_globals = PR_globals(w->progs, PR_CURRENT); + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); + pr_global_struct->time = w->physicstime; + G_FLOAT(OFS_PARM0) = oldwatertype; + G_FLOAT(OFS_PARM1) = newwatertype; + PR_ExecuteProgram (w->progs, ent->xv->contentstransition); + return true; + } + return false; //do legacy behaviour +} + void Q_SetProgsParms(qboolean forcompiler) { progstype = PROG_NONE; @@ -547,6 +562,7 @@ void Q_SetProgsParms(qboolean forcompiler) sv.world.Event_Touch = SVPR_Event_Touch; sv.world.Event_Think = SVPR_Event_Think; sv.world.Event_Sound = SVQ1_StartSound; + sv.world.Event_ContentsTransition = SVPR_Event_ContentsTransition; sv.world.Get_CModel = SVPR_GetCModel; sv.world.Get_FrameState = SVPR_Get_FrameState; PRSV_ClearThreads(); @@ -2957,7 +2973,7 @@ static void QCBUILTIN PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr if (!isDedicated) { if ((sfx = S_PrecacheSound(s))) - S_StartSound(cl.playernum[0], chan, sfx, cl.simorg[0], vol, 0.0, 0, 0); + S_StartSound(cl.playernum[0], chan, sfx, cl.playerview[0].simorg, vol, 0.0, 0, 0); } #endif }; @@ -3904,9 +3920,18 @@ void QCBUILTIN PF_applylightstyle(int style, char *val, int col) // change the string in sv - if (sv.strings.lightstyles[style]) - Z_Free(sv.strings.lightstyles[style]); - sv.strings.lightstyles[style] = Z_Malloc(strlen(val)+1); + if (!svprogfuncs) + { + if (sv.strings.lightstyles[style]) + BZ_Free(sv.strings.lightstyles[style]); + sv.strings.lightstyles[style] = BZ_Malloc(strlen(val)+1); + } + else + { + if (sv.strings.lightstyles[style]) + PR_AddressableFree(svprogfuncs, sv.strings.lightstyles[style]); + sv.strings.lightstyles[style] = PR_AddressableAlloc(svprogfuncs, strlen(val)+1); + } strcpy(sv.strings.lightstyles[style], val); // sv.lightstyles[style] = val; #ifdef PEXT_LIGHTSTYLECOL diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 27d81c27..3cc96668 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -1325,6 +1325,11 @@ void Q1QVM_Event_Think(world_t *w, wedict_t *s) PR_ExecuteProgram (w->progs, s->v->think); } +qboolean Q1QVM_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) +{ + return false; //always do legacy behaviour +} + qboolean PR_LoadQ1QVM(void) { static float writable; @@ -1368,6 +1373,8 @@ qboolean PR_LoadQ1QVM(void) sv.world.Event_Touch = Q1QVM_Event_Touch; sv.world.Event_Think = Q1QVM_Event_Think; + sv.world.Event_Sound = SVQ1_StartSound; + sv.world.Event_ContentsTransition = Q1QVM_Event_ContentsTransition; sv.world.Get_CModel = SVPR_GetCModel; sv.world.num_edicts = 0; //we're not ready for most of the builtins yet diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 88780167..90d36c92 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -191,8 +191,10 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(hull)/*PEXT_HEXEN2*/\ comfieldentity(movechain)/*hexen2*/\ comfieldfunction(chainmoved, ".void()")/*hexen2*/\ + comfieldfunction(contentstransition, ".void(float old, float new)")/*ENTITYCONTENTSTRANSITION*/\ comfieldfloat(dimension_solid)/*EXT_DIMENSION_PHYSICS*/\ comfieldfloat(dimension_hit)/*EXT_DIMENSION_PHYSICS*/\ + comfieldfloat(hitcontentsmask)\ comfieldfloat(scale)/*DP_ENT_SCALE*/\ comfieldfloat(fatness)/*FTE_PEXT_FATNESS*/\ comfieldfloat(alpha)/*DP_ENT_ALPHA*/\ @@ -230,6 +232,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(glow_size)\ comfieldfloat(glow_color)\ comfieldfloat(glow_trail)\ + comfieldfloat(traileffectnum)/*DP_ENT_TRAILEFFECTNUM*/\ comfieldvector(color)/*Hexen2 has a .float color, the warnings should be benign*/ \ comfieldfloat(light_lev)\ comfieldfloat(style)\ diff --git a/engine/server/server.h b/engine/server/server.h index 35213159..4519d135 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1091,9 +1091,11 @@ qboolean PR_ShouldTogglePause(client_t *initiator, qboolean pausedornot); // sv_ents.c // void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignorepvs); +void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg); void SVQ3Q1_BuildEntityPacket(client_t *client, packet_entities_t *pack); int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs); void SV_GibFilterInit(void); +void SV_GibFilterPurge(void); void SV_CleanupEnts(void); void SV_CSQC_DroppedPacket(client_t *client, int sequence); @@ -1310,3 +1312,25 @@ void SV_CheckTimer(void); void SV_LogPlayer(client_t *cl, char *msg); void AddLinksToPmove ( edict_t *player, areanode_t *node ); + + +#ifdef HLSERVER +void SVHL_SaveLevelCache(char *filename); + +//network frame info +void SVHL_Snapshot_Build(client_t *client, packet_entities_t *pack, qbyte *pvs, edict_t *clent, qboolean ignorepvs); +qbyte *SVHL_Snapshot_SetupPVS(client_t *client, qbyte *pvs, unsigned int pvsbufsize); +void SVHL_BuildStats(client_t *client, int *si, float *sf, char **ss); + +//gamecode entry points +int SVHL_InitGame(void); +void SVHL_SetupGame(void); +void SVHL_SpawnEntities(char *entstring); +void SVHL_RunFrame (void); +qboolean SVHL_ClientConnect(client_t *client, netadr_t adr, char rejectmessage[128]); +void SVHL_PutClientInServer(client_t *client); +void SVHL_RunPlayerCommand(client_t *cl, usercmd_t *oldest, usercmd_t *oldcmd, usercmd_t *newcmd); +qboolean HLSV_ClientCommand(client_t *client); +void SVHL_DropClient(client_t *drop); +void SVHL_ShutdownGame(void); +#endif diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index e60242e4..eb12a2f7 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -252,7 +252,7 @@ static qboolean SV_AddCSQCUpdate (client_t *client, edict_t *ent) #endif } sizebuf_t csqcmsgbuffer; -void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) +void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) { #ifdef PEXT_CSQC qbyte messagebuffer[1024]; @@ -321,10 +321,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) if (!writtenheader) { writtenheader=true; - if (client->protocol != SCP_QUAKEWORLD) - MSG_WriteByte(msg, svcdp_csqcentities); - else - MSG_WriteByte(msg, svcfte_csqcentities); + MSG_WriteByte(msg, svcnumber); } MSG_WriteShort(msg, ent->entnum); if (sv.csqcdebug) //optional extra. @@ -823,6 +820,12 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightstyle) bits |= UF_LIGHT; + if (to->u.q1.traileffectnum != from->u.q1.traileffectnum) + bits |= UF_TRAILEFFECT; + + if (to->u.q1.gravitydir[0] != from->u.q1.gravitydir[0] || to->u.q1.gravitydir[1] != from->u.q1.gravitydir[1]) + bits |= UF_GRAVITYDIR; + return bits; } @@ -994,6 +997,8 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ MSG_WriteByte (msg, state->lightstyle); MSG_WriteByte (msg, state->lightpflags); } + if (bits & UF_TRAILEFFECT) + MSG_WriteShort(msg, state->u.q1.traileffectnum); if (bits & UF_COLORMOD) { @@ -1009,6 +1014,29 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ } if (bits & UF_FATNESS) MSG_WriteByte(msg, state->fatness); + if (bits & UF_MODELINDEX2) + { + if (bits & UF_16BIT) + MSG_WriteShort(msg, state->modelindex2); + else + MSG_WriteByte(msg, state->modelindex2); + } + + if (bits & UF_GRAVITYDIR) + { + MSG_WriteByte(msg, state->u.q1.gravitydir[0]); + MSG_WriteByte(msg, state->u.q1.gravitydir[1]); + } +} + +/*dump out the delta from baseline (used for baselines and statics, so has no svc)*/ +void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg) +{ + unsigned int bits; + if (numberisimportant) + MSG_WriteShort(msg, to->number); + bits = UF_RESET | SVFTE_DeltaCalcBits(&nullentitystate, to); + SVFTE_WriteUpdate(bits, to, msg); } /*SVFTE_EmitPacketEntities @@ -2477,6 +2505,18 @@ typedef struct gibfilter_s { int maxframe; } gibfilter_t; gibfilter_t *gibfilter; +void SV_GibFilterPurge(void) +{ + gibfilter_t *gf; + while(gibfilter) + { + gf = gibfilter; + gibfilter = gibfilter->next; + + Z_Free(gf); + } +} + void SV_GibFilterAdd(char *modelname, int min, int max, qboolean allowwarn) { int i; @@ -2504,14 +2544,8 @@ void SV_GibFilterInit(void) char buffer[2048]; char *file; int min, max; - gibfilter_t *gf; - while(gibfilter) - { - gf = gibfilter; - gibfilter = gibfilter->next; - Z_Free(gf); - } + SV_GibFilterPurge(); if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM) return; @@ -2759,6 +2793,20 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli state->light[3] = ent->xv->light_lev; state->lightstyle = ent->xv->style; state->lightpflags = ent->xv->pflags; + state->u.q1.traileffectnum = ent->xv->traileffectnum; + + if (!ent->xv->gravitydir[0] && !ent->xv->gravitydir[1] && !ent->xv->gravitydir[2] || (ent->xv->gravitydir[2] == -1)) + { + state->u.q1.gravitydir[0] = 0; + state->u.q1.gravitydir[1] = 0; + } + else + { + vec3_t ang; + vectoangles(ent->xv->gravitydir, ang); + state->u.q1.gravitydir[0] = ((ang[0]/360) * 256) - 192; + state->u.q1.gravitydir[1] = (ang[1]/360) * 256; + } if (((int)ent->v->flags & FL_CLASS_DEPENDENT) && client && client->playerclass) //hexen2 wierdness. { @@ -3277,7 +3325,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) { SVDP_EmitEntitiesUpdate(client, pack, msg); - SV_EmitCSQCUpdate(client, msg); + SV_EmitCSQCUpdate(client, msg, svcdp_csqcentities); return; } else @@ -3289,6 +3337,8 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore SVNQ_EmitEntityState(msg, &pack->entities[e]); } client->netchan.incoming_sequence++; + + SV_EmitCSQCUpdate(client, msg, svcfte_csqcentities); return; } } @@ -3333,7 +3383,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore SVQW_EmitPacketEntities (client, pack, msg); } - SV_EmitCSQCUpdate(client, msg); + SV_EmitCSQCUpdate(client, msg, svcfte_csqcentities); // now add the specialized nail update SV_EmitNailUpdate (msg, ignorepvs); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index bcbe728e..1ab869ab 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -675,18 +675,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us Mod_ClearAll (); Hunk_FreeToLowMark (host_hunklevel); - if (svs.gametype == GT_PROGS) - { - for (i = 0; i < MAX_LIGHTSTYLES; i++) - { - if (sv.strings.lightstyles[i]) - Z_Free(sv.strings.lightstyles[i]); - sv.strings.lightstyles[i] = NULL; - - sv.strings.lightstylecolours[i] = 7; - } - } - #ifdef USEODE World_ODE_End(&sv.world); #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 30bb77d4..fced3adc 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -259,6 +259,22 @@ void SV_Shutdown (void) if (sv.mvdrecording) SV_MVDStop (0, false); + if (svs.entstatebuffer.entities) + { + BZ_Free(svs.entstatebuffer.entities); + memset(&svs.entstatebuffer.entities, 0, sizeof(svs.entstatebuffer.entities)); + } + if (sv_staticentities) + { + sv_max_staticentities = 0; + sv.num_static_entities = 0; + BZ_Free(sv_staticentities); + sv_staticentities = NULL; + } + + + SV_GibFilterPurge(); + NET_Shutdown (); #ifdef WEBSERVER IWebShutdown(); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 943652ff..564135bb 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -1869,7 +1869,12 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) continue; } - if (!ent) + if (demo.recorder.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + { + MSG_WriteByte(&buf, svcfte_spawnbaseline2); + SVQW_WriteDelta(&from, state, &buf, true, demo.recorder.fteprotocolextensions); + } + else if (!ent) { MSG_WriteByte(&buf, svc_spawnbaseline); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index f20e9aa5..aa8a9fbc 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1029,7 +1029,13 @@ static void WPhys_CheckWaterTransition (world_t *w, wedict_t *ent) return; } - if (cont <= Q1CONTENTS_WATER) + if (ent->v->watertype != cont && w->Event_ContentsTransition(w, ent, ent->v->watertype, cont)) + { + ent->v->watertype = cont; + ent->v->waterlevel = 1; + } + + else if (cont <= Q1CONTENTS_WATER) { if (ent->v->watertype == Q1CONTENTS_EMPTY && *sv_sound_watersplash.string) { // just crossed into water @@ -1223,7 +1229,7 @@ static void WPhys_Physics_Step (world_t *w, wedict_t *ent) if ( (int)ent->v->flags & FL_ONGROUND ) // just hit ground { - if (hitsound) + if (hitsound && *sv_sound_land.string) { w->Event_Sound(ent, 0, sv_sound_land.string, 255, 1, 0); } @@ -1798,7 +1804,6 @@ void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *init } } -#define FL_JUMPRELEASED 4096 /* ================ SV_RunEntity diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 7a1af9fe..254f72ba 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1166,10 +1166,21 @@ void SV_Modellist_f (void) SV_PreSpawn_f ================== */ +enum +{ + PRESPAWN_MAPCHECK=0, + PRESPAWN_SIGNON_BUF, + PRESPAWN_SPAWNSTATIC, + PRESPAWN_CUSTOMTENTS, + PRESPAWN_BASELINES, + PRESPAWN_DONE +}; void SVQW_PreSpawn_f (void) { - unsigned initbuf, buf, start; + unsigned initbuf; unsigned check; + unsigned int ps_type; + unsigned int ps_idx; if (host_client->state != cs_connected) { @@ -1185,9 +1196,12 @@ void SVQW_PreSpawn_f (void) return; } - buf = initbuf = atoi(Cmd_Argv(2)); + initbuf = atoi(Cmd_Argv(2)); - if (!buf) + ps_type = (initbuf & 0xff000000) >> 24; + ps_idx = (initbuf & 0x00ffffff); + + if (ps_type == PRESPAWN_MAPCHECK) { // should be three numbers following containing checksums check = COM_RemapMapChecksum(atoi(Cmd_Argv(3))); @@ -1213,6 +1227,8 @@ void SVQW_PreSpawn_f (void) return; } host_client->checksum = check; + ps_type++; + ps_idx = 0; } //NOTE: This doesn't go through ClientReliableWrite since it's before the user @@ -1242,51 +1258,60 @@ void SVQW_PreSpawn_f (void) #endif { int i; - entity_state_t from; entity_state_t *state; edict_t *ent; svcustomtents_t *ctent; - start = 0; - if (buf >= start) + if (ps_type == PRESPAWN_SIGNON_BUF) { - while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //static entities + while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) { - i = buf - start; - if (i >= sv.num_signon_buffers) + if (ps_idx >= sv.num_signon_buffers) + { + ps_type++; + ps_idx = 0; break; + } - if (host_client->netchan.message.cursize+sv.signon_buffer_size[i]+30 < host_client->netchan.message.maxsize) + if (host_client->netchan.message.cursize+sv.signon_buffer_size[ps_idx]+30 < host_client->netchan.message.maxsize) { SZ_Write (&host_client->netchan.message, - sv.signon_buffers[i], - sv.signon_buffer_size[i]); - buf++; + sv.signon_buffers[ps_idx], + sv.signon_buffer_size[ps_idx]); } else break; + ps_idx++; } } - start += sv.num_signon_buffers; - if (buf >= start) + if (ps_type == PRESPAWN_SPAWNSTATIC) { - memset(&from, 0, sizeof(from)); while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //static entities { - if (buf - start >= sv.num_static_entities) + if (ps_idx >= sv.num_static_entities) + { + ps_type++; + ps_idx = 0; break; + } - state = &sv_staticentities[buf - start]; - buf++; + state = &sv_staticentities[ps_idx]; + ps_idx++; + if (host_client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + { + MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic2); + SVFTE_EmitBaseline(state, false, &host_client->netchan.message); + continue; + } if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2) { /*if it uses some new feature, use the updated spawnstatic*/ if (state->hexen2flags || state->trans || state->modelindex >= 256 || state->frame > 255 || state->scale || state->abslight) { MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic2); - SVQW_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); + SVQW_WriteDelta(&nullentitystate, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); continue; } } @@ -1310,98 +1335,93 @@ void SVQW_PreSpawn_f (void) } } } - start += sv.num_static_entities; - if (buf >= start) + if (ps_type == PRESPAWN_CUSTOMTENTS) { while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) { - i = buf - start; - if (i >= 255) - break; - - ctent = &sv.customtents[i]; - - buf++; - if (!*ctent->particleeffecttype) - { //effect isn't registered. - continue; - } - - if (host_client->fteprotocolextensions & PEXT_CUSTOMTEMPEFFECTS) + if (ps_idx >= 255) { - MSG_WriteByte(&host_client->netchan.message, svcfte_customtempent); - MSG_WriteByte(&host_client->netchan.message, 255); - MSG_WriteByte(&host_client->netchan.message, i); - MSG_WriteByte(&host_client->netchan.message, ctent->netstyle); - MSG_WriteString(&host_client->netchan.message, ctent->particleeffecttype); - if (ctent->netstyle & CTE_STAINS) + ps_type++; + ps_idx = 0; + break; + } + + ctent = &sv.customtents[ps_idx]; + + if (*ctent->particleeffecttype) + { + if (host_client->fteprotocolextensions & PEXT_CUSTOMTEMPEFFECTS) { - MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); - MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); - MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); - MSG_WriteByte(&host_client->netchan.message, ctent->radius); - } - if (ctent->netstyle & CTE_GLOWS) - { - MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[0]); - MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[1]); - MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[2]); - MSG_WriteByte(&host_client->netchan.message, ctent->dlightradius); - MSG_WriteByte(&host_client->netchan.message, ctent->dlighttime); + MSG_WriteByte(&host_client->netchan.message, svcfte_customtempent); + MSG_WriteByte(&host_client->netchan.message, 255); + MSG_WriteByte(&host_client->netchan.message, ps_idx); + MSG_WriteByte(&host_client->netchan.message, ctent->netstyle); + MSG_WriteString(&host_client->netchan.message, ctent->particleeffecttype); + if (ctent->netstyle & CTE_STAINS) + { + MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); + MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); + MSG_WriteChar(&host_client->netchan.message, ctent->stain[0]); + MSG_WriteByte(&host_client->netchan.message, ctent->radius); + } + if (ctent->netstyle & CTE_GLOWS) + { + MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[0]); + MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[1]); + MSG_WriteByte(&host_client->netchan.message, ctent->dlightrgb[2]); + MSG_WriteByte(&host_client->netchan.message, ctent->dlightradius); + MSG_WriteByte(&host_client->netchan.message, ctent->dlighttime); + } } } + ps_idx++; } } - start += 255; - if (buf >= start) + if (ps_type == PRESPAWN_BASELINES) { while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //baselines { - if (buf - start >= sv.world.num_edicts) + if (ps_idx >= sv.world.num_edicts) + { + ps_type++; + ps_idx = 0; break; + } - ent = EDICT_NUM(svprogfuncs, buf - start); + ent = EDICT_NUM(svprogfuncs, ps_idx); + + if (!ent) + state = &nullentitystate; + else + state = &ent->baseline; - state = &ent->baseline; if (!state->number || !state->modelindex) { //ent doesn't have a baseline - buf++; + ps_idx++; continue; } - if (!ent) - { - MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); - - MSG_WriteShort (&host_client->netchan.message, buf - start); - - MSG_WriteByte (&host_client->netchan.message, 0); - - MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteByte (&host_client->netchan.message, 0); - for (i=0 ; i<3 ; i++) - { - MSG_WriteCoord(&host_client->netchan.message, 0); - MSG_WriteAngle(&host_client->netchan.message, 0); - } - } - else if (state->number >= host_client->max_net_ents || state->modelindex >= host_client->maxmodels) + if (state->number >= host_client->max_net_ents || state->modelindex >= host_client->maxmodels) { /*can't send this ent*/ } + else if (host_client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + { + MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2); + SVFTE_EmitBaseline(state, true, &host_client->netchan.message); + } else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2) { MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2); - SVQW_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); + SVQW_WriteDelta(&nullentitystate, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); } else if (state->modelindex < 256) { MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); - MSG_WriteShort (&host_client->netchan.message, buf - start); + MSG_WriteShort (&host_client->netchan.message, ps_idx); MSG_WriteByte (&host_client->netchan.message, state->modelindex); @@ -1415,13 +1435,12 @@ void SVQW_PreSpawn_f (void) } } - buf++; + ps_idx++; } } - start += sv.world.num_edicts; } - if (initbuf >= start) + if (ps_type > PRESPAWN_DONE || (ps_type == PRESPAWN_DONE && ps_idx)) { SV_EndRedirect(); Con_Printf ("SV_Modellist_f: %s send an invalid index\n", host_client->name); @@ -1429,7 +1448,7 @@ void SVQW_PreSpawn_f (void) return; } - if (buf == start) + if (ps_type == PRESPAWN_DONE) { // all done prespawning MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i\n",svs.spawncount) ); @@ -1438,7 +1457,7 @@ void SVQW_PreSpawn_f (void) { // need to prespawn more MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, - va("cmd prespawn %i %i\n", svs.spawncount, buf) ); + va("cmd prespawn %i %i\n", svs.spawncount, (ps_type<<24) | ps_idx) ); } } @@ -4350,10 +4369,10 @@ void Cmd_FPSList_f(void) void SV_EnableClientsCSQC(void) { #ifdef PEXT_CSQC - if (host_client->fteprotocolextensions & PEXT_CSQC || atoi(Cmd_Argv(1))) +// if ((host_client->fteprotocolextensions & PEXT_CSQC) || atoi(Cmd_Argv(1))) host_client->csqcactive = true; - else - SV_ClientPrintf(host_client, PRINT_HIGH, "CSQC entities not enabled - no support from network protocol\n"); +// else +// SV_ClientPrintf(host_client, PRINT_HIGH, "CSQC entities not enabled - no support from network protocol\n"); #endif } void SV_DisableClientsCSQC(void) @@ -5723,7 +5742,6 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) oldvz = sv_player->v->velocity[2]; if (progstype != PROG_QW) { -#define FL_JUMPRELEASED 4096 jumpable = ((int)sv_player->v->flags & FL_JUMPRELEASED) && ((int)sv_player->v->flags & FL_ONGROUND); pmove.waterjumptime = sv_player->v->teleport_time; diff --git a/engine/server/svhl_game.c b/engine/server/svhl_game.c index 6844acfe..a0a57459 100644 --- a/engine/server/svhl_game.c +++ b/engine/server/svhl_game.c @@ -6,13 +6,26 @@ I think globals.maxentities is the hard cap, rather than current max like in q1. #ifdef HLSERVER +#include "winquake.h" #include "svhl_gcapi.h" +#include "pr_common.h" #include "crc.h" #include "model_hl.h" +#if defined(_MSC_VER) + #if _MSC_VER >= 1300 + #define __func__ __FUNCTION__ + #else + #define __func__ "unknown" + #endif +#else + //I hope you're c99 and have a __func__ +#endif + #define ignore(s) Con_Printf("Fixme: " s "\n") -#define notimp(l) Con_Printf("halflife sv builtin not implemented on line %i\n", l) +#define notimpl(l) Con_Printf("halflife sv builtin not implemented on line %i\n", l) +#define notimpf(f) Con_Printf("halflife sv builtin %s not implemented\n", f) dllhandle_t *hlgamecode; @@ -61,7 +74,7 @@ int QDECL GHL_PrecacheModel(char *name) if (sv.state != ss_loading) { - Con_DPrintf("Delayed model precache: %s\n", s); + Con_DPrintf("Delayed model precache: %s\n", name); MSG_WriteByte(&sv.reliable_datagram, svcfte_precache); MSG_WriteShort(&sv.reliable_datagram, i); MSG_WriteString(&sv.reliable_datagram, name); @@ -106,7 +119,7 @@ int QDECL GHL_PrecacheSound(char *name) if (sv.state != ss_loading) { - Con_DPrintf("Delayed sound precache: %s\n", s); + Con_DPrintf("Delayed sound precache: %s\n", name); MSG_WriteByte(&sv.reliable_datagram, svcfte_precache); MSG_WriteShort(&sv.reliable_datagram, -i); MSG_WriteString(&sv.reliable_datagram, name); @@ -143,7 +156,7 @@ void QDECL GHL_SetModel(hledict_t *ed, char *modelname) } SVHL_LinkEdict(ed, false); } -unk QDECL GHL_ModelIndex(unk){notimp(__LINE__);} +unk QDECL GHL_ModelIndex(unk){notimpf(__func__);} int QDECL GHL_ModelFrames(int midx) { //returns the number of frames(sequences I assume) this model has @@ -160,8 +173,8 @@ void QDECL GHL_ChangeLevel(char *nextmap, char *startspot) { Cbuf_AddText(va("changelevel %s %s@%f@%f@%f\n", nextmap, startspot, SVHL_Globals.landmark[0], SVHL_Globals.landmark[1], SVHL_Globals.landmark[2]), RESTRICT_PROGS); } -unk QDECL GHL_GetSpawnParms(unk){notimp(__LINE__);} -unk QDECL GHL_SaveSpawnParms(unk){notimp(__LINE__);} +unk QDECL GHL_GetSpawnParms(unk){notimpf(__func__);} +unk QDECL GHL_SaveSpawnParms(unk){notimpf(__func__);} float QDECL GHL_VecToYaw(float *inv) { vec3_t outa; @@ -173,9 +186,9 @@ void QDECL GHL_VecToAngles(float *inv, float *outa) { VectorAngles(inv, NULL, outa); } -unk QDECL GHL_MoveToOrigin(unk){notimp(__LINE__);} -unk QDECL GHL_ChangeYaw(unk){notimp(__LINE__);} -unk QDECL GHL_ChangePitch(unk){notimp(__LINE__);} +unk QDECL GHL_MoveToOrigin(unk){notimpf(__func__);} +unk QDECL GHL_ChangeYaw(unk){notimpf(__func__);} +unk QDECL GHL_ChangePitch(unk){notimpf(__func__);} hledict_t *QDECL GHL_FindEntityByString(hledict_t *last, char *field, char *value) { hledict_t *ent; @@ -207,7 +220,7 @@ hledict_t *QDECL GHL_FindEntityByString(hledict_t *last, char *field, char *valu } return SVHL_Edict; } -unk QDECL GHL_GetEntityIllum(unk){notimp(__LINE__);} +unk QDECL GHL_GetEntityIllum(unk){notimpf(__func__);} hledict_t *QDECL GHL_FindEntityInSphere(hledict_t *last, float *org, float radius) { int i, j; @@ -250,7 +263,7 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed) //fixme: we need to track some state //a different client should be returned each call _per ent_ (so it can be used once per frame) - viewerpvs = sv.worldmodel->funcs.LeafPVS(sv.worldmodel, sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, ed->v.origin), NULL, 0); + viewerpvs = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, ed->v.origin), NULL, 0); for (i = 0; i < MAX_CLIENTS; i++) { @@ -262,7 +275,7 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed) if (svs.clients[i].spectator) continue; //ignore spectators - leafnum = sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, other->v.origin)-1;/*pvs is 1 based, leafs are 0 based*/ + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, other->v.origin)-1;/*pvs is 1 based, leafs are 0 based*/ if (viewerpvs[leafnum>>3] & (1<<(leafnum&7))) { VectorSubtract(ed->v.origin, other->v.origin, ofs); @@ -281,7 +294,7 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed) return &SVHL_Edict[best]; return NULL; } -unk QDECL GHL_EntitiesInPVS(unk){notimp(__LINE__);} +unk QDECL GHL_EntitiesInPVS(unk){notimpf(__func__);} void QDECL GHL_MakeVectors(float *angles) { AngleVectors(angles, SVHL_Globals.v_forward, SVHL_Globals.v_right, SVHL_Globals.v_up); @@ -352,15 +365,15 @@ void *QDECL GHL_PvAllocEntPrivateData(hledict_t *ed, long quant) } unk QDECL GHL_PvEntPrivateData(unk) { - notimp(__LINE__); + notimpf(__func__); } unk QDECL GHL_FreeEntPrivateData(unk) { - notimp(__LINE__); + notimpf(__func__); } unk QDECL GHL_GetVarsOfEnt(unk) { - notimp(__LINE__); + notimpf(__func__); } hledict_t *QDECL GHL_PEntityOfEntOffset(int ednum) { @@ -380,13 +393,13 @@ hledict_t *QDECL GHL_PEntityOfEntIndex(int idx) } unk QDECL GHL_FindEntityByVars(unk) { - notimp(__LINE__); + notimpf(__func__); } /////////////////////////////////////////////////////// -unk QDECL GHL_MakeStatic(unk){notimp(__LINE__);} -unk QDECL GHL_EntIsOnFloor(unk){notimp(__LINE__);} +unk QDECL GHL_MakeStatic(unk){notimpf(__func__);} +unk QDECL GHL_EntIsOnFloor(unk){notimpf(__func__);} int QDECL GHL_DropToFloor(hledict_t *ed) { vec3_t top; @@ -416,7 +429,7 @@ void QDECL GHL_EmitSound(hledict_t *ed, int chan, char *soundname, float vol, fl } void QDECL GHL_EmitAmbientSound(hledict_t *ed, float *org, char *soundname, float vol, float atten, unsigned int flags, int pitch) { - SV_StartSound(0, org, ~0, 0, soundname, vol*255, atten); + SV_StartSound(0, org, ~0, 0, soundname, vol*255, atten, 0); } void QDECL GHL_TraceLine(float *start, float *end, int flags, hledict_t *ignore, hltraceresult_t *result) { @@ -437,13 +450,13 @@ void QDECL GHL_TraceLine(float *start, float *end, int flags, hledict_t *ignore, result->touched = &SVHL_Edict[0]; result->hitgroup = 0; } -unk QDECL GHL_TraceToss(unk){notimp(__LINE__);} -unk QDECL GHL_TraceMonsterHull(unk){notimp(__LINE__);} +unk QDECL GHL_TraceToss(unk){notimpf(__func__);} +unk QDECL GHL_TraceMonsterHull(unk){notimpf(__func__);} void QDECL GHL_TraceHull(float *start, float *end, int flags, int hullnum, hledict_t *ignore, hltraceresult_t *result) { trace_t t; - t = SVHL_Move(start, sv.worldmodel->hulls[hullnum].clip_mins, sv.worldmodel->hulls[hullnum].clip_maxs, end, flags, 0, ignore); + t = SVHL_Move(start, sv.world.worldmodel->hulls[hullnum].clip_mins, sv.world.worldmodel->hulls[hullnum].clip_maxs, end, flags, 0, ignore); result->allsolid = t.allsolid; result->startsolid = t.startsolid; @@ -456,15 +469,15 @@ void QDECL GHL_TraceHull(float *start, float *end, int flags, int hullnum, hledi result->touched = t.ent; result->hitgroup = 0; } -unk QDECL GHL_TraceModel(unk){notimp(__LINE__);} +unk QDECL GHL_TraceModel(unk){notimpf(__func__);} char *QDECL GHL_TraceTexture(hledict_t *againstent, vec3_t start, vec3_t end) { trace_t tr; - sv.worldmodel->funcs.Trace(sv.worldmodel, 0, 0, start, end, vec3_origin, vec3_origin, &tr); + sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, MASK_WORLDSOLID, &tr); return tr.surface->name; } -unk QDECL GHL_TraceSphere(unk){notimp(__LINE__);} -unk QDECL GHL_GetAimVector(unk){notimp(__LINE__);} +unk QDECL GHL_TraceSphere(unk){notimpf(__func__);} +unk QDECL GHL_GetAimVector(unk){notimpf(__func__);} void QDECL GHL_ServerCommand(char *cmd) { Cbuf_AddText(cmd, RESTRICT_PROGS); @@ -473,8 +486,8 @@ void QDECL GHL_ServerExecute(void) { Cbuf_ExecuteLevel(RESTRICT_PROGS); } -unk QDECL GHL_ClientCommand(unk){notimp(__LINE__);} -unk QDECL GHL_ParticleEffect(unk){notimp(__LINE__);} +unk QDECL GHL_ClientCommand(unk){notimpf(__func__);} +unk QDECL GHL_ParticleEffect(unk){notimpf(__func__);} void QDECL GHL_LightStyle(int stylenum, char *stylestr) { PF_applylightstyle(stylenum, stylestr, 7); @@ -606,7 +619,7 @@ void QDECL GHL_EngineFprintf(FILE *f, char *fmt, ...) { SV_Error("Halflife gamecode tried to use EngineFprintf\n"); } -unk QDECL GHL_SzFromIndex(unk){notimp(__LINE__);} +unk QDECL GHL_SzFromIndex(unk){notimpf(__func__);} void *QDECL GHL_GetModelPtr(hledict_t *ed) { #ifdef SERVERONLY @@ -643,8 +656,8 @@ int QDECL GHL_RegUserMsg(char *msgname, int msgsize) return lastusermessage--; } -unk QDECL GHL_AnimationAutomove(unk){notimp(__LINE__);} -unk QDECL GHL_GetBonePosition(unk){notimp(__LINE__);} +unk QDECL GHL_AnimationAutomove(unk){notimpf(__func__);} +unk QDECL GHL_GetBonePosition(unk){notimpf(__func__);} hlintptr_t QDECL GHL_FunctionFromName(char *name) { @@ -658,7 +671,7 @@ char *QDECL GHL_NameForFunction(hlintptr_t function) unk QDECL GHL_ClientPrintf(unk) { // SV_ClientPrintf( - notimp(__LINE__); + notimpf(__func__); } void QDECL GHL_ServerPrint(char *msg) { @@ -676,7 +689,7 @@ int QDECL GHL_Cmd_Argc(unk) { return Cmd_Argc(); } -unk QDECL GHL_GetAttachment(unk){notimp(__LINE__);} +unk QDECL GHL_GetAttachment(unk){notimpf(__func__);} void QDECL GHL_CRC32_Init(hlcrc_t *crc) { unsigned short crc16 = *crc; @@ -711,9 +724,9 @@ float QDECL GHL_RandomFloat(float minv, float maxv) { return minv + frandom()*(maxv-minv); } -unk QDECL GHL_SetView(unk){notimp(__LINE__);} -unk QDECL GHL_Time(unk){notimp(__LINE__);} -unk QDECL GHL_CrosshairAngle(unk){notimp(__LINE__);} +unk QDECL GHL_SetView(unk){notimpf(__func__);} +unk QDECL GHL_Time(unk){notimpf(__func__);} +unk QDECL GHL_CrosshairAngle(unk){notimpf(__func__);} void *QDECL GHL_LoadFileForMe(char *name, int *size_out) { int fsize; @@ -729,7 +742,7 @@ void QDECL GHL_FreeFile(void *fptr) { FS_FreeFile(fptr); } -unk QDECL GHL_EndSection(unk){notimp(__LINE__);} +unk QDECL GHL_EndSection(unk){notimpf(__func__);} #include int QDECL GHL_CompareFileTime(char *fname1, char *fname2, int *result) { @@ -762,14 +775,14 @@ void QDECL GHL_GetGameDir(char *gamedir) //warning: the output buffer size is not specified! Q_strncpyz(gamedir, gamedirfile, MAX_QPATH); } -unk QDECL GHL_Cvar_RegisterVariable(unk){notimp(__LINE__);} -unk QDECL GHL_FadeClientVolume(unk){notimp(__LINE__);} +unk QDECL GHL_Cvar_RegisterVariable(unk){notimpf(__func__);} +unk QDECL GHL_FadeClientVolume(unk){notimpf(__func__);} unk QDECL GHL_SetClientMaxspeed(unk) { - notimp(__LINE__); + notimpf(__func__); } -unk QDECL GHL_CreateFakeClient(unk){notimp(__LINE__);} -unk QDECL GHL_RunPlayerMove(unk){notimp(__LINE__);} +unk QDECL GHL_CreateFakeClient(unk){notimpf(__func__);} +unk QDECL GHL_RunPlayerMove(unk){notimpf(__func__);} int QDECL GHL_NumberOfEntities(void) { return 0; @@ -785,11 +798,11 @@ char *QDECL GHL_InfoKeyValue(char *infostr, char *key) { return Info_ValueForKey(infostr, key); } -unk QDECL GHL_SetKeyValue(unk){notimp(__LINE__);} -unk QDECL GHL_SetClientKeyValue(unk){notimp(__LINE__);} -unk QDECL GHL_IsMapValid(unk){notimp(__LINE__);} -unk QDECL GHL_StaticDecal(unk){notimp(__LINE__);} -unk QDECL GHL_PrecacheGeneric(unk){notimp(__LINE__);} +unk QDECL GHL_SetKeyValue(unk){notimpf(__func__);} +unk QDECL GHL_SetClientKeyValue(unk){notimpf(__func__);} +unk QDECL GHL_IsMapValid(unk){notimpf(__func__);} +unk QDECL GHL_StaticDecal(unk){notimpf(__func__);} +unk QDECL GHL_PrecacheGeneric(unk){notimpf(__func__);} int QDECL GHL_GetPlayerUserId(hledict_t *ed) { unsigned int clnum = (ed - SVHL_Edict) - 1; @@ -797,7 +810,7 @@ int QDECL GHL_GetPlayerUserId(hledict_t *ed) return -1; return svs.clients[clnum].userid; } -unk QDECL GHL_BuildSoundMsg(unk){notimp(__LINE__);} +unk QDECL GHL_BuildSoundMsg(unk){notimpf(__func__);} int QDECL GHL_IsDedicatedServer(void) { @@ -956,11 +969,11 @@ void QDECL GHL_CVarSetString(char *vname, char *value) Con_Printf("cvar %s does not exist\n", vname); } -unk QDECL GHL_GetPlayerWONId(unk){notimp(__LINE__);} -unk QDECL GHL_Info_RemoveKey(unk){notimp(__LINE__);} -unk QDECL GHL_GetPhysicsKeyValue(unk){notimp(__LINE__);} -unk QDECL GHL_SetPhysicsKeyValue(unk){notimp(__LINE__);} -unk QDECL GHL_GetPhysicsInfoString(unk){notimp(__LINE__);} +unk QDECL GHL_GetPlayerWONId(unk){notimpf(__func__);} +unk QDECL GHL_Info_RemoveKey(unk){notimpf(__func__);} +unk QDECL GHL_GetPhysicsKeyValue(unk){notimpf(__func__);} +unk QDECL GHL_SetPhysicsKeyValue(unk){notimpf(__func__);} +unk QDECL GHL_GetPhysicsInfoString(unk){notimpf(__func__);} unsigned short QDECL GHL_PrecacheEvent(int eventtype, char *eventname) { Con_Printf("Fixme: GHL_PrecacheEvent: %s\n", eventname); @@ -970,42 +983,46 @@ void QDECL GHL_PlaybackEvent(int flags, hledict_t *ent, unsigned short eventidx, { ignore("GHL_PlaybackEvent not implemented"); } -unk QDECL GHL_SetFatPVS(unk){notimp(__LINE__);} -unk QDECL GHL_SetFatPAS(unk){notimp(__LINE__);} -unk QDECL GHL_CheckVisibility(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaSetField(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaUnsetField(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaAddEncoder(unk){notimp(__LINE__);} -unk QDECL GHL_GetCurrentPlayer(unk){notimp(__LINE__);} -unk QDECL GHL_CanSkipPlayer(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaFindField(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaSetFieldByIndex(unk){notimp(__LINE__);} -unk QDECL GHL_DeltaUnsetFieldByIndex(unk){notimp(__LINE__);} -unk QDECL GHL_SetGroupMask(unk){notimp(__LINE__);} -unk QDECL GHL_CreateInstancedBaseline(unk){notimp(__LINE__);} -unk QDECL GHL_Cvar_DirectSet(unk){notimp(__LINE__);} -unk QDECL GHL_ForceUnmodified(unk){notimp(__LINE__);} -unk QDECL GHL_GetPlayerStats(unk){notimp(__LINE__);} -unk QDECL GHL_AddServerCommand(unk){notimp(__LINE__);} -unk QDECL GHL_Voice_GetClientListening(unk){notimp(__LINE__);} +unk QDECL GHL_SetFatPVS(unk){notimpf(__func__);} +unk QDECL GHL_SetFatPAS(unk){notimpf(__func__);} +unk QDECL GHL_CheckVisibility(unk){notimpf(__func__);} +unk QDECL GHL_DeltaSetField(unk){notimpf(__func__);} +unk QDECL GHL_DeltaUnsetField(unk){notimpf(__func__);} +unk QDECL GHL_DeltaAddEncoder(unk){notimpf(__func__);} +unk QDECL GHL_GetCurrentPlayer(unk){notimpf(__func__);} +int QDECL GHL_CanSkipPlayer(hledict_t *playerent) +{ + return false; +// notimpf(__func__); +} +unk QDECL GHL_DeltaFindField(unk){notimpf(__func__);} +unk QDECL GHL_DeltaSetFieldByIndex(unk){notimpf(__func__);} +unk QDECL GHL_DeltaUnsetFieldByIndex(unk){notimpf(__func__);} +unk QDECL GHL_SetGroupMask(unk){notimpf(__func__);} +unk QDECL GHL_CreateInstancedBaseline(unk){notimpf(__func__);} +unk QDECL GHL_Cvar_DirectSet(unk){notimpf(__func__);} +unk QDECL GHL_ForceUnmodified(unk){notimpf(__func__);} +unk QDECL GHL_GetPlayerStats(unk){notimpf(__func__);} +unk QDECL GHL_AddServerCommand(unk){notimpf(__func__);} +unk QDECL GHL_Voice_GetClientListening(unk){notimpf(__func__);} qboolean QDECL GHL_Voice_SetClientListening(int listener, int sender, int shouldlisten) { return false; } -unk QDECL GHL_GetPlayerAuthId(unk){notimp(__LINE__);} -unk QDECL GHL_SequenceGet(unk){notimp(__LINE__);} -unk QDECL GHL_SequencePickSentence(unk){notimp(__LINE__);} -unk QDECL GHL_GetFileSize(unk){notimp(__LINE__);} -unk QDECL GHL_GetApproxWavePlayLen(unk){notimp(__LINE__);} -unk QDECL GHL_IsCareerMatch(unk){notimp(__LINE__);} -unk QDECL GHL_GetLocalizedStringLength(unk){notimp(__LINE__);} -unk QDECL GHL_RegisterTutorMessageShown(unk){notimp(__LINE__);} -unk QDECL GHL_GetTimesTutorMessageShown(unk){notimp(__LINE__);} -unk QDECL GHL_ProcessTutorMessageDecayBuffer(unk){notimp(__LINE__);} -unk QDECL GHL_ConstructTutorMessageDecayBuffer(unk){notimp(__LINE__);} -unk QDECL GHL_ResetTutorMessageDecayData(unk){notimp(__LINE__);} -unk QDECL GHL_QueryClientCvarValue(unk){notimp(__LINE__);} -unk QDECL GHL_QueryClientCvarValue2(unk){notimp(__LINE__);} +unk QDECL GHL_GetPlayerAuthId(unk){notimpf(__func__);} +unk QDECL GHL_SequenceGet(unk){notimpf(__func__);} +unk QDECL GHL_SequencePickSentence(unk){notimpf(__func__);} +unk QDECL GHL_GetFileSize(unk){notimpf(__func__);} +unk QDECL GHL_GetApproxWavePlayLen(unk){notimpf(__func__);} +unk QDECL GHL_IsCareerMatch(unk){notimpf(__func__);} +unk QDECL GHL_GetLocalizedStringLength(unk){notimpf(__func__);} +unk QDECL GHL_RegisterTutorMessageShown(unk){notimpf(__func__);} +unk QDECL GHL_GetTimesTutorMessageShown(unk){notimpf(__func__);} +unk QDECL GHL_ProcessTutorMessageDecayBuffer(unk){notimpf(__func__);} +unk QDECL GHL_ConstructTutorMessageDecayBuffer(unk){notimpf(__func__);} +unk QDECL GHL_ResetTutorMessageDecayData(unk){notimpf(__func__);} +unk QDECL GHL_QueryClientCvarValue(unk){notimpf(__func__);} +unk QDECL GHL_QueryClientCvarValue2(unk){notimpf(__func__);} @@ -1220,7 +1237,7 @@ int SVHL_InitGame(void) char *gamedll; char *path; char fullname[MAX_OSPATH]; - void (QDECL *GiveFnptrsToDll) (funcs, globals); + void (WINAPI *GiveFnptrsToDll) (funcs, globals); int (QDECL *GetEntityAPI)(SVHL_GameFuncs_t *pFunctionTable, int apivers); dllfunction_t hlgamefuncs[] = @@ -1245,16 +1262,20 @@ int SVHL_InitGame(void) return 1; } - gamedll = Info_ValueForKey(svs.info, "*gamedll"); - path = NULL; - while((path = COM_NextPath (path))) + hlgamecode = Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/dlls/debugmp/mp.dll", hlgamefuncs); + if (!hlgamecode) { - if (!path) - return 0; // couldn't find one anywhere - snprintf (fullname, sizeof(fullname), "%s/%s", path, gamedll); - hlgamecode = Sys_LoadLibrary(fullname, hlgamefuncs); - if (hlgamecode) - break; + gamedll = Info_ValueForKey(svs.info, "*gamedll"); + path = NULL; + while((path = COM_NextPath (path))) + { + if (!path) + return 0; // couldn't find one anywhere + snprintf (fullname, sizeof(fullname), "%s/%s", path, gamedll); + hlgamecode = Sys_LoadLibrary(fullname, hlgamefuncs); + if (hlgamecode) + break; + } } if (!hlgamecode) @@ -1332,7 +1353,7 @@ void SVHL_SpawnEntities(char *entstring) //precache the inline models (and touch them). sv.strings.model_precache[0] = ""; sv.strings.model_precache[1] = sv.modelname; //the qvm doesn't have access to this array - for (i=1 ; inumsubmodels ; i++) + for (i=1 ; inumsubmodels ; i++) { sv.strings.model_precache[1+i] = localmodels[i]; sv.models[i+1] = Mod_ForName (localmodels[i], false); @@ -1499,8 +1520,10 @@ extern vec3_t player_maxs; pmove.cmd = *ucmd; pmove.pm_type = temp1.value;//PM_NORMAL;//FLY; pmove.numphysent = 1; - pmove.physents[0].model = sv.worldmodel; + pmove.physents[0].model = sv.world.worldmodel; pmove.physents[0].info = 0; + pmove.skipent = -1; + pmove.onladder = false; if (ed->v.flags & (1<<24)) { @@ -1554,7 +1577,7 @@ extern vec3_t player_maxs; pe->forcecontentsmask = FTECONTENTS_SKY; break; case -16: - pe->forcecontentsmask = Q2CONTENTS_LADDER; + pe->forcecontentsmask = FTECONTENTS_LADDER; break; default: pe->forcecontentsmask = 0; @@ -1738,8 +1761,17 @@ void SVHL_Snapshot_Build(client_t *client, packet_entities_t *pack, qbyte *pvs, } } -void SVHL_Snapshot_SetupPVS(client_t *client, qbyte *pvs, unsigned int pvsbufsize) +qbyte *SVHL_Snapshot_SetupPVS(client_t *client, qbyte *pvs, unsigned int pvsbufsize) { + vec3_t org; + + if (client->hledict) + { + VectorAdd (client->hledict->v.origin, client->hledict->v.view_ofs, org); + sv.world.worldmodel->funcs.FatPVS(sv.world.worldmodel, org, pvs, pvsbufsize, false); + } + + return pvs; } #endif diff --git a/engine/server/svhl_gcapi.h b/engine/server/svhl_gcapi.h index e15e8126..31c8ec53 100644 --- a/engine/server/svhl_gcapi.h +++ b/engine/server/svhl_gcapi.h @@ -535,7 +535,7 @@ typedef struct unk (QDECL *DeltaUnsetField)(unk); unk (QDECL *DeltaAddEncoder)(unk); unk (QDECL *GetCurrentPlayer)(unk); - unk (QDECL *CanSkipPlayer)(unk); + int (QDECL *CanSkipPlayer)(hledict_t *playerent); unk (QDECL *DeltaFindField)(unk); unk (QDECL *DeltaSetFieldByIndex)(unk); unk (QDECL *DeltaUnsetFieldByIndex)(unk); diff --git a/engine/server/svhl_phys.c b/engine/server/svhl_phys.c index ad363f74..c302aca8 100644 --- a/engine/server/svhl_phys.c +++ b/engine/server/svhl_phys.c @@ -142,11 +142,11 @@ qboolean SVHL_RunThink (hledict_t *ent) if (1) //try and imitate nq as closeley as possible { thinktime = ent->v.nextthink; - if (thinktime <= 0 || thinktime > sv.physicstime + host_frametime) + if (thinktime <= 0 || thinktime > sv.world.physicstime + host_frametime) return true; - if (thinktime < sv.physicstime) - thinktime = sv.physicstime; // don't let things stay in the past. + if (thinktime < sv.world.physicstime) + thinktime = sv.world.physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v.nextthink = 0; @@ -161,11 +161,11 @@ qboolean SVHL_RunThink (hledict_t *ent) thinktime = ent->v.nextthink; if (thinktime <= 0) return true; - if (thinktime > sv.physicstime + host_frametime) + if (thinktime > sv.world.physicstime + host_frametime) return true; - if (thinktime < sv.physicstime) - thinktime = sv.physicstime; // don't let things stay in the past. + if (thinktime < sv.world.physicstime) + thinktime = sv.world.physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v.nextthink = 0; @@ -192,7 +192,7 @@ Two entities have touched, so run their touch functions */ void SVHL_Impact (hledict_t *e1, hledict_t *e2) { - SVHL_Globals.time = sv.physicstime; + SVHL_Globals.time = sv.world.physicstime; if (e1->v.solid != SOLID_NOT) { SVHL_GameFuncs.DispatchTouch(e1, e2); @@ -212,7 +212,20 @@ ClipVelocity Slide off of the impacting object ================== */ -void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce); +#define STOP_EPSILON 0.1 +//courtesy of darkplaces, it's just more efficient. +static void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) +{ + int i; + float backoff; + + backoff = -DotProduct (in, normal) * overbounce; + VectorMA(in, backoff, normal, out); + + for (i = 0;i < 3;i++) + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + out[i] = 0; +} /* @@ -624,7 +637,7 @@ qboolean SVHL_PushAngles (hledict_t *pusher, vec3_t move, vec3_t amove) //FIXME: is there a better way to handle this? // see if anything we moved has touched a trigger for (p=pushed_p-1 ; p>=pushed ; p--) - SVHL_TouchLinks ( p->ent, sv_areanodes ); + SVHL_TouchLinks ( p->ent, sv.world.areanodes ); return true; } @@ -831,7 +844,7 @@ float l; VectorCopy (ent->v.angles, oldang); ent->v.nextthink = 0; - SVHL_Globals.time = sv.physicstime; + SVHL_Globals.time = sv.world.physicstime; SVHL_GameFuncs.DispatchThink(ent); if (ent->isfree) return; @@ -851,7 +864,7 @@ float l; else if (ent->v.flags & (1<<21)) { ent->v.nextthink = 0; - SVHL_Globals.time = sv.physicstime; + SVHL_Globals.time = sv.world.physicstime; SVHL_GameFuncs.DispatchThink(ent); if (ent->isfree) return; @@ -1810,7 +1823,7 @@ void SVHL_RunFrame (void) SVHL_Globals.frametime = host_frametime; - SVHL_Globals.time = sv.physicstime; + SVHL_Globals.time = sv.world.physicstime; SVHL_GameFuncs.StartFrame (); diff --git a/engine/server/svhl_world.c b/engine/server/svhl_world.c index f341a43d..24781bd1 100644 --- a/engine/server/svhl_world.c +++ b/engine/server/svhl_world.c @@ -24,7 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HLSERVER #include "svhl_gcapi.h" -qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace, vec3_t origin, vec3_t angles); +hull_t *World_HullForBox (vec3_t mins, vec3_t maxs); +qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask); /* entities never clip against themselves, or their owner @@ -45,6 +46,7 @@ typedef struct int type; hledict_t *passedict; int hullnum; + unsigned int clipmask; } hlmoveclip_t; /* @@ -94,7 +96,7 @@ void SVHL_TouchLinks ( hledict_t *ent, areanode_t *node ) int linkcount = 0, ln; //work out who they are first. - for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) + for (l = node->edicts.next ; l != &node->edicts ; l = next) { if (linkcount == MAX_NODELINKS) break; @@ -268,7 +270,7 @@ void SVHL_LinkEdict (hledict_t *ent, qboolean touch_triggers) // sv.worldmodel->funcs.FindTouchedLeafs_Q1(sv.worldmodel, ent, ent->v.absmin, ent->v.absmax); // find the first node that the ent's box crosses - node = sv_areanodes; + node = sv.world.areanodes; while (1) { if (node->axis == -1) @@ -283,11 +285,11 @@ void SVHL_LinkEdict (hledict_t *ent, qboolean touch_triggers) // link it in - InsertLinkBefore (&ent->area, &node->solid_edicts); + InsertLinkBefore (&ent->area, &node->edicts); // if touch_triggers, touch all entities at this node and decend for more if (touch_triggers) - SVHL_TouchLinks ( ent, sv_areanodes ); + SVHL_TouchLinks ( ent, sv.world.areanodes ); } @@ -307,7 +309,7 @@ SV_PointContents */ int SVHL_PointContents (vec3_t p) { - return sv.worldmodel->funcs.PointContents(sv.worldmodel, p); + return sv.world.worldmodel->funcs.PointContents(sv.world.worldmodel, NULL, p); } //=========================================================================== @@ -340,7 +342,7 @@ Handles selection or creation of a clipping hull, and offseting (and eventually rotation) of the end points ================== */ -trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel) //hullnum overrides min/max for q1 style bsps +trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel, unsigned int clipmask) //hullnum overrides min/max for q1 style bsps { trace_t trace; model_t *model; @@ -370,7 +372,7 @@ trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t vec3_t boxmins, boxmaxs; VectorSubtract (ent->v.mins, maxs, boxmins); VectorSubtract (ent->v.maxs, mins, boxmaxs); - SV_HullForBox(boxmins, boxmaxs); + World_HullForBox(boxmins, boxmaxs); model = NULL; } @@ -378,12 +380,12 @@ trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t if (ent->v.solid != SOLID_BSP) { ent->v.angles[0]*=-1; //carmack made bsp models rotate wrongly. - TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles, clipmask); ent->v.angles[0]*=-1; } else { - TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles, clipmask); } // fix trace up by the offset @@ -403,10 +405,10 @@ trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t model = sv.models[(int)ent->v.modelindex] = Mod_ForName(sv.strings.model_precache[(int)ent->v.modelindex], false); } - if (model && model->funcs.Trace) + if (model && model->funcs.NativeTrace) { //do the second trace - TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles, MASK_WORLDSOLID); } } @@ -437,7 +439,7 @@ void SVHL_AreaEdicts_r (areanode_t *node) count = 0; // touch linked edicts - start = &node->solid_edicts; + start = &node->edicts; for (l=start->next ; l != start ; l = next) { @@ -487,7 +489,7 @@ int SVHL_AreaEdicts (vec3_t mins, vec3_t maxs, hledict_t **list, int maxcount) area_count = 0; area_maxcount = maxcount; - SVHL_AreaEdicts_r (sv_areanodes); + SVHL_AreaEdicts_r (sv.world.areanodes); return area_count; } @@ -509,7 +511,7 @@ void SVHL_ClipToEverything (hlmoveclip_t *clip) int e; trace_t trace; hledict_t *touch; - for (e=1 ; ev.flags & FL_MONSTER) - trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->clipmask); else - trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->clipmask); if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { @@ -588,7 +590,7 @@ void SVHL_ClipToLinks ( areanode_t *node, hlmoveclip_t *clip ) trace_t trace; // touch linked edicts - for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) + for (l = node->edicts.next ; l != &node->edicts ; l = next) { next = l->next; touch = HLEDICT_FROM_AREA(l); @@ -638,9 +640,9 @@ void SVHL_ClipToLinks ( areanode_t *node, hlmoveclip_t *clip ) } if ((int)touch->v.flags & FL_MONSTER) - trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->clipmask); else - trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->clipmask); if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { @@ -659,6 +661,31 @@ void SVHL_ClipToLinks ( areanode_t *node, hlmoveclip_t *clip ) SVHL_ClipToLinks ( node->children[1], clip ); } +static void SVHL_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) +{ +#if 0 +// debug to test against everything +boxmins[0] = boxmins[1] = boxmins[2] = -9999; +boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999; +#else + int i; + + for (i=0 ; i<3 ; i++) + { + if (end[i] > start[i]) + { + boxmins[i] = start[i] + mins[i] - 1; + boxmaxs[i] = end[i] + maxs[i] + 1; + } + else + { + boxmins[i] = end[i] + mins[i] - 1; + boxmaxs[i] = start[i] + maxs[i] + 1; + } + } +#endif +} + /* ================== SV_Move @@ -685,13 +712,13 @@ trace_t SVHL_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, //z pos/height are assumed to be different from all the others. for (i = 0; i < MAX_MAP_HULLSM; i++) { - if (!sv.worldmodel->hulls[i].available) + if (!sv.world.worldmodel->hulls[i].available) continue; #define sq(x) ((x)*(x)) - diff = sq(sv.worldmodel->hulls[i].clip_maxs[2] - maxs[2]) + - sq(sv.worldmodel->hulls[i].clip_mins[2] - mins[2]) + - sq(sv.worldmodel->hulls[i].clip_maxs[1] - maxs[1]) + - sq(sv.worldmodel->hulls[i].clip_mins[0] - mins[0]); + diff = sq(sv.world.worldmodel->hulls[i].clip_maxs[2] - maxs[2]) + + sq(sv.world.worldmodel->hulls[i].clip_mins[2] - mins[2]) + + sq(sv.world.worldmodel->hulls[i].clip_maxs[1] - maxs[1]) + + sq(sv.world.worldmodel->hulls[i].clip_mins[0] - mins[0]); if (diff < best) { best = diff; @@ -701,8 +728,15 @@ trace_t SVHL_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, hullnum++; } + if (type & MOVE_NOMONSTERS) + clip.clipmask = MASK_WORLDSOLID; /*solid only to world*/ + else if (maxs[0] - mins[0]) + clip.clipmask = MASK_BOXSOLID; /*impacts playerclip*/ + else + clip.clipmask = MASK_POINTSOLID; /*ignores playerclip but hits everything else*/ + // clip to world - clip.trace = SVHL_ClipMoveToEntity ( &SVHL_Edict[0], start, mins, maxs, end, hullnum, false); + clip.trace = SVHL_ClipMoveToEntity ( &SVHL_Edict[0], start, mins, maxs, end, hullnum, false, clip.clipmask); clip.start = start; clip.end = end; @@ -727,13 +761,13 @@ trace_t SVHL_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, } // create the bounding box of the entire move - SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); + SVHL_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); // clip to entities if (clip.type & MOVE_EVERYTHING) SVHL_ClipToEverything (&clip); else - SVHL_ClipToLinks ( sv_areanodes, &clip ); + SVHL_ClipToLinks ( sv.world.areanodes, &clip ); if (clip.trace.startsolid) clip.trace.fraction = 0; diff --git a/engine/server/world.c b/engine/server/world.c index 91b9a6e7..5bf8756c 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -107,7 +107,7 @@ To keep everything totally uniform, bounding boxes are turned into small BSP trees instead of being compared directly. =================== */ -static hull_t *World_HullForBox (vec3_t mins, vec3_t maxs) +hull_t *World_HullForBox (vec3_t mins, vec3_t maxs) { box_planes[0].dist = maxs[0]; box_planes[1].dist = mins[0]; @@ -1701,7 +1701,9 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e } #endif - if (type & MOVE_NOMONSTERS) + if (passedict->xv->hitcontentsmask) + clip.hitcontentsmask = passedict->xv->hitcontentsmask; + else if (type & MOVE_NOMONSTERS) clip.hitcontentsmask = MASK_WORLDSOLID; /*solid only to world*/ else if (maxs[0] - mins[0]) clip.hitcontentsmask = MASK_BOXSOLID; /*impacts playerclip*/ diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl index 1a2bcbb7..a74c1b58 100644 --- a/engine/shaders/glsl/defaultwall.glsl +++ b/engine/shaders/glsl/defaultwall.glsl @@ -95,7 +95,7 @@ void main () lightmaps += texture2D(s_t7, lm4) * e_lmscale[3]; gl_FragColor.rgb *= lightmaps.rgb; #else - gl_FragColor.rgb *= texture2D(s_t1, lm) * e_lmscale; + gl_FragColor.rgb *= (texture2D(s_t1, lm) * e_lmscale).rgb; #endif #ifdef FULLBRIGHT